/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.netbeans.modules.maven;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.swing.SwingUtilities;
import org.apache.maven.DefaultMaven;
import org.apache.maven.Maven;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.cli.MavenCli;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.model.Model;
import org.apache.maven.model.Resource;
import org.apache.maven.model.building.ModelBuildingException;
import org.apache.maven.model.building.ModelBuildingResult;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuilder;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.project.ProjectBuildingRequest;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.api.annotations.common.NullUnknown;
import org.netbeans.api.java.project.classpath.ProjectClassPathModifier;
import org.netbeans.api.project.Project;
import org.netbeans.api.queries.VisibilityQuery;
import org.netbeans.modules.maven.api.Constants;
import org.netbeans.modules.maven.api.FileUtilities;
import org.netbeans.modules.maven.api.NbMavenProject;
import org.netbeans.modules.maven.api.PluginPropertyUtils;
import org.netbeans.modules.maven.api.execute.ActiveJ2SEPlatformProvider;
import org.netbeans.modules.maven.configurations.M2ConfigProvider;
import org.netbeans.modules.maven.configurations.M2Configuration;
import org.netbeans.modules.maven.configurations.ProjectProfileHandlerImpl;
import org.netbeans.modules.maven.cos.CopyResourcesOnSave;
import org.netbeans.modules.maven.debug.MavenJPDAStart;
import org.netbeans.modules.maven.embedder.EmbedderFactory;
import org.netbeans.modules.maven.embedder.MavenEmbedder;
import org.netbeans.modules.maven.modelcache.MavenProjectCache;
import org.netbeans.modules.maven.options.MavenSettings;
import org.netbeans.modules.maven.problems.ProblemReporterImpl;
import org.netbeans.modules.maven.queries.PomCompilerOptionsQueryImpl;
import org.netbeans.modules.maven.queries.UnitTestsCompilerOptionsQueryImpl;
import org.netbeans.modules.maven.spi.nodes.OtherSourcesExclude;
import org.netbeans.modules.maven.spi.queries.JavaLikeRootProvider;
import org.netbeans.spi.java.project.support.LookupMergerSupport;
import org.netbeans.spi.project.ProjectState;
import org.netbeans.spi.project.support.LookupProviderSupport;
import org.netbeans.spi.project.ui.support.UILookupMergerSupport;
import org.openide.filesystems.FileAttributeEvent;
import org.openide.filesystems.FileChangeListener;
import org.openide.filesystems.FileEvent;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileRenameEvent;
import org.openide.filesystems.FileUtil;
import org.openide.util.Lookup;
import org.openide.util.NbBundle.Messages;
import org.openide.util.NbCollections;
import org.openide.util.RequestProcessor;
import org.openide.util.Utilities;
import org.openide.util.WeakListeners;
import org.openide.util.lookup.Lookups;
import org.openide.util.lookup.ProxyLookup;

/**
 * A Maven-based project.
 */
public final class NbMavenProjectImpl implements Project {


    private static final Logger LOG = Logger.getLogger(NbMavenProjectImpl.class.getName());
    
    //sequential execution might be necesary for #166919
    public static final RequestProcessor RELOAD_RP = new RequestProcessor("Maven project reloading", 1); //NOI18
    //minor optimization. In case the queue already holds the task and is not run, delay, if running reschedule.
    private final RequestProcessor.Task reloadTask = RELOAD_RP.create(new Runnable() {
        @Override
        public void run() {
            problemReporter.clearReports(); //#167741 -this will trigger node refresh?
            MavenProject prj = loadOriginalMavenProject(true);
            synchronized (NbMavenProjectImpl.this) {
                MavenProject old = project == null ? null : project.get();
                if (old != null && MavenProjectCache.isFallbackproject(prj)) {
                    prj.setPackaging(old.getPackaging()); //#229366 preserve packaging for broken projects to avoid changing lookup.
                }
                project = new SoftReference<MavenProject>(prj);
                if (hardReferencingMavenProject) {
                    hardRefProject = prj;
                }
            }
            ACCESSOR.doFireReload(watcher);
        }
    });
    private final FileObject fileObject;
    private final FileObject folderFileObject;
    private final File projectFile;
    private final Lookup basicLookup;
    private final Lookup completeLookup;
    private final Lookup lookup;
    private final Updater openedProjectUpdater;
    
    private Reference<MavenProject> project;
    private boolean hardReferencingMavenProject = false; //only should be true when project is open.
    private MavenProject hardRefProject;
    
    private ProblemReporterImpl problemReporter;
    private final @NonNull NbMavenProject watcher;
    private final M2ConfigProvider configProvider;
    private final @NonNull MavenProjectPropsImpl auxprops;
    private ProjectProfileHandlerImpl profileHandler;
    private CopyResourcesOnSave copyResourcesOnSave;
    private final Object COPYRESOURCES_LOCK = new Object();
    @org.netbeans.api.annotations.common.SuppressWarnings("MS_SHOULD_BE_FINAL")
    public static WatcherAccessor ACCESSOR = null;

    static {
        // invokes static initializer of ModelHandle.class
        // that will assign value to the ACCESSOR field above
        Class<?> c = NbMavenProject.class;
        try {
            Class.forName(c.getName(), true, c.getClassLoader());
        } catch (Exception ex) {
            LOG.log(Level.SEVERE, "very wrong, very wrong, yes indeed", ex);
        }
    }

