KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > javacore > JMManager


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.javacore;
21
22 import java.beans.PropertyChangeEvent JavaDoc;
23 import java.beans.PropertyChangeListener JavaDoc;
24 import java.io.BufferedInputStream JavaDoc;
25 import java.io.File JavaDoc;
26 import java.io.FileInputStream JavaDoc;
27 import java.io.FileOutputStream JavaDoc;
28 import java.io.IOException JavaDoc;
29 import java.io.InputStream JavaDoc;
30 import java.lang.ref.WeakReference JavaDoc;
31 import java.net.MalformedURLException JavaDoc;
32 import java.net.URL JavaDoc;
33 import java.security.MessageDigest JavaDoc;
34 import java.security.NoSuchAlgorithmException JavaDoc;
35 import java.util.AbstractList JavaDoc;
36 import java.util.ArrayList JavaDoc;
37 import java.util.Arrays JavaDoc;
38 import java.util.Collection JavaDoc;
39 import java.util.Collections JavaDoc;
40 import java.util.HashMap JavaDoc;
41 import java.util.HashSet JavaDoc;
42 import java.util.Iterator JavaDoc;
43 import java.util.List JavaDoc;
44 import java.util.Map JavaDoc;
45 import java.util.Set JavaDoc;
46 import java.util.logging.Level JavaDoc;
47 import java.util.logging.Logger JavaDoc;
48 import javax.jmi.reflect.InvalidObjectException;
49 import javax.jmi.reflect.RefBaseObject;
50 import org.netbeans.api.java.classpath.ClassPath;
51 import org.netbeans.api.java.queries.SourceForBinaryQuery;
52 import org.netbeans.api.java.queries.SourceLevelQuery;
53 import org.netbeans.api.mdr.MDRepository;
54 import org.netbeans.api.project.FileOwnerQuery;
55 import org.netbeans.jmi.javamodel.Array;
56 import org.netbeans.jmi.javamodel.CallableFeature;
57 import org.netbeans.jmi.javamodel.ClassDefinition;
58 import org.netbeans.jmi.javamodel.Codebase;
59 import org.netbeans.jmi.javamodel.CodebaseClass;
60 import org.netbeans.jmi.javamodel.Element;
61 import org.netbeans.jmi.javamodel.ElementPartKind;
62 import org.netbeans.jmi.javamodel.GenericElement;
63 import org.netbeans.jmi.javamodel.JavaClass;
64 import org.netbeans.jmi.javamodel.JavaModelPackage;
65 import org.netbeans.jmi.javamodel.JavaPackage;
66 import org.netbeans.jmi.javamodel.Parameter;
67 import org.netbeans.jmi.javamodel.ParameterizedType;
68 import org.netbeans.jmi.javamodel.Resource;
69 import org.netbeans.jmi.javamodel.TypeParameter;
70 import org.netbeans.jmi.javamodel.TypedElement;
71 import org.netbeans.jmi.javamodel.UnresolvedClass;
72 import org.netbeans.mdr.NBMDRepositoryImpl;
73 import org.netbeans.mdr.persistence.MOFID;
74 import org.netbeans.mdr.persistence.btreeimpl.btreestorage.BtreeFactory;
75 import org.netbeans.mdr.storagemodel.MdrStorage;
76 import org.netbeans.modules.javacore.classpath.FilterClassPathImplementation;
77 import org.netbeans.modules.javacore.classpath.MergedClassPathImplementation;
78 import org.netbeans.modules.javacore.internalapi.ExternalChange;
79 import org.netbeans.modules.javacore.internalapi.GuardedQuery;
80 import org.netbeans.modules.javacore.internalapi.JavaMetamodel;
81 import org.netbeans.modules.javacore.internalapi.ParsingListener;
82 import org.netbeans.modules.javacore.internalapi.ProgressSupport;
83 import org.netbeans.modules.javacore.jmiimpl.javamodel.JavaPackageClassImpl;
84 import org.netbeans.modules.javacore.jmiimpl.javamodel.MetadataElement;
85 import org.netbeans.modules.javacore.jmiimpl.javamodel.ParameterizedTypeImpl;
86 import org.netbeans.modules.javacore.jmiimpl.javamodel.ResourceClassImpl;
87 import org.netbeans.modules.javacore.jmiimpl.javamodel.ResourceImpl;
88 import org.netbeans.modules.javacore.parser.ArrayRef;
89 import org.netbeans.modules.javacore.parser.NameRef;
90 import org.netbeans.modules.javacore.parser.PrimitiveTypeRef;
91 import org.netbeans.modules.javacore.parser.TypeParamRef;
92 import org.netbeans.modules.javacore.parser.WildCardRef;
93 import org.netbeans.modules.javacore.scanning.FileScanner;
94 import org.netbeans.spi.java.classpath.ClassPathFactory;
95 import org.netbeans.spi.java.classpath.PathResourceImplementation;
96 import org.netbeans.spi.java.classpath.support.ClassPathSupport;
97 import org.openide.ErrorManager;
98 import org.openide.filesystems.FileObject;
99 import org.openide.filesystems.FileStateInvalidException;
100 import org.openide.filesystems.FileUtil;
101 import org.openide.filesystems.URLMapper;
102 import org.openide.loaders.DataObject;
103 import org.openide.loaders.DataObjectNotFoundException;
104 import org.openide.modules.InstalledFileLocator;
105 import org.openide.text.PositionBounds;
106 import org.openide.util.RequestProcessor;
107
108 /**
109  *
110  * @author Martin Matula
111  */

112 public class JMManager extends JavaMetamodel implements PropertyChangeListener JavaDoc {
113     private static final String JavaDoc NAME_MAIN_EXTENT = "JavaCoreMain"; // NOI18N
114
private static final String JavaDoc NAME_MAIN_STORAGE = "Main"; // NOI18N
115

116     private static final String JavaDoc PREFIX_EXTENT_CODEBASE = "codebase:"; // NOI18N
117
private static final String JavaDoc PACKAGE_CODEBASE = "JavaModel"; // NOI18N
118
private static final int THREAD_PRIORITY = Thread.MIN_PRIORITY;
119
120     private static final RequestProcessor EVENT_RP = new RequestProcessor("Parsing Event Queue"); // NOI18N
121
private static final RequestProcessor SCANNING_RP = new RequestProcessor("Scanning Queue"); // NOI18N
122
private static final RequestPoster RESOLVE_POSTER = new RequestPoster(SCANNING_RP);
123     private static final RequestPoster CLEANUP_POSTER = new RequestPoster(SCANNING_RP);
124
125     // constants populated from system properties
126
public static final boolean PERF_DEBUG = Boolean.getBoolean("perf.refactoring");
127     public static final boolean PERF_TEST = Boolean.getBoolean("perf.refactoring.test");
128     public static final boolean INCONSISTENCY_DEBUG = Boolean.getBoolean("javacore.debug.inconsistency");
129     public static final boolean SCAN_DEBUG = Boolean.getBoolean("javacore.debug.scanning");
130     public static final boolean TRANS_DEBUG = Boolean.getBoolean("javacore.debug.transactions");
131     private static final boolean NO_SCAN = Boolean.getBoolean("netbeans.javacore.noscan");
132     private static final int MDR_CACHE_SIZE = Integer.getInteger("org.netbeans.javacore.MDRCache.size", 256).intValue(); // NOI18N
133

134     private static final boolean DEBUG = false;
135     private static final String JavaDoc[] CP_TYPES = {ClassPath.BOOT, ClassPath.SOURCE, ClassPath.COMPILE};
136     private static PropertyChangeListener JavaDoc indentListener;
137     
138     /**
139      * Says a number of bytes read from input file. These bytes are used
140      * for MD5 computation.
141      */

142     public static final int BYTES4MD5 = 8192;
143     
144     /**
145      * Contains path to the structure with preparsed storages.
146      */

147     private static final String JavaDoc PREPARSED_LOCATION;
148     private static final HashSet JavaDoc PREPARSED_CACHE;
149     
150     static {
151         String JavaDoc s = System.getProperty("prebuilt.storage.dir"); // NOI18N
152
if (s == null) {
153             File JavaDoc f = InstalledFileLocator.getDefault().locate("./mdrstorage", "org.netbeans.modules.javacore", false); // NOI18N
154
if (f != null) {
155                 PREPARSED_LOCATION = f.getAbsolutePath() + "/"; // NOI18N
156
} else {
157                 PREPARSED_LOCATION = "./"; // NOI18N
158
}
159         } else {
160             if (s.endsWith("/")) { // NOI18N
161
PREPARSED_LOCATION = s;
162             } else {
163                 PREPARSED_LOCATION = s + '/';
164             }
165         }
166         PREPARSED_CACHE = new HashSet JavaDoc();
167         File JavaDoc f = new File JavaDoc(PREPARSED_LOCATION);
168         File JavaDoc[] files = f.listFiles();
169         if (files != null) {
170             for (int i = 0; i < files.length; i++) {
171                 String JavaDoc name = files[i].getName();
172                 if (name.endsWith(".btd")) {
173                     int pos = name.lastIndexOf("-");
174                     if (pos >= 0) {
175                         PREPARSED_CACHE.add(name.substring(0, pos));
176                     }
177                 }
178             }
179         }
180     }
181
182     private static final Map JavaDoc MDR_CACHE = new CacheClass();
183     
184     private static class CacheClass implements Map JavaDoc {
185         private final Object JavaDoc inner[] = new Object JavaDoc[MDR_CACHE_SIZE];
186         private int size, cursor;
187         
188         public CacheClass () {}
189         
190         public Set JavaDoc keySet() {
191             throw new UnsupportedOperationException JavaDoc();
192         }
193
194         public Set JavaDoc entrySet() {
195             throw new UnsupportedOperationException JavaDoc();
196         }
197
198         public void putAll(Map JavaDoc t) {
199             throw new UnsupportedOperationException JavaDoc();
200         }
201
202         public boolean isEmpty() {
203             return size == 0;
204         }
205
206         public boolean containsKey(Object JavaDoc key) {
207             throw new UnsupportedOperationException JavaDoc();
208         }
209
210         public boolean containsValue(Object JavaDoc value) {
211             throw new UnsupportedOperationException JavaDoc();
212         }
213
214         public Collection JavaDoc values() {
215             throw new UnsupportedOperationException JavaDoc();
216         }
217
218         public Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
219             if (inner[cursor] != value) {
220                 cursor++;
221                 if (size < MDR_CACHE_SIZE) {
222                     size++;
223                 }
224                 if (cursor >= MDR_CACHE_SIZE) {
225                     cursor = 0;
226                 }
227                 inner[cursor] = value;
228             }
229             return null;
230         }
231
232         public void clear() {
233             Arrays.fill(inner, null);
234             size = cursor = 0;
235         }
236
237         public int size() {
238             return size;
239         }
240
241         public Object JavaDoc get(Object JavaDoc key) {
242             throw new UnsupportedOperationException JavaDoc();
243         }
244
245         public Object JavaDoc remove(Object JavaDoc key) {
246             throw new UnsupportedOperationException JavaDoc();
247         }
248     }
249
250
251     private JavaModelPackage mainExtent;
252     // uri->storageId map for mounted partitions
253
// uri => folderURL[sourceLevel]?
254
// folderURL url ending with /
255
// sourceLevel => digit.digit
256
private final HashMap JavaDoc sids = new HashMap JavaDoc();
257     // JavaModelPackage -> FileObject (CPRoot)
258
private final HashMap JavaDoc filesystems = new HashMap JavaDoc();
259     private final HashMap JavaDoc extents = new HashMap JavaDoc();
260
261     private final MergedClassPathImplementation cpImpl;
262     private final ClassPath classPath;
263
264     private static ProgressSupport progressSupport = null;
265     
266     private Cache cpForFileObjectCache = new Cache(5);
267     private HashMap JavaDoc cpForFileObjectMap = new HashMap JavaDoc(10);
268     
269     private static ErrorManager javamodelErr = ErrorManager.getDefault().getInstance("org.netbeans.javacore"); // NOI18N
270

