Package org.netbeans.modules.scala.debugger.projects

Source Code of org.netbeans.modules.scala.debugger.projects.SourcePathProviderImpl$PathRegistryListener

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License.  When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s):
*
* The Original Software is NetBeans. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
* Microsystems, Inc. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/

package org.netbeans.modules.scala.debugger.projects;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.HashSet;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

import org.netbeans.api.java.platform.JavaPlatformManager;

import org.netbeans.spi.debugger.jpda.SourcePathProvider;
import org.netbeans.spi.debugger.ContextProvider;

import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.classpath.GlobalPathRegistry;
import org.netbeans.api.java.classpath.GlobalPathRegistryEvent;
import org.netbeans.api.java.classpath.GlobalPathRegistryListener;
import org.netbeans.api.java.platform.JavaPlatform;
import org.netbeans.api.java.project.JavaProjectConstants;
import org.netbeans.api.java.queries.SourceForBinaryQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.Sources;
import org.netbeans.api.project.ui.OpenProjects;
import org.netbeans.spi.java.classpath.ClassPathProvider;
import org.netbeans.spi.java.classpath.support.ClassPathSupport;

import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileStateInvalidException;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.JarFileSystem;
import org.openide.filesystems.URLMapper;
import org.openide.util.Exceptions;
import org.openide.util.WeakListeners;


/**
*
* @author Jan Jancura
*/
public class SourcePathProviderImpl extends SourcePathProvider {
   
    private static boolean          verbose =
        System.getProperty ("netbeans.debugger.sourcepathproviderimpl") != null;
   
    private static Logger logger = Logger.getLogger("org.netbeans.modules.scala.debugger.projects");
   
    private static final Pattern thisDirectoryPattern = Pattern.compile("(/|\\A)\\./");
    private static final Pattern parentDirectoryPattern = Pattern.compile("(/|\\A)([^/]+?)/\\.\\./");

    /** Contains all known source paths + jdk source path for JPDAStart task */
    private ClassPath               originalSourcePath;
    /** Contains the additional source roots, added at a later time to the original roots. */
    private Set<String>             additionalSourceRoots;
    /** Contains just the source paths which are selected for debugging. */
    private ClassPath               smartSteppingSourcePath;
    private String[]                projectSourceRoots;
    private PropertyChangeSupport   pcs;
    private PathRegistryListener    pathRegistryListener;
   
    public SourcePathProviderImpl () {
        pcs = new PropertyChangeSupport (this);
    }