    //#224012
    private ProjectOpenedHookImpl hookImpl;
    private Exception ex;
    private final Object LOCK_224012 = new Object();
    boolean setIssue224012(ProjectOpenedHookImpl hook, Exception exception) {
        synchronized (LOCK_224012) {
            if (hookImpl == null) {
                hookImpl = hook;
                ex = exception;
                return true;
            } else {
                LOG.log(Level.INFO, "    first creation stacktrace", ex);
                LOG.log(Level.INFO, "    second creation stacktrace", exception);
                LOG.log(Level.WARNING, "Spotted issue 224012 (https://netbeans.org/bugzilla/show_bug.cgi?id=224012). Please report the incident wth IDE log attached.");
                return false;
            }
        }
    }

    
    private final Object MODEL_LOCK = new Object();
    private Model model;
    public Model getRawModel() throws ModelBuildingException {
        synchronized(MODEL_LOCK) {
            if(model == null) {
                MavenEmbedder projectEmbedder = EmbedderFactory.getProjectEmbedder();
                ModelBuildingResult br = projectEmbedder.executeModelBuilder(getPOMFile());
                model = br.getRawModel();
            }
            return model;
        }
    }


    public static abstract class WatcherAccessor {

        public abstract NbMavenProject createWatcher(NbMavenProjectImpl proj);

        public abstract void doFireReload(NbMavenProject watcher);
    }

    /**
     * Creates a new instance of MavenProject, should never be called by user code.
     * but only by MavenProjectFactory!!!
     */
    NbMavenProjectImpl(FileObject folder, FileObject projectFO, ProjectState projectState) {
        this.projectFile = FileUtil.normalizeFile(FileUtil.toFile(projectFO));
        fileObject = projectFO;
        folderFileObject = folder;
        lookup = Lookups.proxy(new Lookup.Provider() {
            @Override
            public Lookup getLookup() {
                if (completeLookup == null) {
                    //not fully initialized constructor
                    LOG.log(Level.FINE, "accessing project's lookup before the instance is fully initialized at " + projectFile, new Exception());
                    assert basicLookup != null;
                    return basicLookup;
                } else {
                    return completeLookup;
                }
            }
        });
        watcher = ACCESSOR.createWatcher(this);
        openedProjectUpdater = new Updater(new FileProvider() {

            @Override
            public File[] getFiles() {
                File homeFile = FileUtil.normalizeFile(MavenCli.USER_MAVEN_CONFIGURATION_HOME);
                return new File[] {
                    new File(projectFile.getParentFile(), "nb-configuration.xml"), //NOI18N
                    projectFile,
                    new File(new File(projectFile.getParentFile(), ".mvn"), "maven.config"), //NOI18N
                    new File(homeFile, "settings.xml"), //NOI18N
                };
            }
        });
        problemReporter = new ProblemReporterImpl(this);
        M2AuxilaryConfigImpl auxiliary = new M2AuxilaryConfigImpl(folder, true);
        auxprops = new MavenProjectPropsImpl(auxiliary, this);
        profileHandler = new ProjectProfileHandlerImpl(this, auxiliary);
        configProvider = new M2ConfigProvider(this, auxiliary, profileHandler);
        // @PSP's and the like, and PackagingProvider impls, may check project lookup for e.g. NbMavenProject, so init lookup in two stages:
        basicLookup = createBasicLookup(projectState, auxiliary);
        //here we always load the MavenProject instance because we need to touch the packaging from pom.
        completeLookup = LookupProviderSupport.createCompositeLookup(basicLookup, new PackagingTypeDependentLookup(watcher));
    }

    public File getPOMFile() {
        return projectFile;
    }

    public @NonNull NbMavenProject getProjectWatcher() {
        return watcher;
    }

    public ProblemReporterImpl getProblemReporter() {
        return problemReporter;
    }

    public String getHintJavaPlatform() {
        String hint = getAuxProps().get(Constants.HINT_JDK_PLATFORM, true);
        if (hint == null) {
            hint = MavenSettings.getDefault().getDefaultJdk();
        }
        return hint == null || hint.isEmpty() ? null : hint;
    }

    /**
     * load a project with properties and profiles other than the current ones.
     * @param embedder embedder to use
     * @param activeProfiles
     * @param properties
     * @return
     */
    //TODO revisit usage, eventually should be only reuse MavenProjectCache
    public @NonNull MavenProject loadMavenProject(MavenEmbedder embedder, List<String> activeProfiles, Properties properties) {
        try {
            MavenExecutionRequest req = embedder.createMavenExecutionRequest();
            req.addActiveProfiles(activeProfiles);
            req.setPom(projectFile);
            req.setNoSnapshotUpdates(true);
            req.setUpdateSnapshots(false);
            //#238800 important to merge, not replace
            if (properties != null) {
                Properties uprops = req.getUserProperties();
                uprops.putAll(properties);
                req.setUserProperties(uprops);
            }
            //MEVENIDE-634 i'm wondering if this fixes the issue
            req.setInteractiveMode(false);
            req.setOffline(true);
            // recursive == false is important to avoid checking all submodules for extensions
            // that will not be used in current pom anyway..
            // #135070
            req.setRecursive(false);
            MavenExecutionResult res = embedder.readProjectWithDependencies(req, true);
            //#215159 clear the project building request, it references multiple Maven Models via the RepositorySession cache
            //is not used in maven itself, most likely used by m2e only..
            if (!res.hasExceptions()) {
                res.getProject().setProjectBuildingRequest(null);
                return res.getProject();
            } else {
                List<Throwable> exc = res.getExceptions();
                for (Throwable ex : exc) {
                    LOG.log(Level.FINE, "Exception thrown while loading maven project at " + getProjectDirectory(), ex); //NOI18N
                }
            }
        } catch (RuntimeException exc) {
            //guard against exceptions that are not processed by the embedder
            //#136184 NumberFormatException
            LOG.log(Level.INFO, "Runtime exception thrown while loading maven project at " + getProjectDirectory(), exc); //NOI18N
        }
        return MavenProjectCache.getFallbackProject(this.getPOMFile());
    }
    
