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


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:
0042:        package org.openide.loaders;
0043:
0044:        import java.beans.*;
0045:        import java.io.IOException;
0046:        import java.lang.ref.*;
0047:        import java.util.*;
0048:        import java.util.logging.*;
0049:        import org.openide.filesystems.*;
0050:        import org.openide.util.*;
0051:
0052:        /** Watches a folder and its children.
0053:         *
0054:         * <p>{@link java.beans.PropertyChangeListener}s
0055:         * may be registered which will be informed about changes in the ordered
0056:         * children list. The {@link java.beans.PropertyChangeEvent}s fired by instances
0057:         * of this class do neither contain information about the old value nor about
0058:         * the new value of the children list.</p>
0059:         *
0060:         * <p>The list of children can be retrieved by calls to
0061:         * the methods {@link #getChildren()} resp. {@link #getChildrenList()}. If you
0062:         * want to filter the children which shall be included into the folder list,
0063:         * call {@link #computeChildrenList(FolderListListener)}. The same is true
0064:         * if you want to trigger children computation asynchronously. In this case
0065:         * the implementation of {@link FolderListListener#finished(List)} shall be 
0066:         * used to get informed about the result of the computation.</p>
0067:         *
0068:         * <p>To retrieve the appropriate instance of this class for a given folder
0069:         *   call {@link #find(FileObject, boolean)}.</p>
0070:         *
0071:         * @author Jaroslav Tulach
0072:         */
0073:        final class FolderList extends Object implements  FileChangeListener,
0074:                DataObject.Container {
0075:
0076:            /* -------------------------------------------------------------------- */
0077:            /* -- Constants ------------------------------------------------------- */
0078:            /* -------------------------------------------------------------------- */
0079:
0080:            /** serial version UID */
0081:            static final long serialVersionUID = -592616022226761148L;
0082:
0083:            /** priority for tasks that can be run later */
0084:            private static final int LATER_PRIORITY = Thread.NORM_PRIORITY;
0085:
0086:            /** request processor for recognizing of folders */
0087:            private static final RequestProcessor PROCESSOR = new RequestProcessor(
0088:                    "Folder recognizer" // NOI18N
0089:            );
0090:
0091:            /** map of (FileObject, Reference (FolderList)) */
0092:            private static final Map<FileObject, Reference<FolderList>> map = new WeakHashMap<FileObject, Reference<FolderList>>(
0093:                    101);
0094:
0095:            /** refresh time in milliseconds */
0096:            private static int REFRESH_TIME = -1; // will be updated in getRefreshTime
0097:
0098:            /* -------------------------------------------------------------------- */
0099:            /* -- Instance attributes --------------------------------------------- */
0100:            /* -------------------------------------------------------------------- */
0101:
0102:            /** data folder to work with */
0103:            private FileObject folder;
0104:
0105:            /** The task that computes the content of FolderList. There is also
0106:             * only one computation task in the PROCESSOR for each FolderList.
0107:             * Whenever a new change notification arrives (thru file listener)
0108:             * the previous task is canceled (if not running) and new is created.
0109:             */
0110:            transient private RequestProcessor.Task refreshTask;
0111:            /** task that is non-null if a setOrder has been called
0112:             */
0113:            transient private volatile RequestProcessor.Task comparatorTask;
0114:
0115:            /** Primary files in this folder. Maps (FileObject, Reference (DataObject))
0116:             */
0117:            transient private Map<FileObject, Reference<DataObject>> primaryFiles = null;
0118:
0119:            /** order of primary files (FileObject) */
0120:            transient private List<FileObject> order;
0121:
0122:            private static final Logger err = Logger
0123:                    .getLogger("org.openide.loaders.FolderList"); // NOI18N
0124:
0125:            /** property change support */
0126:            transient private PropertyChangeSupport pcs;
0127:
0128:            /**
0129:             * If true, this folder has been fully created (though it might
0130:             * still be refreshing etc.). Used to avoid e.g. MDO.PROP_FILES
0131:             * firing before the folder is ready.
0132:             */
0133:            transient private boolean folderCreated = false;
0134:
0135:            transient private FileChangeListener weakFCL = FileUtil
0136:                    .weakFileChangeListener(this , null);
0137:
0138:            /* -------------------------------------------------------------------- */
0139:            /* -- Constructor (private) ------------------------------------------- */
0140:            /* -------------------------------------------------------------------- */
0141:
0142:            /**
0143:             * @param df data folder to show
0144:             */
0145:            private FolderList(FileObject folder, boolean attach) {
0146:                this .folder = folder;
0147:                if (attach) {
0148:                    // creates object that handles all elements in array and
0149:                    // assignes it to the
0150:                    folder.addFileChangeListener(weakFCL);
0151:                }
0152:            }
0153:
0154:            /*    final void reassign(DataFolder df, FileObject fo) {
0155:             folder = df;
0156:             // reassign is called from DataFolder.handleMove()
0157:             // in this time the folder - df - does not have
0158:             // setup the right primary file
0159:             // so the fo is the new primary file for df
0160:             fo.addFileChangeListener (WeakListener.fileChange (this, fo));
0161:             }
0162:             */
0163:            @Override
0164:            public String toString() {
0165:                return "FolderList{" + folder + "}"; // NOI18N
0166:            }
0167:
0168:            /* -------------------------------------------------------------------- */
0169:            /* -- Factory method (static) ----------------------------------------- */
0170:            /* -------------------------------------------------------------------- */
0171:
0172:            /** A public method to get the correct list for given file object.
0173:             *
0174:             * @param folder the folder to find FolderList for
0175:             * @param create if true than new FolderList should be created if it does not exists
0176:             * @return the FolderList or null if create was false
0177:             */
0178:            public static FolderList find(FileObject folder, boolean create) {
0179:                FolderList list = null;
0180:                synchronized (FolderList.class) {
0181:                    Reference<FolderList> ref = map.get(folder);
0182:                    list = ref == null ? null : ref.get();
0183:                    if (list == null && create) {
0184:                        list = new FolderList(folder, true);
0185:                        map.put(folder, new SoftReference<FolderList>(list));
0186:                    }
0187:                }
0188:                return list;
0189:            }
0190:
0191:            /**
0192:             * Has this FolderList finished creation of this list (at least once)?
0193:             * @return true if it has been created (may still be refreshing), false if still in progress
0194:             */
0195:            public boolean isCreated() {
0196:                return folderCreated;
0197:            }
0198:
0199:            /* -------------------------------------------------------------------- */
0200:            /* -- Static methods -------------------------------------------------- */
0201:            /* -------------------------------------------------------------------- */
0202:
0203:            /** Checks whether the calling thread is the FolderRecognizer.
0204:             */
0205:            public static boolean isFolderRecognizerThread() {
0206:                return PROCESSOR.isRequestProcessorThread();
0207:            }
0208:
0209:            /* -------------------------------------------------------------------- */
0210:            /* -- Static methods to inform FolderList for a given folder ---------- */
0211:            /* -------------------------------------------------------------------- */
0212:
0213:            /** A method used to notify the FolderList system that order has changed
0214:             * for a given file object. 
0215:             * 
0216:             * @param folder the affected file object
0217:             */
0218:            public static void changedFolderOrder(FileObject folder) {
0219:                FolderList list = find(folder, false);
0220:                if (list != null) {
0221:                    list.changeComparator();
0222:                }
0223:            }
0224:
0225:            /** Called when a data system changed so much that there is a need for refresh
0226:             * of a content of a folder.
0227:             *
0228:             * @param folder file object that can be affected
0229:             */
0230:            public static void changedDataSystem(FileObject folder) {
0231:                FolderList list = find(folder, false);
0232:                if (err.isLoggable(Level.FINE)) {
0233:                    err.fine("changedDataSystem: " + folder + " on "
0234:                            + Thread.currentThread()); // NOI18N
0235:                }
0236:                if (list != null) {
0237:                    list.refresh();
0238:                }
0239:            }
0240:
0241:            /* -------------------------------------------------------------------- */
0242:            /* -- Folder content and content processing --------------------------- */
0243:            /* -------------------------------------------------------------------- */
0244:
0245:            /** Computes array of children associated
0246:             * with this folder.
0247:             */
0248:            public DataObject[] getChildren() {
0249:                List<DataObject> res = getChildrenList();
0250:                if (res == null) {
0251:                    return new DataObject[0];
0252:                }
0253:                DataObject[] arr = new DataObject[res.size()];
0254:                res.toArray(arr);
0255:                return arr;
0256:            }
0257:
0258:            /** List all children.
0259:             * @return array with children
0260:             */
0261:            public List<DataObject> getChildrenList() {
0262:                ListTask lt;
0263:                try {
0264:                    DataObjectPool.getPOOL()
0265:                            .enterPrivilegedProcessor(PROCESSOR);
0266:                    lt = getChildrenList(null);
0267:                    lt.task.waitFinished();
0268:                } finally {
0269:                    DataObjectPool.getPOOL().exitPrivilegedProcessor(PROCESSOR);
0270:                }
0271:                assert lt.result != null;
0272:                return lt.result;
0273:            }
0274:
0275:            /** Blocks if the processing of content of folder is in progress.
0276:             */
0277:            public void waitProcessingFinished() {
0278:                Task t = comparatorTask;
0279:                if (t != null) {
0280:                    t.waitFinished();
0281:                }
0282:
0283:                t = refreshTask;
0284:                if (t != null) {
0285:                    t.waitFinished();
0286:                }
0287:            }
0288:
0289:            /** Starts computation of children list asynchronously.
0290:             */
0291:            public RequestProcessor.Task computeChildrenList(
0292:                    FolderListListener filter) {
0293:                return getChildrenList(filter).task;
0294:            }
0295:
0296:            private ListTask getChildrenList(FolderListListener filter) {
0297:                ListTask lt = new ListTask(filter);
0298:                int priority = Thread.currentThread().getPriority();
0299:
0300:                // and then post your read task and wait
0301:                lt.task = PROCESSOR.post(lt, 0, priority);
0302:                return lt;
0303:            }
0304:
0305:            /** Setter for sort mode.
0306:             */
0307:            private synchronized void changeComparator() {
0308:                final boolean LOG = err.isLoggable(Level.FINE);
0309:                if (LOG)
0310:                    err.fine("changeComparator on " + folder);
0311:                final RequestProcessor.Task previous = comparatorTask;
0312:                final RequestProcessor.Task[] COMP = new RequestProcessor.Task[1];
0313:                synchronized (COMP) {
0314:                    comparatorTask = PROCESSOR.post(new Runnable() {
0315:                        public void run() {
0316:                            synchronized (COMP) {
0317:                                if (previous != null) {
0318:                                    previous.waitFinished();
0319:                                }
0320:                                // if has been notified
0321:                                // change mode and regenerated children
0322:                                if (primaryFiles != null) {
0323:                                    // the old children
0324:                                    if (LOG)
0325:                                        err.fine("changeComparator on "
0326:                                                + folder + ": get old");
0327:                                    List<DataObject> v = getObjects(null);
0328:                                    if (v.size() != 0) {
0329:                                        // the new children - also are stored to be returned next time from getChildrenList ()
0330:                                        order = null;
0331:                                        if (LOG)
0332:                                            err
0333:                                                    .fine("changeComparator: get new");
0334:                                        List<DataObject> r = getObjects(null);
0335:                                        if (LOG)
0336:                                            err
0337:                                                    .fine("changeComparator: fire change");
0338:                                        fireChildrenChange(r, v);
0339:                                    }
0340:                                }
0341:                                synchronized (FolderList.this ) {
0342:                                    // clean  the task if is my own not assigned by somebody else
0343:                                    if (comparatorTask == COMP[0]) {
0344:                                        comparatorTask = null;
0345:                                    }
0346:                                }
0347:                            }
0348:                        }
0349:                    }, 0, Thread.MIN_PRIORITY);
0350:                    COMP[0] = comparatorTask;
0351:                }
0352:            }
0353:
0354:            /* -------------------------------------------------------------------- */
0355:            /* -- Refresh --------------------------------------------------------- */
0356:            /* -------------------------------------------------------------------- */
0357:
0358:            /** Refreshes the list of children.
0359:             */
0360:            public void refresh() {
0361:                final long now = System.currentTimeMillis();
0362:                final boolean LOG = err.isLoggable(Level.FINE);
0363:                if (LOG)
0364:                    err.fine("refresh on " + folder + " @" + now);
0365:                synchronized (this ) {
0366:                    if (refreshTask == null) {
0367:                        refreshTask = PROCESSOR.post(new Runnable() {
0368:                            public void run() {
0369:                                RequestProcessor.Task t = comparatorTask;
0370:                                if (t != null) {
0371:                                    // first of all finish setting up comparator
0372:                                    t.waitFinished();
0373:                                }
0374:
0375:                                if (LOG)
0376:                                    err.fine("-- refresh on " + folder
0377:                                            + ": now=" + now);
0378:                                if (primaryFiles != null) {
0379:                                    // list of children is created, recreate it for new files
0380:                                    createBoth(null, true);
0381:                                }
0382:                            }
0383:                        }, getRefreshTime(), LATER_PRIORITY);
0384:                    } else {
0385:                        refreshTask.schedule(getRefreshTime());
0386:                    }
0387:                }
0388:            }
0389:
0390:            /** Tries to read the value of the refresh time from a system property.
0391:             * If the system property is not present a default value (currently 10)
0392:             * is used.
0393:             */
0394:            private static int getRefreshTime() {
0395:                if (REFRESH_TIME >= 0) {
0396:                    return REFRESH_TIME;
0397:                }
0398:
0399:                String sysProp = System
0400:                        .getProperty("org.openide.loaders.FolderList.refresh.interval"); // NOI18N
0401:                if (sysProp != null) {
0402:                    try {
0403:                        REFRESH_TIME = Integer.parseInt(sysProp);
0404:                    } catch (NumberFormatException nfe) {
0405:                        Logger.getLogger(FolderList.class.getName()).log(
0406:                                Level.WARNING, null, nfe);
0407:                    }
0408:                }
0409:                if (REFRESH_TIME < 0) {
0410:                    REFRESH_TIME = 10;
0411:                }
0412:                return REFRESH_TIME;
0413:            }
0414:
0415:            /* -------------------------------------------------------------------- */
0416:            /* -- Implementation of FileChangeListener ---------------------------- */
0417:            /* -------------------------------------------------------------------- */
0418:
0419:            /** Fired when a file has been changed. Refreshes the list when a 
0420:             *  has be changed which up to now was not a member of the list but
0421:             *  becomes a member as a consequence of the change.
0422:             *
0423:             * @param fe the event describing context where action has taken place
0424:             */
0425:            public void fileChanged(FileEvent fe) {
0426:                final boolean LOG = err.isLoggable(Level.FINE);
0427:                if (LOG)
0428:                    err.fine("fileChanged: " + fe);
0429:
0430:                FileObject fo = fe.getFile();
0431:
0432:                /** condition fo.isValid () is hot fix for solving problem (similar to #17328)
0433:                 * inside filesystems  and should be reviewed.
0434:                 */
0435:                if (fo.isData() && fo.isValid()) {
0436:                    // when a data on the disk has been changed, look whether we
0437:                    // should reparse children
0438:                    if (primaryFiles != null) {
0439:                        // a file has been changed and the list of files is created
0440:                        try {
0441:                            DataObject obj = DataObject.find(fo);
0442:                            if (!primaryFiles.containsKey(obj.getPrimaryFile())) {
0443:                                // BUGFIX: someone who recognized the file and who isn't registered
0444:                                // yet =>
0445:                                // may be still not O.K.
0446:
0447:                                // this primary file is not registered yet
0448:                                // so recreate list of children
0449:                                refresh();
0450:                            }
0451:                        } catch (DataObjectNotFoundException ex) {
0452:                            Logger.getLogger(FolderList.class.getName()).log(
0453:                                    Level.WARNING, null, ex);
0454:                            // file without data object => no changes
0455:                        }
0456:                    }
0457:
0458:                    // Resort if sorting by last modification or size:
0459:                    DataFolder.SortMode sortMode = getComparator()
0460:                            .getSortMode();
0461:                    if (sortMode == DataFolder.SortMode.LAST_MODIFIED
0462:                            || sortMode == DataFolder.SortMode.SIZE) {
0463:                        changeComparator();
0464:                    }
0465:                }
0466:            }
0467:
0468:            /** Fired when a file has been deleted.
0469:             * @param fe the event describing context where action has taken place
0470:             */
0471:            public void fileDeleted(FileEvent fe) {
0472:                final boolean LOG = err.isLoggable(Level.FINE);
0473:                if (LOG)
0474:                    err.fine("fileDeleted: " + fe);
0475:                //    boolean debug = fe.getFile().toString().equals("P"); // NOI18N
0476:                //if (debug) System.out.println ("fileDeleted: " + fe.getFile ()); // NOI18N
0477:                //if (debug) System.out.println ("fileList: " + fileList + " file: " + fileList.get (fe.getFile ())); // NOI18N
0478:                if (primaryFiles == null
0479:                        || primaryFiles.containsKey(fe.getFile())) {
0480:                    // one of main files has been deleted => reparse
0481:                    //if (debug) System.out.println ("RecreateChildenList"); // NOI18N
0482:                    refresh();
0483:                    //if (debug) System.out.println ("Done"); // NOI18N
0484:                }
0485:            }
0486:
0487:            /** Fired when a new file has been created. This action can only be
0488:             * listened in folders containing the created file up to the root of
0489:             * file system.
0490:             *
0491:             * @param fe the event describing context where action has taken place
0492:             */
0493:            public void fileDataCreated(FileEvent fe) {
0494:                final boolean LOG = err.isLoggable(Level.FINE);
0495:                if (LOG)
0496:                    err.fine("fileDataCreated: " + fe);
0497:                refresh();
0498:            }
0499:
0500:            /** Fired when a new file has been created. This action can only be
0501:             * listened in folders containing the created file up to the root of
0502:             * file system.
0503:             *
0504:             * @param fe the event describing context where action has taken place
0505:             */
0506:            public void fileFolderCreated(FileEvent fe) {
0507:                final boolean LOG = err.isLoggable(Level.FINE);
0508:                if (LOG)
0509:                    err.fine("fileFolderCreated: " + fe);
0510:                refresh();
0511:            }
0512:
0513:            /** Fired when a new file has been renamed.
0514:             *
0515:             * @param fe the event describing context where action has taken place
0516:             */
0517:            public void fileRenamed(FileRenameEvent fe) {
0518:                final boolean LOG = err.isLoggable(Level.FINE);
0519:                if (LOG)
0520:                    err.fine("fileRenamed: " + fe);
0521:                refresh();
0522:                // Typically order may change as a result (#13820):
0523:                changeComparator();
0524:            }
0525:
0526:            /** Fired when a file attribute has been changed.
0527:             *
0528:             * @param fe the event describing context where action has taken place
0529:             */
0530:            public void fileAttributeChanged(FileAttributeEvent fe) {
0531:                final boolean LOG = err.isLoggable(Level.FINE);
0532:                if (LOG)
0533:                    err.fine("fileAttributeChanged: " + fe);
0534:                // update list when attrs defining order were changed
0535:                if (fe.getFile() == folder) {
0536:                    /** Means one of attributes were changed*/
0537:                    if (fe.getName() == null) {
0538:                        changeComparator();
0539:                        return;
0540:                    }
0541:                    if (DataFolder.EA_ORDER.equals(fe.getName())
0542:                            || DataFolder.EA_SORT_MODE.equals(fe.getName())) {
0543:                        changeComparator();
0544:                    }
0545:                } else if (FileUtil.affectsOrder(fe)) {
0546:                    changeComparator();
0547:                }
0548:            }
0549:
0550:            /* -------------------------------------------------------------------- */
0551:            /* -- Processing methods (only called in PROCESSOR) ------------------- */
0552:            /* -------------------------------------------------------------------- */
0553:
0554:            /** The comparator for this file objects.
0555:             * @return the comparator to use
0556:             */
0557:            private FolderOrder getComparator() {
0558:                return FolderOrder.findFor(folder);
0559:            }
0560:
0561:            /** Getter for list of children.
0562:             * @param f filter to be notified about additions
0563:             * @return List with DataObject types
0564:             */
0565:            private List<DataObject> getObjects(FolderListListener f) {
0566:                final boolean LOG = err.isLoggable(Level.FINE);
0567:                if (LOG)
0568:                    err.fine("getObjects on " + folder);
0569:                List<DataObject> res;
0570:                if (primaryFiles == null) {
0571:                    res = createBoth(f, false);
0572:                } else {
0573:                    if (order != null) {
0574:                        res = createObjects(order, primaryFiles, f);
0575:                    } else {
0576:                        res = createObjects(primaryFiles.keySet(),
0577:                                primaryFiles, f);
0578:                        res = carefullySort(res, getComparator());
0579:                        order = createOrder(res);
0580:                    }
0581:                }
0582:                return res;
0583:                /* createChildrenAndFiles ();/*
0584:                ArrayList v = (Collection)childrenList.get ();
0585:                //if (debug) System.out.println ("Children list xxxxxxxxxxxxxx");
0586:                if (v == null) {
0587:                //if (debug) System.out.println ("Create them xxxxxxxxxxxx");
0588:                  v = createChildrenList (f);
0589:                //if (debug) System.out.println ("result: " + v);
0590:                }
0591:                return v;*/
0592:            }
0593:
0594:            /** Sort a list of DataObject's carefully.
0595:             * The supplied comparator should supply a basic ordering,
0596:             * and may also have an associated overriding partial ordering.
0597:             * If the partial ordering is given and is self-contradictory,
0598:             * it will be ignored and a warning issued.
0599:             * @param l the list to sort
0600:             * @param c a comparator and maybe partial comparator to use
0601:             * @return the sorted list (may or may not be the same)
0602:             */
0603:            private List<DataObject> carefullySort(List<DataObject> l,
0604:                    FolderOrder c) {
0605:                final boolean LOG = err.isLoggable(Level.FINE);
0606:                if (LOG)
0607:                    err.fine("carefullySort on " + folder);
0608:                Collections.sort(l, c);
0609:                Map<FileObject, DataObject> files = new LinkedHashMap<FileObject, DataObject>(
0610:                        l.size());
0611:                for (DataObject d : l) {
0612:                    FileObject f = d.getPrimaryFile();
0613:                    if (folder.equals(f.getParent())) {
0614:                        f.removeFileChangeListener(weakFCL);
0615:                        f.addFileChangeListener(weakFCL);
0616:                        files.put(f, d);
0617:                    }
0618:                }
0619:                if (LOG)
0620:                    err.fine("carefullySort before getOrder");
0621:                List<FileObject> sorted = FileUtil.getOrder(files.keySet(),
0622:                        true);
0623:                List<DataObject> dobs = new ArrayList<DataObject>(sorted.size());
0624:                for (FileObject f : sorted) {
0625:                    dobs.add(files.get(f));
0626:                }
0627:                return dobs;
0628:            }
0629:
0630:            /** Creates list of primary files from the list of data objects.
0631:             * @param list list of DataObject
0632:             * @return list of FileObject
0633:             */
0634:            private static List<FileObject> createOrder(List<DataObject> list) {
0635:                int size = list.size();
0636:                List<FileObject> res = new ArrayList<FileObject>(size);
0637:
0638:                for (int i = 0; i < size; i++) {
0639:                    res.add(list.get(i).getPrimaryFile());
0640:                }
0641:
0642:                return res;
0643:            }
0644:
0645:            /** Creates array of data objects from given order
0646:             * and mapping between files and data objects.
0647:             *
0648:             * @param order list of FileObjects that define the order to use
0649:             * @param map mapping (FileObject, Reference (DataObject)) to create data objects from
0650:             * @param f filter that is notified about additions - only items
0651:             * which are accepted by the filter will be added. Null means no filtering.
0652:             * @return array of data objects
0653:             */
0654:            private/*static*/List<DataObject> createObjects(
0655:                    Collection<FileObject> order,
0656:                    Map<FileObject, Reference<DataObject>> map,
0657:                    FolderListListener f) {
0658:                final boolean LOG = err.isLoggable(Level.FINE);
0659:                if (LOG) {
0660:                    err.fine("createObjects on " + folder);
0661:                }
0662:                int size = order.size();
0663:
0664:                Iterator it = order.iterator();
0665:
0666:                List<DataObject> res = new ArrayList<DataObject>(size);
0667:                for (FileObject fo : order) {
0668:
0669:                    if (LOG) {
0670:                        err.fine("  iterating" + fo);
0671:                    }
0672:                    if (!fo.isValid()) {
0673:                        if (LOG) {
0674:                            err.fine("    not valid, continue");
0675:                        }
0676:                        continue;
0677:                    }
0678:                    Reference<DataObject> ref = map.get(fo);
0679:                    DataObject obj = ref != null ? ref.get() : null;
0680:
0681:                    if (obj == null) {
0682:                        // try to find new data object
0683:                        if (LOG) {
0684:                            err.fine("    reference is " + ref + " obj is "
0685:                                    + obj);
0686:                        }
0687:                        try {
0688:                            obj = DataObject.find(fo);
0689:                            ref = new SoftReference<DataObject>(obj);
0690:                            map.put(fo, ref);
0691:                        } catch (DataObjectNotFoundException ex) {
0692:                            Logger.getLogger(FolderList.class.getName()).log(
0693:                                    Level.WARNING, null, ex);
0694:                        }
0695:                    }
0696:                    // add if accepted
0697:                    if (obj != null) {
0698:                        if (LOG) {
0699:                            err.fine("    deliver: ref is " + ref + " obj is "
0700:                                    + obj);
0701:                        }
0702:                        // JST: Cannot be avoided otherwise DataObject.files () can be unconsistent
0703:                        // avoid to checkFiles(this)
0704:                        // obj.recognizedByFolder();
0705:                        if (f == null) {
0706:                            // accept all objects
0707:                            res.add(obj);
0708:                        } else {
0709:                            // allow the listener f to filter
0710:                            // objects in the array res
0711:                            f.process(obj, res);
0712:                        }
0713:                    }
0714:                }
0715:
0716:                if (f != null) {
0717:                    if (LOG) {
0718:                        err.fine("  finished: " + res); // NOI18N
0719:                    }
0720:                    f.finished(res);
0721:                }
0722:
0723:                if (LOG) {
0724:                    err.fine("createObjects ends on " + folder); // NOI18N
0725:                }
0726:                return res;
0727:            }
0728:
0729:            /** Scans for files in the folder and creates representation for
0730:             * children. Fires info about changes in the nodes.
0731:             *
0732:             * @param filter listener to addition of nodes or null
0733:             * @param notify true if changes in the children should be fired
0734:             * @return vector of children
0735:             */
0736:            private List<DataObject> createBoth(FolderListListener filter,
0737:                    boolean notify) {
0738:                final boolean LOG = err.isLoggable(Level.FINE);
0739:                if (LOG)
0740:                    err.fine("createBoth on " + folder);
0741:                // map for (FileObject, DataObject)
0742:                final HashMap<FileObject, Reference<DataObject>> file = new HashMap<FileObject, Reference<DataObject>>();
0743:
0744:                // list of all processed objects
0745:                List<DataObject> all = new ArrayList<DataObject>();
0746:                // result list to return from the method
0747:                List<DataObject> res = new ArrayList<DataObject>();
0748:
0749:                // map of current objects (FileObject, DataObject)
0750:                final Map<FileObject, Reference<DataObject>> remove = primaryFiles == null ? new HashMap<FileObject, Reference<DataObject>>()
0751:                        : new HashMap<FileObject, Reference<DataObject>>(
0752:                                primaryFiles);
0753:
0754:                // list of new objects to add
0755:                final List<DataObject> add = new ArrayList<DataObject>();
0756:
0757:                DataLoaderPool pool = DataLoaderPool.getDefault();
0758:
0759:                // hashtable with FileObjects that are marked to be recognized
0760:                // and that is why being out of enumeration
0761:                final HashSet<FileObject> marked = new HashSet<FileObject>();
0762:                DataLoader.RecognizedFiles recog = new DataLoader.RecognizedFiles() {
0763:                    /** Adds the file object to the marked hashtable.
0764:                     * @param fo file object (can be <CODE>null</CODE>)
0765:                     */
0766:                    public void markRecognized(FileObject fo) {
0767:                        if (fo != null) {
0768:                            marked.add(fo);
0769:                        }
0770:                    }
0771:                };
0772:                // enumeration of all files in the folder
0773:                Enumeration<? extends FileObject> en = folder
0774:                        .getChildren(false);
0775:                while (en.hasMoreElements()) {
0776:                    FileObject fo = en.nextElement();
0777:                    if (!marked.contains(fo)) {
0778:                        // the object fo has not been yet marked as recognized
0779:                        // => continue in computation
0780:                        DataObject obj;
0781:                        try {
0782:                            obj = pool.findDataObject(fo, recog);
0783:                        } catch (DataObjectExistsException ex) {
0784:                            // use existing data object
0785:                            obj = ex.getDataObject();
0786:                        } catch (IOException ex) {
0787:                            // data object not recognized or not found
0788:                            obj = null;
0789:                            Exceptions.printStackTrace(ex);
0790:                        } catch (Throwable td) {
0791:                            obj = null;
0792:                            err.log(Level.WARNING, "Error recognizing " + fo,
0793:                                    td);
0794:                        }
0795:
0796:                        if (obj != null) {
0797:                            // adds object to data if it is not already there
0798:
0799:                            // avoid to checkFiles(this)
0800:                            obj.recognizedByFolder();
0801:
0802:                            // primary file
0803:                            FileObject primary = obj.getPrimaryFile();
0804:
0805:                            boolean doNotRemovePrimaryFile = false;
0806:                            if (!file.containsKey(primary)) {
0807:                                // realy added object, test if it is new
0808:
0809:                                // if we have not created primaryFiles before, then it is new
0810:                                boolean goIn = primaryFiles == null;
0811:                                if (!goIn) {
0812:                                    Reference<DataObject> r = primaryFiles
0813:                                            .get(primary);
0814:                                    // if its primary file is not between original primary files
0815:                                    // then data object is new
0816:                                    goIn = r == null;
0817:                                    if (!goIn) {
0818:                                        // if the primary file is there, but the previous data object
0819:                                        // exists and is different, then this one is new
0820:                                        DataObject obj2 = r.get();
0821:                                        goIn = obj2 == null || obj2 != obj;
0822:                                        if (goIn) {
0823:                                            doNotRemovePrimaryFile = true;
0824:                                        }
0825:                                    }
0826:                                }
0827:
0828:                                if (goIn) {
0829:                                    // realy new
0830:                                    add.add(obj);
0831:                                    /* JST: In my opinion it should not be here
0832:                                     * so I moved this out of this if. Is it ok?
0833:
0834:                                    if (filter != null) {
0835:                                      // fire info about addition
0836:                                      filter.acceptDataObject (obj);
0837:                                    }
0838:                                     */
0839:                                }
0840:                                // adds the object
0841:                                all.add(obj);
0842:                                if (filter == null) {
0843:                                    res.add(obj);
0844:                                } else {
0845:                                    filter.process(obj, res);
0846:                                }
0847:                            }
0848:
0849:                            if (!doNotRemovePrimaryFile) {
0850:                                // this object exists it should not be removed
0851:                                remove.remove(primary);
0852:                            }
0853:
0854:                            // add it to the list of primary files
0855:                            file.put(primary,
0856:                                    new SoftReference<DataObject>(obj));
0857:                        } else {
0858:                            // 1. nothing to add to data object list
0859:                            // 2. remove this object if it was in list of previous ones
0860:                            // 3. do not put the file into list of know primary files
0861:                            // => do nothing at all
0862:                        }
0863:                    }
0864:                }
0865:
0866:                // !!! section that fires info about changes should be here !!!
0867:
0868:                // now file contains newly inserted files
0869:                // data contains data objects
0870:                // remove contains data objects that should be removed
0871:                // add contains data object that were added
0872:
0873:                primaryFiles = file;
0874:
0875:                all = carefullySort(all, getComparator());
0876:                order = createOrder(all);
0877:                if (all.size() == res.size()) {
0878:                    // assume no filtering has been done
0879:                    res = all;
0880:                } else {
0881:                    // sort also content of res
0882:                    res = carefullySort(res, getComparator());
0883:                }
0884:
0885:                ////if (debug) System.out.println ("Notified: " + notified + " added: " + add.size () + " removed: " + remove.size ()); // NOI18N
0886:                if (notify) {
0887:                    fireChildrenChange(add, remove.keySet());
0888:                }
0889:
0890:                // notify the filter
0891:                if (LOG) {
0892:                    err.fine("Notifying filter: " + filter); // NOI18N
0893:                }
0894:                if (filter != null) {
0895:                    filter.finished(res);
0896:                }
0897:
0898:                return res;
0899:            }
0900:
0901:            /* -------------------------------------------------------------------- */
0902:            /* -- PropertyChangeListener management ------------------------------- */
0903:            /* -------------------------------------------------------------------- */
0904:
0905:            /** Fires info about change of children to the folder.
0906:             * @param add added data objects
0907:             * @param removed removed data objects
0908:             */
0909:            private void fireChildrenChange(Collection<?> add,
0910:                    Collection<?> removed) {
0911:                if (pcs != null) {
0912:                    if (!add.isEmpty() || !removed.isEmpty()) {
0913:                        pcs.firePropertyChange(PROP_CHILDREN, null, null);
0914:                    }
0915:                }
0916:            }
0917:
0918:            /** Removes property change listener.
0919:             * @param l the listener
0920:             */
0921:            public void removePropertyChangeListener(PropertyChangeListener l) {
0922:                if (pcs != null) {
0923:                    pcs.removePropertyChangeListener(l);
0924:                }
0925:            }
0926:
0927:            /** Adds a listener.
0928:             * @param l the listener
0929:             */
0930:            public synchronized void addPropertyChangeListener(
0931:                    PropertyChangeListener l) {
0932:                if (pcs == null) {
0933:                    pcs = new PropertyChangeSupport(this );
0934:                }
0935:                pcs.addPropertyChangeListener(l);
0936:            }
0937:
0938:            /* -------------------------------------------------------------------- */
0939:            /* -- Inner class ListTask -------------------------------------------- */
0940:            /* -------------------------------------------------------------------- */
0941:
0942:            /** Task that holds result and also task. Moreover
0943:             * can do the computation.
0944:             */
0945:            private final class ListTask implements  Runnable {
0946:                private FolderListListener filter;
0947:
0948:                public ListTask(FolderListListener filter) {
0949:                    this .filter = filter;
0950:                }
0951:
0952:                public List<DataObject> result;
0953:                public RequestProcessor.Task task;
0954:
0955:                public void run() {
0956:                    try {
0957:                        computeResult();
0958:                    } catch (Error t) {
0959:                        err.log(Level.WARNING,
0960:                                "cannot compute data objects for " + folder, t); // NOI18N
0961:                        throw t;
0962:                    } catch (RuntimeException ex) {
0963:                        err
0964:                                .log(Level.WARNING,
0965:                                        "cannot compute data objects for "
0966:                                                + folder, ex); // NOI18N
0967:                        throw ex;
0968:                    }
0969:                }
0970:
0971:                private void computeResult() {
0972:                    final boolean LOG = err.isLoggable(Level.FINE);
0973:                    if (LOG)
0974:                        err.fine("ListTask.run 1 on " + folder);
0975:                    // invokes the refresh task before we do anything else
0976:                    if (comparatorTask != null) {
0977:                        comparatorTask.waitFinished();
0978:                    }
0979:                    if (refreshTask != null) {
0980:                        refreshTask.waitFinished();
0981:                    }
0982:                    err.fine("ListTask.run 2");
0983:
0984:                    result = getObjects(filter);
0985:                    assert result != null;
0986:                    err.log(Level.FINE, "ListTask.run 3: {0}", result);
0987:
0988:                    folderCreated = true;
0989:                }
0990:
0991:                @Override
0992:                public String toString() {
0993:                    return "ListTask@"
0994:                            + Integer
0995:                                    .toHexString(System.identityHashCode(this ))
0996:                            + "[" + folder + "]"; // NOI18N
0997:                }
0998:            }
0999:
1000:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.