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.
 */

/*
 * RepositoryUpdater.java
 *
 * Created on 17. leden 2004, 14:17
 */

package org.netbeans.modules.javacore;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import javax.swing.SwingUtilities;
import org.netbeans.jmi.javamodel.JavaModelPackage;
import org.netbeans.jmi.javamodel.Resource;
import org.netbeans.modules.javacore.internalapi.JavaMetamodel;
import org.netbeans.modules.javacore.jmiimpl.javamodel.ResourceClassImpl;
import org.netbeans.modules.javacore.jmiimpl.javamodel.ResourceImpl;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.modules.javacore.jmiimpl.javamodel.GeneralException;
import org.openide.ErrorManager;
import org.openide.filesystems.*;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.util.RequestProcessor;

/**
 *
 * @author  Jan Becicka
 */
public class RepositoryUpdater implements FileChangeListener {
    private static final boolean DEBUG = false;
    
    private static RepositoryUpdater updater = null;
    private JMManager manager = (JMManager) JavaMetamodel.getManager();
    private Set fileObjectsToSave = Collections.synchronizedSet(new HashSet());

    
    /** Creates a new instance of RepositoryUpdater */
    private RepositoryUpdater() {
        //--- This will be replaced with master = MasterFileSystem.getDefault()
        Util.addFileSystemsListener(this);
    }
    
    public static RepositoryUpdater getDefault() {
        if (updater == null) {
            updater = new RepositoryUpdater();
        }
        return updater;
    }
    
    public void fileAttributeChanged(FileAttributeEvent fe) {
        //fileChanged(fe);
    }
    
    public void fileChanged(FileEvent fe) {
        try {
            if (changesDisabled)
                return ;
            if (DEBUG) System.out.println("file changed: " + fe.getFile().getPath()); // NOI18N
            if (!isJavaFile(fe)) return;
            updateResource(fe.getFile());
        } catch (Exception e) {
            ErrorManager.getDefault().notify(e);
        }
    }
    
    private boolean changesDisabled = false;
    public void setListenOnChanges(boolean listen) {
        changesDisabled = !listen;
    }
    
    private FileObject getCPRoot(FileObject fo) {
        return manager.getMergedClassPath().findOwnerRoot(fo);
    }
    
    public void addFileObjectToSave(FileObject file) {
        fileObjectsToSave.add(file); 
    }
    
    static void updateTimeStamp(FileObject fo) {
        if (fo != null) {
            ResourceImpl r = (ResourceImpl) JavaMetamodel.getManager().getResource(fo);
            if (r != null) {
                Date lm = fo.lastModified();
                assert lm != null : "FileObject.lastModified() returned null for " + fo;
                r.setTimestamp(lm.getTime());
            }
        }
    }
    
    private void updateResource(final FileObject fo) {
        boolean isSave = fileObjectsToSave.remove(fo);
        boolean synchronous = Thread.currentThread() == manager.getTransactionMutex().getThread();
        if (isSave) {
            if (synchronous) {
                updateTimeStamp(fo);
            } else {
                manager.getTransactionMutex().addUpdateTS(fo);
            }
        } else {
            DataObject dobj;
            try {
                dobj=DataObject.find(fo);
            } catch (DataObjectNotFoundException e) {
                // we don't care about files that don't have a dataobject
                return;
            }
            
            if (synchronous) {
                createOrUpdateResource(dobj);
            } else {
                manager.getTransactionMutex().addModifiedRW(dobj);
            }
        }
    }
    
    public void fileDataCreated(FileEvent fe) {
        try {
            if (DEBUG) System.out.println("file created: " + fe.getFile().getPath()); // NOI18N
            if (!isJavaFile(fe)) return;
            
//            DataObject dobj;
//            try {
//                dobj=DataObject.find(fe.getFile());
//            } catch (DataObjectNotFoundException e) {
//                // we don't care about files that don't have a dataobject
//                return;
//            }
//            createOrUpdateResource(dobj);
            
            updateResource(fe.getFile());
        } catch (Exception e) {
            ErrorManager.getDefault().notify(e);
        }
    }
    