    /**
     * replacement for MavenProject.getParent() which has bad long term memory behaviour. We offset it by recalculating/reparsing everything
     * therefore should not be used lightly!
     * pass a MavenProject instance and current configuration and other settings will be applied when loading the parent.
     * @param project
     * @return null or the parent mavenproject
     */
    
    public MavenProject loadParentOf(MavenEmbedder embedder, MavenProject project) throws ProjectBuildingException {

        MavenProject parent = null;
        ProjectBuilder builder = embedder.lookupComponent(ProjectBuilder.class);
        MavenExecutionRequest req = embedder.createMavenExecutionRequest();
        M2Configuration active = configProvider.getActiveConfiguration();
        req.addActiveProfiles(active.getActivatedProfiles());
        req.setNoSnapshotUpdates(true);
        req.setUpdateSnapshots(false);
        req.setInteractiveMode(false);
        req.setRecursive(false);
        req.setOffline(true);
        //#238800 important to merge, not replace
        Properties uprops = req.getUserProperties();
        uprops.putAll(MavenProjectCache.createUserPropsForProjectLoading(active.getProperties()));
        req.setUserProperties(uprops);
        
        ProjectBuildingRequest request = req.getProjectBuildingRequest();
        request.setRemoteRepositories(project.getRemoteArtifactRepositories());
        DefaultMaven maven = (DefaultMaven) embedder.lookupComponent(Maven.class);
        
        request.setRepositorySession(maven.newRepositorySession(req));

        if (project.getParentFile() != null) {
            parent = builder.build(project.getParentFile(), request).getProject();
        } else if (project.getModel().getParent() != null) {
            parent = builder.build(project.getParentArtifact(), request).getProject();
        }
        //clear the project building request, it references multiple Maven Models via the RepositorySession cache
        //is not used in maven itself, most likely used by m2e only..
        if (parent != null) {
            parent.setProjectBuildingRequest(null);
        }
        MavenEmbedder.normalizePaths(parent);
        return parent;
    }

    public List<String> getCurrentActiveProfiles() {
        List<String> toRet = new ArrayList<String>();
        toRet.addAll(configProvider.getActiveConfiguration().getActivatedProfiles());
        return toRet;
    }


    //#172952 for property expression resolution we need this to include
    // the properties of the platform to properly resolve stuff like com.sun.boot.class.path
    public Map<? extends String,? extends String> createSystemPropsForPropertyExpressions() {
        Map<String,String> props = NbCollections.checkedMapByCopy(EmbedderFactory.getProjectEmbedder().getSystemProperties(), String.class, String.class, true);
        ActiveJ2SEPlatformProvider platformProvider = getLookup().lookup(ActiveJ2SEPlatformProvider.class);
        if (platformProvider != null) { // may be null inside PackagingProvider
            props.putAll(platformProvider.getJavaPlatform().getSystemProperties());
        }       
        return props;
    }
    
    public  Map<? extends String,? extends String> createUserPropsForPropertyExpressions() {
         return NbCollections.checkedMapByCopy(configProvider.getActiveConfiguration().getProperties(), String.class, String.class, true);
    }

    /**
     * getter for the maven's own project representation.. this instance is cached but gets reloaded
     * when one the pom files have changed.
     */
    public @NonNull MavenProject getOriginalMavenProject() {
        MavenProject mp;
        synchronized (this) {
            mp = project == null ? null : project.get();
            if (mp != null) {
                return mp;
            }
            if (mp == null) {
                // PENDING: should be the whole project load synchronized ?
                mp = loadOriginalMavenProject(false);
                project = new SoftReference<MavenProject>(mp);
                if (hardReferencingMavenProject) {
                    hardRefProject = mp;
                }
            }
        }
        // in case someone got already information from the NbMavenProject:
        ACCESSOR.doFireReload(watcher);
        return mp;
    }
    
    /**
     * a marginally unreliable, non blocking method for figuring if the model is loaded or not.
     * @return 
     */
    public boolean isMavenProjectLoaded() {
        Reference<MavenProject> prj = project;
        if (prj != null) {
            return prj.get() != null;
        }
        return false;
    }
    
    /**
     * open projects should always hard reference the Mavenproject instance to prevent it from
     * being GCed, the instance will get reloaded almost instantly anyway
     */
    void startHardReferencingMavenPoject() {
        synchronized (this) {
            hardReferencingMavenProject = true;
            MavenProject mp = project == null ? null : project.get();
            hardRefProject = mp;
        }
    }
    /**
     * open projects should always hard reference the Mavenproject instance to prevent it from
     * being GCed, the instance will get reloaded almost instantly anyway
     */
    void stopHardReferencingMavenPoject() {
        synchronized (this) {
            hardReferencingMavenProject = false;
            hardRefProject = null;
        }
    }
    