271     private Set JavaDoc extentsToScan = new HashSet JavaDoc();
272     
273     private boolean cancelScan = false;
274
275     /**
276      * Used from computation of src.zip and rt.jar digest. This is used
277      * for setting filenames of pre-parsed storages.
278      */

279     private static final MessageDigest JavaDoc md5digest;
280     private static final MessageDigest JavaDoc digest;
281     
282     private static ThreadLocal JavaDoc documentLocks;
283     private static IndentationSettingsProvider settingsProvider;
284     
285     private static ModifiedDOProvider modifiedDOProvider;
286     
287     public static synchronized void setDocumentLocksCounter(ThreadLocal JavaDoc documentLocks) {
288         JMManager.documentLocks = documentLocks;
289     }
290     
291     static synchronized ThreadLocal JavaDoc getDocumentLocksCounter() {
292         return documentLocks;
293     }
294
295     static {
296         try {
297             digest = MessageDigest.getInstance("SHA"); // NOI18N
298
md5digest = MessageDigest.getInstance("MD5"); // NOI18N
299
} catch (NoSuchAlgorithmException JavaDoc e) {
300             throw new RuntimeException JavaDoc("Fatal error: " + e); // NOI18N
301
}
302     }
303     
304     public JMManager(MDRepository repository) {
305         super(repository, Codebase.class);
306         cpImpl = MergedClassPathImplementation.getDefault();
307         cpImpl.addPropertyChangeListener(this);
308         classPath = ClassPathFactory.createClassPath (cpImpl);
309         classPath.addPropertyChangeListener (this);
310     }
311
312     private void init() {
313         if (mainExtent == null) {
314             repository.beginTrans(true);
315             boolean fail = true;
316             try {
317                 int retry = 0;
318                 String JavaDoc mainExtentSid = null;
319                 String JavaDoc storageFileName = getFileName(NAME_MAIN_STORAGE);
320                 while (mainExtent == null && retry < 2) {
321                     try {
322                         if (DEBUG) System.err.println("Initializing repository."); // NOI18N
323
if (retry == 0) {
324                             mainExtentSid = mountStorage(NAME_MAIN_STORAGE, storageFileName); // NOI18N
325
} else {
326                             mainExtentSid = rebootStorage(NAME_MAIN_STORAGE, storageFileName, mainExtentSid); // NOI18N
327
}
328                         JavaModelPackage main = (JavaModelPackage) repository.getExtent(NAME_MAIN_EXTENT);
329                         if (main == null) {
330                             NBMDRepositoryImpl nbRep = (NBMDRepositoryImpl) repository;
331                             main = (JavaModelPackage) nbRep.createExtent(NAME_MAIN_EXTENT, findRootPackage(PACKAGE_CODEBASE), null, mainExtentSid);
332                         }
333                         mainExtent = main;
334                     } catch (Exception JavaDoc e) {
335                         retry++;
336                         if (retry >= 2) {
337                             JMManager.getLog().notify(e);
338                             // TODO: fatal error - stop NetBeans
339
} else {
340                             JMManager.getLog().log(ErrorManager.WARNING, "Rebooting Main storage because of a fatal error during storage mount."); // NOI18N
341
JMManager.getLog().notify(ErrorManager.INFORMATIONAL, e);
342                         }
343                     }
344                 }
345                 fail = false;
346             } finally {
347                 repository.endTrans(fail);
348             }
349             RepositoryUpdater.getDefault();
350         }
351     }
352     
353     /**
354      * Returns the instance of Error Manager used for logging model problems
355      * and debug messages.
356      *
357      * @return instance of error manager
358      */

359     public static ErrorManager getLog() {
360         return javamodelErr;
361     }
362     
363     private String JavaDoc getDirName() {
364         NBMDRepositoryImpl nbRep = (NBMDRepositoryImpl) repository;
365         String JavaDoc fileName = nbRep.getParameter(BtreeFactory.STORAGE_FILE_NAME);
366         int li = Math.max(fileName.lastIndexOf('/'), fileName.lastIndexOf('\\'));
367         String JavaDoc folderName = getVersion();
368         if (li > 0) {
369             folderName = fileName.substring(0, li + 1) + folderName;
370         }
371         return folderName;
372     }
373     
374     public String JavaDoc getFileName(String JavaDoc name) {
375         String JavaDoc folderName = getDirName();
376         new File JavaDoc(folderName).mkdirs();
377         return folderName.concat("/").concat(name); // NOI18N
378
}
379     
380     private String JavaDoc mountStorage(String JavaDoc name, String JavaDoc fileName) {
381         HashMap JavaDoc properties = new HashMap JavaDoc();
382         NBMDRepositoryImpl nbRep = (NBMDRepositoryImpl) repository;
383         properties.put(BtreeFactory.STORAGE_FILE_NAME, fileName);
384         properties.put(BtreeFactory.CACHE_INSTANCE, MDR_CACHE); // NOI18N
385
String JavaDoc sid;
386         try {
387             if (DEBUG) System.out.println("mounting: " + fileName); // NOI18N
388
sid = nbRep.mountStorage(nbRep.getParameter("storage"), properties); // NOI18N
389
MdrStorage.ValuesObject values = nbRep.getMdrStorage().storageValues(sid);
390             values.store(NameRef.class.getName());
391             values.store(TypeParamRef.class.getName());
392             values.store(PrimitiveTypeRef.class.getName());
393             values.store(WildCardRef.class.getName());
394             values.store(ArrayRef.class.getName());
395             
396             return sid;
397         } catch (Exception JavaDoc e) {
398             throw (RuntimeException JavaDoc) ErrorManager.getDefault().annotate(new RuntimeException JavaDoc(), e);
399         }
400     }
401     
402     private String JavaDoc rebootStorage(String JavaDoc name, String JavaDoc fileName, String JavaDoc sid) {
403         NBMDRepositoryImpl nbRep = (NBMDRepositoryImpl) repository;
404         nbRep.disableEvents();
405         nbRep.unmountStorage(sid);
406         nbRep.enableEvents();
407         new File JavaDoc(fileName + ".btx").delete(); // NOI18N
408
new File JavaDoc(fileName + ".btd").delete(); // NOI18N
409
new File JavaDoc(fileName + ".btb").delete(); // NOI18N
410
return mountStorage(name, fileName);
411     }
412
413     public ClassPath getClassPath() {
414         ClassPath result = ((ExclusiveMutex) ((NBMDRepositoryImpl) repository).getTransactionMutex()).getClassPath();
415
416         // [TODO] remove the following line once all the usages of this method are fixed
417
if (result == null) {
418             result = FilterClassPathImplementation.createClassPath(Collections.singletonList(getMergedClassPath()), false);
419         }
420         
421         return result;
422     }
423
424     public ClassPath getMergedClassPath() {
425         return classPath;
426     }
427     
428     MergedClassPathImplementation getMergedClassPathImpl() {
429         return cpImpl;
430     }
431     
432     public boolean mergedCPContains(FileObject fo) {
433         return cpImpl.contains(fo);
434     }
435     
436     public boolean mergedCPContainsRoot(FileObject fo) {
437         return cpImpl.getRoots().contains(fo);
438     }
439
440     /** Sets classpath for the duration of the current transaction
441      *
442      * @param cp Classpath to be used during the current transaction.
443      */

