alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 *
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun
 * Microsystems, Inc. All Rights Reserved.
 */
package org.netbeans.modules.javacore.scanning;

import java.io.*;
import java.util.*;
import javax.jmi.reflect.RefObject;
import org.netbeans.jmi.javamodel.JavaModelPackage;
import org.netbeans.jmi.javamodel.Resource;
import org.netbeans.modules.classfile.Access;
import org.netbeans.modules.classfile.ClassFile;
import org.netbeans.modules.classfile.ClassName;
import org.netbeans.modules.javacore.ClassIndex;
import org.netbeans.modules.javacore.JMManager;
import org.netbeans.modules.javacore.internalapi.JavaMetamodel;
import org.netbeans.modules.javacore.jmiimpl.javamodel.*;
import org.openide.ErrorManager;
import org.openide.filesystems.FileObject;
import org.openide.loaders.MultiDataObject;

/**
 *
 * @author  Tomas Hurka
 */
public class ClassUpdater {    
    private Map fileObjectToClassFile;
    private Map nameToResource;
    private Map resourceToSuperCodes;    
    private Map unmodifiedResources;
    private Map resourceToClasses;
    private ResourceClassImpl resProxy;
    private JavaClassClassImpl clsProxy;
    private JavaEnumClassImpl enumProxy;
    private AnnotationTypeClassImpl annoProxy;
    private ClassIndex classIndex;
    private ResourceImpl updatedResource;
    private long indexTimestamp;
    
    /** Creates a new instance of ClassUpdater */
    public ClassUpdater(JavaModelPackage mofModel) {
        clsProxy = (JavaClassClassImpl) mofModel.getJavaClass();
        enumProxy = (JavaEnumClassImpl) mofModel.getJavaEnum();
        resProxy = (ResourceClassImpl) mofModel.getResource();
        annoProxy = (AnnotationTypeClassImpl) mofModel.getAnnotationType();
        classIndex=ClassIndex.getIndex(mofModel);
    }
 
    
    public static void updateIndex(ResourceImpl resource,MultiDataObject dobj) {
        JavaMetamodel.getDefaultRepository().beginTrans(false);
        try {
            JavaModelPackage pck=(JavaModelPackage)resource.refOutermostPackage();
            Map cls=new HashMap();
            FileObject file=dobj.getPrimaryFile();
            String fname=file.getNameExt();
            Iterator it=dobj.secondaryEntries().iterator();
            
            cls.put(fname,new FObjectInfo(file));
            while (it.hasNext()) {
                MultiDataObject.Entry en= (MultiDataObject.Entry)it.next();
                file=en.getFile();
                cls.put(file.getNameExt(),new FObjectInfo(file));   
            }            
            ClassUpdater instance=new ClassUpdater(pck);
            instance.updatedResource=resource;
            instance.updateResources(Collections.EMPTY_MAP,cls);
        } finally {
            JavaMetamodel.getDefaultRepository().endTrans();
        }
    }
    
    public Collection updateResources(Map sources,Map classes) 
    {
        Iterator iter, iter2;
        indexTimestamp=classIndex.getTimestamp();
        unmodifiedResources = new HashMap();
        fileObjectToClassFile = new HashMap();
        nameToResource = new HashMap();
        resourceToClasses = new HashMap();
        resourceToSuperCodes = new HashMap();
        iter = classes.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();
            String name = (String) entry.getKey();
            
            // ignore classes with correcponding java files in the same directory
            String srcName = name.substring(0, name.length() - ".class".length()) + ".java";
            if (sources.containsKey(srcName)) continue;
            // ------------------------
            
            FileInfo file = (FileInfo) entry.getValue();
            ClassFile clsFile = getClassFile (file);
            if ((clsFile == null) || isAnonymous(clsFile)) {
                continue;
            }            
            int index = name.indexOf('$');
            String resName = (index > -1) ? name.substring(0, index) + ".class" : name;   //NOI18N
            Set superCodes = getSuperCodes(resName, classes);
            if (superCodes == null) {
                continue;
            }
            addFileToMap (resName, clsFile);
            addSuperCodes(superCodes, clsFile);
        } // while
        
        iter = resourceToSuperCodes.entrySet().iterator();
        for (int x = 0; iter.hasNext(); x++) {
            Map.Entry entry = (Map.Entry) iter.next();
            Set codes = (Set) entry.getValue();
            int size = codes.size();
            int[] hc = new int[size];
            iter2 = codes.iterator();
            for (int y = 0; y < size; y++) {
                hc[y] = ((Integer) iter2.next()).intValue();
            }
            ResourceImpl resource = (ResourceImpl) entry.getKey();
            classIndex.setIdentifiers(resource,hc);
        } // for

