1 19 20 package org.netbeans.modules.javacore.scanning; 21 import java.io.InputStream ; 22 import java.io.BufferedInputStream ; 23 import java.lang.reflect.Modifier ; 24 import java.util.*; 25 import org.netbeans.jmi.javamodel.*; 26 import org.netbeans.jmi.javamodel.JavaEnum; 27 import org.netbeans.lib.java.parser.ParserTokens; 28 import org.netbeans.modules.javacore.ClassIndex; 29 import org.netbeans.modules.javacore.JMManager; 30 import org.netbeans.modules.javacore.jmiimpl.javamodel.*; 31 import org.netbeans.modules.javacore.parser.TokenIterator; 32 import org.netbeans.modules.javacore.parser.MDRParser; 33 import org.netbeans.modules.javacore.internalapi.JavaMetamodel; 34 import org.openide.ErrorManager; 35 36 40 public class JavaUpdater { 41 private final JavaClassClassImpl jclsClass; 42 private final JavaEnumClassImpl enumClass; 43 private final AnnotationTypeClassImpl annTypeClass; 44 private final ResourceClassImpl resourceClass; 45 private final ClassIndex classIndex; 46 private final String sourceLevel; 47 private final FileScanner fileScanner; 48 private static final int[] NULL_INTS=new int[0]; 49 50 51 public JavaUpdater(JavaModelPackage mofModel,String srcLevel, FileScanner fileScanner) { 52 jclsClass = (JavaClassClassImpl) mofModel.getJavaClass(); 53 enumClass = (JavaEnumClassImpl) mofModel.getJavaEnum(); 54 resourceClass = (ResourceClassImpl) mofModel.getResource(); 55 annTypeClass = (AnnotationTypeClassImpl) mofModel.getAnnotationType(); 56 sourceLevel = srcLevel; 57 classIndex=ClassIndex.getIndex(mofModel); 58 this.fileScanner = fileScanner; 59 } 60 61 public int[] computeIndex(ResourceImpl resource,TokenIterator tokens) { 62 JavaMetamodel.getDefaultRepository().beginTrans(false); 63 try { 64 return makeIndex(resource,tokens,false); 65 } finally { 66 JavaMetamodel.getDefaultRepository().endTrans(); 67 } 68 } 69 70 private int[] makeIndex(ResourceImpl resource,TokenIterator tokens, boolean removeFeatures) { 71 int idIndexes[]=NULL_INTS; 72 boolean resInited=resource.isInitialized(); 73 HashSet reinitToDo = new HashSet(); 74 List javaClasses; 75 Set remainingClasses; 76 Set usedClasses = new HashSet(); 77 78 javaClasses=resource.getPersistentClassifiers(); 79 80 remainingClasses=getAllClassesFromResource(resource,javaClasses); 81 if (!resInited) { 82 javaClasses.clear(); 83 } 84 try { 85 final int S_NORMAL=0; 86 final int S_PACKAGE=1; 87 final int S_CLASS=2; 88 89 String id; 90 IntSet ids=new IntSet(); 91 Iterator idIt; 92 int i=0; 93 int token; 94 int last_token=0; 95 int state=S_NORMAL; 96 int modifiers=0; 97 String pack=""; 98 Stack classes=new Stack(); 99 int br_level=0; 100 boolean packageSet = false; 101 102 while((token=tokens.getNextTokenType())!=0) { 103 String text=null; 104 105 if (token==ParserTokens.IDENTIFIER) { 106 int hash=tokens.getIdentifierHash(); 107 ids.add(hash); 108 } 109 if (tokens.isDeprecated()) 110 modifiers|=FeatureImpl.DEPRECATED; 111 switch (token) { 112 case ParserTokens.PUBLIC: 113 modifiers|=Modifier.PUBLIC; 114 break; 115 case ParserTokens.PROTECTED: 116 modifiers|=Modifier.PROTECTED; 117 break; 118 case ParserTokens.PRIVATE: 119 modifiers|=Modifier.PRIVATE; 120 break; 121 case ParserTokens.ABSTRACT: 122 modifiers|=Modifier.ABSTRACT; 123 break; 124 case ParserTokens.STATIC: 125 modifiers|=Modifier.STATIC; 126 break; 127 case ParserTokens.FINAL: 128 modifiers|=Modifier.FINAL; 129 break; 130 case ParserTokens.SYNCHRONIZED: 131 modifiers|=Modifier.SYNCHRONIZED; 132 break; 133 case ParserTokens.NATIVE: 134 modifiers|=Modifier.NATIVE; 135 break; 136 case ParserTokens.STRICTFP: 137 modifiers|=Modifier.STRICT; 138 break; 139 case ParserTokens.TRANSIENT: 140 modifiers|=Modifier.TRANSIENT; 141 break; 142 case ParserTokens.VOLATILE: 143 modifiers|=Modifier.VOLATILE; 144 break; 145 case ParserTokens.SEMICOLON: 146 modifiers=tokens.isDeprecated() ? 147 FeatureImpl.DEPRECATED : 0; 148 break; 149 case ParserTokens.L_CURLY: 150 br_level++; 151 modifiers=tokens.isDeprecated() ? 152 FeatureImpl.DEPRECATED : 0; 153 break; 154 case ParserTokens.R_CURLY: 155 if (br_level==classes.size() && !classes.isEmpty()) 156 classes.pop(); 157 br_level--; 158 break; 159 } 160 if (last_token==ParserTokens.MONKEYS_AT && 161 token==ParserTokens.IDENTIFIER) { 162 String s=tokens.getIdentifierText(); 163 if (s.equals("Deprecated") || s.equals("java.lang.Deprecated")) modifiers|=FeatureImpl.DEPRECATED; 167 } 168 switch (state) { 169 case S_NORMAL: 170 if (token==ParserTokens.PACKAGE) 171 state=S_PACKAGE; 172 else if ((token==ParserTokens.CLASS || token==ParserTokens.INTERFACE || token==ParserTokens.ENUM) && last_token!=ParserTokens.DOT) { 173 if (!packageSet) { 174 if (JMManager.INCONSISTENCY_DEBUG) System.err.println("JavaUpdater: Setting package name of resource " + resource.getName() + " to " + pack); 175 resource._setPackageName(pack); 176 packageSet = true; 177 } 178 if (last_token==ParserTokens.MONKEYS_AT && token==ParserTokens.INTERFACE) { 179 modifiers|=MDRParser.M_ANNOTATION; ids.add("Annotation".hashCode()); } 182 state=S_CLASS; 183 } 184 break; 185 case S_PACKAGE: 186 if (token==ParserTokens.IDENTIFIER) 187 text=tokens.getIdentifierText(); 188 if (text!=null) { 189 if (pack.length()==0) 190 pack=text; 191 else 192 pack=pack + '.' + text; } 194 if (token==ParserTokens.SEMICOLON) { 195 state=S_NORMAL; 196 } 197 break; 198 case S_CLASS: 199 if (token==ParserTokens.IDENTIFIER) 200 text=tokens.getIdentifierText(); 201 if (br_level==classes.size() && text!=null) { 202 String fqn; 203 JavaClassImpl jcls; 204 JavaClassImpl enclosingClass=null; 205 206 if (!classes.empty()) 207 enclosingClass=(JavaClassImpl)classes.peek(); 208 fqn=constructFqn(pack,classes,text); 209 if (last_token==ParserTokens.INTERFACE) { 210 modifiers|=Modifier.INTERFACE; 211 } else if (last_token == ParserTokens.ENUM) { 212 modifiers |= MDRParser.M_ENUM; 213 ids.add("Enum".hashCode()); } 215 jcls=createJavaClass(fqn,modifiers,removeFeatures,text,remainingClasses,usedClasses,enclosingClass); 216 usedClasses.add(jcls); 217 classes.push(jcls); 218 remainingClasses.remove(jcls); 219 if (jcls.refImmediateComposite() == null) { 220 if (enclosingClass!=null) { 221 boolean contentsInited = enclosingClass.contentsInited(); 222 boolean persisted = enclosingClass.isPersisted(); 223 if (persisted) { 224 enclosingClass.getPersistentContents().add(jcls); 225 if (contentsInited) { 226 reinitToDo.add(enclosingClass); 227 } 228 } else { 229 jcls.setParentClass(enclosingClass); 230 } 231 } else { 232 javaClasses.add(jcls); 233 } 234 } 235 } 236 state=S_NORMAL; 237 } 238 last_token=token; 239 } 240 if (!packageSet) { 241 if (JMManager.INCONSISTENCY_DEBUG) System.err.println("JavaUpdater: Setting package name of resource " + resource.getName() + " to " + pack); 242 resource._setPackageName(pack); 243 } 244 idIndexes=ids.toArray(); 245 for (Iterator it = remainingClasses.iterator(); it.hasNext();) { 248 JavaClassImpl cls = (JavaClassImpl) it.next(); 249 if (cls.isValid()) { 254 Object parent = cls.refImmediateComposite(); 255 if (parent == resource) { 256 javaClasses.remove(cls); 257 } else if (parent instanceof JavaClassImpl) { 258 JavaClassImpl enclosingClass = (JavaClassImpl) parent; 259 boolean contentsInited = enclosingClass.contentsInited(); 260 boolean persisted = enclosingClass.isPersisted(); 261 if (persisted) { 262 enclosingClass.getPersistentContents().remove(cls); 263 if (contentsInited) { 264 reinitToDo.add(enclosingClass); 265 } 266 } else { 267 cls.setParentClass(null); 268 } 269 } 270 cls.refDelete(); 271 } 272 } 273 if (resource.classifiersInited()) 275 resource.reinitClassifiers(); 276 for (Iterator it = reinitToDo.iterator(); it.hasNext();) { 277 JavaClassImpl cls = (JavaClassImpl) it.next(); 281 if (cls.isValid()) { 282 cls.reinitContents(); 283 } 284 } 285 } catch (Exception ex) { 286 ErrorManager.getDefault().notify(ex); 287 } 288 return idIndexes; 289 } 290 291 private JavaClassImpl createJavaClass(String fqn, int modifiers,boolean removeFeatures, String simpleName,Set remainingClasses,Set usedClasses,JavaClass enclosingClass) { 292 Collection classes = classIndex.getClassesByFqn(fqn); 293 JavaClass jcls = null; 294 295 if (JMManager.INCONSISTENCY_DEBUG) System.err.println("JavaUpdater: Looking for class: " + fqn); 296 for (Iterator it = classes.iterator(); it.hasNext();) { 297 JavaClass temp = (JavaClass) it.next(); 298 if ((!removeFeatures && enclosingClass != null && enclosingClass.equals(temp.refImmediateComposite()) && !usedClasses.contains(temp)) || remainingClasses.contains(temp)) { 299 if (JMManager.INCONSISTENCY_DEBUG) System.err.println("JavaUpdater: Existing class found in index."); 300 301 int declType = temp instanceof JavaEnum ? 1 : (temp instanceof AnnotationType ? 2 : 0); 304 if ((declType == 1 && !isEnum(modifiers)) || (declType != 1 && isEnum(modifiers)) || 305 (declType == 2 && !isAnnotation(modifiers)) || (declType != 2 && isAnnotation(modifiers))) 306 { 307 if (JMManager.INCONSISTENCY_DEBUG) System.err.println("JavaUpdater: The found class is of wrong type: " + temp.getClass().getName() + " -> deleting..."); 309 remainingClasses.add(temp); 312 } else { 313 jcls = temp; 314 } 315 break; 316 } 317 } 318 319 if (jcls==null) { 320 if (JMManager.INCONSISTENCY_DEBUG) System.err.println("JavaUpdater: No suitable class found -> creating..."); 321 if (isEnum(modifiers)) { 322 jcls = enumClass.create(fqn, modifiers, false); 323 } else if (isAnnotation(modifiers)) { 324 jcls = annTypeClass.create(fqn, modifiers, false); 325 } else { 326 jcls = jclsClass.create(fqn, modifiers, null, null, false); 327 } 328 } else { 331 if (removeFeatures) { 332 ClassUpdater.removePersisted((JavaClassImpl) jcls); 333 } 334 } 335 return (JavaClassImpl) jcls; 336 } 337 338 private Set getAllClassesFromResource(Resource res,Collection topLevelClasses) { 339 Iterator topIt=topLevelClasses.iterator(); 340 Set allClasses=new HashSet(); 341 342 while(topIt.hasNext()) { 343 JavaClass topJcls=(JavaClass)topIt.next(); 344 Iterator innerListIt=classIndex.getClassesByFQNPrefix(topJcls.getName().concat(".")).iterator(); 346 allClasses.add(topJcls); 347 while (innerListIt.hasNext()) { 348 JavaClass innerJcls=(JavaClass)innerListIt.next(); 349 350 if (res.equals(innerJcls.getResource())) { 351 allClasses.add(innerJcls); 352 } 353 } 354 } 355 return allClasses; 356 } 357 358 private static boolean isEnum(int modifiers) { 359 return (modifiers & MDRParser.M_ENUM) != 0; 360 } 361 362 private static boolean isAnnotation(int modifiers) { 363 return (modifiers & MDRParser.M_ANNOTATION) != 0; 364 } 365 366 private String constructFqn(String pack,Stack names,String simpleName) { 367 String name; 368 369 if (names.isEmpty()) { 370 if (pack.length()>0) { 371 name=pack+'.'; 372 } else { 373 name=""; 374 } 375 } else { 376 name=((JavaClass)names.peek()).getName()+'.'; 377 } 378 return name.concat(simpleName); 379 } 380 381 public Collection updateResources(Map javaFiles) 382 { 383 JavaMetamodel.getDefaultRepository().beginTrans(false); 384 try { 385 Iterator resIt=javaFiles.values().iterator(); 386 List resList=new ArrayList(); 387 long indexTimestamp; 388 389 indexTimestamp=classIndex.getTimestamp(); 390 while(resIt.hasNext()) { 391 FileInfo file=(FileInfo)resIt.next(); 392 try { 393 String name=file.getPath(); 394 long timestamp=file.lastModified(); 395 ResourceImpl resource=(ResourceImpl) resourceClass.resolveResource(name,true,false); 396 397 resList.add(resource); 398 if (resource.getTimestamp()!=timestamp || resource.isFromMemory() || indexTimestamp<timestamp) { 399 resource.setTimestamp(timestamp, false); 400 if (fileScanner != null) fileScanner.checkParseEagerly(resource); 401 InputStream stream=new BufferedInputStream (file.getInputStream()); 402 403 try { 404 int ids[]=makeIndex(resource, new TokenIterator(stream,sourceLevel,true), !resource.isInitialized()); 405 classIndex.setIdentifiers(resource,ids); 406 } finally { 407 stream.close(); 408 } 409 } 410 } catch (Exception ex) { 411 ErrorManager.getDefault().notify(ex); 412 } 413 } 414 return resList; 415 } finally { 416 JavaMetamodel.getDefaultRepository().endTrans(); 417 } 418 } 419 } 420 | Popular Tags |