    @Messages({
        "TXT_RuntimeException=RuntimeException occurred in Apache Maven embedder while loading",
        "TXT_RuntimeExceptionLong=RuntimeException occurred in Apache Maven embedder while loading the project. \n"
            + "This is preventing the project model from loading properly. \n"
            + "Please file a bug report with details about your project and the IDE's log file.\n\n"
    })
    private @NonNull MavenProject loadOriginalMavenProject(boolean reload) {
        MavenProject newproject;
        try {
            synchronized(MODEL_LOCK) {
                model = null;
            }
            newproject = MavenProjectCache.getMavenProject(this.getPOMFile(), reload);
            if (newproject == null) { //null when no pom.xml in project folder..
                newproject = MavenProjectCache.getFallbackProject(projectFile);
            }
            final MavenExecutionResult res = MavenProjectCache.getExecutionResult(newproject);
            final MavenProject np = newproject;
        } finally {
            if (LOG.isLoggable(Level.FINE) && SwingUtilities.isEventDispatchThread()) {
                LOG.log(Level.FINE, "Project " + getProjectDirectory().getPath() + " loaded in AWT event dispatching thread!", new RuntimeException());
            }
        }
        assert newproject != null;
        return newproject;
    }



    public RequestProcessor.Task fireProjectReload() {
        //#227101 not only AWT and project read/write mutex has to be checked, there are some additional more
        //complex scenarios that can lead to deadlock. Just give up and always fire changes in separate RP.
        if (Boolean.getBoolean("test.reload.sync")) {
            reloadTask.run();
            //for tests just do sync reload, even though silly, even sillier is to attempt to sync the threads..
        } else {
            reloadTask.schedule(0); //asuming here that schedule(0) will move the scheduled task in the queue if not yet executed
        }
        return reloadTask;
    }

    public static void refreshLocalRepository(NbMavenProjectImpl project) {
        File file = project.getEmbedder().getLocalRepositoryFile();
        FileUtil.refreshFor(file);
    }

    /** Begin listening to pom.xml changes. */
    void attachUpdater() {
        openedProjectUpdater.attachAll();
    }
   void detachUpdater() {
        openedProjectUpdater.detachAll();
    }

    /**
     * The root directory of the project where the POM resides.
     */
    @Override
    public FileObject getProjectDirectory() {
        return folderFileObject;
    }

    public @CheckForNull String getArtifactRelativeRepositoryPath() {
        Artifact artifact = getOriginalMavenProject().getArtifact();
        if (artifact == null) {
            return null;
        }
        return getArtifactRelativeRepositoryPath(artifact);
    }

    /**
     * path of test artifact in local repository
     * @return
     */
    public @CheckForNull String getTestArtifactRelativeRepositoryPath() {
        Artifact main = getOriginalMavenProject().getArtifact();
        if (main == null) {
            return null;
        }

        ArtifactHandlerManager artifactHandlerManager = getEmbedder().lookupComponent(ArtifactHandlerManager.class);
        assert artifactHandlerManager != null : "ArtifactHandlerManager component not found in maven";

        Artifact test = new DefaultArtifact(main.getGroupId(), main.getArtifactId(), main.getVersionRange(),
                Artifact.SCOPE_TEST, "test-jar", "tests", artifactHandlerManager.getArtifactHandler("test-jar"));
        return getArtifactRelativeRepositoryPath(test);

    }

    public String getArtifactRelativeRepositoryPath(@NonNull Artifact artifact) {
        return getEmbedder().getLocalRepository().pathOf(artifact);
    }

    public MavenEmbedder getEmbedder() {
        return EmbedderFactory.getProjectEmbedder();
    }

    public @NonNull MavenProjectPropsImpl getAuxProps() {
        return auxprops;
    }

    /**
     * The method will migrate to regular FileUtilities after NB13 release. The issue is that the result of 
     * {@link FileUtilities#convertStringToUri(java.lang.String)} result depends on whether the directory 
     * identified by the string exists or not. If it exists, the URI ends with a "/". For non-existent directories
     * the URI lacks the trailing "/". This can break URI keys in a Map (if the directory gets created) and prevents
     * from creating a ClassPath from such URLs (/ is checked). But FileUtilities is API and this behaviour is there for
     * ages, so the correction should be added with a parameter.
     */
    public static @NullUnknown URI convertStringToUri(@NullAllowed String str, boolean slashIfNotExist) {
        if (str != null) {
            File fil = new File(str);
            fil = FileUtil.normalizeFile(fil);
            // this conversion returns URIs that end with "/" if fil is an existing directory, but returns
            // without the slash if the directory just does not exist yet.
            URI uri = Utilities.toURI(fil);
            String s = uri.toString();
            if (slashIfNotExist && !s.endsWith("/") && (fil.isDirectory() || !fil.exists())) { // NOI18N
                try {
                    return new URI(s + "/"); // NOI18N
                } catch (URISyntaxException ex) {
                    throw new IllegalArgumentException(str);
                }
            } else {
                return uri;
            }
        }
        return null;
    }