        iter = nameToResource.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();
            String resName = (String) entry.getKey();
            ResourceImpl res = (ResourceImpl) entry.getValue();
            updateClasses (resName, res);
        }
        Collection resources=new ArrayList(resourceToSuperCodes.keySet());
        resources.addAll(unmodifiedResources.values());
        return resources;
    }
    
    public void addSuperCodes(Set codes, ClassFile classFile) {
        ClassName superName = classFile.getSuperClass();
        if (superName != null) {
            codes.add (nameToHashCode(superName));
        }
        Iterator iter = classFile.getInterfaces().iterator();            
        while (iter.hasNext()) {
            codes.add (nameToHashCode((ClassName) iter.next()));
        }
    }
    
    private Set getSuperCodes(String name, Map classes) {
        if (unmodifiedResources.containsKey(name)) {
            return null;
        }
        Resource res = (Resource) nameToResource.get (name);
        if (res == null) {
            FileInfo file = (FileInfo) classes.get (name);
            if (file == null) {
                // ignore this class [PENDING]
                unmodifiedResources.put(name,null);
                JMManager.getLog().log("ClassUpdater, cannot find file object: " + name); // NOI18N
                return null;
            }
            if (updatedResource!=null) {
                assert updatedResource.getName().endsWith(name): updatedResource.getName()+" "+name; // NOI18N
                res = updatedResource;
            } else {
                res = resProxy.resolveResource(file.getPath(), true, false);
            }
            long timestamp = file.lastModified();
            if (res.getTimestamp() != timestamp || indexTimestamp -1) {
            name = name.substring (index + 1);
        }
        return name;
    }
    
    public Integer nameToHashCode (ClassName clsName) {
        return new Integer (getSimpleName (clsName).hashCode());
    }        

    public boolean isAnonymous (ClassFile clsFile) {
        String name = clsFile.getName().getSimpleName();
        int index = name.lastIndexOf ('.') + 1;
        if (name.length() == index) {
            JMManager.getLog().log("ClassUpdater, class name ends with a dot: " + name); // NOI18N
        }
        return (index > 0) && (name.length() > index) && Character.isDigit(name.charAt (index));        
    }
    
    public ClassFile getClassFile (FileInfo file) {
        ClassFile clsFile = (ClassFile) fileObjectToClassFile.get (file);
        if (clsFile == null) {
            try {
                InputStream stream=new BufferedInputStream(file.getInputStream());
                try {
                    clsFile = new ClassFile (stream, false);
                    fileObjectToClassFile.put (file, clsFile);
                } finally {
                    stream.close();
                }
            } catch (IOException ex) {
                ErrorManager errmgr = ErrorManager.getDefault();
                errmgr.annotate(ex, ErrorManager.EXCEPTION, file.getName(), null, null, null);
                errmgr.notify(ErrorManager.INFORMATIONAL, ex);
            }    
        } // if
        return clsFile;    
    }

    public void addFileToMap (String resName, ClassFile clsFile) {
        Map map = (Map) resourceToClasses.get (resName);
        if (map == null) {
            map = new HashMap ();
            resourceToClasses.put (resName, map);
        }
        map.put (clsFile.getName().getSimpleName(), clsFile);
    }
    
    public void updateClasses (String resName, ResourceImpl resource) {
        Collection javaClasses = resource.getNakedClassifiers();
        Map map = (Map) resourceToClasses.get (resName);
        Map result = new HashMap ();
        Iterator classIt=javaClasses.iterator();
        
        while(classIt.hasNext()) {
            RefObject oldJcls=(RefObject)classIt.next();            
            classIt.remove();
            oldJcls.refDelete();
        }
        while (map.size () > 0) {
            Map.Entry entry = (Map.Entry) map.entrySet().iterator().next();
            ClassFile clsFile = (ClassFile) entry.getValue();            
            createJavaClass (resource, javaClasses, clsFile, map, result);
        } // while
    }
    
    private JavaClassImpl createJavaClass (ResourceImpl resource, Collection resClassifiers, ClassFile clsFile, Map map, Map createdClasses) {
        ClassName clsName = clsFile.getName();
        String fullName = clsName.getExternalName();
        String simpleName = clsName.getSimpleName();
        int index = simpleName.lastIndexOf('.');
        JavaClassImpl outer = null;
        if (index > -1) {
            // obtain outerclass
            String outerName = simpleName.substring (0, index);
            outer = (JavaClassImpl) createdClasses.get (outerName);
            if (outer == null) {
                ClassFile outerClassFile = (ClassFile) map.get (outerName);
                if (outerClassFile == null) {
                    map.remove (simpleName);                    
                    return null;
                }
                outer = createJavaClass (resource, resClassifiers, outerClassFile, map, createdClasses);
            }
        }        
        String pkgName = clsName.getPackage(); // [PENDING] ?? should be obtained only once (globally)        
        resource._setPackageName(pkgName);
        int access = (clsFile.getAccess() & ~Access.SYNCHRONIZED) | (clsFile.isDeprecated() ? FeatureImpl.DEPRECATED : 0);
        JavaClassImpl jc;
        if (clsFile.isAnnotation()) {
            jc = (JavaClassImpl) annoProxy.create(fullName, access, false);
        } else if (clsFile.isEnum()) {
            jc = (JavaClassImpl) enumProxy.create(fullName, access, false);
        } else {
            jc = (JavaClassImpl) clsProxy.create(fullName, access, null, null, false);
        }
        // should not add to class to the index - > it is added in the create method
        //classIndex.addClass(jc, fullName, getSimpleName(clsName));
        if (outer != null) {
            jc.setParentClass(outer);
        } else {
            resClassifiers.add(jc);
        }
        createdClasses.put (simpleName,  jc);
        map.remove (simpleName);
        return jc;
    }
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.