    public SourcePathProviderImpl (ContextProvider contextProvider) {
        pcs = new PropertyChangeSupport (this);
        //this.session = (Session) contextProvider.lookupFirst
        //    (null, Session.class);
        Map properties = contextProvider.lookupFirst(null, Map.class);
       
        // 2) get default allSourceRoots of source roots used for stepping
        if (properties != null) {
            smartSteppingSourcePath = (ClassPath) properties.get ("sourcepath");
            ClassPath jdkCP = (ClassPath) properties.get ("jdksources");
            if ( (jdkCP == null) && (JavaPlatform.getDefault () != null) )
                jdkCP = JavaPlatform.getDefault ().getSourceFolders ();
            originalSourcePath = jdkCP == null ?
                smartSteppingSourcePath :
                ClassPathSupport.createProxyClassPath (
                    new ClassPath[] {
                        jdkCP,
                        smartSteppingSourcePath
                    }
            );
            projectSourceRoots = getSourceRoots(originalSourcePath);
            Set<FileObject> preferredRoots = new HashSet<FileObject>();
            preferredRoots.addAll(Arrays.asList(originalSourcePath.getRoots()));
            Set<FileObject> globalRoots = new TreeSet<FileObject>(new FileObjectComparator());
            globalRoots.addAll(GlobalPathRegistry.getDefault().getSourceRoots());
            globalRoots.removeAll(preferredRoots);
            ClassPath globalCP = ClassPathSupport.createClassPath(globalRoots.toArray(new FileObject[0]));
            originalSourcePath = ClassPathSupport.createProxyClassPath(
                    originalSourcePath,
                    globalCP
            );
        } else {
            pathRegistryListener = new PathRegistryListener();
            GlobalPathRegistry.getDefault().addGlobalPathRegistryListener(
                    WeakListeners.create(GlobalPathRegistryListener.class,
                                         pathRegistryListener,
                                         GlobalPathRegistry.getDefault()));
            JavaPlatformManager.getDefault ().addPropertyChangeListener(
                    WeakListeners.propertyChange(pathRegistryListener,
                                                 JavaPlatformManager.getDefault()));
           
            List<FileObject> allSourceRoots = new ArrayList<FileObject>();
            Set<FileObject> preferredRoots = new HashSet<FileObject>();
            Set<FileObject> addedBinaryRoots = new HashSet<FileObject>();
            Project mainProject = OpenProjects.getDefault().getMainProject();
            if (mainProject != null) {
                SourceGroup[] sgs = ProjectUtils.getSources(mainProject).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
                for (SourceGroup sg : sgs) {
                    ClassPath ecp = ClassPath.getClassPath(sg.getRootFolder(), ClassPath.EXECUTE);
                    if (ecp == null) {
                        ecp = ClassPath.getClassPath(sg.getRootFolder(), ClassPath.SOURCE);
                    }
                    if (ecp != null) {
                        FileObject[] binaryRoots = ecp.getRoots();
                        for (FileObject fo : binaryRoots) {
                            if (addedBinaryRoots.contains(fo)) {
                                continue;
                            }
                            addedBinaryRoots.add(fo);
                            try {
                                FileObject[] roots = SourceForBinaryQuery.findSourceRoots(fo.getURL()).getRoots();
                                for (FileObject fr : roots) {
                                    if (!preferredRoots.contains(fr)) {
                                        allSourceRoots.add(fr);
                                        preferredRoots.add(fr);
                                    }
                                }
                            } catch (FileStateInvalidException ex) {
                                Exceptions.printStackTrace(ex);
                            }
                        }
                    }
                }
            }
            Set<FileObject> globalRoots = new TreeSet<FileObject>(new FileObjectComparator());
            globalRoots.addAll(GlobalPathRegistry.getDefault().getSourceRoots());
            for (FileObject fo : globalRoots) {
                if (!preferredRoots.contains(fo)) {
                    allSourceRoots.add(fo);
                }
            }
           
            List<FileObject> allSourceRoots1 = new ArrayList<FileObject>(allSourceRoots.size());
            for (FileObject fo: allSourceRoots) {
                if (FileUtil.isArchiveFile(fo)) {
                    allSourceRoots1.add(FileUtil.getArchiveRoot(fo));
                } else {
                    allSourceRoots1.add(fo);
                }
            }
            originalSourcePath = ClassPathSupport.createClassPath (
                allSourceRoots1.toArray(new FileObject [allSourceRoots1.size()])
            );
            projectSourceRoots = getSourceRoots(originalSourcePath);
           
            JavaPlatform[] platforms = JavaPlatformManager.getDefault ().
                getInstalledPlatforms ();
            int i, k = platforms.length;
            for (i = 0; i < k; i++) {
                FileObject[] roots = platforms [i].getSourceFolders ().
                    getRoots ();
                int j, jj = roots.length;
                for (j = 0; j < jj; j++)
                    allSourceRoots1.remove (roots [j]);
            }
            smartSteppingSourcePath = ClassPathSupport.createClassPath (
                allSourceRoots1.toArray
                    (new FileObject [allSourceRoots1.size()])
            );
        }
       
        if (verbose)
            System.out.println
                ("SPPI: init originalSourcePath " + originalSourcePath);   
        if (verbose)
            System.out.println (
                "SPPI: init smartSteppingSourcePath " + smartSteppingSourcePath
            );   
    }