444     public void setClassPath(List JavaDoc/*<ClassPath>*/ cps) {
445         setClassPath(cps, false);
446     }
447     
448     public void setClassPath(List JavaDoc/*<ClassPath>*/ cps, boolean preferSource) {
449         if (cps == null || cps.isEmpty()) return;
450         ((ExclusiveMutex) ((NBMDRepositoryImpl) repository).getTransactionMutex()).setClassPath(cps, preferSource);
451     }
452     
453     public void setClassPath(ClassPath cp) {
454         setClassPath(Collections.singletonList(cp));
455     }
456     
457     public void setClassPath(Resource rsc) {
458         setClassPath(getFileObject(rsc));
459     }
460     
461     public void setClassPath(Resource rsc, boolean preferSource) {
462         setClassPath(getFileObject(rsc), preferSource);
463     }
464     
465     private class CPList extends AbstractList JavaDoc implements Cache.CachedElement {
466         private final FileObject fo;
467         private final WeakReference JavaDoc inner[] = new WeakReference JavaDoc[CP_TYPES.length];
468         
469         public CPList(FileObject fo) {
470             this.fo = fo;
471             for (int i = 0; i < CP_TYPES.length; i++) {
472                 ClassPath cp = ClassPath.getClassPath(fo, CP_TYPES[i]);
473                 inner[i] = cp == null ? null : new WeakReference JavaDoc(cp);
474             }
475             cpForFileObjectMap.put(fo, this);
476         }
477         
478         public Object JavaDoc get(int index) {
479             return inner[index] == null ? null : ((WeakReference JavaDoc) inner[index]).get();
480         }
481         
482         public int size() {
483             return 3;
484         }
485         
486         public boolean isValid() {
487             return true;
488         }
489         
490         public void release() {
491             cpForFileObjectMap.remove(fo);
492         }
493     }
494
495     public void setClassPath(FileObject fo) {
496         setClassPath(fo, false);
497     }
498
499     // does not need to be thread safe/synchronized, since it should always be invoked from a transaction
500
public void setClassPath(FileObject fo, boolean preferSource) {
501         if (fo == null) return;
502         List JavaDoc cps = (List JavaDoc) cpForFileObjectMap.get(fo);
503         if (cps == null) {
504             cps = new CPList(fo);
505         }
506         cpForFileObjectCache.put(cps);
507         setClassPath(cps, preferSource);
508     }
509
510     public JavaModelPackage getDefaultExtent() {
511         init();
512         return mainExtent;
513     }
514     
515     public void setSafeTrans(boolean isSafeTrans) {
516         getTransactionMutex().setSafeTrans(isSafeTrans);
517     }
518
519     public static ExclusiveMutex getTransactionMutex() {
520         return (ExclusiveMutex) ((NBMDRepositoryImpl) getDefaultRepository()).getTransactionMutex();
521     }
522
523     public JavaModelPackage resolveJavaExtent(FileObject cpRoot) {
524         repository.beginTrans(false);
525         try {
526             synchronized (this) {
527                 JavaModelPackage extent = getJavaExtent(cpRoot);
528                 if (extent == null) {
529                     ClassPath cp = ClassPath.getClassPath(cpRoot, ClassPath.SOURCE);
530                     if (cp!=null) {
531                         resolveCPRoot(cpRoot, false);
532                         extent = (JavaModelPackage) extents.get(cpRoot);
533                         if (FileOwnerQuery.getOwner(cpRoot) != null) {
534                             try {
535                                 URL JavaDoc cpRootUrl = cpRoot.getURL();
536                                 cpImpl.addClassPaths(new ClassPath[] {cp, ClassPath.getClassPath(cpRoot, ClassPath.COMPILE), ClassPath.getClassPath(cpRoot, ClassPath.BOOT)});
537                             } catch (FileStateInvalidException e) {
538                                 // ignore
539
}
540                         }
541                     }
542                 }
543                 return extent;
544             }
545         } finally {
546             repository.endTrans();
547         }
548     }
549
550     public synchronized JavaModelPackage getJavaExtent(FileObject cpRoot) {
551         if (cpImpl.getRoots().contains(cpRoot)) {
552             return (JavaModelPackage) extents.get(cpRoot);
553         } else {
554             return null;
555         }
556     }
557     
558     public Resource getResource(FileObject fo) {
559         return getResource(fo, true);
560     }
561
562     public Resource getResource(FileObject fo, boolean force) {
563         if (fo.isVirtual() || !fo.isValid()) {
564             //simply ignore virtual and invalid files
565
return null;
566         }
567         repository.beginTrans(false);
568         try {
569             FileObject cpRoot = this.cpImpl.findOwnerRoot(fo);
570             if (cpRoot==null && force) {
571                 String JavaDoc ext=fo.getExt();
572                 ClassPath cp=null;
573                 if ("java".equals(ext)) // NOI18N
574
cp = ClassPath.getClassPath(fo, ClassPath.SOURCE);
575                 else if ("class".equals(ext)) // NOI18N
576
cp = ClassPath.getClassPath(fo, ClassPath.EXECUTE);
577                if (cp != null) {
578                     cpRoot = cp.findOwnerRoot(fo);
579                 }
580             }
581             Resource result = null;
582             if (cpRoot != null) {
583                 String JavaDoc resourceName = getResourceName (cpRoot, fo);
584                 result = getResource(cpRoot, resourceName);
585             }
586             return result;
587         } catch (Exception JavaDoc ex) {
588             ErrorManager.getDefault().notify(ex);
589         } finally {
590             repository.endTrans();
591         }
592         return null;
593     }
594
595     public JavaPackage getPackage(FileObject fo) {
596         repository.beginTrans(false);
597         try {
598             FileObject cpRoot = this.cpImpl.findOwnerRoot (fo);
599             if (cpRoot == null) return null;
600
601             JavaModelPackage extent = getJavaExtent(cpRoot);
602             if (extent == null) return null;
603             
604             String JavaDoc packageName = getResourceName (cpRoot, fo);
605             packageName = packageName.replace('/', '.');
606             
607             return ((JavaPackageClassImpl) extent.getJavaPackage()).findRealPackage(packageName);
608         } catch (Exception JavaDoc ex) {
609             ErrorManager.getDefault().notify(ex);
610         } finally {
611             repository.endTrans();
612         }
613         return null;
614     }
615
616     public void registerExtChange(ExternalChange ch) {
617         getTransactionMutex().registerExtChange(ch);
618     }
619     
620     public void registerUndoElement(ExternalChange ch) {
621         getTransactionMutex().registerUndoElement(ch);
622     }
623     
624     public Resource getResource(FileObject cpRoot, String JavaDoc name) {
625         repository.beginTrans(false);
626         try {
627             if (cpRoot != null && cpRoot.isValid()) {
628                 JavaModelPackage pck=resolveJavaExtent(cpRoot);
629                 if (pck == null) {
630                     return null;
631                 }
632                 ResourceClassImpl resClass=(ResourceClassImpl)pck.getResource();
633                 ResourceImpl result = (ResourceImpl) resClass.resolveResource(name, false);
634                 
635                 // ignore classfiles if there are corresponding java files in the same directory
636
// i.e. pass resource corresponding to the java file
637
if (result == null && name.endsWith(".class")) { // NOI18N
638
String JavaDoc srcName = name.substring(0, name.length() - ".class".length()) + ".java"; // NOI18N
639
if (cpRoot.getFileObject(srcName) != null) {
640                         name = srcName;
641                         result = (ResourceImpl) resClass.resolveResource(name, false);
642                     }
643                 }
644                 // -----------------------------------
645

646                 if (result == null) {
647                     result = (ResourceImpl) resClass.resolveResource(name, true, false);
648                     if (result != null) {
649                         if (!result.isValid()) return null;
650                         FileObject fobj = getFileObject(result);
651                         if (fobj != null) {
652                             result.updateFromFileObject(fobj, false);
653                         } else {
654                             result.refDelete();
655                             return null;
656                         }
657                     }
658                 }
659                 return result;
660             } else {
661                 return null;
662             }
663         } catch (Exception JavaDoc ex) {
664             ErrorManager.getDefault().notify(ex);
665         } finally {
666             repository.endTrans();
667         }
668
669         return null;
670     }
671
672     public FileObject getFileObject(Resource res) {
673         if (res == null) return null;
674         repository.beginTrans(false);
675         try {
676             if (!res.isValid()) {
677                 return null;
678             }
679             FileObject cpRoot = getCPRoot((JavaModelPackage) res.refImmediatePackage());
680             if (cpRoot != null) {
681                 FileObject result = cpRoot.getFileObject(res.getName());
682                 return result;
683             }
684             return null;
685         } catch (InvalidObjectException e) {
686             return null;
687         } finally {
688             repository.endTrans();
689         }
690     }
691
692     public synchronized FileObject getCPRoot(JavaModelPackage javaModelPackage) {
693         return (FileObject) filesystems.get(javaModelPackage);
694     }
695
696     public DataObject getDataObject(Resource res) {
697         FileObject fo = getFileObject(res);
698         DataObject result = null;
699         if (fo != null) {
700             if (fo.isVirtual()) {
701                 return null;
702             }
703             try {
704                 result = DataObject.find(fo);
705             } catch (DataObjectNotFoundException e) {
706                 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
707                 result = null;
708             }
709         }
710         if (result != null && !result.isValid()) result = null;
711         return result;
712     }
713
714     public boolean waitScanFinished() {
715         if (NO_SCAN) return false;
716         boolean wait=false;
717         while (cpImpl.getUnresolvedRoots().length > 0) {
718             wait=true;
719             try {
720                 boolean isStartupInProgress = JavaCoreModule.isStartupInProgress();
721                 ProgressDisplayer disp = ProgressDisplayer.getVisibleProgressDisplayer();
722                 if (SCAN_DEBUG) {
723                     System.err.println("JMManager.waitScanFinished(), isStartupInProgress = " + isStartupInProgress);
724                     System.err.println("JMManager.waitScanFinished(), getVisibleProgressDisplayer() = " + disp);
725                 }
726                 if (!isStartupInProgress && (disp == null)) {
727                     SCANNING_RP.post(new Runnable JavaDoc() {
728                         public void run() {
729                             refreshCodebases();
730                         }
731                     }, 0, THREAD_PRIORITY);
732                 }
733                 Thread.sleep(100);
734             } catch (InterruptedException JavaDoc e) {
735             }
736         }
737         return wait;
738     }
739     
740     public boolean isScanInProgress() {
741         return ProgressDisplayer.getVisibleProgressDisplayer()!=null;
742     }
743     
744     // ..........................................................................
745