    static void createOrUpdateResource(DataObject dob) {
        JMManager manager = (JMManager) JMManager.getManager();
        FileObject primaryFo = dob.getPrimaryFile();
        if (!primaryFo.isValid())
            return ;
        FileObject cpRoot = manager.getMergedClassPath().findOwnerRoot(primaryFo);
        if (cpRoot == null) return;
        JMManager.getDefaultRepository().beginTrans(true);
        try {
            ResourceImpl r = (ResourceImpl) JavaMetamodel.getManager().getResource(primaryFo);
            if (r == null) {
                //resource does not exist - create it
                JavaModelPackage modelPckg = manager.resolveJavaExtent(cpRoot);
                if (modelPckg==null) {
                    ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, new GeneralException(primaryFo.getPath() + " was not found in any extent. There is no resource to update.")); //NOI18N
                    return;
                }
                r = (ResourceImpl) ((ResourceClassImpl) modelPckg.getResource()).resolveResource(
                manager.getResourceName(primaryFo),true, false);
            }
            r.updateFromDataObject(dob, false);
        } finally {
            JMManager.getDefaultRepository().endTrans(false);
        }
    }
    
    private Queue deletedFiles = new Queue();
    private RequestProcessor.Task DELETE_TASK;
    private Runnable DELETE_RUNNABLE = new Runnable() {
        public void run() {
            if (deletedFiles.isEmpty())
                return ;
            
            while (!deletedFiles.isEmpty()) {
                JMManager.getDefaultRepository().beginTrans(true);
                try {
                    while (!deletedFiles.isEmpty()) {
                        FileObject fo = (FileObject) deletedFiles.get();
                        FileObject cpRoot = getCPRoot(fo);
                        if (cpRoot == null) return; // ignore fileobjects that are not visible from our merged classpath
                        
                        JavaModelPackage modelPckg = manager.resolveJavaExtent(cpRoot);
                        if (modelPckg==null) return;
                        Resource res = (ResourceImpl) ((ResourceClassImpl) modelPckg.getResource()).resolveResource(
                        manager.getResourceName(fo), false, false);

                        if (res!=null) {
                            res.refDelete();
                        }
                        if (JMManager.getTransactionMutex().isSwingWaiting()) {
                            break;
                        }
                    }
                } finally {
                    JMManager.getDefaultRepository().endTrans();
                }
            }
        }
    };
    

    public void fileDeleted(FileEvent fe) {
        try {
            if (DEBUG) System.out.println("file deleted: " + fe.getFile().getPath()); // NOI18N
            String  ext = fe.getFile().getExt();
            if (!("java".equals(ext) || "class".equals(ext))) return; // NOI18N
            synchronized(deletedFiles) {
                deletedFiles.put(fe.getFile());
                if (DELETE_TASK == null || DELETE_TASK.isFinished()) {
                    DELETE_TASK = RequestProcessor.getDefault().post(DELETE_RUNNABLE);
                }
            }
        } catch (Exception e) {
            ErrorManager.getDefault().notify(e);
        }
    }

    private boolean isJavaFile(FileEvent fe) {
        if (fe.getFile().isVirtual())
            return false;
        String  ext = fe.getFile().getExt();
        return ("java".equals(ext) || "class".equals(ext)) && (getCPRoot(fe.getFile()) != null); // NOI18N
    }

    public void fileFolderCreated(FileEvent fe) {
        FileObject cpRoot = getCPRoot(fe.getFile());
        if (getCPRoot(fe.getFile()) == null)
            return;
        Enumeration en = fe.getFile().getChildren(true);
        while (en.hasMoreElements()) {
            FileObject f = (FileObject) en.nextElement();
            if (Util.isJavaFile(f)) {
                updateResource(f);
            }
        }
    }
    
    public void fileRenamed(FileRenameEvent fe) {
        try {
            if (isJavaFile(fe)) {
                javaFileRenamed(fe);
            } else if (fe.getFile().isFolder()) {
                folderRenamed(fe);
            }
        } catch (Exception e) {
            ErrorManager.getDefault().notify(e);
        }
    }
    
    private void javaFileRenamed(FileRenameEvent fe) {
        FileObject oldFo = fe.getFile();
        boolean failed = true;
        JMManager.getDefaultRepository().beginTrans(true);
        try {
            String oldName = fe.getName();
            FileObject cpRoot = getCPRoot(oldFo);
            if (cpRoot == null) return; // ignore fileobjects that are not visible from our merged classpath
            JavaModelPackage model = manager.getJavaExtent(cpRoot);
            if (model != null) {
                String path = manager.getResourceName(oldFo.getParent());
                String lookForName = oldName + '.' + fe.getExt(); // file name with extension
                if (path.length() > 0) {
                    path += '/';
                    // put the path to the string if the file is located in package
                    lookForName = path + lookForName;
                }
                Resource oldRes = model.getResource().resolveResource(lookForName, false);
                if (oldRes != null) {
                    oldRes.setName(path + oldFo.getNameExt());
                } else {
                    ((ResourceClassImpl) model.getResource()).resolveResource(path + oldFo.getNameExt(), true, false);
                }
            }

            failed = false;
        } finally {
            JMManager.getDefaultRepository().endTrans(failed);
        }
    }
    
    private void folderRenamed(FileRenameEvent fe) {
        FileObject oldFo = fe.getFile();
        boolean failed = true;
        
        JMManager.getDefaultRepository().beginTrans(true);
        try {
            Enumeration children = oldFo.getChildren(true);
            FileObject cpRoot = getCPRoot(oldFo);
            if (cpRoot == null) {
                // ignore folders that are not visible from our merged classpath
                return;
            }
            String dirName = JMManager.getResourceName(cpRoot, oldFo);
            while (children.hasMoreElements()) {
                FileObject f = (FileObject) children.nextElement();
                if ("java".equals(f.getExt()) && !f.isVirtual()) { // NOI18N
                    String newName = JMManager.getResourceName(cpRoot, f);
                    String oldName = replaceStart(newName, dirName, fe.getName());
                    oldName = replaceEnd(dirName, fe.getName());
                    oldName = replaceStart(newName, dirName, oldName);
                    if (DEBUG)
                        System.out.println("Folder renamed: Resource " + oldName + " renamed to " + newName); // NOI18N
                    manager.getResource(cpRoot, oldName).setName(newName);
                }
            }
            failed = false;
        } finally {
            JMManager.getDefaultRepository().endTrans(failed);
        }
    }
    
    /**
     * example: where = "examples/colorpicker/ColorPreview.java"
     *          what  = "examples/colorpicker"
     *          withWhat = "examples/xxx
     * returns "examples/xxx/ColorPreview.java"
     */
    
    private static final String replaceStart(String where, String what, String withWhat) {
        return withWhat.concat(where.substring(what.length()));
    }
    
    /**
     * example: where = "examples/colorpicker"
     *          what  = "xxx"
     * returns "examples/xxx"
     */
    
    private static final String replaceEnd(String where, String what) {
        int i = where.lastIndexOf('/');
        if (i>0) { 
            return where.substring(0,i+1).concat(what);
        } else {
            return what;
        }
    }
    
    private class Queue {

        private LinkedList queue = new LinkedList();
        
        /** Adds new item.
        * @param o object to add
        */
        public void put (Object o) {
            queue.addFirst(o);
//            notify ();
        }

        /** Gets an object from the queue. If there is no such object the
        * thread is suspended until some object arrives
        *
        * @return object from the queue
        */
        public synchronized Object get () {
            for (;;) {
                if (!queue.isEmpty()) {
                    return queue.removeLast (); 
                } else {
//                    try {
//                        wait ();
//                    } catch (InterruptedException ex) {
//                    }
                }
            }
        }
        
        public synchronized boolean isEmpty() {
            return queue.isEmpty();
        }
    }
    
}
... 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.