    /**
     * Translates a relative path ("java/lang/Thread.java") to url
     * ("file:///C:/Sources/java/lang/Thread.java"). Uses GlobalPathRegistry
     * if global == true.
     *
     * @param relativePath a relative path (java/lang/Thread.java)
     * @param global true if global path should be used
     * @return url or <code>null</code>
     */
    public String getURL (String relativePath, boolean global) {    if (verbose) System.out.println ("SPPI: getURL " + relativePath + " global " + global);
        FileObject fo;
        relativePath = normalize(relativePath);
        if (originalSourcePath == null) {
            fo = GlobalPathRegistry.getDefault().findResource(relativePath);
        } else {
            synchronized (this) {
                if (!global) {
                    fo = smartSteppingSourcePath.findResource(relativePath);
                                                                    if (verbose) System.out.println ("SPPI:   fo " + fo);
                } else {
                    fo = originalSourcePath.findResource(relativePath);
                                                                    if (verbose) System.out.println ("SPPI:   fo " + fo);
                }
            }
        }
        if (fo == null) return null;
        try {
            return fo.getURL ().toString ();
        } catch (FileStateInvalidException e) {                     if (verbose) System.out.println ("SPPI:   FileStateInvalidException");
            return null;
        }
    }
   
    /**
     * Translates a relative path to all possible URLs.
     * Uses GlobalPathRegistry if global == true.
     *
     * @param relativePath a relative path (java/lang/Thread.java)
     * @param global true if global path should be used
     * @return url
     */
    public String[] getAllURLs (String relativePath, boolean global) {      if (verbose) System.out.println ("SPPI: getURL " + relativePath + " global " + global);
        List<FileObject> fos;
        relativePath = normalize(relativePath);
        if (originalSourcePath == null) {
            fos = new ArrayList<FileObject>();
            for (ClassPath cp : GlobalPathRegistry.getDefault().getPaths(ClassPath.SOURCE)) {
                fos.addAll(cp.findAllResources(relativePath));
            }
        } else {
            synchronized (this) {
                if (!global) {
                    fos = smartSteppingSourcePath.findAllResources(relativePath);
                                                                            if (verbose) System.out.println ("SPPI:   fos " + fos);
                } else {
                    fos = originalSourcePath.findAllResources(relativePath);
                                                                            if (verbose) System.out.println ("SPPI:   fos " + fos);
                }
            }
        }
        List<String> urls = new ArrayList<String>(fos.size());
        for (FileObject fo : fos) {
            try {
                urls.add(fo.getURL().toString());
            } catch (FileStateInvalidException e) {                         if (verbose) System.out.println ("SPPI:   FileStateInvalidException for "+fo);
                // skip it
            }
        }
        return urls.toArray(new String[0]);
    }
   
    /**
     * Returns relative path for given url.
     *
     * @param url a url of resource file
     * @param directorySeparator a directory separator character
     * @param includeExtension whether the file extension should be included
     *        in the result
     *
     * @return relative path
     */
    public String getRelativePath (
        String url,
        char directorySeparator,
        boolean includeExtension
    ) {
        // 1) url -> FileObject
        FileObject fo = null;                                       if (verbose) System.out.println ("SPPI: getRelativePath " + url);
        try {
            fo = URLMapper.findFileObject (new URL (url));          if (verbose) System.out.println ("SPPI:   fo " + fo);
        } catch (MalformedURLException e) {
            //e.printStackTrace ();
            return null;
        }
        String relativePath = smartSteppingSourcePath.getResourceName (
            fo,
            directorySeparator,
            includeExtension
        );
        if (relativePath == null) {
            // fallback to FileObject's class path
            ClassPath cp = ClassPath.getClassPath (fo, ClassPath.SOURCE);
            if (cp == null)
                cp = ClassPath.getClassPath (fo, ClassPath.COMPILE);
            if (cp == null) return null;
            relativePath = cp.getResourceName (
                fo,
                directorySeparator,
                includeExtension
            );
        }
        return relativePath;
    }
   