746     public boolean isElementGuarded(Element element) {
747         PositionBounds pos = getElementPosition(element);
748         if (pos == null) {
749             return false;
750         }
751         RefBaseObject refObj = element;
752         while ((refObj instanceof Element) && !(refObj instanceof Resource)) {
753             refObj = ((Element)refObj).refImmediateComposite();
754         }
755         if (!(refObj instanceof Resource)) {
756             return false;
757         }
758         ResourceImpl resource = (ResourceImpl)refObj;
759         return GuardedQuery.isSectionGuarded(resource, pos);
760     }
761     
762     // ..........................................................................
763

764     public PositionBounds getElementPosition(Element element) {
765         return getElementPosition(element, false);
766     }
767     
768     /**
769      * @param inclDoc if false, then start offset of first token of startTree
770      * is beginning, otherwise it starts from its javadoc
771      * comment.
772      */

773     public PositionBounds getElementPosition(Element element, boolean inclDoc) {
774         if (element instanceof ParameterizedType)
775             element=((ParameterizedType)element).getDefinition();
776         else if (element instanceof ParameterizedTypeImpl.Wrapper)
777             element=(Element)((ParameterizedTypeImpl.Wrapper)element).getWrappedObject();
778         if (element instanceof MetadataElement) {
779             return ((MetadataElement) element).getPosition(inclDoc);
780         } else {
781             return null;
782         }
783     }
784
785     public PositionBounds getElementPartPosition(Element element, ElementPartKind part, int position) {
786         if (element instanceof ParameterizedType)
787             element=((ParameterizedType)element).getDefinition();
788         else if (element instanceof ParameterizedTypeImpl.Wrapper)
789             element=(Element)((ParameterizedTypeImpl.Wrapper)element).getWrappedObject();
790         if (element instanceof MetadataElement) {
791             return ((MetadataElement) element).getPartPosition(part, position);
792         } else {
793             return null;
794         }
795     }
796
797     public Element getElementByOffset(FileObject file,int offset) {
798         repository.beginTrans(false);
799         try {
800             Resource cr = getResource(file);
801             if (cr == null) {
802                 return null;
803             }
804             return cr.getElementByOffset(offset);
805         } finally {
806             repository.endTrans();
807         }
808     }
809
810     // ---- helper methods --------------------------------------------------------------------
811
// THESE METHODS SHOULD NOT BE CALLED FROM OTHER MODULES
812

813     private static String JavaDoc getCBExtentName(String JavaDoc uri) {
814         return PREFIX_EXTENT_CODEBASE + uri;
815     }
816     
817     void startResolution() {
818         if (SCAN_DEBUG) System.err.println("JMManager: startResolution1");
819         RESOLVE_POSTER.post(new Runnable JavaDoc () {
820             public void run() {
821                 if (SCAN_DEBUG) System.err.println("JMManager: startResolution2 - runnable");
822                 try {
823                     resolveCodebases();
824                 } catch (Throwable JavaDoc e) {
825                     ErrorManager.getDefault().notify(e);
826                 }
827                 if (SCAN_DEBUG) System.err.println("JMManager: startResolution3 - runnable");
828             }
829         });
830         if (SCAN_DEBUG) System.err.println("JMManager: startResolution4");
831     }
832     
833     /** Resolves all extents referenced from project's classpath.
834      * This method has to be called within a writable transaction.
835      */