    public URI[] getSourceRoots(boolean test) {
        List<URI> uris = new ArrayList<URI>();
        for (String root : test ? getOriginalMavenProject().getTestCompileSourceRoots() : getOriginalMavenProject().getCompileSourceRoots()) {
            uris.add(convertStringToUri(root, true));
        }
        for (JavaLikeRootProvider rp : getLookup().lookupAll(JavaLikeRootProvider.class)) {
            // XXX for a few purposes (listening) it is desirable to list these even before they exist, but usually it is just noise (cf. #196414 comment #2)
            FileObject root = getProjectDirectory().getFileObject("src/" + (test ? "test" : "main") + "/" + rp.kind());
            if (root != null && root.isFolder()) {
                uris.add(root.toURI());
            }
        }
        return uris.toArray(new URI[uris.size()]);
    }

    public URI[] getGeneratedSourceRoots(boolean test) {
        //#241874 calculate the test source roots up front just in case they are in target/generated-sources. if so, remove the from non-test generated source roots
        Set<URI> BHTestUris = new HashSet<URI>();
        String[] buildHelpers = PluginPropertyUtils.getPluginPropertyList(this,
                "org.codehaus.mojo", //NOI18N
                "build-helper-maven-plugin", "sources", "source", "add-test-source"); //NOI18N
        if (buildHelpers != null && buildHelpers.length > 0) {
            File root = FileUtil.toFile(getProjectDirectory());
            for (String helper : buildHelpers) {
                BHTestUris.add(FileUtilities.getDirURI(root, helper));
            }
        }
        
        
        
        URI uri = FileUtilities.getDirURI(getProjectDirectory(), test ? "target/generated-test-sources" : "target/generated-sources"); //NOI18N
        Set<URI> uris = new HashSet<URI>();
        File[] roots = Utilities.toFile(uri).listFiles();
        if (roots != null) {
            for (File root : roots) {
                if (!VisibilityQuery.getDefault().isVisible(root)) { //#214002
                   continue;
                }
                if (!test && root.getName().startsWith("test-")) {
                    continue;
                }
                File[] kids = root.listFiles();
                URI u = Utilities.toURI(root);
                if (!test && BHTestUris.contains(u)) {
                    continue; //a test source root was put in target/generated-sources - #241874
                }
                if (kids != null && /* #190626 */kids.length > 0) {
                    uris.add(u);
                } else {
                    watcher.addWatchedPath(u); //TODO who reacts to this?
                }
            }
        }
        if (test) { // MCOMPILER-167
            roots = Utilities.toFile(FileUtilities.getDirURI(getProjectDirectory(), "target/generated-sources")).listFiles();
            if (roots != null) {
                for (File root : roots) {
                    if (!VisibilityQuery.getDefault().isVisible(root)) { //#214002
                       continue;
                    }                    
                    if (root.getName().startsWith("test-")) {
                        File[] kids = root.listFiles();
                        if (kids != null && kids.length > 0) {
                            uris.add(Utilities.toURI(root));
                        } else {
                            watcher.addWatchedPath(Utilities.toURI(root)); //TODO who reacts to this?
                        }
                    }
                }
            }
        }

        if (!test) {
            buildHelpers = PluginPropertyUtils.getPluginPropertyList(this,
                    "org.codehaus.mojo", //NOI18N
                    "build-helper-maven-plugin", "sources", "source", "add-source"); //NOI18N
            if (buildHelpers != null && buildHelpers.length > 0) {
                File root = FileUtil.toFile(getProjectDirectory());
                for (String helper : buildHelpers) {
                    uris.add(FileUtilities.getDirURI(root, helper));
                }
            }
        } else {
            uris.addAll(BHTestUris);
        }

        return uris.toArray(new URI[uris.size()]);
    }

    public URI getWebAppDirectory() {
        //TODO hack, should be supported somehow to read this..
        String prop = PluginPropertyUtils.getPluginProperty(this, Constants.GROUP_APACHE_PLUGINS,
                Constants.PLUGIN_WAR, //NOI18N
                "warSourceDirectory", //NOI18N
                "war", null); //NOI18N

        prop = prop == null ? "src/main/webapp" : prop; //NOI18N

        return FileUtilities.getDirURI(getProjectDirectory(), prop);
    }

    public URI getSiteDirectory() {
        //TODO hack, should be supported somehow to read this..
        String prop = PluginPropertyUtils.getPluginProperty(this, Constants.GROUP_APACHE_PLUGINS,
                Constants.PLUGIN_SITE, //NOI18N
                "siteDirectory", //NOI18N
                "site", null); //NOI18N

        prop = prop == null ? "src/site" : prop; //NOI18N

        return FileUtilities.getDirURI(getProjectDirectory(), prop);
    }

    public URI getEarAppDirectory() {
        //TODO hack, should be supported somehow to read this..
        String prop = PluginPropertyUtils.getPluginProperty(this, Constants.GROUP_APACHE_PLUGINS,
                Constants.PLUGIN_EAR, //NOI18N
                "earSourceDirectory", //NOI18N
                "ear", null); //NOI18N

        prop = prop == null ? "src/main/application" : prop; //NOI18N

        return FileUtilities.getDirURI(getProjectDirectory(), prop);
    }