    /**
     * Returns the source root (if any) for given url.
     *
     * @param url a url of resource file
     *
     * @return the source root or <code>null</code> when no source root was found.
     */
    @Override
    public synchronized String getSourceRoot(String url) {
        FileObject fo;
        try {
            fo = URLMapper.findFileObject(new java.net.URL(url));
        } catch (java.net.MalformedURLException ex) {
            fo = null;
        }
        FileObject[] roots = null;
        if (fo != null) {
            ClassPath cp = ClassPath.getClassPath(fo, ClassPath.SOURCE);
            if (cp != null) {
                roots = cp.getRoots();
            }
        }
        if (roots == null) {
            roots = originalSourcePath.getRoots();
        }
        for (FileObject fileObject : roots) {
            try {
                String rootURL = fileObject.getURL().toString();
                if (url.startsWith(rootURL)) {
                    String root = getRoot(fileObject);
                    if (root != null) {
                        return root;
                    }
                }
            } catch (FileStateInvalidException ex) {
                // Invalid source root - skip
            }
        }
        return null; // not found
    }
   
    private String[] getSourceRoots(ClassPath classPath) {
        FileObject[] sourceRoots = classPath.getRoots();
        List<String> roots = new ArrayList<String>(sourceRoots.length);
        for (FileObject fo : sourceRoots) {
            String root = getRoot(fo);
            if (root != null) {
                roots.add(root);
            }
        }
        return roots.toArray(new String[0]);
    }
   
    /**
     * Returns allSourceRoots of original source roots.
     *
     * @return allSourceRoots of original source roots
     */
    public synchronized String[] getOriginalSourceRoots () {
        return getSourceRoots(originalSourcePath);
    }
   
    /**
     * Returns array of source roots.
     *
     * @return array of source roots
     */
    public synchronized String[] getSourceRoots () {
        return getSourceRoots(smartSteppingSourcePath);
    }
   
    /**
     * Returns the project's source roots.
     *
     * @return array of source roots belonging to the project
     */
    public String[] getProjectSourceRoots() {
        return projectSourceRoots;
    }
   
    /**
     * Sets array of source roots.
     *
     * @param sourceRoots a new array of sourceRoots
     */
    public void setSourceRoots (String[] sourceRoots) {
        if (logger.isLoggable(Level.FINE)) {
            logger.fine("SourcePathProviderImpl.setSourceRoots("+java.util.Arrays.asList(sourceRoots)+")");
        }
        Set<String> newRoots = new HashSet<String>(Arrays.asList(sourceRoots));
        ClassPath oldCP = null;
        ClassPath newCP = null;
        synchronized (this) {
            List<FileObject> sourcePath = new ArrayList<FileObject>(
                    Arrays.asList(smartSteppingSourcePath.getRoots()));
            List<FileObject> sourcePathOriginal = new ArrayList<FileObject>(
                    Arrays.asList(originalSourcePath.getRoots()));

            // First check whether there are some new source roots
            Set<String> newOriginalRoots = new HashSet<String>(newRoots);
            for (FileObject fo : sourcePathOriginal) {
                newOriginalRoots.remove(getRoot(fo));
            }
            if (!newOriginalRoots.isEmpty()) {
                for (String root : newOriginalRoots) {
                    FileObject fo = getFileObject(root);
                    if (fo != null) {
                        sourcePathOriginal.add(fo);
                    }
                }
                originalSourcePath =
                        ClassPathSupport.createClassPath(
                            sourcePathOriginal.toArray(new FileObject[0]));
                if (additionalSourceRoots == null) {
                    additionalSourceRoots = new HashSet<String>();
                }
                additionalSourceRoots.addAll(newOriginalRoots);
            }

            // Then correct the smart-stepping path
            Set<String> newSteppingRoots = new HashSet<String>(newRoots);
            for (FileObject fo : sourcePath) {
                newSteppingRoots.remove(getRoot(fo));
            }
            Set<FileObject> removedSteppingRoots = new HashSet<FileObject>();
            Set<FileObject> removedOriginalRoots = new HashSet<FileObject>();
            for (FileObject fo : sourcePath) {
                String spr = getRoot(fo);
                if (!newRoots.contains(spr)) {
                    removedSteppingRoots.add(fo);
                    if (additionalSourceRoots != null && additionalSourceRoots.contains(spr)) {
                        removedOriginalRoots.add(fo);
                        additionalSourceRoots.remove(spr);
                        if (additionalSourceRoots.size() == 0) {
                            additionalSourceRoots = null;
                        }
                    }
                }
            }
            if (removedOriginalRoots.size() > 0) {
                sourcePathOriginal.removeAll(removedOriginalRoots);
                originalSourcePath =
                        ClassPathSupport.createClassPath(
                            sourcePathOriginal.toArray(new FileObject[0]));
            }
            if (newSteppingRoots.size() > 0 || removedSteppingRoots.size() > 0) {
                for (String root : newSteppingRoots) {
                    FileObject fo = getFileObject(root);
                    if (fo != null) {
                        sourcePath.add(fo);
                    }
                }
                sourcePath.removeAll(removedSteppingRoots);
                oldCP = smartSteppingSourcePath;
                smartSteppingSourcePath =
                        ClassPathSupport.createClassPath(
                            sourcePath.toArray(new FileObject[0]));
                newCP = smartSteppingSourcePath;
            }
        }
       
        if (oldCP != null) {
            pcs.firePropertyChange (PROP_SOURCE_ROOTS, oldCP, newCP);
        }
    }
   