836     protected void resolveCodebases() {
837         boolean fail = true;
838         //fix of #49020
839
try {
840             repository.beginTrans(true);
841             repository.endTrans();
842         } catch (Throwable JavaDoc t) {
843             ErrorManager.getDefault().notify(t);
844         }
845         //end of fix
846
repository.beginTrans(true);
847         try {
848             ArrayList JavaDoc resources = new ArrayList JavaDoc(Arrays.asList((Object JavaDoc[]) cpImpl.getUnresolvedRoots()));
849 // resources.addAll(cpImpl.getResources()); Ufff, why to resolve something what is already resolved?
850
this.getProgressSupport().fireProgressListenerStart(0,resources.size());
851             for (Iterator JavaDoc it = resources.iterator(); it.hasNext() && !cancelScan;) {
852                 try {
853                     this.getProgressSupport().fireProgressListenerStep();
854                 } catch (Throwable JavaDoc t) {
855                     JMManager.getLog().notify(t);
856                 }
857                 PathResourceImplementation resource = (PathResourceImplementation) it.next();
858                 URL JavaDoc url = resource.getRoots()[0];
859                 FileObject root = URLMapper.findFileObject(url);
860                 if (root != null) {
861                     URL JavaDoc rootURL;
862                     try {
863                         rootURL = root.getURL();
864                     } catch (FileStateInvalidException e) {
865                         JMManager.getLog().notify(e);
866                         rootURL = null;
867                     }
868                     if (!url.equals(rootURL)) {
869                         JMManager.getLog().notify(new RuntimeException JavaDoc("ClassPath returned the invalid (non-normalized) URL from getRoots(): " + url + ". This classpath element will not be scanned.")); // NOI18N
870
cpImpl.removeRoot(resource);
871                         continue;
872                     }
873                     resolveCPRoot(root, true);
874                 } else {
875                     //Todo: Root does not exist physically, needs more handling
876
//Todo: some listenig is needed otherwise will cause invalid nonparseble objects, FileScanner(URL) ???
877
cpImpl.removeRoot(resource);
878                 }
879             }
880             fail = false;
881         } catch (RuntimeException JavaDoc e) {
882             ErrorManager.getDefault().notify(e);
883         } catch (AssertionError JavaDoc e) {
884             ErrorManager.getDefault().notify(e);
885         } finally {
886             repository.endTrans(fail);
887             this.getProgressSupport().fireProgressListenerStop();
888         }
889     }
890     
891     private void cleanUpCodebases () {
892         List JavaDoc/*<PathResourceImplementation>*/ rootsToReresolve = new ArrayList JavaDoc ();
893         getDefaultRepository().beginTrans(true);
894         boolean fail = true;
895         try {
896             synchronized (this) {
897                 Set JavaDoc backup = new HashSet JavaDoc(sids.keySet());
898                 Set JavaDoc existingUnresolved = new HashSet JavaDoc();
899                 FileObject[] roots = this.classPath.getRoots();
900                 for (int i = 0; i < roots.length; i++) {
901                     try {
902                         String JavaDoc uriBase = roots[i].getURL().toString();
903                         if (!removeURI(backup, uriBase)) {
904                             existingUnresolved.add(uriBase);
905                         }
906                     } catch (FileStateInvalidException e) {
907                         JMManager.getLog().notify(ErrorManager.INFORMATIONAL, e);
908                     }
909                 }
910                 PathResourceImplementation unresolved[] = this.cpImpl.getUnresolvedRoots();
911                 for (int i = 0; i < unresolved.length; i++) {
912                     PathResourceImplementation resource = unresolved[i];
913                     URL JavaDoc url = resource.getRoots()[0];
914                     FileObject root = URLMapper.findFileObject(url);
915                     if (root != null) {
916                         try {
917                             String JavaDoc uriBase = root.getURL().toString();
918                             if (!removeURI(backup, uriBase)) {
919                                 existingUnresolved.add(url.toString());
920                             }
921                         } catch (FileStateInvalidException e) {
922                             JMManager.getLog().notify(ErrorManager.INFORMATIONAL, e);
923                         }
924                     }
925                 }
926
927                 for (Iterator JavaDoc it = backup.iterator(); it.hasNext();) {
928                     String JavaDoc uri = (String JavaDoc) it.next ();
929                     disposeCodebase(uri);
930                     //The change of platform (boot classpath) may
931
//affect the source and build folders of project
932
int index = uri.lastIndexOf('/'); //NOI18N
933
if (index < uri.length()-1) {
934                         String JavaDoc url = uri.substring(0,index+1);
935                         if (existingUnresolved.remove(url)) {
936                             try {
937                                 rootsToReresolve.add (ClassPathSupport.createResource(new URL JavaDoc (url)));
938                             } catch (MalformedURLException JavaDoc mfe) {
939                                 ErrorManager.getDefault().notify(mfe);
940                             }
941                         }
942                     }
943                 }
944             }
945             fail = false;
946         } finally {
947             getDefaultRepository().endTrans(fail);
948         }
949         if (rootsToReresolve.size() > 0) {
950             cpImpl.addUnresolvedRoots (rootsToReresolve);
951         }
952     }
953     private boolean removeURI(Set JavaDoc/*<String>*/ uris, String JavaDoc uriBase) {
954         // #72006: cleanUpCodebases should not call getRootURI since it calls SourceLevelQuery
955
// and that can trigger reloading the project we are supposed to be collecting!
956
boolean removed = false; // try to remove >1 if possible, since we don't know which is right
957
if (uris.remove(uriBase)) {
958             removed = true;
959         }
960         if (uris.remove(uriBase + "1.4")) { // NOI18N
961
removed = true;
962         }
963         if (uris.remove(uriBase + "1.5")) { // NOI18N
964
removed = true;
965         }
966         if (removed) {
967             return true;
968         }
969         // Didn't find it that way; maybe 1.3 or 1.6 or something else?
970
String JavaDoc prefix = uriBase + "1."; // NOI18N
971
Iterator JavaDoc it = uris.iterator();
972         while (it.hasNext()) {
973             String JavaDoc uri = (String JavaDoc) it.next();
974             if (uri.startsWith(prefix)) {
975                 // Guess that it is a source level.
976
it.remove();
977                 return true;
978             }
979         }
980         return false;
981     }
982
983     private void resolveCPRoot(FileObject root, boolean scanIfNeeded) {
984         if (root == null) return;
985         boolean fail = true;
986         if (!scanIfNeeded) getDefaultRepository().beginTrans(true);
987         try {
988             JavaModelPackage extent;
989             int state = 0;
990             synchronized (this) {
991                 String JavaDoc uri = getRootURI(root);
992                 String JavaDoc extentName = getCBExtentName(uri);
993                 extent = (JavaModelPackage) repository.getExtent(extentName);
994                 if (extent == null) {
995                     state++;
996                     init();
997                     int retry = 0;
998                     String JavaDoc sid = null;
999                     String JavaDoc storageName = getValidName(uri);
1000                    String JavaDoc storageFileName = getFileName(storageName);
1001                    String JavaDoc simpleName = getCodebaseSimpleName(root);
1002                    while (extent == null && retry < 2) {
1003                        try {
1004                            boolean preparsedUsed = false;
1005                            if (retry == 0) {
1006                                if (simpleName != null) {
1007                                    preparsedUsed = usePreparsed(simpleName, root, getFileName(storageName));
1008                                    if (preparsedUsed) {
1009                                        System.err.println("Using '" + uri + "' pre-parsed database!");
1010                                    }
1011                                }
1012                                sid = mountStorage(storageName, storageFileName);
1013                            } else {
1014                                sid = rebootStorage(storageName, storageFileName, sid);
1015                            }
1016                            sids.put(uri, sid);
1017                            if (!preparsedUsed) {
1018                                extent = (JavaModelPackage) repository.getExtent(extentName);
1019                            }
1020                            if (extent == null && simpleName != null) {
1021                                extent = (JavaModelPackage) repository.getExtent(getCBExtentName(simpleName)); // NOI18N
1022
if (extent != null) {
1023                                    preparsedUsed = true;
1024                                }
1025                            }
1026                            NBMDRepositoryImpl nbRep = (NBMDRepositoryImpl) repository;
1027                            if (extent == null) {
1028                                state += 2;
1029                                extent = (JavaModelPackage) nbRep.createExtent(extentName, findRootPackage(PACKAGE_CODEBASE), null, sid);
1030                                ClassIndex.addIndex(extent, storageFileName);
1031                            } else {
1032                                // check consistency of the extent
1033
Collection JavaDoc/*<Codebase>*/ c = extent.getCodebase().refAllOfClass();
1034                                
1035                                if (preparsedUsed) {
1036                                    // we used preparsed database, copied from
1037
// install location to user dir. We have to
1038
// set codebase name correctly as different
1039
// users have their jdk installed in different
1040
// locations.
1041
if (c.size() != 1) {
1042                                        // storage is corrupted -> throw exception to make sure the storage is recreated
1043
throw new RuntimeException JavaDoc("Not exactly one codebase in extent!"); // NOI18N
1044
}
1045                                    Codebase cb = (Codebase) c.iterator().next();
1046                                    cb.setName(uri);
1047                                    cb.setTimestamp(FileUtil.getArchiveFile(root).lastModified().getTime());
1048                                    nbRep.renameExtent(extent, extentName);
1049                                } else {
1050                                    // the following call may through an exception in case the storage is inconsistent
1051
// in that case the storage will be automatically rebooted (#67158)
1052
c.isEmpty();
1053                                }
1054                                // walk through all the packages in the extent and add them to the proxy packages
1055
((JavaPackageClassImpl) extent.getJavaPackage()).addAllRealPackages();
1056                                if (!ClassIndex.loadIndex(storageFileName, extent)) {
1057                                    state++;
1058                                }
1059                                if (preparsedUsed) {
1060                                    ClassIndex.getIndex(extent).setTimestamp();
1061                                }
1062                            }
1063                        } catch (Exception JavaDoc e) {
1064                            sids.remove(uri);
1065                            retry++;
1066                            if (retry >= 2) {
1067                                JMManager.getLog().notify(e);
1068                            } else {
1069                                JMManager.getLog().log(ErrorManager.WARNING, "Rebooting storage for " + root.getURL() + " because of a fatal error during storage mount."); // NOI18N
1070
JMManager.getLog().notify(ErrorManager.INFORMATIONAL, e);
1071                            }
1072                        }
1073                    }
1074                    extents.put(root, extent);
1075                    filesystems.put(extent, root);
1076                } else {
1077                    CodebaseClass cbClass = extent.getCodebase();
1078                    if (cbClass.refAllOfClass().isEmpty()) {
1079                        state++;
1080                    } else {
1081                        Codebase cb = (Codebase) cbClass.refAllOfClass().iterator().next();
1082                        long timeStamp = cb.getTimestamp();
1083                        long fileTimeStamp;
1084                        FileObject f = FileUtil.getArchiveFile(root);
1085                        if (f != null) {
1086                            fileTimeStamp = f.lastModified().getTime();
1087                        } else {
1088                            fileTimeStamp = root.lastModified().getTime();
1089                        }
1090                        if (timeStamp != 0 && fileTimeStamp != timeStamp) {
1091                            state++;
1092                        }
1093                    }
1094                }
1095            }
1096            if (scanIfNeeded) {
1097                Resource[] resourcesToParse;
1098                if (state != 0 || extentsToScan.remove(extent)) { // new or mounted codebase
1099
resourcesToParse = scanFiles(root, extent, state > 1);
1100    // ClassIndex.saveIndex(extent);
1101
} else {
1102                    resourcesToParse = new Resource[0];
1103                }
1104                // resolve the root only if the classpath scan did not fail (i.e. returned a non-null result)
1105
if (resourcesToParse != null) {
1106                    this.cpImpl.classPathRootResolved(root.getURL());
1107                    if (resourcesToParse.length > 0) {
1108                        for (int i = 0; i < resourcesToParse.length; i++) {
1109                            setClassPath(resourcesToParse[i]);
1110                            traverseResource(resourcesToParse[i]);
1111                            setClassPath(resourcesToParse[i], true);
1112                            traverseResource(resourcesToParse[i]);
1113                        }
1114                    }
1115                }
1116            } else {
1117                extentsToScan.add(extent);
1118            }
1119            fail = false;
1120        } catch (FileStateInvalidException e) {
1121            ErrorManager.getDefault().notify(e);
1122        } finally {
1123            if (!scanIfNeeded) getDefaultRepository().endTrans(fail);
1124        }
1125    }
1126    
1127    private void traverseResource(Resource resource) {
1128        for (Iterator JavaDoc it = resource.getClassifiers().iterator(); it.hasNext();) {
1129            traverseClass((JavaClass) it.next());
1130        }
1131    }
1132    
1133    private void traverseGenericElement(GenericElement element) {
1134        for (Iterator JavaDoc it = element.getTypeParameters().iterator(); it.hasNext();) {
1135            ((TypeParameter) it.next()).getSuperClass();
1136        }
1137    }
1138    
1139    private void traverseCallableFeature(CallableFeature element) {
1140        for (Iterator JavaDoc it = element.getParameters().iterator(); it.hasNext();) {
1141            ((Parameter) it.next()).getType();
1142        }
1143    }
1144    
1145    private void traverseClass(JavaClass cls) {
1146        traverseGenericElement(cls);
1147        JavaClass superClass = cls.getSuperClass();
1148        if (superClass != null) traverseClass(superClass);
1149        for (Iterator JavaDoc it = cls.getInterfaces().iterator(); it.hasNext();) {
1150            traverseClass((JavaClass) it.next());
1151        }
1152        Object JavaDoc[] features=cls.getContents().toArray();
1153        for (int i=0;i<features.length;i++) {
1154            Object JavaDoc temp = features[i];
1155            if (temp instanceof JavaClass) {
1156                traverseClass((JavaClass) temp);
1157            } else if (temp instanceof GenericElement) {
1158                traverseGenericElement((GenericElement) temp);
1159                if (temp instanceof CallableFeature) {
1160                    traverseCallableFeature((CallableFeature) temp);
1161                }
1162            } else if (temp instanceof TypedElement) {
1163                ((TypedElement) temp).getType();
1164            }
1165        }
1166    }
1167    
1168    // always called from within a transaction - no need for explicit transactions
1169
Resource[] scanFiles(FileObject root, JavaModelPackage extent, boolean isInitial) {
1170        CodebaseClass cbClass = extent.getCodebase();
1171        if (cbClass.refAllOfClass().isEmpty()) {
1172            cbClass.createCodebase(getRootURI(root), 0, false, null);
1173        }
1174        Codebase cb = (Codebase) cbClass.refAllOfClass().iterator().next();
1175        try {
1176            URL JavaDoc url = root.getURL();
1177            String JavaDoc uri = null;
1178            long startT = 0, endT;
1179            if (PERF_DEBUG || PERF_TEST) {
1180                startT = 0;
1181                startT = System.currentTimeMillis();
1182                uri = url.toString();
1183            }
1184            String JavaDoc sourceLevel = SourceLevelQuery.getSourceLevel(root);
1185            Resource[] resources = new FileScanner(url,sourceLevel,cb).scan();
1186            if (PERF_DEBUG || PERF_TEST) {
1187                endT = System.currentTimeMillis();
1188                System.out.println("PERF: '" + uri + "' scanning takes " + (endT - startT) + " ms."); // NOI18N
1189

1190                if (PERF_TEST) {
1191                    try {
1192                        Class JavaDoc c = Class.forName("org.netbeans.performance.test.utilities.LoggingScanClasspath",true,Thread.currentThread().getContextClassLoader()); // NOI18N
1193
java.lang.reflect.Method JavaDoc m = c.getMethod("reportScanOfFile", new Class JavaDoc[] {String JavaDoc.class, Long JavaDoc.class}); // NOI18N
1194
Object JavaDoc o = m.invoke(c.newInstance(), new Object JavaDoc[] {new String JavaDoc(uri), new Long JavaDoc(endT - startT)});
1195                    } catch (Exception JavaDoc e) {
1196                        e.printStackTrace(System.err);
1197                    }
1198                }
1199            }
1200            return resources;
1201        } catch (Exception JavaDoc ex) {
1202            ErrorManager.getDefault().notify(ex);
1203        }
1204        return null;
1205    }
1206
1207    private String JavaDoc getSourceLevel(FileObject root) {
1208        String JavaDoc result = SourceLevelQuery.getSourceLevel(root);
1209        return result == null ? "" : result;
1210    }
1211    
1212    public String JavaDoc getRootURI(FileObject root) {
1213        try {
1214            return root.getURL().toString() + getSourceLevel(root);
1215        } catch (FileStateInvalidException e) {
1216            throw (RuntimeException JavaDoc) ErrorManager.getDefault().annotate(new RuntimeException JavaDoc(), e);
1217        }
1218    }
1219
1220    /** Unmounts codebase - always called from within a transaction - no need for explicit transaction */
1221    private synchronized void disposeCodebase(String JavaDoc uri) {
1222        JavaModelPackage extent = (JavaModelPackage) repository.getExtent(getCBExtentName(uri));
1223        if (extent != null) {
1224            ((JavaPackageClassImpl) extent.getJavaPackage()).removeAllRealPackages();
1225            FileObject root = (FileObject) filesystems.remove(extent);
1226            ((NBMDRepositoryImpl) repository).unmountStorage((String JavaDoc) sids.remove(uri));
1227            JavaModelPackage oldExtent = (JavaModelPackage) extents.remove(root);
1228            if (!extent.equals(oldExtent)) {
1229                extents.put(root, oldExtent);
1230            }
1231            ClassIndex.removeIndex(extent);
1232        }
1233// System.out.println("unmounted: " + uri);
1234
}
1235    
1236    private static String JavaDoc computeHash(String JavaDoc val) {
1237        int len = val.length();
1238        byte[] data=new byte[len*2];
1239        int offset=0;
1240        for (int i = 0; i < len; i++) {
1241            char ch = val.charAt(i);
1242            data[offset++]=(byte)(ch>>8);
1243            data[offset++]=(byte)ch;
1244        }
1245        byte[] hashCode = digest.digest(data);
1246        int len2 = hashCode.length;
1247        StringBuffer JavaDoc sb = new StringBuffer JavaDoc(len2 * 3);
1248        for (int i = 0; i < len2; i++) {
1249            String JavaDoc number = Integer.toHexString((int) hashCode[i] - Byte.MIN_VALUE);
1250            if (number.length() == 1) {
1251                sb.append('0');
1252            }
1253            sb.append(number);
1254        }
1255        return sb.toString();
1256    }
1257
1258     public void resetExtents() {
1259        cleanUpCodebases();
1260        init();
1261        
1262        getDefaultRepository().beginTrans(true);
1263        boolean fail = true;
1264        try {
1265            synchronized (this) {
1266                Set JavaDoc sidSet = new HashSet JavaDoc(sids.keySet());
1267                for (Iterator JavaDoc it = sidSet.iterator(); it.hasNext();) {
1268                    String JavaDoc uri = (String JavaDoc) it.next();
1269                    disposeCodebase(uri);
1270                }
1271                Iterator JavaDoc itr = cpImpl.getRoots().iterator();
1272                while (itr.hasNext()) {
1273                    Object JavaDoc obj = itr.next();
1274                    FileObject resource = (FileObject)obj;
1275                    try {
1276                        cpImpl.updateRoot(resource.getURL());
1277                    } catch (FileStateInvalidException e) {
1278                        
1279                    }
1280                }
1281                resolveCodebases();
1282                fail = false;
1283            }
1284        } finally {
1285            getDefaultRepository().endTrans(fail);
1286            Logger.getLogger("global").log(Level.INFO, "rescanning " + fail);
1287            if (!fail)
1288                startRescan();
1289        }
1290    }
1291     
1292    /** Returns a valid name for a storage file */
1293    public static String JavaDoc getValidName(String JavaDoc uri) {
1294        String JavaDoc hashCode = computeHash(uri);
1295        StringBuffer JavaDoc result = new StringBuffer JavaDoc(uri.length());
1296        for (int i = 0; i < uri.length(); i++) {
1297            char z = uri.charAt(i);
1298            if ((z >= 'A' && z <= 'Z') || (z >= 'a' && z <= 'z') || (z >= '0' && z <= '9')) {
1299                result.append(z);
1300            }
1301        }
1302        int len = result.length();
1303        return 'f' + hashCode + (len > 18 ? result.substring(len - 18) : result.toString());
1304    }
1305
1306
1307    private synchronized boolean shouldOpenProgress() {
1308        return ProgressDisplayer.getVisibleProgressDisplayer()==null;
1309    }
1310
1311    public void propertyChange(PropertyChangeEvent JavaDoc evt) {
1312        String JavaDoc propName = evt.getPropertyName();
1313        if (MergedClassPathImplementation.PROP_UNRESOLVED_ROOTS.equals(propName)) {
1314            if (JavaCoreModule.isStartupInProgress()) {
1315                return;
1316            }
1317            if (SCAN_DEBUG) System.err.println("JMManager: globalpath changed");
1318            // refreshCodebases has to be called in a different thread
1319
// to prevent deadlocks (since refreshCodebases calls isProgressOpened which is synchronized)
1320
SCANNING_RP.post(new Runnable JavaDoc() {
1321                public void run() {
1322                    refreshCodebases();
1323                }
1324            }, 0, THREAD_PRIORITY);
1325        }
1326        else if (ClassPath.PROP_ROOTS.equals(propName)) {
1327            if (JavaCoreModule.isStartupInProgress()) {
1328                return;
1329            }
1330            if (SCAN_DEBUG) System.err.println("JMManager: posting cleanup");
1331            CLEANUP_POSTER.post(new Runnable JavaDoc() {
1332                public void run() {
1333                    try {
1334                        if (SCAN_DEBUG) System.err.println("JMManager: cleanup running");
1335                        cleanUpCodebases();
1336                    } catch (Throwable JavaDoc e) {
1337                        ErrorManager.getDefault().notify(e);
1338                    }
1339                }
1340            });
1341        }
1342    }
1343    
1344    private void refreshCodebases() {
1345        if (NO_SCAN) return;
1346        if (shouldOpenProgress()) {
1347            if (SCAN_DEBUG) System.err.println("JMManager: refreshCodebases1");
1348            if (cpImpl.getUnresolvedRoots().length > 0) {
1349                    ProgressDisplayer.showProgress(JMManager.this);
1350            }
1351        }
1352        if (SCAN_DEBUG) System.err.println("JMManager: refreshCodebases2");
1353    }
1354    
1355    /**
1356     * Computes the resource name of file within the classpath root
1357     * @param cpRoot the classpath root
1358     * @param file resource
1359     * @return String, never returns null
1360     */