    public URI[] getResources(boolean test) {
        List<URI> toRet = new ArrayList<URI>();
        URI projectroot = getProjectDirectory().toURI();
        Set<URI> sourceRoots = null;
        List<Resource> res = test ? getOriginalMavenProject().getTestResources() : getOriginalMavenProject().getResources();
        LBL : for (Resource elem : res) {
            String dir = elem.getDirectory();
            if (dir == null) {
                continue; // #191742
            }
            URI uri = FileUtilities.getDirURI(getProjectDirectory(), dir);
            if (elem.getTargetPath() != null || !elem.getExcludes().isEmpty() || !elem.getIncludes().isEmpty()) {
                URI rel = projectroot.relativize(uri);
                if (rel.isAbsolute()) { //outside of project directory
                    continue;// #195928, #231517
                }
                if (sourceRoots == null) {
                    sourceRoots = new HashSet<URI>();
                    sourceRoots.addAll(Arrays.asList(getSourceRoots(true)));
                    sourceRoots.addAll(Arrays.asList(getSourceRoots(false)));
                    //should we also consider generated sources? most like not necessary
                }
                for (URI sr : sourceRoots) {
                    if (!uri.relativize(sr).isAbsolute()) {
                        continue LBL;// #195928, #231517
                    }
                }
                //hope for the best now
            }
//            if (new File(uri).exists()) {
            toRet.add(uri);
//            }
        }
        return toRet.toArray(new URI[toRet.size()]);
    }

    public File[] getOtherRoots(boolean test) {
        URI uri = FileUtilities.getDirURI(getProjectDirectory(), test ? "src/test" : "src/main"); //NOI18N
        Set<File> toRet = new HashSet<File>();
        File fil = Utilities.toFile(uri);
        if (fil.exists()) {
            try {
                Path sourceRoot = fil.toPath();
                OtherRootsVisitor visitor = new OtherRootsVisitor(getLookup(), sourceRoot);
                Files.walkFileTree(sourceRoot, visitor);
                toRet.addAll(visitor.getOtherRoots());
            } catch (IOException ex) {
                // log as info to keep trace about possible problems, 
                // but lets not be too agressive with level and notification                
                // see also issue #251071
                LOG.log(Level.INFO, null, ex);
            }
        }
        URI[] res = getResources(test);
        for (URI rs : res) {
            File fl = Utilities.toFile(rs);
            //in node view we need only the existing ones, if anything else needs all,
            // a new method is probably necessary..
            if (fl.exists()) {
                toRet.add(fl);
            }
        }
        return toRet.toArray(new File[0]);
    }

    private static class OtherRootsVisitor extends SimpleFileVisitor<Path> {

        private final Lookup lookup;
        private final List<Path> otherRoots;
        private final Path sourceRoot;

        public OtherRootsVisitor(Lookup lookup, Path sourceRoot) {
            this.lookup = lookup;
            this.sourceRoot = sourceRoot;
            this.otherRoots = new ArrayList<>();
        }

        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
            // To avoid including src/main and src/test directories
            if (sourceRoot.equals(dir)) {
                return FileVisitResult.CONTINUE;
            }

            if(!VisibilityQuery.getDefault().isVisible(dir.toFile())) {
                return FileVisitResult.SKIP_SUBTREE;
            }
            
            for (OtherSourcesExclude rp : lookup.lookupAll(OtherSourcesExclude.class)) {
                for (Path folder : rp.excludedFolders()) {
                    // In case of excluded folders (e.g. src/main/java) we can simply skip whole subtree
                    if (folder.equals(dir)) {
                        return FileVisitResult.SKIP_SUBTREE;
                    }

                    // We are vising directory which is a parent of one of excluded directory.
                    // In such case we don't want to skip the subtree (b/c it might contain directories
                    // that falling under other roots), but we also don't want to add it to the results
                    // (to avoid adding everything)
                    if (folder.startsWith(dir)) {
                        return FileVisitResult.CONTINUE;
                    }
                }
            }
            for (JavaLikeRootProvider rp : lookup.lookupAll(JavaLikeRootProvider.class)) {
                if (rp.kind().equalsIgnoreCase(dir.getFileName().toString())) {
                    return FileVisitResult.SKIP_SUBTREE;
                }
            }

            // If the directory wasn't excluded until now, it should be shown in Other Sources node
            if (isOtherRoot(dir)) {
                otherRoots.add(dir);
            }
            return FileVisitResult.CONTINUE;
        }

        private boolean isOtherRoot(Path dir) throws IOException {
            if (!dir.toFile().isDirectory() || Files.isHidden(dir)) {
                return false;
            }

            // Walk through the other roots and check if a parent of this dir is
            // already available in other roots to avoid folder duplication
            for (Path path : otherRoots) {
                if (dir.startsWith(path)) {
                    return false;
                }
            }
            return true;
        }