    /**
     * Adds property change listener.
     *
     * @param l new listener.
     */
    public void addPropertyChangeListener (PropertyChangeListener l) {
        pcs.addPropertyChangeListener (l);
    }

    /**
     * Removes property change listener.
     *
     * @param l removed listener.
     */
    public void removePropertyChangeListener (
        PropertyChangeListener l
    ) {
        pcs.removePropertyChangeListener (l);
    }
   
   
    // helper methods ..........................................................
   
    /**
     * Normalizes the given path by removing unnecessary "." and ".." sequences.
     * This normalization is needed because the compiler stores source paths like "foo/../inc.jsp" into .class files.
     * Such paths are not supported by our ClassPath API.
     * TODO: compiler bug? report to JDK?
     *
     * @param path path to normalize
     * @return normalized path without "." and ".." elements
     */
    public static String normalize(String path) {
      for (Matcher m = thisDirectoryPattern.matcher(path); m.find(); )
      {
        path = m.replaceAll("$1");
        m = thisDirectoryPattern.matcher(path);
      }
      for (Matcher m = parentDirectoryPattern.matcher(path); m.find(); )
      {
        if (!m.group(2).equals("..")) {
          path = path.substring(0, m.start()) + m.group(1) + path.substring(m.end());
          m = parentDirectoryPattern.matcher(path);       
        }
      }
      return path;
    }
   
    /**
     * Returns source root for given ClassPath root as String, or <code>null</code>.
     */
    private static String getRoot(FileObject fileObject) {
        File f = null;
        String path = "";
        try {
            if (fileObject.getFileSystem () instanceof JarFileSystem) {
                f = ((JarFileSystem) fileObject.getFileSystem ()).getJarFile ();
                if (!fileObject.isRoot()) {
                    path = "!/"+fileObject.getPath();
                }
            } else {
                f = FileUtil.toFile (fileObject);
            }
        } catch (FileStateInvalidException ex) {
        }
        if (f != null) {
            return f.getAbsolutePath () + path;
        } else {
            return null;
        }
    }

    /**
     * Returns FileObject for given String.
     */
    private FileObject getFileObject (String file) {
        File f = new File (file);
        FileObject fo = FileUtil.toFileObject (f);
        String path = null;
        if (fo == null && file.contains("!/")) {
            int index = file.indexOf("!/");
            f = new File(file.substring(0, index));
            fo = FileUtil.toFileObject (f);
            path = file.substring(index + "!/".length());
        }
        if (fo != null && FileUtil.isArchiveFile (fo)) {
            fo = FileUtil.getArchiveRoot (fo);
            if (path !=null) {
                fo = fo.getFileObject(path);
            }
        }
        return fo;
    }
   