1361    public static String JavaDoc getResourceName (FileObject cpRoot, FileObject file) {
1362        assert cpRoot != null && file!= null;
1363        return FileUtil.getRelativePath(cpRoot, file);
1364    }
1365
1366
1367    /**
1368     * Computes the resource name of file within the global merged classpath
1369     * @param fo resource
1370     * @return String, the resource name, or null when the fo is not valid resource on merged class path.
1371     */

1372    public String JavaDoc getResourceName (FileObject fo) {
1373        repository.beginTrans(false);
1374        try {
1375            FileObject cpRoot = this.cpImpl.findOwnerRoot (fo);
1376            if (cpRoot == null) {
1377                ClassPath cp = ClassPath.getClassPath(fo, ClassPath.SOURCE);
1378                if (cp!=null) {
1379                    cpRoot = cp.findOwnerRoot(fo);
1380                }
1381            }
1382            String JavaDoc result = null;
1383            if (cpRoot != null) {
1384                result = getResourceName(cpRoot,fo);
1385            }
1386            return cpRoot == null ? null : getResourceName(cpRoot, fo);
1387        } catch (Exception JavaDoc ex) {
1388            ErrorManager.getDefault().notify(ex);
1389        } finally {
1390            repository.endTrans();
1391        }
1392        return null;
1393    }
1394
1395    void removeListener() {
1396        classPath.removePropertyChangeListener(this);
1397    }
1398    
1399    public ProgressSupport getProgressSupport() {
1400        if (progressSupport == null) {
1401            progressSupport = new ProgressSupport();
1402        }
1403        return progressSupport;
1404    }
1405
1406    public void addModified(FileObject fo) {
1407        getTransactionMutex().addModified(fo);
1408    }
1409    
1410    public boolean isModified(FileObject fo) {
1411        return getTransactionMutex().isModified(fo);
1412    }
1413
1414    public static void fireResourceParsed(final MOFID mofId) {
1415        /** processor dedicated for parser events. */
1416        EVENT_RP.post(new Runnable JavaDoc() {
1417            public void run() {
1418                ArrayList JavaDoc listenersCopy;
1419                synchronized (listeners) {
1420                    if (listeners.isEmpty()) return;
1421                    listenersCopy = (ArrayList JavaDoc) listeners.clone();
1422                }
1423                Resource rsc = (Resource) ((NBMDRepositoryImpl) JavaMetamodel.getDefaultRepository()).getByMofId(mofId);
1424                if (rsc == null) return;
1425                for (Iterator JavaDoc it = listenersCopy.iterator(); it.hasNext();) {
1426                    ParsingListener listener = (ParsingListener) it.next();
1427                    listener.resourceParsed(rsc);
1428                }
1429            }
1430        });
1431    }
1432    
1433    public void startupFinished() {
1434        if (cpImpl.getUnresolvedRoots().length > 0) {
1435            SCANNING_RP.post(new Runnable JavaDoc() {
1436                public void run() {
1437                    refreshCodebases();
1438                }
1439            });
1440        } else {
1441            RequestProcessor.getDefault().post(new Runnable JavaDoc() {
1442                public void run() {
1443                    init();
1444                }
1445            }, 1500);
1446        }
1447    }
1448
1449    public ClassDefinition getSourceElementIfExists(ClassDefinition cls) {
1450        if (cls == null) return null;
1451        
1452        repository.beginTrans(false);
1453        try {
1454            Resource rsc=cls.getResource();
1455
1456            if (rsc!=null) {
1457                if (rsc.getName().endsWith(".java")) {
1458                    return cls;
1459                }
1460            } else {
1461                return cls;
1462            }
1463            try {
1464                ClassDefinition realJcls=cls instanceof ParameterizedType ? ((ParameterizedType)cls).getDefinition(): cls;
1465
1466                if (!(realJcls instanceof UnresolvedClass) && !(realJcls instanceof Array)) {
1467                    FileObject fo = getCPRoot((JavaModelPackage)realJcls.refImmediatePackage());
1468                    FileObject[] fos = SourceForBinaryQuery.findSourceRoots(fo.getURL()).getRoots();
1469                    String JavaDoc name=realJcls.getName();
1470
1471                    for (int i = 0; i < fos.length; i++) {
1472                        FileObject fileObject = fos[i];
1473                        JavaModelPackage javaExtent = getJavaExtent(fileObject);
1474                        ClassIndex ci = ClassIndex.getIndex(javaExtent);
1475
1476                        if (ci != null) {
1477                            JavaClass jc = ci.getClassByFqn(name);
1478
1479                            if (jc != null && cls instanceof ParameterizedType) {
1480                                ParameterizedType parType = (ParameterizedType)cls;
1481                                ClassDefinition outerCls = parType.getDeclaringClass();
1482                                List JavaDoc pars = parType.getParameters();
1483
1484                                jc = javaExtent.getParameterizedType().resolveParameterizedType(jc, pars, outerCls instanceof ParameterizedType ? (ParameterizedType)outerCls : null);
1485                                if (parType instanceof ParameterizedTypeImpl) {
1486                                    ParameterizedTypeImpl parTypeImpl = (ParameterizedTypeImpl)parType;
1487                                    ParameterizedTypeImpl newTypeImpl = (ParameterizedTypeImpl)jc;
1488                                    int size = pars.size();
1489                                    
1490                                    for (int j=0;j<size;j++) {
1491                                        newTypeImpl.setWildCardStatus(j,parTypeImpl.getWildCardStatus(j));
1492                                    }
1493                                }
1494                            }
1495                            if (jc != null) {
1496                                return jc;
1497                            }
1498                        }
1499                    }
1500                }
1501            } catch (Exception JavaDoc e) {
1502                ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
1503            }
1504            return cls;
1505        } finally {
1506            repository.endTrans();
1507        }
1508    }
1509    
1510    /**
1511     * Initializes indentation. Currently, it reads editor options and sets
1512     * our formatting engine to respect settings. Used for indentation,
1513     * bracket and parenthesis formatting.
1514     */