        public List<File> getOtherRoots() {
            List<File> result = new ArrayList<>();
            for (Path path : otherRoots) {
                result.add(path.toFile());
            }
            return Collections.unmodifiableList(result);
        }
    }

    @Override
    public Lookup getLookup() {
        return lookup;
    }
    
    CopyResourcesOnSave getCopyOnSaveResources() {
        synchronized (COPYRESOURCES_LOCK) {
            if (copyResourcesOnSave == null) {
                copyResourcesOnSave = new CopyResourcesOnSave(watcher, this);
            }
            return copyResourcesOnSave;
        }
    }

    private static class PackagingTypeDependentLookup extends ProxyLookup implements PropertyChangeListener {

        //#243866 both NbMavenProject and PackagingTypeDependentLookup are hard referenced from NbMavenProjectImpl
        //it should be safe to weak reference here, all should be GCed together.
        private final WeakReference<NbMavenProject> watcherRef;
        private String packaging;
        private final Lookup general;
        
        private volatile List<String> currentIds = new ArrayList<>();

        @SuppressWarnings("LeakingThisInConstructor")
        PackagingTypeDependentLookup(NbMavenProject watcher) {
            this.watcherRef = new WeakReference<NbMavenProject>(watcher);
            //needs to be kept around to prevent recreating instances
            general = Lookups.forPath("Projects/org-netbeans-modules-maven/Lookup"); //NOI18N
            check();
            watcher.addPropertyChangeListener(WeakListeners.propertyChange(this, watcher));
        }
        
        private String pluginDirectory(Artifact pluginArtifact) {
            String groupId = pluginArtifact.getGroupId();
            String artId = pluginArtifact.getArtifactId();
            
            return groupId + ":" + artId;
        }
        
        /**
         * Defines at least some order: let the layer positions to 
         * @param componentSet
         * @return 
         */
        private List<String> partialComponentsOrder(Collection<String> componentSet) {
            List<FileObject> fos = new ArrayList<>();
            FileObject root = FileUtil.getConfigFile("Projects/org-netbeans-modules-maven");
            for (String s : componentSet) {
                FileObject f = root.getFileObject(s);
                if (f != null) {
                    fos.add(f);
                }
            }
            List<String> orderedNames = FileUtil.getOrder(fos, false).stream().map(FileObject::getNameExt).collect(Collectors.toList());
            List<String> origList = new ArrayList<>(componentSet);
            origList.removeAll(orderedNames);
            orderedNames.addAll(origList);
            return orderedNames;
        }

        private void check() {
            //this call effectively calls project.getLookup(), when called in constructor will get back to the project's baselookup only.
            // but when called from propertyChange() then will call on entire composite lookup, is it a problem?  #230469
            List<String> newComponents = new ArrayList<>();
            NbMavenProject watcher = watcherRef.get();
            String newPackaging = packaging != null ? packaging : NbMavenProject.TYPE_JAR;
            List<Lookup> lookups = new ArrayList<>();
            List<String> old = currentIds;
            if (watcher != null) {
                newPackaging = watcher.getPackagingType(); 
                if (newPackaging == null) {
                    newPackaging = NbMavenProject.TYPE_JAR;
                }
                Set<Artifact> arts = watcher.getMavenProject().getPluginArtifacts();
                List<String> compNames = new ArrayList<>();
                if (arts != null) {
                    for (Artifact a : arts) {
                        compNames.add(pluginDirectory(a));
                    }
                }
                compNames.add(newPackaging);
                
                newComponents = partialComponentsOrder(compNames);
            } else {
                newComponents.add(newPackaging);
            }
            
            if (!newComponents.equals(old)) {
                for (String s : newComponents) {
                    lookups.add(Lookups.forPath("Projects/org-netbeans-modules-maven/" + s + "/Lookup")); // NOI18N
                }
                // put the general lookup last, so plugin - specific ones can override it
                lookups.add(general);
                lookups.add(Lookups.forPath("Projects/org-netbeans-modules-maven/_any/Lookup")); // NOI18N
                synchronized (this) {
                    if (currentIds != old) {
                        // the next computation started after us, do not interfere.
                        return;
                    }
                    currentIds = newComponents;
                }
                setLookups(lookups.toArray(new Lookup[lookups.size()]));
            }
        }
        
        public @Override void propertyChange(PropertyChangeEvent evt) {
            if (NbMavenProject.PROP_PROJECT.equals(evt.getPropertyName())) {
                check();
            }
        }
    }

    private Lookup createBasicLookup(ProjectState state, M2AuxilaryConfigImpl auxiliary) {
        return Lookups.fixed(
                    this,
                    fileObject,
                    auxiliary,
                    auxiliary.getProblemProvider(),
                    auxprops,
                    new MavenProjectPropsImpl.Merger(auxprops),
                    profileHandler,
                    configProvider,
                    problemReporter,
                    watcher,
                    state,
                    UILookupMergerSupport.createPrivilegedTemplatesMerger(),
                    UILookupMergerSupport.createRecommendedTemplatesMerger(),
                    UILookupMergerSupport.createProjectProblemsProviderMerger(),
                    LookupProviderSupport.createSourcesMerger(),
                    LookupProviderSupport.createSharabilityQueryMerger(),
                    ProjectClassPathModifier.extenderForModifier(this),
                    LookupMergerSupport.createClassPathModifierMerger(),
                    new UnitTestsCompilerOptionsQueryImpl(this),
                    new PomCompilerOptionsQueryImpl(this),
                    LookupMergerSupport.createCompilerOptionsQueryMerger(),
                    MavenJPDAStart.create(this)
        );
    }

    //MEVENIDE-448 seems to help against creation of duplicate project instances
    // no idea why, it's supposed to be ProjectManager job.. maybe related to
    // maven impl of SubProjectProvider or FileOwnerQueryImplementation
    //TODO need to investigate why it's like that..
    
    //a renamed FileObject for project folder stays the same, changing the identity of the project, we have to use File.
    @Override
    public int hashCode() {
        return getPOMFile().hashCode() * 13;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Project) {
            NbMavenProjectImpl impl;
            if (obj instanceof NbMavenProjectImpl) {
                impl = ((NbMavenProjectImpl) obj);
            } else {
                impl = ((Project) obj).getLookup().lookup(NbMavenProjectImpl.class);
            }
            if (impl != null) {
                return getPOMFile().equals(impl.getPOMFile());
            }
        }
        return false;
    }

    @Override
    public String toString() {
        return "Maven[" + getPOMFile().getAbsolutePath() + "]"; //NOI18N

    }
    
    interface FileProvider {
        File[] getFiles();
    }

    private class Updater implements FileChangeListener {

        
        private final FileProvider fileProvider;
        private List<File> filesToWatch;
        private long lastTime = 0;
        
        private Map<File, Long> lastMods;
        
        /** Relative file paths to watch. */
        Updater(FileProvider toWatch) {
            fileProvider = toWatch;            
        }

        @Override
        public void fileAttributeChanged(FileAttributeEvent fileAttributeEvent) {
        }

        @Override
        public void fileChanged(FileEvent fileEvent) {
                if (lastTime < fileEvent.getTime()) {
                    lastTime = System.currentTimeMillis();
//                    System.out.println("fired based on " + fileEvent.getFile() + fileEvent.getTime());
                    NbMavenProject.fireMavenProjectReload(NbMavenProjectImpl.this);
                }
        }

        @Override
        public void fileDataCreated(FileEvent fileEvent) {
                if (lastTime < fileEvent.getTime()) {
                    lastTime = System.currentTimeMillis();
//                    System.out.println("fired based on " + fileEvent.getFile() + fileEvent.getTime());
                    NbMavenProject.fireMavenProjectReload(NbMavenProjectImpl.this);
                }
        }

        @Override
        public void fileDeleted(FileEvent fileEvent) {
                lastTime = System.currentTimeMillis();
                NbMavenProject.fireMavenProjectReload(NbMavenProjectImpl.this);
        }

        @Override
        public void fileFolderCreated(FileEvent fileEvent) {
            //TODO possibly remove this fire.. watch for actual path..
//            NbMavenProject.fireMavenProjectReload(NbMavenProjectImpl.this);
        }    

        @Override
        public void fileRenamed(FileRenameEvent fileRenameEvent) {
        }

        synchronized void attachAll() {
            this.filesToWatch = new ArrayList<>(Arrays.asList(fileProvider.getFiles()));
            
            filesToWatch.addAll(getParents()); 
            Collections.sort(filesToWatch);
            for (File file : filesToWatch) {
                try {
                    FileUtil.addFileChangeListener(this, file);
                } catch (IllegalArgumentException ex) {
                    //giving up  on ever figuring why OPH is sometimes calls opened() twice in a row on single project.
                    //There's way too many moving parts. 
                    // * project lookup could be creating multiple instances of OPH
                    // * a close or open method for a random project/OPH could throw exception skipping our close? 
                    //   while OPL catches RuntimeExceptions, OPH merger bypasses that behaviour and handles all OPH as unit.
                    // * something in OPL or Group is wrong in terms of threading, timing or open/close projects calculation (could be equals/hascode on project related)
                    LOG.log(Level.INFO, "project opened twice in a row, issue #236211 for " + projectFile.getAbsolutePath(), ex);
                    Thread.dumpStack();
                    assert false : "project opened twice in a row, issue #236211 for " + projectFile.getAbsolutePath();
                }
            }
            
            if(lastMods == null) {
                // attached for the first time, 
                // preserve lastModified of interestig files 
                lastMods = new HashMap<>(filesToWatch.size());
                for (File file : filesToWatch) {
                    lastMods.put(file, file.lastModified());
                }
            } else {
                for (Map.Entry<File, Long> e : lastMods.entrySet()) {
                    File file = e.getKey();
                    long ts = file.lastModified();
                    if( e.getValue() < ts ) {
                        // attached after being previously dettached and 
                        // lastModified of an interesting file changed in the meantime 
                        // -> force pom refresh
                        lastMods.put(file, ts);
                        NbMavenProject.fireMavenProjectReload(NbMavenProjectImpl.this);
                    }
                }
                
            }            
        }

        protected List<File> getParents() {
            LinkedList<File> ret = new LinkedList<>();
            MavenProject project = getOriginalMavenProject();
            while(true) {
                try {
                    MavenProject parent = loadParentOf(getEmbedder(), project);
                    File parentFile = parent != null ? parent.getFile() : null;
                    if(parentFile != null) {
                        ret.add(parentFile);
                        project = parent;
                    } else {
                        break;
                    }
                } catch (ProjectBuildingException ex) {
                    break;
                }
            } 
            return ret;
        }

        synchronized void detachAll() {
            if (filesToWatch != null) {
                List<File> toWatch = filesToWatch;
                filesToWatch = null;
                for (File file : toWatch) {
                    try {
                        FileUtil.removeFileChangeListener(this, file);
                    } catch (IllegalArgumentException ex) {
                        LOG.log(Level.INFO, "project closed twice in a row, issue #236211 for " + projectFile.getAbsolutePath(), ex);
                        Thread.dumpStack();
                        assert false : "project closed twice in a row, issue #236211 for " + projectFile.getAbsolutePath();
                    }
                }
            }
        }
    }

}