    private class PathRegistryListener implements GlobalPathRegistryListener, PropertyChangeListener {
       
        public void pathsAdded(GlobalPathRegistryEvent event) {
            List<FileObject> addedRoots = new ArrayList<FileObject>();
            for (ClassPath cp : event.getChangedPaths()) {
                for (FileObject fo : cp.getRoots()) {
                    addedRoots.add(fo);
                }
            }
            if (addedRoots.size() > 0) {
                synchronized (SourcePathProviderImpl.this) {
                    List<FileObject> sourcePaths = new ArrayList<FileObject>(
                            Arrays.asList(originalSourcePath.getRoots()));
                    sourcePaths.addAll(addedRoots);
                    originalSourcePath =
                            ClassPathSupport.createClassPath(
                                sourcePaths.toArray(new FileObject[0]));

                    sourcePaths = new ArrayList<FileObject>(
                            Arrays.asList(smartSteppingSourcePath.getRoots()));
                    sourcePaths.addAll(addedRoots);
                    smartSteppingSourcePath =
                            ClassPathSupport.createClassPath(
                                sourcePaths.toArray(new FileObject[0]));
                }
                pcs.firePropertyChange (PROP_SOURCE_ROOTS, null, null);
            }
        }
       
        public void pathsRemoved(GlobalPathRegistryEvent event) {
            List<FileObject> removedRoots = new ArrayList<FileObject>();
            for (ClassPath cp : event.getChangedPaths()) {
                for (FileObject fo : cp.getRoots()) {
                    removedRoots.add(fo);
                }
            }
            if (removedRoots.size() > 0) {
                synchronized (SourcePathProviderImpl.this) {
                    List<FileObject> sourcePaths = new ArrayList<FileObject>(
                            Arrays.asList(originalSourcePath.getRoots()));
                    sourcePaths.removeAll(removedRoots);
                    originalSourcePath =
                            ClassPathSupport.createClassPath(
                                sourcePaths.toArray(new FileObject[0]));

                    sourcePaths = new ArrayList<FileObject>(
                            Arrays.asList(smartSteppingSourcePath.getRoots()));
                    sourcePaths.removeAll(removedRoots);
                    smartSteppingSourcePath =
                            ClassPathSupport.createClassPath(
                                sourcePaths.toArray(new FileObject[0]));
                }
                pcs.firePropertyChange (PROP_SOURCE_ROOTS, null, null);
            }
        }

        public void propertyChange(PropertyChangeEvent evt) {
            // JDK sources changed
            JavaPlatform[] platforms = JavaPlatformManager.getDefault ().
                getInstalledPlatforms ();
            boolean changed = false;
            synchronized (SourcePathProviderImpl.this) {
                List<FileObject> sourcePaths = new ArrayList<FileObject>(
                        Arrays.asList(originalSourcePath.getRoots()));
                for(JavaPlatform jp : platforms) {
                    FileObject[] roots = jp.getSourceFolders().getRoots ();
                    for (FileObject fo : roots) {
                        if (!sourcePaths.contains(fo)) {
                            sourcePaths.add(fo);
                            changed = true;
                        }
                    }
                }
                if (changed) {
                    originalSourcePath =
                            ClassPathSupport.createClassPath(
                                sourcePaths.toArray(new FileObject[0]));
                }
            }
            if (changed) {
                pcs.firePropertyChange (PROP_SOURCE_ROOTS, null, null);
            }
        }
    }
   
    private static final class FileObjectComparator implements Comparator<FileObject> {

        public int compare(FileObject fo1, FileObject fo2) {
            String r1 = getRoot(fo1);
            String r2 = getRoot(fo2);
            if (r1 == null) {
                return -1;
            }
            if (r2 == null) {
                return +1;
            }
            return r1.compareTo(r2);
        }
       
    }
}
TOP

Related Classes of org.netbeans.modules.scala.debugger.projects.SourcePathProviderImpl$PathRegistryListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.