1515    public static void initIndentation() {
1516        if (MetadataElement.getIndentSpace() != -1) {
1517            return;
1518        }
1519        IndentationSettingsProvider settingsProvider = getIndentationSettingsProvider();
1520        if (settingsProvider == null) {
1521            setIndentSpace(4, true);
1522            formatCurlies(false);
1523            formatParenthesis(false);
1524            return;
1525        }
1526        Boolean JavaDoc tabs = (Boolean JavaDoc) settingsProvider.getPropertyValue("expandTabs"); // NO18N
1527
Integer JavaDoc spaces = (Integer JavaDoc) settingsProvider.getPropertyValue("spacesPerTab"); // NO18N
1528
if (spaces == null || tabs == null) {
1529            setIndentSpace(4, true);
1530        } else {
1531            setIndentSpace(spaces.intValue(), tabs.booleanValue());
1532        }
1533        Boolean JavaDoc newlineBrace = (Boolean JavaDoc) settingsProvider.getPropertyValue("javaFormatNewlineBeforeBrace"); // NO18N
1534
if (newlineBrace == null) {
1535            formatCurlies(false);
1536        } else {
1537            formatCurlies(newlineBrace.booleanValue());
1538        }
1539        Boolean JavaDoc parenthesisSpace = (Boolean JavaDoc) settingsProvider.getPropertyValue("javaFormatSpaceBeforeParenthesis"); // NO18N
1540
if (parenthesisSpace == null) {
1541            formatParenthesis(false);
1542        } else {
1543            formatParenthesis(parenthesisSpace.booleanValue());
1544        }
1545    }
1546    
1547    /**
1548     * Sets the correct formatting for all brackets. If the parameter is true,
1549     * it sets newline before brace. Otherwise brace is on the same line
1550     * separated only by the space.
1551     *
1552     * @param breakBefore use true if you want to have bracket on the new line
1553     */

1554    private static void formatCurlies(boolean breakBefore) {
1555        int[] curlies = {
1556            MetadataElement.CLASS_OPEN_CURLY,
1557            MetadataElement.BODY_OPEN_CURLY,
1558            MetadataElement.ARRAY_OPEN_CURLY,
1559            MetadataElement.BLOCK_OPEN_CURLY
1560        };
1561        String JavaDoc before = breakBefore ? "ni" : "s"; // NOI18N
1562
for (int i = 0; i < curlies.length; i++) {
1563            MetadataElement.setFormattingFor(curlies[i], before, MetadataElement.getFormattingFor(curlies[i])[2]);
1564        }
1565    }
1566
1567    /**
1568     * Sets the correct formatting for the parenthesis. When parameter is true,
1569     * space is added before every opening parenthesis generated by our
1570     * code-generator. Otherwise, parenthesis is immediately after identifier.
1571     *
1572     * @param parenthesisSpace true if you want space before opening parethesis
1573     */

1574    private static void formatParenthesis(boolean parenthesisSpace) {
1575        int[] parenthesis = {
1576            MetadataElement.PAR_OPEN_BRACKET,
1577        };
1578        String JavaDoc before = parenthesisSpace ? "s" : ""; // NOI18N
1579
for (int i = 0; i < parenthesis.length; i++) {
1580            MetadataElement.setFormattingFor(parenthesis[i], before, MetadataElement.getFormattingFor(parenthesis[i])[2]);
1581        }
1582    }
1583    
1584    /**
1585     * Sets the default indentation of the element.
1586     *
1587     * @param spaces number of spaces used for indentation
1588     * @param expandTabs if this parameter is true, tab character is used
1589     * instead of spaces
1590     */

