Source Code Cross Referenced for Source.java in  » IDE-Netbeans » gsf » org » netbeans » napi » gsfret » source » 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 » gsf » org.netbeans.napi.gsfret.source 
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.netbeans.napi.gsfret.source;
0043:
0044:        import java.beans.PropertyChangeEvent;
0045:        import java.beans.PropertyChangeListener;
0046:        import java.io.File;
0047:        import java.io.FileOutputStream;
0048:        import java.io.IOException;
0049:        import java.io.OutputStream;
0050:        import java.io.OutputStreamWriter;
0051:        import java.io.PrintWriter;
0052:        import java.lang.ref.Reference;
0053:        import java.lang.ref.WeakReference;
0054:        import java.lang.reflect.Method;
0055:        import java.util.ArrayList;
0056:        import java.util.Arrays;
0057:        import java.util.Collection;
0058:        import java.util.Collections;
0059:        import java.util.Comparator;
0060:        import java.util.HashMap;
0061:        import java.util.HashSet;
0062:        import java.util.Iterator;
0063:        import java.util.LinkedList;
0064:        import java.util.List;
0065:        import java.util.Map;
0066:        import java.util.WeakHashMap;
0067:        import java.util.concurrent.Executors;
0068:        import java.util.concurrent.PriorityBlockingQueue;
0069:        import java.util.concurrent.ThreadFactory;
0070:        import java.util.concurrent.TimeUnit;
0071:        import java.util.concurrent.atomic.AtomicBoolean;
0072:        import java.util.concurrent.locks.ReentrantLock;
0073:        import java.util.logging.Level;
0074:        import java.util.logging.Logger;
0075:        import javax.swing.event.ChangeEvent;
0076:        import javax.swing.event.ChangeListener;
0077:        import javax.swing.event.DocumentEvent;
0078:        import javax.swing.event.DocumentListener;
0079:        import javax.swing.text.AbstractDocument;
0080:        import javax.swing.text.Document;
0081:        import javax.swing.text.StyledDocument;
0082:        import javax.swing.event.CaretEvent;
0083:        import javax.swing.event.CaretListener;
0084:        import javax.swing.event.ChangeListener;
0085:        import javax.swing.text.JTextComponent;
0086:        import org.netbeans.api.editor.EditorRegistry;
0087:        import org.netbeans.modules.gsf.api.ParserFile;
0088:        import org.netbeans.modules.gsf.api.TranslatedSource;
0089:        import org.netbeans.modules.gsfpath.api.classpath.ClassPath;
0090:        import org.netbeans.modules.gsfpath.api.platform.JavaPlatformManager;
0091:        import org.netbeans.modules.gsfpath.api.queries.SourceLevelQuery;
0092:        import org.netbeans.modules.gsf.api.Error;
0093:        import org.netbeans.modules.gsf.api.ParseEvent;
0094:        import org.netbeans.modules.gsf.api.ParseListener;
0095:        import org.netbeans.modules.gsf.api.Parser;
0096:        import org.netbeans.modules.gsf.api.ParserResult;
0097:        import org.netbeans.modules.gsf.api.SourceFileReader;
0098:        import org.netbeans.modules.gsf.api.CancellableTask;
0099:        import org.netbeans.modules.gsf.api.EmbeddingModel;
0100:        import org.netbeans.napi.gsfret.source.ClasspathInfo.PathKind;
0101:        import org.netbeans.napi.gsfret.source.ModificationResult.Difference;
0102:        import org.netbeans.napi.gsfret.source.ParserTaskImpl;
0103:        import org.netbeans.napi.gsfret.source.support.CaretAwareSourceTaskFactory; //import org.netbeans.api.timers.TimesCollector;
0104:        import org.netbeans.editor.Registry;
0105:        import org.netbeans.modules.gsf.Language;
0106:        import org.netbeans.modules.gsf.LanguageRegistry;
0107:        import org.netbeans.modules.gsfret.source.SourceAccessor;
0108:        import org.netbeans.modules.gsfret.source.parsing.SourceFileObject;
0109:        import org.netbeans.modules.gsfret.source.usages.ClassIndexImpl;
0110:        import org.netbeans.modules.gsfret.source.usages.ClassIndexManager;
0111:        import org.netbeans.modules.gsfret.source.util.LowMemoryEvent;
0112:        import org.netbeans.modules.gsfret.source.util.LowMemoryListener;
0113:        import org.netbeans.modules.gsfret.source.util.LowMemoryNotifier;
0114:        import org.netbeans.modules.gsf.spi.DefaultParserFile;
0115:        import org.openide.cookies.EditorCookie;
0116:        import org.openide.filesystems.FileChangeAdapter;
0117:        import org.openide.filesystems.FileChangeListener;
0118:        import org.openide.filesystems.FileEvent;
0119:        import org.openide.filesystems.FileObject;
0120:        import org.openide.filesystems.FileRenameEvent;
0121:        import org.openide.filesystems.FileUtil;
0122:        import org.openide.filesystems.FileUtil;
0123:        import org.openide.loaders.DataObject;
0124:        import org.openide.loaders.DataObjectNotFoundException;
0125:        import org.openide.util.Exceptions;
0126:        import org.openide.util.NbBundle;
0127:        import org.openide.util.RequestProcessor;
0128:        import org.openide.util.WeakListeners;
0129:
0130:        /**
0131:         * This file is originally from Retouche, the Java Support 
0132:         * infrastructure in NetBeans. I have modified the file as little
0133:         * as possible to make merging Retouche fixes back as simple as
0134:         * possible. 
0135:         *
0136:         *
0137:         * This file is based on the JavaSource class in Retouche's org.netbeans.modules.gsfpath.api.source package.
0138:         * It represents an open source file in the editor.
0139:         *
0140:         * @author Petr Hrebejk
0141:         * @author Tomas Zezula
0142:         * @author Tor Norbye
0143:         */
0144:        public final class Source {
0145:
0146:            public static enum Priority {
0147:                MAX, HIGH, ABOVE_NORMAL, NORMAL, BELOW_NORMAL, LOW, MIN
0148:            }
0149:
0150:            /**
0151:             * This specialization of {@link IOException} signals that a {@link Source#runUserActionTask}
0152:             * or {@link Source#runModificationTask} failed due to lack of memory. The {@link InsufficientMemoryException#getFile}
0153:             * method returns a file which cannot be processed.
0154:             */
0155:            public static final class InsufficientMemoryException extends
0156:                    IOException {
0157:
0158:                private FileObject fo;
0159:
0160:                private InsufficientMemoryException(final String message,
0161:                        final FileObject fo) {
0162:                    super (message);
0163:                    this .fo = fo;
0164:                }
0165:
0166:                private InsufficientMemoryException(FileObject fo) {
0167:                    this (NbBundle.getMessage(Source.class,
0168:                            "MSG_UnsufficientMemoryException", FileUtil
0169:                                    .getFileDisplayName(fo)), fo);
0170:                }
0171:
0172:                /**
0173:                 * Returns file which cannot be processed due to lack of memory.
0174:                 * @return {@link FileObject}
0175:                 */
0176:                public FileObject getFile() {
0177:                    return this .fo;
0178:                }
0179:            }
0180:
0181:            /**
0182:             * Constants for Source.flags
0183:             */
0184:            private static final int INVALID = 1;
0185:            private static final int CHANGE_EXPECTED = INVALID << 1;
0186:            private static final int RESCHEDULE_FINISHED_TASKS = CHANGE_EXPECTED << 1;
0187:            private static final int UPDATE_INDEX = RESCHEDULE_FINISHED_TASKS << 1;
0188:
0189:            /**Slow task reporting*/
0190:            private static final boolean reportSlowTasks = Boolean
0191:                    .getBoolean("org.netbeans.napi.gsfret.source.Source.reportSlowTasks"); //NOI18N
0192:            /**Limit for task to be marked as a slow one, in ms*/
0193:            private static final int SLOW_TASK_LIMIT = 250;
0194:            private static final int SLOW_CANCEL_LIMIT = 50;
0195:
0196:            /**Not final for tests.*/
0197:            static int REPARSE_DELAY = 500;
0198:
0199:            /**
0200:             * Helper maps mapping the {@link Phase} to key and message for
0201:             * the {@link TimesCollector}
0202:             */
0203:            private static Map<Phase, String> phase2Key = new HashMap<Phase, String>();
0204:            private static Map<Phase, String> phase2Message = new HashMap<Phase, String>();
0205:
0206:            /**
0207:             * Init the maps
0208:             */
0209:            static {
0210:                SourceAccessor.setINSTANCE(new JavaSourceAccessorImpl());
0211:                phase2Key.put(Phase.PARSED, "parsed"); //NOI18N
0212:                phase2Message.put(Phase.PARSED, "Parsed"); //NOI18N
0213:
0214:                phase2Key.put(Phase.ELEMENTS_RESOLVED, "sig-attributed"); //NOI18N
0215:                phase2Message.put(Phase.ELEMENTS_RESOLVED,
0216:                        "Signatures Attributed"); //NOI18N
0217:
0218:                phase2Key.put(Phase.RESOLVED, "attributed"); //NOI18N
0219:                phase2Message.put(Phase.RESOLVED, "Attributed"); //NOI18N
0220:
0221:            }
0222:
0223:            private final static PriorityBlockingQueue<Request> requests = new PriorityBlockingQueue<Request>(
0224:                    10, new RequestComparator());
0225:            private final static Map<Source, Collection<Request>> finishedRequests = new WeakHashMap<Source, Collection<Request>>();
0226:            private final static Map<Source, Collection<Request>> waitingRequests = new WeakHashMap<Source, Collection<Request>>();
0227:            private final static Collection<CancellableTask> toRemove = new LinkedList<CancellableTask>();
0228:            private final static SingleThreadFactory factory = new SingleThreadFactory();
0229:            private final static CurrentRequestReference currentRequest = new CurrentRequestReference();
0230:            private final static EditorRegistryListener editorRegistryListener = new EditorRegistryListener();
0231:            //Only single thread can operate on the single javac
0232:            private final static ReentrantLock javacLock = new ReentrantLock(
0233:                    true);
0234:            private final Collection<FileObject> files;
0235:
0236:            private final FileObject rootFo;
0237:            private final FileChangeListener fileChangeListener;
0238:            private DocListener listener;
0239:            private DataObjectListener dataObjectListener;
0240:            private String sourceLevel;
0241:
0242:            private final ClasspathInfo classpathInfo;
0243:            private CompilationInfo currentInfo;
0244:            private java.util.Stack<CompilationInfo> infoStack = new java.util.Stack<CompilationInfo>();
0245:
0246:            private int flags = 0;
0247:
0248:            //Preprocessor support
0249:            private Object/*FilterListener*/filterListener;
0250:
0251:            static {
0252:                Executors.newSingleThreadExecutor(factory).submit(
0253:                        new CompilationJob());
0254:            }
0255:
0256:            /**
0257:             * Returns a {@link Source} instance representing given {@link org.openide.filesystems.FileObject}s
0258:             * and classpath represented by given {@link ClasspathInfo}.
0259:             *
0260:             *
0261:             * @param cpInfo the classpaths to be used.
0262:             * @param files for which the {@link Source} should be created
0263:             * @return a new {@link Source}
0264:             * @throws {@link IllegalArgumentException} if fileObject or cpInfo is null
0265:             */
0266:            public static Source create(final ClasspathInfo cpInfo,
0267:                    final Collection<? extends FileObject> files)
0268:                    throws IllegalArgumentException {
0269:                if (files == null || cpInfo == null) {
0270:                    throw new IllegalArgumentException();
0271:                }
0272:                try {
0273:                    return new Source(cpInfo, files);
0274:                } catch (DataObjectNotFoundException donf) {
0275:                    Logger.getLogger("global").warning(
0276:                            "Ignoring non existent file: "
0277:                                    + FileUtil.getFileDisplayName(donf
0278:                                            .getFileObject())); //NOI18N
0279:                } catch (IOException ex) {
0280:                    Exceptions.printStackTrace(ex);
0281:                }
0282:                return null;
0283:            }
0284:
0285:            /**
0286:             * Returns a {@link Source} instance representing given {@link org.openide.filesystems.FileObject}s
0287:             * and classpath represented by given {@link ClasspathInfo}.
0288:             *
0289:             *
0290:             * @param cpInfo the classpaths to be used.
0291:             * @param files for which the {@link Source} should be created
0292:             * @return a new {@link Source}
0293:             * @throws {@link IllegalArgumentException} if fileObject or cpInfo is null
0294:             */
0295:            public static Source create(final ClasspathInfo cpInfo,
0296:                    final FileObject... files) throws IllegalArgumentException {
0297:                if (files == null || cpInfo == null) {
0298:                    throw new IllegalArgumentException();
0299:                }
0300:                return create(cpInfo, Arrays.asList(files));
0301:            }
0302:
0303:            private static Map<FileObject, Reference<Source>> file2JavaSource = new WeakHashMap<FileObject, Reference<Source>>();
0304:
0305:            public static void clearSourceCache() {
0306:                file2JavaSource.clear();
0307:            }
0308:
0309:            /**
0310:             * Returns a {@link Source} instance associated to given {@link org.openide.filesystems.FileObject},
0311:             * it returns null if the {@link Document} is not associanted with data type providing the {@link Source}.
0312:             *
0313:             *
0314:             * @param fileObject for which the {@link Source} should be found/created.
0315:             * @return {@link Source} or null
0316:             * @throws {@link IllegalArgumentException} if fileObject is null
0317:             */
0318:            public static Source forFileObject(FileObject fileObject)
0319:                    throws IllegalArgumentException {
0320:                if (fileObject == null) {
0321:                    throw new IllegalArgumentException("fileObject == null"); //NOI18N
0322:                }
0323:                if (!fileObject.isValid() || fileObject.isFolder()) {
0324:                    return null;
0325:                }
0326:                if (!LanguageRegistry.getInstance().isSupported(
0327:                        fileObject.getMIMEType())) {
0328:                    return null;
0329:                }
0330:
0331:                Reference<Source> ref = file2JavaSource.get(fileObject);
0332:                Source js = ref != null ? ref.get() : null;
0333:
0334:                if (js == null) {
0335:                    file2JavaSource.put(fileObject, new WeakReference(
0336:                            js = create(ClasspathInfo.create(fileObject),
0337:                                    fileObject)));
0338:                }
0339:
0340:                return js;
0341:            }
0342:
0343:            /**
0344:             * Returns a {@link Source} instance associated to {@link org.openide.filesystems.FileObject}
0345:             * the {@link Document} was created from, it returns null if the {@link Document} is not
0346:             * associanted with data type providing the {@link Source}.
0347:             *
0348:             *
0349:             * @param doc {@link Document} for which the {@link Source} should be found/created.
0350:             * @return {@link Source} or null
0351:             * @throws {@link IllegalArgumentException} if doc is null
0352:             */
0353:            public static Source forDocument(Document doc)
0354:                    throws IllegalArgumentException {
0355:                if (doc == null) {
0356:                    throw new IllegalArgumentException("doc == null"); //NOI18N
0357:                }
0358:                Reference<Source> ref = (Reference<Source>) doc
0359:                        .getProperty(Source.class);
0360:                Source js = ref != null ? ref.get() : null;
0361:                if (js == null) {
0362:                    DataObject dObj = (DataObject) doc
0363:                            .getProperty(Document.StreamDescriptionProperty);
0364:                    if (dObj != null)
0365:                        js = forFileObject(dObj.getPrimaryFile());
0366:                }
0367:                return js;
0368:            }
0369:
0370:            /**
0371:             * Creates a new instance of Source
0372:             *
0373:             *
0374:             * @param files to create Source for
0375:             * @param cpInfo classpath info
0376:             */
0377:            private Source(ClasspathInfo cpInfo,
0378:                    Collection<? extends FileObject> files) throws IOException {
0379:                this .files = Collections.unmodifiableList(new ArrayList(files)); //Create a defensive copy, prevent modification
0380:                this .fileChangeListener = new FileChangeListenerImpl();
0381:                boolean multipleSources = this .files.size() > 1, filterAssigned = false;
0382:                for (Iterator<? extends FileObject> it = this .files.iterator(); it
0383:                        .hasNext();) {
0384:                    FileObject file = it.next();
0385:                    try {
0386:                        //TimesCollector.getDefault().reportReference( file, Source.class.toString(), "[M] Source", this );       //NOI18N
0387:                        if (!multipleSources) {
0388:                            file.addFileChangeListener(FileUtil
0389:                                    .weakFileChangeListener(
0390:                                            this .fileChangeListener, file));
0391:                            this .assignDocumentListener(file);
0392:                            this .dataObjectListener = new DataObjectListener(
0393:                                    file);
0394:                        }
0395:                        //if (!filterAssigned) {
0396:                        //    filterAssigned = true;
0397:                        //    JavaFileFilterImplementation filter = JavaFileFilterQuery.getFilter(file);
0398:                        //    if (filter != null) {
0399:                        //        this.filterListener = new FilterListener (filter);
0400:                        //    }
0401:                        //}
0402:                    } catch (DataObjectNotFoundException donf) {
0403:                        if (multipleSources) {
0404:                            Logger
0405:                                    .getLogger("global")
0406:                                    .warning(
0407:                                            "Ignoring non existent file: "
0408:                                                    + FileUtil
0409:                                                            .getFileDisplayName(file)); //NOI18N
0410:                            it.remove();
0411:                        } else {
0412:                            throw donf;
0413:                        }
0414:                    }
0415:                }
0416:                this .classpathInfo = cpInfo;
0417:                if (files.size() == 1) {
0418:                    this .rootFo = classpathInfo.getClassPath(PathKind.SOURCE)
0419:                            .findOwnerRoot(files.iterator().next());
0420:                } else {
0421:                    this .rootFo = null;
0422:                }
0423:                this .classpathInfo.addChangeListener(WeakListeners.change(
0424:                        this .listener, this .classpathInfo));
0425:
0426:            }
0427:
0428:            /** Runs a task which permits for controlling phases of the parsing process.
0429:             * You probably do not want to call this method unless you are reacting to
0430:             * some user's GUI input which requires immediate action (e.g. code completion popup).
0431:             * In all other cases use {@link JavaSourceTaskFactory}.<BR>
0432:             * Call to this method will cancel processing of all the phase completion tasks until
0433:             * this task does not finish.<BR>
0434:             * @see org.netbeans.napi.gsfret.source.CancellableTask for information about implementation requirements
0435:             * @param task The task which.
0436:             * @param shared if true the java compiler may be reused by other {@link org.netbeans.napi.gsfret.source.CancellableTasks},
0437:             * the value false may have negative impact on the IDE performance.
0438:             */
0439:            public void runUserActionTask(
0440:                    final CancellableTask<CompilationController> task,
0441:                    final boolean shared) throws IOException {
0442:                if (task == null) {
0443:                    throw new IllegalArgumentException("Task cannot be null"); //NOI18N
0444:                }
0445:
0446:                assert javacLock.isHeldByCurrentThread()
0447:                        || !holdsDocumentWriteLock(files) : "Source.runCompileControlTask called under Document write lock."; //NOI18N
0448:
0449:                if (this .files.size() <= 1) {
0450:                    final Source.Request request = currentRequest
0451:                            .getTaskToCancel();
0452:                    try {
0453:                        if (request != null) {
0454:                            request.task.cancel();
0455:                        }
0456:                        this .javacLock.lock();
0457:                        try {
0458:                            CompilationInfo currentInfo = null;
0459:                            synchronized (this ) {
0460:                                if (this .currentInfo != null
0461:                                        && (this .flags & INVALID) == 0) {
0462:                                    currentInfo = this .currentInfo;
0463:                                }
0464:                                if (!shared) {
0465:                                    this .flags |= INVALID;
0466:                                }
0467:                            }
0468:                            if (currentInfo == null) {
0469:                                currentInfo = createCurrentInfo(this ,
0470:                                        this .files.isEmpty() ? null
0471:                                                : this .files.iterator().next(),
0472:                                        filterListener, null);
0473:                                if (shared) {
0474:                                    synchronized (this ) {
0475:                                        if (this .currentInfo == null
0476:                                                || (this .flags & INVALID) != 0) {
0477:                                            this .currentInfo = currentInfo;
0478:                                            this .flags &= ~INVALID;
0479:                                        } else {
0480:                                            currentInfo = this .currentInfo;
0481:                                        }
0482:                                    }
0483:                                }
0484:                            }
0485:                            assert currentInfo != null;
0486:                            if (shared) {
0487:                                if (!infoStack.isEmpty()) {
0488:                                    currentInfo = infoStack.peek();
0489:                                }
0490:                            } else {
0491:                                infoStack.push(currentInfo);
0492:                            }
0493:                            try {
0494:                                task
0495:                                        .run(new CompilationController(
0496:                                                currentInfo));
0497:                            } finally {
0498:                                if (!shared) {
0499:                                    infoStack.pop();
0500:                                }
0501:                            }
0502:                        } catch (RuntimeException e) {
0503:                            throw e;
0504:                        } catch (Exception e) {
0505:                            IOException ioe = new IOException();
0506:                            ioe.initCause(e);
0507:                            throw ioe;
0508:                        } finally {
0509:                            this .javacLock.unlock();
0510:                        }
0511:                    } finally {
0512:                        currentRequest.cancelCompleted(request);
0513:                    }
0514:                } else {
0515:                    final Source.Request request = currentRequest
0516:                            .getTaskToCancel();
0517:                    try {
0518:                        if (request != null) {
0519:                            request.task.cancel();
0520:                        }
0521:                        this .javacLock.lock();
0522:                        try {
0523:                            ParserTaskImpl jt = null;
0524:                            FileObject activeFile = null;
0525:                            Iterator<FileObject> files = this .files.iterator();
0526:                            while (files.hasNext() || activeFile != null) {
0527:                                boolean restarted;
0528:                                if (activeFile == null) {
0529:                                    activeFile = files.next();
0530:                                    restarted = false;
0531:                                } else {
0532:                                    restarted = true;
0533:                                }
0534:                                CompilationInfo ci = createCurrentInfo(this ,
0535:                                        activeFile, filterListener, jt);
0536:                                task.run(new CompilationController(ci));
0537:                                if (!ci.needsRestart) {
0538:                                    jt = ci.getParserTask();
0539:                                    //                            Log.instance(jt.getContext()).nerrors = 0;
0540:                                    activeFile = null;
0541:                                } else {
0542:                                    jt = null;
0543:                                    ci = null;
0544:                                    System.gc();
0545:                                    if (restarted) {
0546:                                        throw new InsufficientMemoryException(
0547:                                                activeFile);
0548:                                    }
0549:                                }
0550:                            }
0551:                        } catch (RuntimeException e) {
0552:                            throw e;
0553:                        } catch (Exception e) {
0554:                            IOException ioe = new IOException();
0555:                            ioe.initCause(e);
0556:                            throw ioe;
0557:                        } finally {
0558:                            this .javacLock.unlock();
0559:                        }
0560:                    } finally {
0561:                        currentRequest.cancelCompleted(request);
0562:                    }
0563:                }
0564:            }
0565:
0566:            /** Runs a task which permits for modifying the sources.
0567:             * Call to this method will cancel processig of all the phase completion tasks until
0568:             * this task does not finish.<BR>
0569:             * @see CancellableTask for information about implementation requirements
0570:             * @param task The task which.
0571:             */
0572:            public ModificationResult runModificationTask(
0573:                    CancellableTask<WorkingCopy> task) throws IOException {
0574:                if (task == null) {
0575:                    throw new IllegalArgumentException("Task cannot be null"); //NOI18N
0576:                }
0577:
0578:                assert javacLock.isHeldByCurrentThread()
0579:                        || !holdsDocumentWriteLock(files) : "Source.runCompileControlTask called under Document write lock."; //NOI18N
0580:
0581:                ModificationResult result = new ModificationResult(this );
0582:                if (this .files.size() <= 1) {
0583:                    //long start = System.currentTimeMillis();            
0584:                    final Source.Request request = currentRequest
0585:                            .getTaskToCancel();
0586:                    try {
0587:                        if (request != null) {
0588:                            request.task.cancel();
0589:                        }
0590:                        this .javacLock.lock();
0591:                        try {
0592:                            CompilationInfo currentInfo = null;
0593:                            synchronized (this ) {
0594:                                if (this .currentInfo != null
0595:                                        && (this .flags & INVALID) == 0) {
0596:                                    currentInfo = this .currentInfo;
0597:                                }
0598:                            }
0599:                            if (currentInfo == null) {
0600:                                currentInfo = createCurrentInfo(this ,
0601:                                        this .files.isEmpty() ? null
0602:                                                : this .files.iterator().next(),
0603:                                        filterListener, null);
0604:                                synchronized (this ) {
0605:                                    if (this .currentInfo == null
0606:                                            || (this .flags & INVALID) != 0) {
0607:                                        this .currentInfo = currentInfo;
0608:                                        this .flags &= ~INVALID;
0609:                                    } else {
0610:                                        currentInfo = this .currentInfo;
0611:                                    }
0612:                                }
0613:                            }
0614:                            assert currentInfo != null;
0615:                            WorkingCopy copy = new WorkingCopy(currentInfo);
0616:                            task.run(copy);
0617:                            List<Difference> diffs = copy.getChanges();
0618:                            if (diffs != null && diffs.size() > 0)
0619:                                result.diffs.put(currentInfo.getFileObject(),
0620:                                        diffs);
0621:                        } catch (RuntimeException e) {
0622:                            throw e;
0623:                        } catch (Exception e) {
0624:                            IOException ioe = new IOException();
0625:                            ioe.initCause(e);
0626:                            throw ioe;
0627:                        } finally {
0628:                            this .javacLock.unlock();
0629:                        }
0630:                    } finally {
0631:                        currentRequest.cancelCompleted(request);
0632:                    }
0633:                    //TimesCollector.getDefault().reportTime(currentInfo.getFileObject(),  "gsf-source-modification-task",   //NOI18N
0634:                    //  "Modification Task", System.currentTimeMillis() - start);   //NOI18N
0635:                } else {
0636:                    final Source.Request request = currentRequest
0637:                            .getTaskToCancel();
0638:                    try {
0639:                        if (request != null) {
0640:                            request.task.cancel();
0641:                        }
0642:                        this .javacLock.lock();
0643:                        try {
0644:                            ParserTaskImpl jt = null;
0645:                            FileObject activeFile = null;
0646:                            Iterator<FileObject> files = this .files.iterator();
0647:                            while (files.hasNext() || activeFile != null) {
0648:                                boolean restarted;
0649:                                if (activeFile == null) {
0650:                                    activeFile = files.next();
0651:                                    restarted = false;
0652:                                } else {
0653:                                    restarted = true;
0654:                                }
0655:                                CompilationInfo ci = createCurrentInfo(this ,
0656:                                        activeFile, filterListener, jt);
0657:                                WorkingCopy copy = new WorkingCopy(ci);
0658:                                task.run(copy);
0659:                                if (!ci.needsRestart) {
0660:                                    jt = ci.getParserTask();
0661:                                    //jt = ci.getParserTask();
0662:                                    //                            Log.instance(jt.getContext()).nerrors = 0;
0663:                                    List<Difference> diffs = copy.getChanges();
0664:                                    if (diffs != null && diffs.size() > 0)
0665:                                        result.diffs.put(ci.getFileObject(),
0666:                                                diffs);
0667:                                    activeFile = null;
0668:                                } else {
0669:                                    jt = null;
0670:                                    ci = null;
0671:                                    System.gc();
0672:                                    if (restarted) {
0673:                                        throw new InsufficientMemoryException(
0674:                                                activeFile);
0675:                                    }
0676:                                }
0677:                            }
0678:                        } catch (RuntimeException e) {
0679:                            throw e;
0680:                        } catch (Exception e) {
0681:                            IOException ioe = new IOException();
0682:                            ioe.initCause(e);
0683:                            throw ioe;
0684:                        } finally {
0685:                            this .javacLock.unlock();
0686:                        }
0687:                    } finally {
0688:                        currentRequest.cancelCompleted(request);
0689:                    }
0690:                }
0691:                synchronized (this ) {
0692:                    this .flags |= INVALID;
0693:                }
0694:                return result;
0695:            }
0696:
0697:            /** Adds a task to given compilation phase. The tasks will run sequentially by
0698:             * priorty after given phase is reached.
0699:             * @see CancellableTask for information about implementation requirements
0700:             * @task The task to run.
0701:             * @phase In which phase should the task run
0702:             * @priority Priority of the task.
0703:             */
0704:            void addPhaseCompletionTask(CancellableTask<CompilationInfo> task,
0705:                    Phase phase, Priority priority) throws IOException {
0706:                if (task == null) {
0707:                    throw new IllegalArgumentException("Task cannot be null"); //NOI18N
0708:                }
0709:                if (phase == null || phase == Phase.MODIFIED) {
0710:                    throw new IllegalArgumentException(String.format(
0711:                            "The %s is not a legal value of phase", phase)); //NOI18N
0712:                }
0713:                if (priority == null) {
0714:                    throw new IllegalArgumentException(
0715:                            "The priority cannot be null"); //NOI18N
0716:                }
0717:                CompilationInfo currentInfo;
0718:                synchronized (this ) {
0719:                    currentInfo = this .currentInfo;
0720:                }
0721:                if (currentInfo == null) {
0722:                    currentInfo = createCurrentInfo(this ,
0723:                            this .files.isEmpty() ? null : this .files.iterator()
0724:                                    .next(), filterListener, null);
0725:                }
0726:                synchronized (this ) {
0727:                    if (this .currentInfo == null) {
0728:                        this .currentInfo = currentInfo;
0729:                    }
0730:                }
0731:                handleAddRequest(new Request(task, this , phase, priority, true));
0732:            }
0733:
0734:            /** Removes the task from the phase queue.
0735:             * @task The task to remove.
0736:             */
0737:            void removePhaseCompletionTask(CancellableTask<CompilationInfo> task) {
0738:                synchronized (Source.class) {
0739:                    toRemove.add(task);
0740:                }
0741:            }
0742:
0743:            /**Rerun the task in case it was already run. Does nothing if the task was not already run.
0744:             *
0745:             * @task to reschedule
0746:             */
0747:            void rescheduleTask(CancellableTask<CompilationInfo> task) {
0748:                synchronized (Source.class) {
0749:                    Source.Request request = this .currentRequest
0750:                            .getTaskToCancel(task);
0751:                    if (request == null) {
0752:                        out: for (Iterator<Collection<Request>> it = finishedRequests
0753:                                .values().iterator(); it.hasNext();) {
0754:                            Collection<Request> cr = it.next();
0755:                            for (Iterator<Request> it2 = cr.iterator(); it2
0756:                                    .hasNext();) {
0757:                                Request fr = it2.next();
0758:                                if (task == fr.task) {
0759:                                    it2.remove();
0760:                                    Source.requests.add(fr);
0761:                                    if (cr.size() == 0) {
0762:                                        it.remove();
0763:                                    }
0764:                                    break out;
0765:                                }
0766:                            }
0767:                        }
0768:                    } else {
0769:                        currentRequest.cancelCompleted(request);
0770:                    }
0771:                }
0772:            }
0773:
0774:            /**
0775:             * Marks this {@link Source} as modified, causes that the cached information are
0776:             * cleared and all the PhaseCompletionTasks are restarted.
0777:             * The only client of this method should be the JavaDataObject or other DataObjects
0778:             * providing the {@link Source}. If you call this method in another case you are
0779:             * probably doing something incorrect.
0780:             */
0781:            void revalidate() {
0782:                this .resetState(true, false);
0783:            }
0784:
0785:            /**
0786:             * Returns the classpaths ({@link ClasspathInfo}) used by this
0787:             * {@link Source}
0788:             *
0789:             *
0790:             * @return {@link ClasspathInfo}, never returns null.
0791:             */
0792:            public ClasspathInfo getClasspathInfo() {
0793:                return classpathInfo;
0794:            }
0795:
0796:            /**
0797:             * Returns unmodifiable {@link Collection} of {@link FileObject}s used by this {@link Source}
0798:             * @return the {@link FileObject}s
0799:             */
0800:            public Collection<FileObject> getFileObjects() {
0801:                return files;
0802:            }
0803:
0804:            ParserTaskImpl createParserTask(
0805:                    /*final DiagnosticListener<? super SourceFileObject> diagnosticListener,*/CompilationInfo compilationInfo) {
0806:                //assert diagnosticListener == null;
0807:                Language language = compilationInfo.getLanguage();
0808:                assert language != null;
0809:                ParserTaskImpl javacTask = createParserTask(language,
0810:                        compilationInfo, getClasspathInfo(), /*diagnosticListener,*/
0811:                        sourceLevel, false);
0812:                //        Context context = javacTask.getContext();
0813:                //        Messager.preRegister(context, null);
0814:                //        ErrorHandlingJavadocEnter.preRegister(context);
0815:                //        JavadocMemberEnter.preRegister(context);
0816:                //        SourceUtils.JavaDocEnv.preRegister(context, getClasspathInfo());
0817:                //        Scanner.Factory.instance(context);
0818:                //        Builder2.instance(context).keepComments = true;
0819:                return javacTask;
0820:            }
0821:
0822:            private static ParserTaskImpl createParserTask(Language language,
0823:                    final CompilationInfo currentInfo,
0824:                    final ClasspathInfo cpInfo, /*final DiagnosticListener<? super SourceFileObject> diagnosticListener,*/
0825:                    final String sourceLevel,
0826:                    final boolean backgroundCompilation) {
0827:                ParserTaskImpl jti = new ParserTaskImpl(language);
0828:
0829:                return jti;
0830:            }
0831:
0832:            /**
0833:             * Not synchronized, only the CompilationJob's thread can call it!!!!
0834:             *
0835:             */
0836:            static Phase moveToPhase(final Phase phase,
0837:                    final CompilationInfo currentInfo, final boolean cancellable)
0838:                    throws IOException {
0839:                Phase currentPhase = currentInfo.getPhase();
0840:                final boolean isMultiFiles = currentInfo.getSource().files
0841:                        .size() > 1;
0842:                LowMemoryNotifier lm = null;
0843:                LMListener lmListener = null;
0844:                if (isMultiFiles) {
0845:                    lm = LowMemoryNotifier.getDefault();
0846:                    assert lm != null;
0847:                    lmListener = new LMListener();
0848:                    lm.addLowMemoryListener(lmListener);
0849:                }
0850:                try {
0851:                    if (lmListener != null
0852:                            && lmListener.lowMemory.getAndSet(false)) {
0853:                        currentInfo.needsRestart = true;
0854:                        return currentPhase;
0855:                    }
0856:                    if (currentPhase.compareTo(Phase.PARSED) < 0
0857:                            && phase.compareTo(Phase.PARSED) >= 0) {
0858:                        if (cancellable && currentRequest.isCanceled()) {
0859:                            //Keep the currentPhase unchanged, it may happen that an userActionTask
0860:                            //runnig after the phace completion task may still use it.
0861:                            return Phase.MODIFIED;
0862:                        }
0863:                        long start = System.currentTimeMillis();
0864:
0865:                        List<ParserFile> sourceFiles = new ArrayList<ParserFile>(
0866:                                1);
0867:                        sourceFiles.add(new DefaultParserFile(currentInfo
0868:                                .getFileObject(), null, false));
0869:                        final FileObject bufferFo = currentInfo.getFileObject();
0870:
0871:                        final ParserResult[] resultHolder = new ParserResult[1];
0872:                        ParseListener listener = new ParseListener() {
0873:                            final List<Error> errors = new ArrayList<Error>();
0874:
0875:                            public void started(ParseEvent e) {
0876:                                errors.clear();
0877:                            }
0878:
0879:                            public void error(Error error) {
0880:                                errors.add(error);
0881:                            }
0882:
0883:                            public void exception(Exception exception) {
0884:                                Exceptions.printStackTrace(exception);
0885:                            }
0886:
0887:                            public void finished(ParseEvent e) {
0888:                                // TODO - check state
0889:                                if (e.getKind() == ParseEvent.Kind.PARSE) {
0890:                                    ParserResult result = e.getResult();
0891:                                    for (Error error : errors) {
0892:                                        result.addError(error);
0893:                                    }
0894:                                    resultHolder[0] = result;
0895:                                }
0896:                            }
0897:                        };
0898:
0899:                        LanguageRegistry registry = LanguageRegistry
0900:                                .getInstance();
0901:                        String mimeType = currentInfo.getFileObject()
0902:                                .getMIMEType();
0903:                        List<Language> languages = registry
0904:                                .getApplicableLanguages(mimeType);
0905:
0906:                        for (Language language : languages) {
0907:                            EmbeddingModel model = registry.getEmbedding(
0908:                                    language.getMimeType(), mimeType);
0909:                            assert language != null;
0910:                            Parser parser = language.getParser(); // Todo - call createParserTask here?
0911:
0912:                            if (parser != null) {
0913:                                if (model != null) {
0914:                                    Document document;
0915:                                    try {
0916:                                        document = currentInfo.getDocument();
0917:
0918:                                        if (document == null) {
0919:                                            // Ensure document is forced open such that info.getDocument() will not yield null
0920:                                            UiUtils.getDocument(currentInfo
0921:                                                    .getFileObject(), true);
0922:                                            document = currentInfo
0923:                                                    .getDocument();
0924:                                        }
0925:                                    } catch (IOException ex) {
0926:                                        Exceptions.printStackTrace(ex);
0927:                                        return null;
0928:                                    }
0929:
0930:                                    if (document == null) {
0931:                                        // TODO - log problem
0932:                                        continue;
0933:                                    }
0934:
0935:                                    Collection<? extends TranslatedSource> translations = model
0936:                                            .translate(document);
0937:                                    for (TranslatedSource translatedSource : translations) {
0938:                                        String buffer = translatedSource
0939:                                                .getSource();
0940:                                        SourceFileReader reader = new StringSourceFileReader(
0941:                                                buffer, bufferFo);
0942:                                        Parser.Job job = new Parser.Job(
0943:                                                sourceFiles, listener, reader,
0944:                                                translatedSource);
0945:                                        parser.parseFiles(job);
0946:                                        ParserResult result = resultHolder[0];
0947:                                        result
0948:                                                .setTranslatedSource(translatedSource);
0949:                                        assert result != null;
0950:                                        currentInfo.addEmbeddingResult(language
0951:                                                .getMimeType(), result);
0952:                                    }
0953:                                } else {
0954:                                    String buffer = currentInfo.getText();
0955:                                    SourceFileReader reader = new StringSourceFileReader(
0956:                                            buffer, bufferFo);
0957:                                    Parser.Job job = new Parser.Job(
0958:                                            sourceFiles, listener, reader, null);
0959:                                    parser.parseFiles(job);
0960:                                    ParserResult result = resultHolder[0];
0961:                                    assert result != null;
0962:                                    currentInfo.addEmbeddingResult(language
0963:                                            .getMimeType(), result);
0964:                                }
0965:                            }
0966:                        }
0967:                        currentPhase = Phase.PARSED;
0968:                        long end = System.currentTimeMillis();
0969:                        FileObject file = currentInfo.getFileObject();
0970:                        //TimesCollector.getDefault().reportReference(file, "compilationUnit", "[M] Compilation Unit", unit);     //NOI18N
0971:                        logTime(file, currentPhase, (end - start));
0972:                    }
0973:                    if (lmListener != null
0974:                            && lmListener.lowMemory.getAndSet(false)) {
0975:                        currentInfo.needsRestart = true;
0976:                        return currentPhase;
0977:                    }
0978:                    if (currentPhase == Phase.PARSED
0979:                            && phase.compareTo(Phase.ELEMENTS_RESOLVED) >= 0) {
0980:                        if (cancellable && currentRequest.isCanceled()) {
0981:                            return Phase.MODIFIED;
0982:                        }
0983:                        long start = System.currentTimeMillis();
0984:                        // Noop right now - revisit when I add a parser which needs it (groovy?)
0985:                        //currentInfo.getParserTask().enter();
0986:                        currentPhase = Phase.ELEMENTS_RESOLVED;
0987:                        long end = System.currentTimeMillis();
0988:                        logTime(currentInfo.getFileObject(), currentPhase,
0989:                                (end - start));
0990:                    }
0991:                    if (lmListener != null
0992:                            && lmListener.lowMemory.getAndSet(false)) {
0993:                        currentInfo.needsRestart = true;
0994:                        return currentPhase;
0995:                    }
0996:                    if (currentPhase == Phase.ELEMENTS_RESOLVED
0997:                            && phase.compareTo(Phase.RESOLVED) >= 0) {
0998:                        if (cancellable && currentRequest.isCanceled()) {
0999:                            return Phase.MODIFIED;
1000:                        }
1001:                        long start = System.currentTimeMillis();
1002:                        // Noop right now - revisit when I add a parser which needs it (groovy?)
1003:                        //currentInfo.getParserTask().analyze();
1004:                        currentPhase = Phase.RESOLVED;
1005:                        long end = System.currentTimeMillis();
1006:                        logTime(currentInfo.getFileObject(), currentPhase,
1007:                                (end - start));
1008:                    }
1009:                    if (lmListener != null
1010:                            && lmListener.lowMemory.getAndSet(false)) {
1011:                        currentInfo.needsRestart = true;
1012:                        return currentPhase;
1013:                    }
1014:                    if (currentPhase == Phase.RESOLVED
1015:                            && phase.compareTo(Phase.UP_TO_DATE) >= 0) {
1016:                        currentPhase = Phase.UP_TO_DATE;
1017:                    }
1018:                    //} catch (Error abort) { // Abort in com.sun.tools is not here
1019:                    //    currentPhase = Phase.UP_TO_DATE;
1020:                    //        } catch (IOException ex) {
1021:                    //            dumpSource(currentInfo, ex);
1022:                    //            throw ex;
1023:                } catch (RuntimeException ex) {
1024:                    dumpSource(currentInfo, ex);
1025:                    throw ex;
1026:                } catch (java.lang.Error ex) {
1027:                    dumpSource(currentInfo, ex);
1028:                    throw ex;
1029:                } finally {
1030:                    if (isMultiFiles) {
1031:                        assert lm != null;
1032:                        assert lmListener != null;
1033:                        lm.removeLowMemoryListener(lmListener);
1034:                    }
1035:                    currentInfo.setPhase(currentPhase);
1036:                }
1037:                return currentPhase;
1038:            }
1039:
1040:            static void logTime(FileObject source, Phase phase, long time) {
1041:                assert source != null && phase != null;
1042:                String key = phase2Key.get(phase);
1043:                String message = phase2Message.get(phase);
1044:                assert key != null && message != null;
1045:                //TimesCollector.getDefault().reportTime (source,key,message,time);
1046:            }
1047:
1048:            private final RequestProcessor.Task resetTask = RequestProcessor
1049:                    .getDefault().create(new Runnable() {
1050:                        public void run() {
1051:                            resetStateImpl();
1052:                        }
1053:                    });
1054:
1055:            private void resetState(boolean invalidate, boolean updateIndex) {
1056:                boolean invalid;
1057:                synchronized (this ) {
1058:                    invalid = (this .flags & INVALID) != 0;
1059:                    this .flags |= CHANGE_EXPECTED;
1060:                    if (invalidate) {
1061:                        this .flags |= (INVALID | RESCHEDULE_FINISHED_TASKS);
1062:                    }
1063:                    if (updateIndex) {
1064:                        this .flags |= UPDATE_INDEX;
1065:                    }
1066:                }
1067:                if (updateIndex && !invalid) {
1068:                    //First change set the index as dirty
1069:                    updateIndex();
1070:                }
1071:                Request r = currentRequest.getTaskToCancel(this );
1072:                try {
1073:                    if (r != null) {
1074:                        r.task.cancel();
1075:                    }
1076:                } finally {
1077:                    currentRequest.cancelCompleted(r);
1078:                }
1079:                resetTask.schedule(REPARSE_DELAY);
1080:            }
1081:
1082:            /**
1083:             * Not synchronized, only sets the atomic state and clears the listeners
1084:             *
1085:             */
1086:            private void resetStateImpl() {
1087:                synchronized (Source.class) {
1088:                    boolean reschedule, updateIndex;
1089:                    synchronized (this ) {
1090:                        reschedule = (this .flags & RESCHEDULE_FINISHED_TASKS) != 0;
1091:                        updateIndex = (this .flags & UPDATE_INDEX) != 0;
1092:                        this .flags &= ~(RESCHEDULE_FINISHED_TASKS
1093:                                | CHANGE_EXPECTED | UPDATE_INDEX);
1094:                    }
1095:                    if (updateIndex) {
1096:                        //Last change set the index as dirty
1097:                        updateIndex();
1098:                    }
1099:                    Collection<Request> cr;
1100:                    if (reschedule) {
1101:                        if ((cr = Source.finishedRequests.remove(this )) != null
1102:                                && cr.size() > 0) {
1103:                            Source.requests.addAll(cr);
1104:                        }
1105:                    }
1106:                    if ((cr = Source.waitingRequests.remove(this )) != null
1107:                            && cr.size() > 0) {
1108:                        Source.requests.addAll(cr);
1109:                    }
1110:                }
1111:            }
1112:
1113:            private void updateIndex() {
1114:                if (this .rootFo != null) {
1115:                    try {
1116:                        for (Language language : LanguageRegistry.getInstance()) {
1117:                            if (language.getIndexer() != null) {
1118:                                ClassIndexImpl ciImpl = ClassIndexManager.get(
1119:                                        language).getUsagesQuery(
1120:                                        this .rootFo.getURL());
1121:                                if (ciImpl != null) {
1122:                                    ciImpl.setDirty(this );
1123:                                }
1124:                            }
1125:                        }
1126:                    } catch (IOException ioe) {
1127:                        Exceptions.printStackTrace(ioe);
1128:                    }
1129:                }
1130:            }
1131:
1132:            /** For test framework only */
1133:            public void testUpdateIndex() {
1134:                updateIndex();
1135:            }
1136:
1137:            private void assignDocumentListener(FileObject fo)
1138:                    throws IOException {
1139:                DataObject od = DataObject.find(fo);
1140:                EditorCookie.Observable ec = (EditorCookie.Observable) od
1141:                        .getCookie(EditorCookie.Observable.class);
1142:                if (ec != null) {
1143:                    this .listener = new DocListener(ec);
1144:                } else {
1145:                    Logger.getLogger("global").log(
1146:                            Level.WARNING,
1147:                            String.format(
1148:                                    "File: %s has no EditorCookie.Observable",
1149:                                    FileUtil.getFileDisplayName(fo))); //NOI18N
1150:                }
1151:            }
1152:
1153:            private static class Request {
1154:                private final CancellableTask<? extends CompilationInfo> task;
1155:                private final Source javaSource; //XXX: Maybe week, depends on the semantics
1156:                private final Phase phase;
1157:                private final Priority priority;
1158:                private final boolean reschedule;
1159:
1160:                public Request(
1161:                        final CancellableTask<? extends CompilationInfo> task,
1162:                        final Source javaSource, final Phase phase,
1163:                        final Priority priority, final boolean reschedule) {
1164:                    assert task != null;
1165:                    this .task = task;
1166:                    this .javaSource = javaSource;
1167:                    this .phase = phase;
1168:                    this .priority = priority;
1169:                    this .reschedule = reschedule;
1170:                }
1171:
1172:                public @Override
1173:                String toString() {
1174:                    if (reschedule) {
1175:                        return String
1176:                                .format(
1177:                                        "Periodic request for phase: %s with priority: %s to perform: %s",
1178:                                        phase.name(), priority, task.toString()); //NOI18N
1179:                    } else {
1180:                        return String
1181:                                .format(
1182:                                        "One time request for phase: %s with priority: %d to perform: %s",
1183:                                        phase != null ? phase.name() : "<null>",
1184:                                        priority, task.toString()); //NOI18N
1185:                    }
1186:                }
1187:
1188:                public @Override
1189:                int hashCode() {
1190:                    return this .priority.ordinal();
1191:                }
1192:
1193:                public @Override
1194:                boolean equals(Object other) {
1195:                    if (other instanceof  Request) {
1196:                        Request otherRequest = (Request) other;
1197:                        return priority == otherRequest.priority
1198:                                && reschedule == otherRequest.reschedule
1199:                                && phase.equals(otherRequest.phase)
1200:                                && task.equals(otherRequest.task);
1201:                    } else {
1202:                        return false;
1203:                    }
1204:                }
1205:            }
1206:
1207:            private static class RequestComparator implements 
1208:                    Comparator<Request> {
1209:                public int compare(Request r1, Request r2) {
1210:                    assert r1 != null && r2 != null;
1211:                    return r1.priority.compareTo(r2.priority);
1212:                }
1213:            }
1214:
1215:            private static class CompilationJob implements  Runnable {
1216:
1217:                @SuppressWarnings("unchecked")
1218:                //NOI18N
1219:                public void run() {
1220:                    try {
1221:                        while (true) {
1222:                            try {
1223:                                synchronized (Source.class) {
1224:                                    //Clean up toRemove tasks
1225:                                    if (!toRemove.isEmpty()) {
1226:                                        for (Iterator<Collection<Request>> it = finishedRequests
1227:                                                .values().iterator(); it
1228:                                                .hasNext();) {
1229:                                            Collection<Request> cr = it.next();
1230:                                            for (Iterator<Request> it2 = cr
1231:                                                    .iterator(); it2.hasNext();) {
1232:                                                Request fr = it2.next();
1233:                                                if (toRemove.remove(fr.task)) {
1234:                                                    it2.remove();
1235:                                                }
1236:                                            }
1237:                                            if (cr.size() == 0) {
1238:                                                it.remove();
1239:                                            }
1240:                                        }
1241:                                    }
1242:                                }
1243:                                Request r = Source.requests.poll(2,
1244:                                        TimeUnit.SECONDS);
1245:                                if (r != null) {
1246:                                    currentRequest.setCurrentTask(r);
1247:                                    try {
1248:                                        Source js = r.javaSource;
1249:                                        if (js == null) {
1250:                                            assert r.phase == null;
1251:                                            assert r.reschedule == false;
1252:                                            javacLock.lock();
1253:                                            try {
1254:                                                r.task.run(null);
1255:                                            } catch (RuntimeException re) {
1256:                                                Exceptions.printStackTrace(re);
1257:                                            } finally {
1258:                                                javacLock.unlock();
1259:                                            }
1260:                                        } else {
1261:                                            assert js.files.size() <= 1;
1262:                                            boolean jsInvalid;
1263:                                            CompilationInfo ci;
1264:                                            synchronized (Source.class) {
1265:                                                //jl:what does this comment mean?
1266:                                                //Not only the finishedRequests for the current request.javaSource should be cleaned,
1267:                                                //it will cause a starvation
1268:                                                if (toRemove.remove(r.task)) {
1269:                                                    continue;
1270:                                                }
1271:                                                synchronized (js) {
1272:                                                    boolean changeExpected = (js.flags & CHANGE_EXPECTED) != 0;
1273:                                                    if (changeExpected) {
1274:                                                        //Skip the task, another invalidation is comming
1275:                                                        Collection<Request> rc = Source.waitingRequests
1276:                                                                .get(r.javaSource);
1277:                                                        if (rc == null) {
1278:                                                            rc = new LinkedList<Request>();
1279:                                                            Source.waitingRequests
1280:                                                                    .put(
1281:                                                                            r.javaSource,
1282:                                                                            rc);
1283:                                                        }
1284:                                                        rc.add(r);
1285:                                                        continue;
1286:                                                    }
1287:                                                    jsInvalid = (js.flags & INVALID) != 0;
1288:                                                    ci = js.currentInfo;
1289:                                                }
1290:                                            }
1291:                                            try {
1292:                                                //createCurrentInfo has to be out of synchronized block, it aquires an editor lock
1293:                                                if (jsInvalid) {
1294:                                                    ci = createCurrentInfo(
1295:                                                            js,
1296:                                                            js.files.isEmpty() ? null
1297:                                                                    : js.files
1298:                                                                            .iterator()
1299:                                                                            .next(),
1300:                                                            js.filterListener,
1301:                                                            null);
1302:                                                    synchronized (js) {
1303:                                                        if ((js.flags & INVALID) != 0) {
1304:                                                            js.currentInfo = ci;
1305:                                                            js.flags &= ~INVALID;
1306:                                                        } else {
1307:                                                            ci = js.currentInfo;
1308:                                                        }
1309:                                                    }
1310:                                                }
1311:                                                assert ci != null;
1312:                                                javacLock.lock();
1313:                                                try {
1314:                                                    final Phase phase = Source
1315:                                                            .moveToPhase(
1316:                                                                    r.phase,
1317:                                                                    ci, true);
1318:                                                    boolean shouldCall = phase
1319:                                                            .compareTo(r.phase) >= 0;
1320:                                                    if (shouldCall) {
1321:                                                        synchronized (js) {
1322:                                                            shouldCall &= (js.flags & INVALID) == 0;
1323:                                                        }
1324:                                                        if (shouldCall) {
1325:                                                            //The state (or greater) was reached and document was not modified during moveToPhase
1326:                                                            try {
1327:                                                                final long startTime = System
1328:                                                                        .currentTimeMillis();
1329:                                                                ((CancellableTask<CompilationInfo>) r.task)
1330:                                                                        .run(ci); //XXX: How to do it in save way?
1331:                                                                final long endTime = System
1332:                                                                        .currentTimeMillis();
1333:                                                                if (reportSlowTasks) {
1334:                                                                    if ((endTime - startTime) > SLOW_TASK_LIMIT) {
1335:                                                                        Logger
1336:                                                                                .getLogger(
1337:                                                                                        "global")
1338:                                                                                .log(
1339:                                                                                        Level.INFO,
1340:                                                                                        String
1341:                                                                                                .format(
1342:                                                                                                        "Source executed a slow task: %s in %d ms.", //NOI18N
1343:                                                                                                        r.task
1344:                                                                                                                .getClass()
1345:                                                                                                                .toString(),
1346:                                                                                                        (endTime - startTime)));
1347:                                                                    }
1348:                                                                    final long cancelTime = currentRequest
1349:                                                                            .getCancelTime();
1350:                                                                    if (cancelTime >= startTime
1351:                                                                            && (endTime - cancelTime) > SLOW_CANCEL_LIMIT) {
1352:                                                                        Logger
1353:                                                                                .getLogger(
1354:                                                                                        "global")
1355:                                                                                .log(
1356:                                                                                        Level.INFO,
1357:                                                                                        String
1358:                                                                                                .format(
1359:                                                                                                        "Task: %s ignored cancel for %d ms.", //NOI18N
1360:                                                                                                        r.task
1361:                                                                                                                .getClass()
1362:                                                                                                                .toString(),
1363:                                                                                                        (endTime - cancelTime)));
1364:                                                                    }
1365:                                                                }
1366:                                                            } catch (RuntimeException re) {
1367:                                                                Exceptions
1368:                                                                        .printStackTrace(re);
1369:                                                            }
1370:                                                        }
1371:                                                    }
1372:                                                } finally {
1373:                                                    javacLock.unlock();
1374:                                                }
1375:
1376:                                                if (r.reschedule) {
1377:                                                    synchronized (Source.class) {
1378:                                                        boolean canceled = currentRequest
1379:                                                                .setCurrentTask(null);
1380:                                                        synchronized (js) {
1381:                                                            if ((js.flags & INVALID) != 0
1382:                                                                    || canceled) {
1383:                                                                //The Source was changed or canceled rechedule it now
1384:                                                                Source.requests
1385:                                                                        .add(r);
1386:                                                            } else {
1387:                                                                //Up to date Source add it to the finishedRequests
1388:                                                                Collection<Request> rc = Source.finishedRequests
1389:                                                                        .get(r.javaSource);
1390:                                                                if (rc == null) {
1391:                                                                    rc = new LinkedList<Request>();
1392:                                                                    Source.finishedRequests
1393:                                                                            .put(
1394:                                                                                    r.javaSource,
1395:                                                                                    rc);
1396:                                                                }
1397:                                                                rc.add(r);
1398:                                                            }
1399:                                                        }
1400:                                                    }
1401:                                                }
1402:                                            } catch (final IOException invalidFile) {
1403:                                                //Ideally the requests should be removed by JavaSourceTaskFactory and task should be put to finishedRequests,
1404:                                                //but the reality is different, the task cannot be put to finished request because of possible memory leak
1405:                                            }
1406:                                        }
1407:                                    } finally {
1408:                                        currentRequest.setCurrentTask(null);
1409:                                    }
1410:                                }
1411:                            } catch (Throwable e) {
1412:                                if (e instanceof  InterruptedException) {
1413:                                    throw (InterruptedException) e;
1414:                                } else if (e instanceof  ThreadDeath) {
1415:                                    throw (ThreadDeath) e;
1416:                                } else {
1417:                                    Exceptions.printStackTrace(e);
1418:                                }
1419:                            }
1420:                        }
1421:                    } catch (InterruptedException ie) {
1422:                        ie.printStackTrace();
1423:                        // stop the service.
1424:                    }
1425:                }
1426:            }
1427:
1428:            private class DocListener implements  DocumentListener,
1429:                    PropertyChangeListener, ChangeListener {
1430:
1431:                private EditorCookie.Observable ec;
1432:                private DocumentListener docListener;
1433:
1434:                public DocListener(EditorCookie.Observable ec) {
1435:                    assert ec != null;
1436:                    this .ec = ec;
1437:                    this .ec
1438:                            .addPropertyChangeListener((PropertyChangeListener) WeakListeners
1439:                                    .propertyChange(this , this .ec));
1440:                    Document doc = ec.getDocument();
1441:                    if (doc != null) {
1442:                        doc.addDocumentListener(docListener = WeakListeners
1443:                                .create(DocumentListener.class, this , doc));
1444:                    }
1445:                }
1446:
1447:                public void insertUpdate(DocumentEvent e) {
1448:                    //Has to reset cache asynchronously
1449:                    //the callback cannot be in synchronized section
1450:                    //since NbDocument.runAtomic fires under lock
1451:                    Source.this .resetState(true, true);
1452:                }
1453:
1454:                public void removeUpdate(DocumentEvent e) {
1455:                    //Has to reset cache asynchronously
1456:                    //the callback cannot be in synchronized section
1457:                    //since NbDocument.runAtomic fires under lock
1458:                    Source.this .resetState(true, true);
1459:                }
1460:
1461:                public void changedUpdate(DocumentEvent e) {
1462:                }
1463:
1464:                public void propertyChange(PropertyChangeEvent evt) {
1465:                    if (EditorCookie.Observable.PROP_DOCUMENT.equals(evt
1466:                            .getPropertyName())) {
1467:                        Object old = evt.getOldValue();
1468:                        if (old instanceof  Document && docListener != null) {
1469:                            ((Document) old)
1470:                                    .removeDocumentListener(docListener);
1471:                            docListener = null;
1472:                        }
1473:                        Document doc = ec.getDocument();
1474:                        if (doc != null) {
1475:                            doc.addDocumentListener(docListener = WeakListeners
1476:                                    .create(DocumentListener.class, this , doc));
1477:                            resetState(true, false);
1478:                        }
1479:                    }
1480:                }
1481:
1482:                public void stateChanged(ChangeEvent e) {
1483:                    Source.this .resetState(true, false);
1484:                }
1485:
1486:            }
1487:
1488:            private static class EditorRegistryListener implements 
1489:                    ChangeListener, CaretListener {
1490:
1491:                private JTextComponent lastEditor;
1492:
1493:                public EditorRegistryListener() {
1494:                    Registry.addChangeListener(this );
1495:                }
1496:
1497:                public void stateChanged(ChangeEvent event) {
1498:                    final JTextComponent editor = Registry
1499:                            .getMostActiveComponent();
1500:                    if (lastEditor != editor) {
1501:                        if (lastEditor != null) {
1502:                            lastEditor.removeCaretListener(this );
1503:                        }
1504:                        lastEditor = editor;
1505:                        if (lastEditor != null) {
1506:                            lastEditor.addCaretListener(this );
1507:                        }
1508:                    }
1509:                }
1510:
1511:                public void caretUpdate(CaretEvent event) {
1512:                    if (lastEditor != null) {
1513:                        Document doc = lastEditor.getDocument();
1514:                        if (doc != null) {
1515:                            Source js = forDocument(doc);
1516:                            if (js != null) {
1517:                                js.resetState(false, false);
1518:                            }
1519:                        }
1520:                    }
1521:                }
1522:            }
1523:
1524:            private class FileChangeListenerImpl extends FileChangeAdapter {
1525:
1526:                public @Override
1527:                void fileChanged(final FileEvent fe) {
1528:                    Source.this .resetState(true, false);
1529:                }
1530:
1531:                public @Override
1532:                void fileRenamed(FileRenameEvent fe) {
1533:                    Source.this .resetState(true, false);
1534:                }
1535:            }
1536:
1537:            private final class DataObjectListener implements 
1538:                    PropertyChangeListener {
1539:
1540:                private DataObject dobj;
1541:                private final FileObject fobj;
1542:                private PropertyChangeListener wlistener;
1543:
1544:                public DataObjectListener(FileObject fo)
1545:                        throws DataObjectNotFoundException {
1546:                    this .fobj = fo;
1547:                    this .dobj = DataObject.find(fo);
1548:                    wlistener = WeakListeners.propertyChange(this , dobj);
1549:                    this .dobj.addPropertyChangeListener(wlistener);
1550:                }
1551:
1552:                public void propertyChange(PropertyChangeEvent pce) {
1553:                    DataObject invalidDO = (DataObject) pce.getSource();
1554:                    if (invalidDO != dobj)
1555:                        return;
1556:                    if (DataObject.PROP_VALID.equals(pce.getPropertyName())) {
1557:                        handleInvalidDataObject(invalidDO);
1558:                    } else if (pce.getPropertyName() == null && !dobj.isValid()) {
1559:                        handleInvalidDataObject(invalidDO);
1560:                    }
1561:                }
1562:
1563:                private void handleInvalidDataObject(DataObject invalidDO) {
1564:                    invalidDO.removePropertyChangeListener(wlistener);
1565:                    if (fobj.isValid()) {
1566:                        // file object still exists try to find new data object
1567:                        try {
1568:                            dobj = DataObject.find(fobj);
1569:                            dobj.addPropertyChangeListener(wlistener);
1570:                            assignDocumentListener(fobj);
1571:                            resetState(true, true);
1572:                        } catch (IOException ex) {
1573:                            // should not occur
1574:                            Logger.getLogger(Source.class.getName()).log(
1575:                                    Level.SEVERE, ex.getMessage(), ex);
1576:                        }
1577:                    }
1578:                }
1579:
1580:            }
1581:
1582:            private static CompilationInfo createCurrentInfo(final Source js,
1583:                    final FileObject fo,
1584:                    final Object/*FilterListener*/filterListener,
1585:                    final ParserTaskImpl javac) throws IOException {
1586:                if (js.sourceLevel == null && fo != null)
1587:                    js.sourceLevel = SourceLevelQuery.getSourceLevel(fo);
1588:                if (js.sourceLevel == null)
1589:                    js.sourceLevel = JavaPlatformManager.getDefault()
1590:                            .getDefaultPlatform().getSpecification()
1591:                            .getVersion().toString();
1592:                CompilationInfo info = new CompilationInfo(js, fo, javac);
1593:
1594:                //TimesCollector.getDefault().reportReference(fo, CompilationInfo.class.toString(), "[M] CompilationInfo", info);     //NOI18N
1595:                return info;
1596:            }
1597:
1598:            private static void handleAddRequest(final Request nr) {
1599:                assert nr != null;
1600:                requests.add(nr);
1601:                Source.Request request = currentRequest
1602:                        .getTaskToCancel(nr.priority);
1603:                try {
1604:                    if (request != null) {
1605:                        request.task.cancel();
1606:                    }
1607:                } finally {
1608:                    currentRequest.cancelCompleted(request);
1609:                }
1610:            }
1611:
1612:            private static class SingleThreadFactory implements  ThreadFactory {
1613:
1614:                private Thread t;
1615:
1616:                public Thread newThread(Runnable r) {
1617:                    assert this .t == null;
1618:                    this .t = new Thread(r, "GSF Source Worker Thread"); //NOI18N
1619:                    return this .t;
1620:                }
1621:
1622:                public boolean isDispatchThread(Thread t) {
1623:                    assert t != null;
1624:                    return this .t == t;
1625:                }
1626:            }
1627:
1628:            private static class JavaSourceAccessorImpl extends SourceAccessor {
1629:                private StackTraceElement[] javacLockedStackTrace;
1630:
1631:                protected @Override
1632:                void runSpecialTaskImpl(CancellableTask<CompilationInfo> task,
1633:                        Priority priority) {
1634:                    handleAddRequest(new Request(task, null, null, priority,
1635:                            false));
1636:                }
1637:
1638:                @Override
1639:                public ParserTaskImpl createParserTask(Language language,
1640:                        ClasspathInfo cpInfo, /*DiagnosticListener<? super SourceFileObject> diagnosticListener,*/
1641:                        String sourceLevel) {
1642:                    if (sourceLevel == null)
1643:                        sourceLevel = JavaPlatformManager.getDefault()
1644:                                .getDefaultPlatform().getSpecification()
1645:                                .getVersion().toString();
1646:                    //            return Source.createParserTask(cpInfo, diagnosticListener, sourceLevel, true);
1647:                    //            throw new RuntimeException("Not yet implemented - I need the CompilationInfo here so I can pass in the language etc.");
1648:                    boolean backgroundCompilation = true; // Is this called from anywhere else?
1649:                    return Source.createParserTask(language, null, cpInfo,
1650:                            sourceLevel, backgroundCompilation);
1651:                }
1652:
1653:                @Override
1654:                public ParserTaskImpl/*JavacTaskImpl*/getParserTask(
1655:                        final CompilationInfo compilationInfo) {
1656:                    assert compilationInfo != null;
1657:                    return compilationInfo.getParserTask();
1658:                }
1659:
1660:                @Override
1661:                public CompilationInfo getCurrentCompilationInfo(
1662:                        final Source js, final Phase phase) throws IOException {
1663:                    assert js != null;
1664:                    assert isDispatchThread();
1665:                    CompilationInfo info = null;
1666:                    synchronized (js) {
1667:                        if ((js.flags & INVALID) == 0) {
1668:                            info = js.currentInfo;
1669:                        }
1670:                    }
1671:                    if (info == null) {
1672:                        return null;
1673:                    }
1674:                    Phase currentPhase = moveToPhase(phase, info, true);
1675:                    return currentPhase.compareTo(phase) < 0 ? null : info;
1676:                }
1677:
1678:                @Override
1679:                public void revalidate(Source js) {
1680:                    js.revalidate();
1681:                }
1682:
1683:                @Override
1684:                public boolean isDispatchThread() {
1685:                    return factory.isDispatchThread(Thread.currentThread());
1686:                }
1687:
1688:                @Override
1689:                public void lockParser() {
1690:                    javacLock.lock();
1691:                    try {
1692:                        this .javacLockedStackTrace = Thread.currentThread()
1693:                                .getStackTrace();
1694:                    } catch (RuntimeException e) {
1695:                        //Not important, thrown by logging code
1696:                    }
1697:                }
1698:
1699:                @Override
1700:                public void unlockParser() {
1701:                    try {
1702:                        this .javacLockedStackTrace = null;
1703:                    } finally {
1704:                        javacLock.unlock();
1705:                    }
1706:                }
1707:
1708:                @Override
1709:                public boolean isParserLocked() {
1710:                    return javacLock.isLocked();
1711:                }
1712:            }
1713:
1714:            private static class CurrentRequestReference {
1715:
1716:                private Source.Request reference;
1717:                private Source.Request canceledReference;
1718:                private long cancelTime;
1719:                private boolean canceled;
1720:
1721:                public CurrentRequestReference() {
1722:                }
1723:
1724:                public boolean setCurrentTask(Source.Request reference)
1725:                        throws InterruptedException {
1726:                    boolean result = false;
1727:                    synchronized (this ) {
1728:                        while (this .canceledReference != null) {
1729:                            this .wait();
1730:                        }
1731:                        result = this .canceled;
1732:                        this .canceled = false;
1733:                        this .cancelTime = 0;
1734:                        this .reference = reference;
1735:                    }
1736:                    return result;
1737:                }
1738:
1739:                public Source.Request getTaskToCancel(final Priority priority) {
1740:                    Source.Request request = null;
1741:                    if (!factory.isDispatchThread(Thread.currentThread())) {
1742:                        synchronized (this ) {
1743:                            if (this .reference != null
1744:                                    && priority
1745:                                            .compareTo(this .reference.priority) < 0) {
1746:                                assert this .canceledReference == null;
1747:                                request = this .reference;
1748:                                this .canceledReference = request;
1749:                                this .reference = null;
1750:                                this .canceled = true;
1751:                                if (reportSlowTasks) {
1752:                                    cancelTime = System.currentTimeMillis();
1753:                                }
1754:                            }
1755:                        }
1756:                    }
1757:                    return request;
1758:                }
1759:
1760:                public Source.Request getTaskToCancel(final Source js) {
1761:                    Source.Request request = null;
1762:                    if (!factory.isDispatchThread(Thread.currentThread())) {
1763:                        synchronized (this ) {
1764:                            if (this .reference != null
1765:                                    && js.equals(this .reference.javaSource)) {
1766:                                assert this .canceledReference == null;
1767:                                request = this .reference;
1768:                                this .canceledReference = request;
1769:                                this .reference = null;
1770:                                this .canceled = true;
1771:                                if (reportSlowTasks) {
1772:                                    cancelTime = System.currentTimeMillis();
1773:                                }
1774:                            }
1775:                        }
1776:                    }
1777:                    return request;
1778:                }
1779:
1780:                public Source.Request getTaskToCancel(final CancellableTask task) {
1781:                    Source.Request request = null;
1782:                    if (!factory.isDispatchThread(Thread.currentThread())) {
1783:                        synchronized (this ) {
1784:                            if (this .reference != null
1785:                                    && task == this .reference.task) {
1786:                                assert this .canceledReference == null;
1787:                                request = this .reference;
1788:                                this .canceledReference = request;
1789:                                this .reference = null;
1790:                                this .canceled = true;
1791:                            }
1792:                        }
1793:                    }
1794:                    return request;
1795:                }
1796:
1797:                public Source.Request getTaskToCancel() {
1798:                    Source.Request request = null;
1799:                    if (!factory.isDispatchThread(Thread.currentThread())) {
1800:                        synchronized (this ) {
1801:                            request = this .reference;
1802:                            if (request != null) {
1803:                                assert this .canceledReference == null;
1804:                                this .canceledReference = request;
1805:                                this .reference = null;
1806:                                this .canceled = true;
1807:                                if (reportSlowTasks) {
1808:                                    cancelTime = System.currentTimeMillis();
1809:                                }
1810:                            }
1811:                        }
1812:                    }
1813:                    return request;
1814:                }
1815:
1816:                public synchronized boolean isCanceled() {
1817:                    return this .canceled;
1818:                }
1819:
1820:                public synchronized long getCancelTime() {
1821:                    return this .cancelTime;
1822:                }
1823:
1824:                public void cancelCompleted(final Source.Request request) {
1825:                    if (request != null) {
1826:                        synchronized (this ) {
1827:                            assert request == this .canceledReference;
1828:                            this .canceledReference = null;
1829:                            this .notify();
1830:                        }
1831:                    }
1832:                }
1833:            }
1834:
1835:            private static class LMListener implements  LowMemoryListener {
1836:                private AtomicBoolean lowMemory = new AtomicBoolean(false);
1837:
1838:                public void lowMemory(LowMemoryEvent event) {
1839:                    lowMemory.set(true);
1840:                }
1841:            }
1842:
1843:            /**
1844:             *Ugly and slow, called only when -ea
1845:             *
1846:             */
1847:            private static boolean holdsDocumentWriteLock(
1848:                    Iterable<FileObject> files) {
1849:                final Class<AbstractDocument> docClass = AbstractDocument.class;
1850:                try {
1851:                    final Method method = docClass
1852:                            .getDeclaredMethod("getCurrentWriter"); //NOI18N
1853:                    method.setAccessible(true);
1854:                    final Thread currentThread = Thread.currentThread();
1855:                    for (FileObject fo : files) {
1856:                        try {
1857:                            final DataObject dobj = DataObject.find(fo);
1858:                            final EditorCookie ec = (EditorCookie) dobj
1859:                                    .getCookie(EditorCookie.class);
1860:                            if (ec != null) {
1861:                                final StyledDocument doc = ec.getDocument();
1862:                                if (doc instanceof  AbstractDocument) {
1863:                                    Object result = method.invoke(doc);
1864:                                    if (result == currentThread) {
1865:                                        return true;
1866:                                    }
1867:                                }
1868:                            }
1869:                        } catch (Exception e) {
1870:                            Exceptions.printStackTrace(e);
1871:                        }
1872:                    }
1873:                } catch (NoSuchMethodException e) {
1874:                    Exceptions.printStackTrace(e);
1875:                }
1876:                return false;
1877:            }
1878:
1879:            private static final int MAX_DUMPS = 255;
1880:
1881:            /**
1882:             * Dumps the source code to the file. Used for parser debugging. Only a limited number
1883:             * of dump files is used. If the last file exists, this method doesn't dump anything.
1884:             *
1885:             * @param  info  CompilationInfo for which the error occurred.
1886:             * @param  exc  exception to write to the end of dump file
1887:             */
1888:            private static void dumpSource(CompilationInfo info, Throwable exc) {
1889:                String dumpDir = System.getProperty("netbeans.user")
1890:                        + "/var/log/"; //NOI18N
1891:                String src = info.getText();
1892:                FileObject file = info.getFileObject();
1893:                String fileName = FileUtil.getFileDisplayName(info
1894:                        .getFileObject());
1895:                String origName = file.getName();
1896:                File f = new File(dumpDir + origName + ".dump"); // NOI18N
1897:                boolean dumpSucceeded = false;
1898:                int i = 1;
1899:                while (i < MAX_DUMPS) {
1900:                    if (!f.exists())
1901:                        break;
1902:                    f = new File(dumpDir + origName + '_' + i + ".dump"); // NOI18N
1903:                    i++;
1904:                }
1905:                if (!f.exists()) {
1906:                    try {
1907:                        OutputStream os = new FileOutputStream(f);
1908:                        PrintWriter writer = new PrintWriter(
1909:                                new OutputStreamWriter(os, "UTF-8")); // NOI18N
1910:                        try {
1911:                            writer.println(src);
1912:                            writer
1913:                                    .println("----- Classpath: ---------------------------------------------"); // NOI18N
1914:
1915:                            final ClassPath bootPath = info.getClasspathInfo()
1916:                                    .getClassPath(ClasspathInfo.PathKind.BOOT);
1917:                            final ClassPath classPath = info.getClasspathInfo()
1918:                                    .getClassPath(
1919:                                            ClasspathInfo.PathKind.COMPILE);
1920:                            final ClassPath sourcePath = info
1921:                                    .getClasspathInfo().getClassPath(
1922:                                            ClasspathInfo.PathKind.SOURCE);
1923:
1924:                            writer.println("bootPath: "
1925:                                    + (bootPath != null ? bootPath.toString()
1926:                                            : "null"));
1927:                            writer.println("classPath: "
1928:                                    + (classPath != null ? classPath.toString()
1929:                                            : "null"));
1930:                            writer.println("sourcePath: "
1931:                                    + (sourcePath != null ? sourcePath
1932:                                            .toString() : "null"));
1933:
1934:                            writer
1935:                                    .println("----- Original exception ---------------------------------------------"); // NOI18N
1936:                            exc.printStackTrace(writer);
1937:                        } finally {
1938:                            writer.close();
1939:                            dumpSucceeded = true;
1940:                        }
1941:                    } catch (IOException ioe) {
1942:                        Logger.getLogger("global").log(Level.INFO,
1943:                                "Error when writing parser dump file!", ioe); // NOI18N
1944:                    }
1945:                }
1946:                if (dumpSucceeded) {
1947:                    Throwable t = Exceptions
1948:                            .attachMessage(
1949:                                    exc,
1950:                                    "An error occurred during parsing of \'"
1951:                                            + fileName
1952:                                            + "\'. Please report a bug against ruby and attach dump file '" // NOI18N
1953:                                            + f.getAbsolutePath() + "'."); // NOI18N
1954:                    Exceptions.printStackTrace(t);
1955:                } else {
1956:                    Logger
1957:                            .getLogger("global")
1958:                            .log(
1959:                                    Level.WARNING,
1960:                                    "Dump could not be written. Either dump file could not "
1961:                                            + // NOI18N
1962:                                            "be created or all dump files were already used. Please "
1963:                                            + // NOI18N
1964:                                            "check that you have write permission to '"
1965:                                            + dumpDir + "' and " + // NOI18N
1966:                                            "clean all *.dump files in that directory."); // NOI18N
1967:                }
1968:            }
1969:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.