KickJava   Java API By Example, From Geeks To Geeks.

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


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.io.BufferedInputStream JavaDoc;
23 import java.io.BufferedOutputStream JavaDoc;
24 import java.io.File JavaDoc;
25 import java.io.FileInputStream JavaDoc;
26 import java.io.FileOutputStream JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.io.InputStream JavaDoc;
29 import java.io.OutputStream JavaDoc;
30 import java.io.StringReader JavaDoc;
31 import java.util.AbstractSet JavaDoc;
32 import java.util.ArrayList JavaDoc;
33 import java.util.Arrays JavaDoc;
34 import java.util.Collection JavaDoc;
35 import java.util.Collections JavaDoc;
36 import java.util.Comparator JavaDoc;
37 import java.util.ConcurrentModificationException JavaDoc;
38 import java.util.HashMap JavaDoc;
39 import java.util.HashSet JavaDoc;
40 import java.util.Iterator JavaDoc;
41 import java.util.List JavaDoc;
42 import java.util.Map JavaDoc;
43 import java.util.NoSuchElementException JavaDoc;
44 import java.util.Set JavaDoc;
45 import java.util.SortedMap JavaDoc;
46 import java.util.TreeMap JavaDoc;
47 import org.netbeans.api.java.classpath.ClassPath;
48 import org.netbeans.api.java.queries.SourceLevelQuery;
49 import org.netbeans.api.mdr.MDRepository;
50 import org.netbeans.jmi.javamodel.JavaClass;
51 import org.netbeans.jmi.javamodel.JavaModelPackage;
52 import org.netbeans.jmi.javamodel.Resource;
53 import org.netbeans.jmi.javamodel.ResourceClass;
54 import org.netbeans.lib.java.parser.Factory;
55 import org.netbeans.lib.java.parser.JScanner;
56 import org.netbeans.lib.java.parser.ParserTokens;
57 import org.netbeans.mdr.NBMDRepositoryImpl;
58 import org.netbeans.mdr.handlers.BaseObjectHandler;
59 import org.netbeans.mdr.persistence.MOFID;
60 import org.netbeans.mdr.util.IOUtils;
61 import org.netbeans.modules.javacore.ClassIndexStorage.QueryItem;
62 import org.netbeans.modules.javacore.internalapi.JavaMetamodel;
63 import org.netbeans.modules.javacore.jmiimpl.javamodel.JavaClassImpl;
64 import org.netbeans.spi.java.classpath.support.ClassPathSupport;
65 import org.openide.ErrorManager;
66 import org.openide.filesystems.FileObject;
67 import org.openide.filesystems.FileStateInvalidException;
68 import org.openide.filesystems.JarFileSystem;
69
70 /**
71  *
72  * @author Tomas Hurka, Martin Matula
73  */