1591    public static void setIndentSpace(int spaces, boolean expandTabs) {
1592        MetadataElement.setIndentSpace(spaces, expandTabs);
1593    }
1594    
1595    /**
1596     * Copies the file from in location to out location.
1597     *
1598     * @param in path to file with filename without extension, which
1599     * will be copied (read)
1600     * @param out path to new location of the file with filename
1601     * without extension which will be written
1602     * @param force if false, it checks 'out' file for existence. If exists,
1603     * method does nothing
1604     *
1605     * @return true if it was copied successfuly, false if error or force
1606     * flag does not allow to copy it (it exists already)
1607     */

1608    public static boolean copyStorage(String JavaDoc in, String JavaDoc out, boolean force) {
1609        long startTime = 0;
1610        if (PERF_DEBUG) startTime = System.currentTimeMillis();
1611
1612        String JavaDoc[] ext = new String JavaDoc[] { "btd", "btx", "cdx" }; // NOI18N
1613

1614        // fix for #58064
1615
for (int i = 0; i < ext.length; i++) {
1616            File JavaDoc f = new File JavaDoc(in + '.' + ext[i]);
1617            if (!f.exists()) {
1618                // one of the source files is missing -> cannot copy
1619
return false;
1620            }
1621        }
1622        
1623        if (!force) {
1624            boolean doCopy = false;
1625            for (int i = 0; i < ext.length; i++) {
1626                File JavaDoc f = new File JavaDoc(out + '.' + ext[i]);
1627                if (!f.exists()) {
1628                    doCopy = true;
1629                    break;
1630                }
1631            }
1632            if (!doCopy) return false;
1633        }
1634        for (int i = 0; i < ext.length; i++) {
1635            FileInputStream JavaDoc fis = null;
1636            FileOutputStream JavaDoc fos = null;
1637            try {
1638                fis = new FileInputStream JavaDoc(new File JavaDoc(in + '.' + ext[i]));
1639                fos = new FileOutputStream JavaDoc(new File JavaDoc(out + '.' + ext[i]));
1640                byte[] buf = new byte[65535];
1641                int j = 0;
1642                while ((j = fis.read(buf)) != -1) {
1643                    fos.write(buf, 0, j);
1644                }
1645            } catch (Exception JavaDoc e) {
1646                System.out.println("copyStorage failed: " + e.getMessage()); // NOI18N
1647
e.printStackTrace();
1648                return false;
1649            } finally {
1650                try {
1651                    if (fis != null)
1652                        fis.close();
1653                    if (fos != null)
1654                        fos.close();
1655                } catch (IOException JavaDoc e) {
1656                    System.out.println("copyStorage failed: " + e.getMessage()); // NOI18N
1657
e.printStackTrace();
1658                    return false;
1659                }
1660            }
1661        }
1662        if (PERF_DEBUG) System.err.println("PERF: Copy of " + in + " took " + // NOI18N
1663
(System.currentTimeMillis() - startTime) + " ms."); // NOI18N
1664
return true;
1665    }
1666
1667    /**
1668     * Checks, if the preparsed storage exists. If so, it checks existence
1669     * of storage in userdir. If it does not exists, it copies the file
1670     * to userdir location with correct name. Oterwise, it does nothing.
1671     *
1672     * @param uri URI to check
1673     * @param root archive root
1674     * @param target location and file name
1675     *
1676     * @return true, if preparsed storage exists and is used. (Either it
1677     * is copied or not.)
1678     */

1679    private static boolean usePreparsed(String JavaDoc simpleName, FileObject root, String JavaDoc storageName) {
1680        try {
1681            if (simpleName != null) {
1682                FileObject archiveRoot = FileUtil.getArchiveFile(root);
1683                String JavaDoc toCopy = PREPARSED_LOCATION + simpleName + "-" + computePreparsedHash(FileUtil.toFile(archiveRoot), BYTES4MD5); // NOI18N
1684
return copyStorage(toCopy, storageName, false);
1685            }
1686        } catch (IOException JavaDoc e) {
1687            ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL, e.getMessage());
1688        }
1689        return false;
1690    }
1691    
1692    private static String JavaDoc getCodebaseSimpleName(FileObject root) {
1693        try {
1694            String JavaDoc uri = root.getURL().toString();
1695            if (uri.endsWith("!/")) { // NOI18N
1696
String JavaDoc simpleName = uri.substring(0, uri.length() - 2);
1697                int pos = simpleName.lastIndexOf('/');
1698                if (pos >= 0) simpleName = simpleName.substring(pos + 1);
1699                pos = simpleName.lastIndexOf('.');
1700                if (pos >= 0) simpleName = simpleName.substring(0, pos);
1701                if (PREPARSED_CACHE.contains(simpleName)) {
1702                    return simpleName;
1703                }
1704            }
1705        } catch (FileStateInvalidException e) {
1706            ErrorManager.getDefault().notify(e);
1707        }
1708        return null;
1709    }
1710    
1711    /**
1712     * Computes hash for provided file. Reads len bytes from the file
1713     * and computes MD5 hash.
1714     *
1715     * @param file file which will be read
1716     * @param len says how much bytes will be read from file for
1717     * computation
1718     * @throws java.io.IOException file was not found or cannot be read
1719     * @return computed hash in string representation
1720     */

1721    public static String JavaDoc computePreparsedHash(File JavaDoc file, int len) throws IOException JavaDoc {
1722        StringBuffer JavaDoc sb = new StringBuffer JavaDoc(32);
1723        InputStream JavaDoc stream = new BufferedInputStream JavaDoc(new FileInputStream JavaDoc(file));
1724        try {
1725            byte[] input = new byte[len];
1726            stream.read(input);
1727            byte[] hash = md5digest.digest(input);
1728            for (int i = 0; i < hash.length; i++) {
1729                String JavaDoc s = Integer.toHexString(hash[i] - Byte.MIN_VALUE);
1730                if (s.length() == 1) sb.append('0');
1731                sb.append(s);
1732            }
1733        } finally {
1734            stream.close();
1735        }
1736        return sb.toString();
1737    }
1738    
1739    public static synchronized void setIndentationSettingsProvider(IndentationSettingsProvider p) {
1740        if (p == null) {
1741            settingsProvider.removePropertyChangeListener(indentListener);
1742            indentListener = null;
1743        } else if (settingsProvider != null && indentListener != null) {
1744            // both orig and new one are non-null and already listening -> reattach listening
1745
settingsProvider.removePropertyChangeListener(indentListener);
1746            p.addPropertyChangeListener(indentListener);
1747        }
1748        settingsProvider = p;
1749    }
1750    
1751    private static synchronized IndentationSettingsProvider getIndentationSettingsProvider() {
1752        if (settingsProvider != null && indentListener == null) { // not listening to prop chgs yet
1753
indentListener = new PropertyChangeListener JavaDoc() {
1754                // listens on changes of properties which are important for
1755
// our formatting engine.
1756
public void propertyChange(PropertyChangeEvent JavaDoc evt) {
1757                    if ("spacesPerTab".equals(evt.getPropertyName())) { // NOI18N
1758
setIndentSpace(((Integer JavaDoc) evt.getNewValue()).intValue(), MetadataElement.isExpandTab());
1759                    } else if ("expandTabs".equals(evt.getPropertyName())) { // NOI18N
1760
setIndentSpace(MetadataElement.getIndentSpace(), ((Boolean JavaDoc) evt.getNewValue()).booleanValue());
1761                    } else if ("javaFormatNewlineBeforeBrace".equals(evt.getPropertyName())) { // NOI18N
1762
formatCurlies(((Boolean JavaDoc) evt.getNewValue()).booleanValue());
1763                    } else if ("javaFormatSpaceBeforeParenthesis".equals(evt.getPropertyName())) { // NOI18N
1764
formatParenthesis(((Boolean JavaDoc) evt.getNewValue()).booleanValue());
1765                    }
1766                }
1767            };
1768            settingsProvider.addPropertyChangeListener(indentListener);
1769        }
1770        return settingsProvider;
1771    }
1772    
1773    private static String JavaDoc defaultEncoding;
1774    
1775    public static String JavaDoc getDefaultEncoding() {
1776        return defaultEncoding;
1777    }
1778    
1779    public static void setDefaultEncoding(String JavaDoc enc) {
1780        defaultEncoding = enc;
1781    }
1782    
1783    public void startRescan() {
1784        ((RescanAction) RescanAction.get(RescanAction.class)).performAction();
1785    }
1786
1787    void cancelScanning() {
1788        cancelScan = true;
1789    }
1790    
1791    public static abstract class ModifiedDOProvider {
1792        private ModifiedDOProvider delegate;
1793        private boolean assigned;
1794        
1795        public final DataObject getModifiedDataObject(FileObject fo) {
1796            DataObject result = getModifiedDOImpl(fo);
1797            if (result == null && delegate != null) {
1798                result = delegate.getModifiedDataObject(fo);
1799            }
1800            return result;
1801        }
1802        
1803        protected abstract DataObject getModifiedDOImpl(FileObject fo);
1804
1805        public static synchronized void setModifiedDOProvider(ModifiedDOProvider provider) {
1806            assert !provider.assigned : "Cannot set the same ModifiedDOProvider twice."; // NOI18N
1807
provider.delegate = modifiedDOProvider;
1808            modifiedDOProvider = provider;
1809            provider.assigned = true;
1810        }
1811    
1812        public static synchronized ModifiedDOProvider getModifiedDOProvider() {
1813            return modifiedDOProvider;
1814        }
1815    }
1816}
1817
Popular Tags