74 public class ClassIndex {
75     private static final boolean DEBUG = false;
76
77     private static final Map JavaDoc codebaseIndexes = Collections.synchronizedMap(new HashMap JavaDoc());
78     private static boolean shutdownListenerRegistered = false;
79     private static final ShutdownL shutdownListener = new ShutdownL();
80     
81     private final ClassIndexStorage storage;
82     private final String JavaDoc storageId;
83     private final NBMDRepositoryImpl rep;
84     
85     private long lastSaved;
86     
87     private HashMap JavaDoc changeLogSN;
88     private HashMap JavaDoc changeLogFQN;
89     private HashMap JavaDoc changeLogI;
90
91     /** Creates a new instance of ClassIndex */
92     private ClassIndex(String JavaDoc file, String JavaDoc storageId) {
93         this.storageId = storageId;
94         rep = (NBMDRepositoryImpl) JavaMetamodel.getDefaultRepository();
95         storage = new CISImpl(file);
96         
97         // register shutdown listener
98
if (!shutdownListenerRegistered) {
99             synchronized (shutdownListener) {
100                 if (!shutdownListenerRegistered) {
101                     ((NBMDRepositoryImpl) JavaMetamodel.getDefaultRepository()).addShutdownListener(shutdownListener);
102                     shutdownListenerRegistered = true;
103                 }
104             }
105         }
106     }
107     
108     static void commit() {
109         for (Iterator JavaDoc it = codebaseIndexes.values().iterator(); it.hasNext();) {
110             ((ClassIndex) it.next()).commitChanges();
111         }
112     }
113     
114     static void rollback() {
115         for (Iterator JavaDoc it = codebaseIndexes.values().iterator(); it.hasNext();) {
116             ((ClassIndex) it.next()).rollbackChanges();
117         }
118     }
119     
120     private void commitChanges() {
121         changeLogSN = null;
122         changeLogFQN = null;
123         changeLogI = null;
124     }
125     
126     private void rollbackChanges() {
127         if (changeLogSN != null) {
128             for (Iterator JavaDoc it = changeLogSN.entrySet().iterator(); it.hasNext();) {
129                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
130                 it.remove();
131                 long mofId = ((Long JavaDoc) entry.getKey()).longValue();
132                 if (entry.getValue() == null) {
133                     JavaClass cls = (JavaClass) rep.getByMofId(makeMofId(mofId));
134                     if (cls != null) {
135                         addClass(cls, cls.getName(), cls.getSimpleName());
136                     }
137                 } else {
138                     removeFromIndex(true, (String JavaDoc) entry.getValue(), mofId);
139                     // list of fqn changes is superset of this list so I don't have to add the class
140
// to index here - it will be done when iterating through changeLogFQN below
141
}
142             }
143         }
144         
145         if (changeLogFQN != null) {
146             for (Iterator JavaDoc it = changeLogFQN.entrySet().iterator(); it.hasNext();) {
147                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
148                 it.remove();
149                 long mofId = ((Long JavaDoc) entry.getKey()).longValue();
150                 JavaClass cls = (JavaClass) rep.getByMofId(makeMofId(mofId));
151                 if (entry.getValue() != null) {
152                     removeFromIndex(false, (String JavaDoc) entry.getValue(), mofId);
153                 }
154                 if (cls != null) {
155                     addClass(cls, cls.getName(), cls.getSimpleName());
156                 }
157             }
158         }
159         
160         if (changeLogI != null) {
161             for (Iterator JavaDoc it = changeLogI.entrySet().iterator(); it.hasNext();) {
162                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
163                 it.remove();
164                 storage.setIdentifiers(((Long JavaDoc) entry.getKey()).longValue(), (int[]) entry.getValue());
165             }
166         }
167     }
168     
169     public static ClassIndex getIndex(JavaModelPackage mofPackage) {
170         return (ClassIndex)codebaseIndexes.get(mofPackage);
171     }
172     
173     private static void saveAllIndexes() {
174         MDRepository rep = JavaMetamodel.getDefaultRepository();
175         
176         rep.beginTrans(false);
177         try {
178             synchronized (codebaseIndexes) {
179                 Iterator JavaDoc indexIt = codebaseIndexes.values().iterator();
180
181                 while (indexIt.hasNext()) {
182                     ClassIndex index = (ClassIndex) indexIt.next();
183                     index.storage.unmount();
184                 }
185             }
186         } finally {
187             rep.endTrans();
188         }
189     }
190     
191     // must be called from a synchronized block
192
static void removeIndex(JavaModelPackage mofPackage) {
193         ClassIndex index = (ClassIndex) codebaseIndexes.remove(mofPackage);
194         index.storage.unmount();
195     }
196     
197     // must be called from a synchronized block
198
static ClassIndex addIndex(JavaModelPackage mofPackage, String JavaDoc filename) {
199         ClassIndex index = new ClassIndex(filename, ((BaseObjectHandler) mofPackage)._getDelegate().getMofId().getStorageID());
200         codebaseIndexes.put(mofPackage, index);
201         return index;
202     }
203     
204     // must be called from a synchronized block
205
static boolean loadIndex(String JavaDoc filename, JavaModelPackage mofPackage) {
206         ClassIndex index = addIndex(mofPackage, filename);
207         return index.storage.mount();
208     }
209
210     public void renameClass(JavaClass jcls, String JavaDoc newName) {
211         long mofId = getMofId(jcls);
212         String JavaDoc name = jcls.getName();
213         String JavaDoc simpleName = jcls.getSimpleName();
214         String JavaDoc newSimpleName = JavaClassImpl.getSimpleName(newName);
215
216         if (JMManager.INCONSISTENCY_DEBUG) System.err.println("ClassIndex: Renaming class: " + name + " to: " + newName + " MOFID: " + jcls.refMofId());
217         //Thread.dumpStack();
218

219         removeFromIndex(false, name, mofId);
220         
221         Long JavaDoc objMofId = new Long JavaDoc(mofId);
222         logFQNChange(objMofId, newName);
223         if (!simpleName.equals(newSimpleName)) {
224             removeFromIndex(true, simpleName, mofId);
225             logSNChange(objMofId, newSimpleName);
226         }
227         addClass(jcls, newName, newSimpleName);
228     }
229     
230     private static HashMap JavaDoc logChange(HashMap JavaDoc map, Long JavaDoc mofId, Object JavaDoc value) {
231         if (map == null) {
232             map = new HashMap JavaDoc();
233         }
234         map.put(mofId, value);
235         return map;
236     }
237     
238     private void logFQNChange(Long JavaDoc mofId, String JavaDoc name) {
239         changeLogFQN = logChange(changeLogFQN, mofId, name);
240     }
241     
242     private void logSNChange(Long JavaDoc mofId, String JavaDoc name) {
243         changeLogSN = logChange(changeLogSN, mofId, name);
244     }
245     
246     public void addClass(JavaClass jcls,String JavaDoc fqn,String JavaDoc simpleName) {
247         if (JMManager.INCONSISTENCY_DEBUG) System.err.println("ClassIndex: Adding class " + fqn + " MOFID: " + jcls.refMofId());
248         long mofId = getMofId(jcls);
249
250         addToIndex(true, simpleName, mofId);
251         addToIndex(false, fqn, mofId);
252     }
253     
254     public long getTimestamp() {
255         return lastSaved;
256     }
257     
258     public void setTimestamp() {
259         lastSaved = System.currentTimeMillis();
260     }
261
262     // may return invalid classes
263
public Set JavaDoc getClassesByFqn(String JavaDoc fqn) {
264         Set JavaDoc result = new HashSet JavaDoc();
265         long[] classes = storage.getIDsForName(fqn, false);
266         if (classes != null) {
267             JavaClass cls = null;
268             int j = 0;
269             for (int i = 0; i < classes.length; i++) {
270                 JavaClass temp = (JavaClass) rep.getByMofId(makeMofId(classes[i]));
271                 if (temp == null) {
272                     logFQNChange(new Long JavaDoc(classes[i]), null);
273                 } else {
274                     classes[j] = classes[i];
275                     j++;
276                     result.add(temp);
277                 }
278             }
279             if (j == 0) {
280                 storage.setIDsForName(fqn, false, null);
281             } else if (j < classes.length) {
282                 long[] newValue = new long[j];
283                 System.arraycopy(classes, 0, newValue, 0, j);
284                 storage.setIDsForName(fqn, false, newValue);
285             }
286         }
287         return result;
288     }
289
290     // never returns an invalid class
291
public JavaClass getClassByFqn(String JavaDoc fqn) {
292         JavaClass cls = null;
293         JavaClass oldCls;
294         do {
295             oldCls = cls;
296             cls = tryToGetClassByFqn(fqn);
297         } while (cls != null && !cls.isValid() && oldCls != cls);
298         if (cls != null && oldCls == cls) {
299             try {
300                 JMManager.getLog().notify(ErrorManager.INFORMATIONAL, new RuntimeException JavaDoc("Class was not cleaned from index: " + cls.getName())); // NOI18N
301
} catch (javax.jmi.reflect.InvalidObjectException e) {
302                 JMManager.getLog().notify(ErrorManager.INFORMATIONAL, e);
303             }
304             cls = null;
305         }
306         return cls;
307     }
308     
309     private JavaClass tryToGetClassByFqn(String JavaDoc fqn) {
310         long[] classes = storage.getIDsForName(fqn, false);
311         if (classes != null) {
312             JavaClass result = null;
313             JavaClass sureResult = null;
314             int j = 0;
315             for (int i = 0; i < classes.length; i++) {
316                 JavaClass temp = (JavaClass) rep.getByMofId(makeMofId(classes[i]));
317                 if (temp == null) {
318                     logFQNChange(new Long JavaDoc(classes[i]), null);
319                 } else {
320                     classes[j] = classes[i];
321                     j++;
322                     result = temp;
323                     // [TODO] the following code can be uncommented if necessary
324
// (it tries to prefer classes that are in the correct folder)
325
// now it is commented out for performance reasons
326
// Resource res = (Resource) result.refImmediateComposite();
327
// if (res != null) {
328
// if (res.getName().replace('/', '.').startsWith(res.getPackageName())) {
329
// sureResult = result;
330
// }
331
// }
332
}
333             }
334             if (j == 0) {
335                 storage.setIDsForName(fqn, false, null);
336             } else if (j < classes.length) {
337                 long[] newValue = new long[j];
338                 System.arraycopy(classes, 0, newValue, 0, j);
339                 storage.setIDsForName(fqn, false, newValue);
340             }
341             return sureResult == null ? result : sureResult;
342         }
343         return null;
344     }
345     
346     // may return invalid classes
347
public LazyImmutableList getClassesByFQNPrefix(String JavaDoc fqnPrefix) {
348         return new LazyImmutableList(new ClassesByFQNPrefixIterator(storage.getFirstForNamePrefix(fqnPrefix, false)));
349     }
350     
351     public LazyImmutableList getClassesByFQNPrefix(String JavaDoc fqnPrefix, boolean caseSensitive) {
352         if (caseSensitive) return getClassesByFQNPrefix(fqnPrefix);
353         
354         int dot = fqnPrefix.lastIndexOf('.');
355         String JavaDoc packagePart = fqnPrefix.substring(0, dot + 1);
356         return new LazyImmutableList(new ClassesByFQNPrefixCIIterator(storage.getFirstForNamePrefix(packagePart, false), fqnPrefix));
357     }
358     
359     /**
360      * Looks for the classes in class index by prefix. Finding mechanism is case
361      * sensitive. May return invalid classes.
362      *
363      * @param snPrefix simple name leading characters of class which will
364      * be looked for
365      * @return list of matching JavaClasses instances ordered by their names
366      */

367     public LazyImmutableList getClassesBySNPrefix(String JavaDoc snPrefix) {
368         return getClassesBySNPrefix(snPrefix, true);
369     }
370     
371     /**
372      * Looks for the classes in class index by prefix. Finding can be either
373      * case-sensitive or case-insensitive. May return invalid classes (i.e. classes for which cls.isValid() == false).
374      *
375      * @param snPrefix simple name leading characters of class which
376      * will be looked for
377      * @return list of matching JavaClasses instances ordered by names
378      */

379     public LazyImmutableList getClassesBySNPrefix(String JavaDoc snPrefix, boolean caseSensitive) {
380         ClassIndexStorage.QueryItem query;
381         boolean camelCase;
382         if (snPrefix.length() > 1 && snPrefix.equals(snPrefix.toUpperCase())) {
383             query = storage.getFirstForNamePrefix(snPrefix.substring(0,1), true);
384             camelCase = true;
385         } else {
386             query = storage.getFirstForNamePrefix(snPrefix.toUpperCase(), true);
387             camelCase = false;
388         }
389         return new LazyImmutableList(new ClassesBySNPrefixIterator(query, snPrefix, caseSensitive, camelCase));
390     }
391     
392     private abstract class ClassesByPrefixIterator extends LazyImmutableList.LazyIterator {
393         private int maxSize = -1;
394         private int currentSize = 0;
395         
396         protected ClassIndexStorage.QueryItem currentItem;
397         
398         private Object JavaDoc next;
399         private boolean hasNext = true;
400         private Iterator JavaDoc inner = Collections.EMPTY_LIST.iterator();
401         
402         ClassesByPrefixIterator(ClassIndexStorage.QueryItem item) {
403             this.currentItem = item;
404         }
405         
406         public final Object JavaDoc next() {
407             if (next == null) {
408                 findNext();
409             }
410             Object JavaDoc result = next;
411             next = null;
412             return result;
413         }
414         
415         public final boolean hasNext() {
416             findNext();
417             return hasNext;
418         }
419         
420         protected final int maxEstimatedSize() {
421             if (maxSize == -1) {
422                 computeSize();
423             }
424             return maxSize;
425         }
426         
427         private void computeSize() {
428             maxSize = currentSize;
429             ClassIndexStorage.QueryItem item = currentItem;
430             while (item != null) {
431                 maxSize += item.getIDs().length;
432                 item = item.getNext();
433             }
434         }
435         
436         private void findNext() {
437             if (!hasNext) {
438                 throw new NoSuchElementException JavaDoc();
439             }
440             while (next == null && hasNext == true) {
441                 if (inner.hasNext()) {
442                     next = inner.next();
443                 } else {
444                     while ((currentItem != null) && (!accept(currentItem))) {
445                         currentItem = currentItem.getNext();
446                     }
447                     if (currentItem != null) {
448                         inner = getClassesByPrefix().iterator();
449                     } else {
450                         hasNext=false;
451                     }
452                 }
453             }
454         }
455         
456         private Collection JavaDoc getClassesByPrefix() {
457             Collection JavaDoc result = new ArrayList JavaDoc();
458             
459             long[] value = currentItem.getIDs();
460             currentSize += value.length;
461             
462             int j = 0;
463             for (int i = 0; i < value.length; i++) {
464                 JavaClass cls = (JavaClass) rep.getByMofId(makeMofId(value[i]));
465                 j += evaluateItem(value, i, j, cls, result);
466             }
467             if (j == 0) {
468                 currentItem.setIDs(null);
469             } else if (j < value.length) {
470                 long[] newValue = new long[j];
471                 System.arraycopy(value, 0, newValue, 0, j);
472                 currentItem.setIDs(newValue);
473             }
474             
475             currentItem = currentItem.getNext();
476             return result;
477         }
478         
479         protected boolean accept(ClassIndexStorage.QueryItem item) {
480             return true;
481         }
482         
483         protected abstract int evaluateItem(long[] value, int i, int j, JavaClass cls, Collection JavaDoc result);
484     }
485     
486     private class ClassesBySNPrefixIterator extends ClassesByPrefixIterator {
487         private final String JavaDoc prefix;
488         private final boolean matchName;
489         private final boolean camelCase;
490         
491         ClassesBySNPrefixIterator(ClassIndexStorage.QueryItem item, String JavaDoc prefix, boolean caseSensitive, boolean camelCase) {
492             super(item);
493             this.prefix = prefix;
494             this.matchName = caseSensitive && prefix.length() > 0;
495             this.camelCase = camelCase;
496         }
497         
498         protected boolean accept(ClassIndexStorage.QueryItem item) {
499             return !camelCase || item.getName().startsWith(prefix) || matchIndexEntry(item.getName());
500         }
501         
502         private boolean matchIndexEntry(String JavaDoc indexEntryName) {
503             int index = -1;
504             for (int i = 0; i < prefix.length(); i++) {
505                 index = indexEntryName.indexOf(prefix.charAt(i), index + 1);
506                 if (index < 0) {
507                     return false;
508                 }
509             }
510             return true;
511         }
512         
513         private boolean matchName(String JavaDoc simpleName) {
514             if (!matchName && simpleName.toUpperCase().startsWith(prefix)) return true;
515             
516             int sni, pi;
517             for (pi = 0, sni = 0; sni < simpleName.length() && pi < prefix.length(); sni++) {
518                 char ch = simpleName.charAt(sni);
519                 if (Character.isUpperCase(ch)) {
520                     if (ch != prefix.charAt(pi++)) {
521                         return false;
522                     }
523                 }
524             }
525             return pi == prefix.length();
526         }
527     
528         protected int evaluateItem(long[] value, int i, int j, JavaClass cls, Collection JavaDoc result) {
529             if (cls == null) {
530                 logSNChange(new Long JavaDoc(value[i]), null);
531                 return 0;
532             } else {
533                 value[j] = value[i];
534                 if ((!matchName && !camelCase) || (matchName && cls.getSimpleName().startsWith(prefix)) || (camelCase && matchName(cls.getSimpleName()))) {
535                     if (((JavaClassImpl) cls).hasComposite()) {
536                         result.add(cls);
537                     } else {
538                         JMManager.getTransactionMutex().invalidateAtCommit(cls);
539                     }
540                 }
541                 return 1;
542             }
543         }
544     }
545     
546     private class ClassesByFQNPrefixIterator extends ClassesByPrefixIterator {
547         ClassesByFQNPrefixIterator(ClassIndexStorage.QueryItem item) {
548             super(item);
549         }
550         
551         protected int evaluateItem(long[] value, int i, int j, JavaClass cls, Collection JavaDoc result) {
552             if (cls == null) {
553                 logFQNChange(new Long JavaDoc(value[i]), null);
554                 return 0;
555             } else {
556                 if (((JavaClassImpl) cls).hasComposite()) {
557                     result.add(cls);
558                 } else {
559                     JMManager.getTransactionMutex().invalidateAtCommit(cls);
560                 }
561                 value[j] = value[i];
562                 return 1;
563             }
564         }
565     }
566     
567     private class ClassesByFQNPrefixCIIterator extends ClassesByFQNPrefixIterator {
568         private final String JavaDoc namePrefix;
569         
570         ClassesByFQNPrefixCIIterator(ClassIndexStorage.QueryItem item, String JavaDoc namePrefix) {
571             super(item);
572             this.namePrefix = namePrefix.toUpperCase();
573         }
574         
575         protected boolean accept(ClassIndexStorage.QueryItem item) {
576             return (namePrefix.length() == 0) || item.getName().toUpperCase().startsWith(namePrefix);
577         }
578     }
579     
580     public boolean doesnotExist(String JavaDoc fqn) {
581         return !storage.existsFQN(fqn);
582     }
583     
584     public boolean hasClass(String JavaDoc fqn) {
585         return getClassByFqn(fqn) != null;
586     }
587     
588     /**
589      * Looks for the classes in class index. Finding mechanism is case
590      * sensitive. May return invalid classes.
591      *
592      * @param simpleName simple (short) name of class which will be looked for
593      * @return collection of matching JavaClasses instances
594      */

595     public Collection JavaDoc getClassesBySimpleName(String JavaDoc simpleName) {
596         return getClassesBySimpleName(simpleName, true);
597     }
598     
599     /**
600      * Looks for the classes in class index. Finding can be either
601      * case-sensitive or case-insensitive. May return invalid classes.
602      *
603      * @param simpleName simple (short) name of class which will be looked for
604      * @param caseSensitive use false when you want to ignore case
605      * @return collection of matching JavaClasses instances
606      */

607     public Collection JavaDoc getClassesBySimpleName(String JavaDoc simpleName, boolean caseSensitive) {
608         String JavaDoc simpleUpper = simpleName.toUpperCase();
609         long[] value = (long[]) storage.getIDsForName(simpleUpper, true);
610         
611         List JavaDoc res = new ArrayList JavaDoc();
612         
613         if (value != null) {
614             int j = 0;
615             for (int i = 0; i < value.length; i++) {
616                 JavaClass cls = (JavaClass) rep.getByMofId(makeMofId(value[i]));
617                 if (cls == null) {
618                     logSNChange(new Long JavaDoc(value[i]), null);
619                 } else {
620                     value[j] = value[i];
621                     j++;
622                     if (!caseSensitive || simpleName.equals(cls.getSimpleName())) {
623                         res.add(cls);
624                     }
625                 }
626             }
627             if (j == 0) {
628                 storage.setIDsForName(simpleUpper, true, null);
629             } else if (j < value.length) {
630                 long[] newValue = new long[j];
631                 System.arraycopy(value, 0, newValue, 0, j);
632                 storage.setIDsForName(simpleUpper, true, newValue);
633             }
634         }
635         return res;
636     }
637     
638     public static boolean hasClass(String JavaDoc fqn,ClassPath classPath) {
639         FileObject[] roots = classPath.getRoots();
640         // iteruj pres rooty a hledej classu podle FQN
641
for (int i = 0; i < roots.length; i++) {
642             JavaModelPackage mofPackage = JavaMetamodel.getManager().getJavaExtent(roots[i]);
643             // test for mofPackage != null is needed when any other thread
644
// mounts the new filesystem and we do not know about it yet.
645
// It is in list of all filesystem roots, but we do not have created
646
// package for it yet. In such a case, the index does not contain
647
// class and we will return false.
648
if (mofPackage!=null && ClassIndex.getIndex(mofPackage).hasClass(fqn))
649                 return true;
650         }
651         return false;
652     }
653
654     public static JavaClass getClassByFqn(String JavaDoc fqn, ClassPath classPath) {
655         FileObject[] roots = classPath.getRoots();
656         for (int i = 0; i < roots.length; i++) {
657             JavaModelPackage mofPackage = org.netbeans.modules.javacore.internalapi.JavaMetamodel.getManager().getJavaExtent(roots[i]);
658             if (mofPackage != null) {
659                 ClassIndex index = ClassIndex.getIndex(mofPackage);
660                 if (index != null) {
661                     JavaClass cls = index.getClassByFqn(fqn);
662                     if (cls != null) {
663                         return cls;
664                     }
665                 }
666             }
667         }
668         return null;
669     }
670
671     public void setIdentifiers(Resource rsc,int identifiers[]) {
672         Arrays.sort(identifiers);
673         storage.setIdentifiers(getMofId(rsc), identifiers);
674     }
675     
676     private long getMofId(Object JavaDoc obj) {
677         return ((BaseObjectHandler) obj)._getMofId().getSerialNumber();
678     }
679     
680     private MOFID makeMofId(long mofId) {
681         return new MOFID(mofId, storageId);
682     }
683     
684     public void removeResource(Resource rsc) {
685         long mofId = getMofId(rsc);
686         int[] o = storage.removeIdentifiers(mofId);
687         changeLogI = logChange(changeLogI, new Long JavaDoc(mofId), o);
688     }
689
690     void updateIdentifiersInResource(Resource rsc,String JavaDoc sourceText) {
691         FileObject file=JavaMetamodel.getManager().getFileObject(rsc);
692         String JavaDoc sourceLevel=SourceLevelQuery.getSourceLevel(file);
693         JScanner scanner=Factory.getDefault().getScanner(new StringReader JavaDoc(sourceText),sourceLevel);
694         int token;
695         int identifiers[] = storage.getIdentifiers(getMofId(rsc));
696         List JavaDoc newIds=new ArrayList JavaDoc(10);
697         int newIdSize;
698         
699         try {
700             while((token=scanner.yylex())!=0) {
701                 if (token==ParserTokens.IDENTIFIER) {
702                     String JavaDoc text=scanner.yytext();
703                     int hash=text.hashCode();
704
705                     if (Arrays.binarySearch(identifiers,hash)<0) {
706                         newIds.add(text);
707                     }
708                 }
709             }
710         }
711         catch (IOException JavaDoc ex) {
712             ErrorManager.getDefault().notify(ex);
713         }
714         newIdSize=newIds.size();
715         if (newIdSize>0) {
716             int ids[]=new int[identifiers.length+newIdSize];
717             String JavaDoc newIdArr[]=(String JavaDoc[])newIds.toArray(new String JavaDoc[newIdSize]);
718             int i;
719             
720             for (i=0;i<newIdSize;i++) {
721                 ids[i]=newIdArr[i].hashCode();
722             }
723             System.arraycopy(identifiers, 0, ids, newIdSize, identifiers.length);
724             setIdentifiers(rsc,ids);
725         }
726     }
727     
728     // made public because java/j2seproject/J2SEProjectUtil depends on it
729
public Collection JavaDoc findResourcesForIdent(String JavaDoc identifier) {
730         long[] ids = storage.getIDsForIdentifier(identifier.hashCode());
731         Collection JavaDoc res = new ArrayList JavaDoc(ids.length);
732         for (int i = 0; i < ids.length; i++) {
733             Object JavaDoc obj = rep.getByMofId(makeMofId(ids[i]));
734             if (obj == null) {
735                 storage.removeIdentifiers(ids[i]);
736             } else {
737                 res.add(obj);
738             }
739         }
740         return res;
741     }
742         
743     public static Resource[] findResourcesForIdentifier(String JavaDoc identifier,boolean includeLibraries) {
744         FileObject[] roots;
745         List JavaDoc cp = ((JMManager) JavaMetamodel.getManager()).getTransactionMutex().getSearchScope();
746         if (cp == null) {
747             roots = JavaMetamodel.getManager().getClassPath().getRoots();
748         } else {
749             if (cp.size() == 1) {
750                 roots = ((ClassPath) cp.get(0)).getRoots();
751             } else {
752                 roots = ClassPathSupport.createProxyClassPath((ClassPath[]) cp.toArray(new ClassPath[cp.size()])).getRoots();
753             }
754         }
755         // iterate through roots and find class by its FQN
756
Collection JavaDoc resources=new ArrayList JavaDoc();
757         HashSet JavaDoc visitedRoots = new HashSet JavaDoc((int) (roots.length / .7));
758         org.netbeans.modules.javacore.internalapi.JavaMetamodel manager=org.netbeans.modules.javacore.internalapi.JavaMetamodel.getManager();
759         boolean isJavaDocTag = identifier.startsWith("@"); // NOI18N
760

761         for (int i = 0; i < roots.length; i++) {
762             FileObject root = roots[i];
763             if (!visitedRoots.add(root)) continue;
764             try {
765                 if (includeLibraries || !(root.getFileSystem() instanceof JarFileSystem)) {
766                     JavaModelPackage mofPackage = manager.getJavaExtent(root);
767                     // [TODO]: temporary solution to enable IsValueFor association implementation
768

769                     if (mofPackage != null) {
770                         if (isJavaDocTag) {
771                             ResourceClass resourceClass = mofPackage.getResource();
772                             resources.addAll(resourceClass.refAllOfClass());
773                         }
774                         else {
775                             resources.addAll(ClassIndex.getIndex(mofPackage).findResourcesForIdent(identifier));
776                         }
777                     }
778                 }
779             } catch (FileStateInvalidException ex) {
780                 ErrorManager.getDefault().notify(ex);
781             }
782         }
783         return (Resource[])resources.toArray(new Resource[resources.size()]);
784     }
785
786     public static Resource[] findResourcesForIdentifier(String JavaDoc identifier) {
787         return findResourcesForIdentifier(identifier,false);
788     }
789
790     public static void updateIdentifiers(Resource rsc,String JavaDoc sourceText) {
791         JavaModelPackage mofPackage=(JavaModelPackage)rsc.refOutermostPackage();
792         ClassIndex.getIndex(mofPackage).updateIdentifiersInResource(rsc, sourceText);
793     }
794     
795     public static boolean containsIdentifier(Resource rsc, int identifier) {
796         JavaModelPackage mofPackage=(JavaModelPackage)rsc.refOutermostPackage();
797         ClassIndex index = ClassIndex.getIndex(mofPackage);
798         int[] idents = (int[]) index.storage.getIdentifiers(index.getMofId(rsc));
799
800         if (idents==null) {
801             JMManager.getLog().log("ids is null for "+rsc.getName());
802             return false;
803         }
804         return Arrays.binarySearch(idents, identifier) >= 0;
805     }
806
807     private void addToIndex(boolean isSimpleName, String JavaDoc name, long value) {
808         if (isSimpleName) {
809             name = name.toUpperCase();
810         }
811         long[] temp = storage.getIDsForName(name, isSimpleName);
812         long[] newValue;
813         int len;
814         if (temp == null) {
815             len = 0;
816             newValue = new long[len + 1];
817         } else {
818             long[] oldValue = temp;
819             len = oldValue.length;
820             newValue = new long[len + 1];
821             for (int i = 0; i < len; i++) {
822                 if (oldValue[i] == value) {
823                     newValue = oldValue;
824                     break;
825                 }
826                 newValue[i] = oldValue[i];
827             }
828         }
829         if (newValue != temp) {
830             newValue[len] = value;
831             storage.setIDsForName(name, isSimpleName, newValue);
832         }
833     }
834
835     private void removeFromIndex(boolean isSimpleName, String JavaDoc name, long value) {
836         if (isSimpleName) {
837             name = name.toUpperCase();
838         }
839         Object JavaDoc temp = storage.getIDsForName(name, isSimpleName);
840         if (temp != null) {
841             long[] oldValue = (long[]) temp;
842             int len = oldValue.length;
843             long[] newValue = new long[len - 1];
844             int i = 0, j = 0;
845             for (; i < len && j < len - 1; i++) {
846                 if (oldValue[i] != value) {
847                     newValue[j++] = oldValue[i];
848                 }
849             }
850
851             if (i < len && oldValue[i] != value) {
852                 if (j < len - 1) {
853                     newValue[j] = oldValue[i];
854                 } else {
855                     newValue = oldValue;
856                 }
857             }
858
859             if (oldValue != newValue) {
860                 if (newValue.length == 0) {
861                     newValue = null;
862                 }
863                 storage.setIDsForName(name, isSimpleName, newValue);
864             }
865         }
866     }
867     
868     // Shutdown listener ........................................................
869

870     private static class ShutdownL implements NBMDRepositoryImpl.ShutdownListener {
871         
872         public void shutdown() {
873             // RequestProcessor.getDefault().post(this);
874
saveAllIndexes();
875         }
876         
877         public void stepFinished() {
878         }
879     }
880
881     private class CISImpl implements ClassIndexStorage {
882         private static final int VERSION = 2;
883         private static final String JavaDoc INDEX_SUFFIX=".cdx"; // NOI18N
884

885         private final SortedMap JavaDoc fqnMap;
886         private final SortedMap JavaDoc simpleMap;
887         private Map JavaDoc identifiersMap;
888         private final String JavaDoc filename;
889         
890         private transient boolean isDirty;
891
892         CISImpl(String JavaDoc filename) {
893             this.filename = filename;
894             fqnMap = new TreeMap JavaDoc();
895             simpleMap = new TreeMap JavaDoc();
896             identifiersMap = new HashMap JavaDoc();
897             isDirty = true;
898         }
899         
900         private QueryItem createNextCIIImpl(Iterator JavaDoc it, int length) throws ConcurrentModificationException JavaDoc {
901             while (it.hasNext()) {
902                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
903                 if (((String JavaDoc) entry.getKey()).lastIndexOf('.') < length) {
904                     return new CIIImpl(it, entry, length);
905                 }
906             }
907             return null;
908         }
909         
910         public QueryItem createNextCIISNImpl(Iterator JavaDoc it) throws ConcurrentModificationException JavaDoc {
911             if (it.hasNext()) {
912                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
913                 return new CIISNImpl(it, entry);
914             }
915             return null;
916         }
917         
918         private abstract class AbstractCIIImpl implements QueryItem {
919             private Iterator JavaDoc it;
920             private final Map.Entry JavaDoc entry;
921             private QueryItem next ;
922             
923             AbstractCIIImpl(Iterator JavaDoc it, Map.Entry JavaDoc entry) {
924                 this.it = it;
925                 this.entry = entry;
926             }
927
928             public final void setIDs(long[] ids) throws ConcurrentModificationException JavaDoc {
929                 isDirty=true;
930                 entry.setValue(ids);
931                 if (ids == null) {
932                     if (it == null) {
933                         QueryItem item = getNext();
934                         while (item != null) item = item.getNext();
935                         remove();
936                     } else {
937                         it.remove();
938                     }
939                 }
940             }
941
942             public final String JavaDoc getName() {
943                 return (String JavaDoc) entry.getKey();
944             }
945
946             public final long[] getIDs() {
947                 return (long[]) entry.getValue();
948             }
949             
950             public final QueryItem getNext() throws ConcurrentModificationException JavaDoc {
951                 if (it != null) {
952                     next = createNext(it);
953                     it = null;
954                 }
955                 return next;
956             }
957             
958             protected abstract QueryItem createNext(Iterator JavaDoc it) throws ConcurrentModificationException JavaDoc;
959             protected abstract void remove();
960         }
961         
962         private class CIIImpl extends AbstractCIIImpl {
963             private final int length;
964
965             CIIImpl(Iterator JavaDoc it, Map.Entry JavaDoc entry, int length) {
966                 super(it, entry);
967                 this.length = length;
968             }
969
970             protected QueryItem createNext(Iterator JavaDoc it) throws ConcurrentModificationException JavaDoc {
971                 return createNextCIIImpl(it, length);
972             }
973             
974             protected void remove() {
975                 setIDsForName(getName(), false, null);
976             }
977         }
978
979         private class CIISNImpl extends AbstractCIIImpl {
980             CIISNImpl(Iterator JavaDoc it, Map.Entry JavaDoc entry) {
981                 super(it, entry);
982             }
983
984             protected QueryItem createNext(Iterator JavaDoc it) throws ConcurrentModificationException JavaDoc {
985                 return createNextCIISNImpl(it);
986             }
987             
988             protected void remove() {
989                 setIDsForName(getName(), true, null);
990             }
991         }
992
993         public QueryItem getFirstForNamePrefix(String JavaDoc prefix, boolean isSimpleName) {
994             SortedMap JavaDoc map;
995             if (prefix == null || prefix.length() == 0) {
996                 map = isSimpleName ? simpleMap : fqnMap;
997             } else {
998                 map = (isSimpleName ? simpleMap : fqnMap).subMap(prefix, prefix + '\uffff');
999             }
1000            if (isSimpleName) {
1001                return createNextCIISNImpl(map.entrySet().iterator());
1002            } else {
1003                int length = prefix.length();
1004                return createNextCIIImpl(map.entrySet().iterator(), length);
1005            }
1006        }
1007        
1008        public boolean existsFQN(String JavaDoc fqn) {
1009            return fqnMap.get(fqn) != null;
1010        }
1011        
1012        public void setIdentifiers(long resourceId, int[] hashCodes) {
1013            assert hashCodes != null;
1014            isDirty=true;
1015            identifiersMap.put(new Long JavaDoc(resourceId), hashCodes);
1016        }
1017        
1018        public boolean mount() {
1019            long t = 0;
1020            try {
1021                if (JMManager.PERF_DEBUG) {
1022                    t = System.currentTimeMillis();
1023                }
1024                
1025                File JavaDoc indexFile = new File JavaDoc(filename.concat(INDEX_SUFFIX));
1026                if (!indexFile.isFile()) {
1027                    JMManager.getLog().log(ErrorManager.WARNING, "Index file missing: " + indexFile);
1028                    return false;
1029                }
1030                InputStream JavaDoc indexStream = new BufferedInputStream JavaDoc(new FileInputStream JavaDoc(indexFile), 65536);
1031                
1032                try {
1033                    read(indexStream);
1034                } finally {
1035                    indexStream.close();
1036                }
1037                isDirty=false;
1038                return true;
1039            } catch (Exception JavaDoc ex) {
1040                JMManager.getLog().notify(ErrorManager.INFORMATIONAL, ex);
1041                return false;
1042            } finally {
1043                if (JMManager.PERF_DEBUG) {
1044                    System.err.println("loading index " + filename + " took: " + (System.currentTimeMillis() - t) + "ms");
1045                }
1046            }
1047        }
1048        
1049        public void unmount() {
1050            if (!isDirty) return;
1051            
1052            if (JMManager.PERF_DEBUG) {
1053                System.err.println("saving index " + filename);
1054            }
1055            
1056            rep.beginTrans(false);
1057            try {
1058                FileOutputStream JavaDoc fos=new FileOutputStream JavaDoc(filename.concat(INDEX_SUFFIX));
1059                BufferedOutputStream JavaDoc indexStream=new BufferedOutputStream JavaDoc(fos, 65536);
1060                try {
1061                    write(indexStream);
1062                } finally {
1063                    indexStream.close();
1064                }
1065                isDirty=false;
1066            } catch (Exception JavaDoc ex) {
1067                JMManager.getLog().notify(ErrorManager.INFORMATIONAL, ex);
1068            } finally {
1069                rep.endTrans();
1070            }
1071        }
1072
1073        private void read(InputStream JavaDoc indexStream) throws IOException JavaDoc {
1074            if (VERSION != IOUtils.readInt(indexStream)) return;
1075            if (!storageId.equals(IOUtils.readString(indexStream))) return;
1076            readMap(indexStream, fqnMap);
1077            readMap(indexStream, simpleMap);
1078
1079            int count = IOUtils.readInt(indexStream);
1080            identifiersMap = new HashMap JavaDoc(count * 4 / 3 + 1);
1081            for (int i = 0; i < count; i++) {
1082                Long JavaDoc key = new Long JavaDoc(IOUtils.readLong(indexStream));
1083                int count2 = IOUtils.readInt(indexStream);
1084                int[] value = new int[count2];
1085                for (int j = 0; j < count2; j++) {
1086                    value[j] = IOUtils.readInt(indexStream);
1087                }
1088                identifiersMap.put(key, value);
1089            }
1090            lastSaved = IOUtils.readLong(indexStream);
1091        }
1092
1093        private void write(OutputStream JavaDoc indexStream) throws IOException JavaDoc {
1094            if (JMManager.PERF_DEBUG) System.err.println("fqnMap: " + fqnMap.size() + " records; identifiersMap: " + identifiersMap.size() + "records");
1095            IOUtils.writeInt(indexStream, VERSION);
1096            IOUtils.writeString(indexStream, storageId);
1097            writeMap(indexStream, fqnMap);
1098            writeMap(indexStream, simpleMap);
1099
1100            IOUtils.writeInt(indexStream, identifiersMap.size());
1101            for (Iterator JavaDoc it = identifiersMap.entrySet().iterator(); it.hasNext();) {
1102                Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
1103                IOUtils.writeLong(indexStream, ((Long JavaDoc) entry.getKey()).longValue());
1104
1105                int[] array = (int[]) entry.getValue();
1106                IOUtils.writeInt(indexStream, array.length);
1107                for (int i = 0; i < array.length; i++) {
1108                    IOUtils.writeInt(indexStream, array[i]);
1109                }
1110            }
1111
1112            IOUtils.writeLong(indexStream, System.currentTimeMillis());
1113        }
1114
1115        private void readMap(InputStream JavaDoc indexStream, Map JavaDoc map) throws IOException JavaDoc {
1116            map.putAll(new StreamBasedSortedMap(indexStream));
1117        }
1118
1119        private void writeMap(OutputStream JavaDoc indexStream, Map JavaDoc map) throws IOException JavaDoc {
1120            IOUtils.writeInt(indexStream, map.size());
1121            for (Iterator JavaDoc it = map.entrySet().iterator(); it.hasNext();) {
1122                Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
1123                IOUtils.writeString(indexStream, (String JavaDoc) entry.getKey());
1124
1125                long[] array = (long[]) entry.getValue();
1126                IOUtils.writeInt(indexStream, array.length);
1127                for (int i = 0; i < array.length; i++) {
1128                    IOUtils.writeLong(indexStream, array[i]);
1129                }
1130            }
1131        }
1132
1133        public long[] getIDsForName(String JavaDoc name, boolean isSimpleName) {
1134            return (long[]) (isSimpleName ? simpleMap : fqnMap).get(name);
1135        }
1136
1137        public long[] getIDsForIdentifier(int hashCode) {
1138            Iterator JavaDoc it = identifiersMap.entrySet().iterator();
1139            Collection JavaDoc result = new ArrayList JavaDoc(50);
1140            while(it.hasNext()) {
1141                Map.Entry JavaDoc en = (Map.Entry JavaDoc) it.next();
1142                int ids[] = (int[]) en.getValue();
1143                if (ids == null) {
1144                    isDirty = true;
1145                    it.remove();
1146                } else if (Arrays.binarySearch(ids, hashCode) >= 0) {
1147                    result.add(en.getKey());
1148                }
1149            }
1150            long[] res = new long[result.size()];
1151            it = result.iterator();
1152            for (int i = 0; it.hasNext(); i++) {
1153                res[i] = ((Long JavaDoc) it.next()).longValue();
1154            }
1155            return res;
1156        }
1157
1158        public void setIDsForName(String JavaDoc name, boolean isSimpleName, long[] classIDs) {
1159            isDirty=true;
1160            Map JavaDoc map = isSimpleName ? simpleMap : fqnMap;
1161            if (classIDs == null || classIDs.length == 0) {
1162                map.remove(name);
1163            } else {
1164                map.put(name, classIDs);
1165            }
1166        }
1167
1168        public int[] getIdentifiers(long resourceId) {
1169            return (int[]) identifiersMap.get(new Long JavaDoc(resourceId));
1170        }
1171
1172        public int[] removeIdentifiers(long resourceId) {
1173            isDirty=true;
1174            return (int[]) identifiersMap.remove(new Long JavaDoc(resourceId));
1175        }
1176    }
1177    
1178    /**
1179     * Special implementation of SortedMap based on archived stream.
1180     * This class is used to initialize TreeMap from sorted data when deserializing ClassIndex
1181     */

1182    private class StreamBasedSortedMap implements SortedMap JavaDoc {
1183        private int size;
1184        InputStream JavaDoc stream;
1185        
1186        private StreamBasedSortedMap(InputStream JavaDoc indexStream) throws IOException JavaDoc {
1187            stream = indexStream;
1188            size = IOUtils.readInt(stream);
1189        }
1190        
1191        public Comparator JavaDoc comparator() {
1192            return null;
1193        }
1194
1195        public SortedMap JavaDoc subMap(Object JavaDoc fromKey, Object JavaDoc toKey) {
1196            throw new UnsupportedOperationException JavaDoc();
1197        }
1198
1199        public SortedMap JavaDoc headMap(Object JavaDoc toKey) {
1200            throw new UnsupportedOperationException JavaDoc();
1201        }
1202
1203        public SortedMap JavaDoc tailMap(Object JavaDoc fromKey) {
1204            throw new UnsupportedOperationException JavaDoc();
1205        }
1206
1207        public Object JavaDoc firstKey() {
1208            throw new UnsupportedOperationException JavaDoc();
1209        }
1210
1211        public Object JavaDoc lastKey() {
1212            throw new UnsupportedOperationException JavaDoc();
1213        }
1214
1215        public int size() {
1216            return size;
1217        }
1218
1219        public boolean isEmpty() {
1220            return size == 0;
1221        }
1222
1223        public boolean containsKey(Object JavaDoc key) {
1224            throw new UnsupportedOperationException JavaDoc();
1225        }
1226
1227        public boolean containsValue(Object JavaDoc value) {
1228            throw new UnsupportedOperationException JavaDoc();
1229        }
1230
1231        public Object JavaDoc get(Object JavaDoc key) {
1232            throw new UnsupportedOperationException JavaDoc();
1233        }
1234
1235        public Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
1236            throw new UnsupportedOperationException JavaDoc();
1237        }
1238
1239        public Object JavaDoc remove(Object JavaDoc key) {
1240            throw new UnsupportedOperationException JavaDoc();
1241        }
1242
1243        public void putAll(Map JavaDoc t) {
1244            throw new UnsupportedOperationException JavaDoc();
1245        }
1246
1247        public void clear() {
1248            throw new UnsupportedOperationException JavaDoc();
1249        }
1250
1251        public Set JavaDoc keySet() {
1252            throw new UnsupportedOperationException JavaDoc();
1253        }
1254
1255        public Collection JavaDoc values() {
1256            throw new UnsupportedOperationException JavaDoc();
1257        }
1258
1259        public Set JavaDoc entrySet() {
1260            return new EntrySet();
1261        }
1262        
1263        private class EntrySet extends AbstractSet JavaDoc {
1264            public Iterator JavaDoc iterator() {
1265                return new EntrySetIterator();
1266            }
1267
1268            public int size() {
1269                return size;
1270            }
1271            
1272            private class EntrySetIterator implements Iterator JavaDoc, Map.Entry JavaDoc {
1273                private int index;
1274                private String JavaDoc key;
1275                private long[] value;
1276                                
1277                public boolean hasNext() {
1278                    return index<size;
1279                }
1280
1281                public Object JavaDoc next() {
1282                    try {
1283                        key = IOUtils.readString(stream);
1284                        int count = IOUtils.readInt(stream);
1285                        value = new long[count];
1286                        for (int j = 0; j < count; j++) {
1287                            value[j] = IOUtils.readLong(stream);
1288                        }
1289                        index++;
1290                    } catch (IOException JavaDoc ex) {
1291                        ex.printStackTrace();
1292                        index = size;
1293                    }
1294                    return this;
1295                }
1296
1297                public void remove() {
1298                    throw new UnsupportedOperationException JavaDoc();
1299                }
1300
1301                public Object JavaDoc getKey() {
1302                    return key;
1303                }
1304
1305                public Object JavaDoc getValue() {
1306                    return value;
1307                }
1308
1309                public Object JavaDoc setValue(Object JavaDoc value) {
1310                    throw new UnsupportedOperationException JavaDoc();
1311                }
1312                
1313            }
1314        }
1315    }
1316}
1317
Popular Tags