All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.modules.maven.problems.MissingModulesProblemProvider Maven / Gradle / Ivy

There is a newer version: RELEASE240
Show newest version
/*
 * 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.problems;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.SwingUtilities;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.api.project.Project;
import org.netbeans.modules.autoupdate.ui.api.PluginManager;
import org.netbeans.modules.maven.api.NbMavenProject;
import static org.netbeans.modules.maven.problems.Bundle.*;
import org.netbeans.spi.project.ProjectServiceProvider;
import org.netbeans.spi.project.ui.ProjectProblemResolver;
import org.netbeans.spi.project.ui.ProjectProblemsProvider;
import org.openide.modules.ModuleInfo;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;

/**
 *
 * @author mkleint
 */
public class MissingModulesProblemProvider implements ProjectProblemsProvider {
    private static final RequestProcessor RP  = new RequestProcessor(MissingModulesProblemProvider.class);
    
    @NbBundle.Messages({
        "ERR_MissingJ2eeModule=Maven Java EE support missing",
        "MSG_MissingJ2eeModule=You are missing the Maven Java EE support module in your installation. "
        + "This means that all EE-related functionality (for example, Deployment, File templates) is missing. "
        + "The most probable cause is that part of the general Java EE support is missing as well. "
        + "Please go to Tools/Plugins and install the plugins related to Java EE."
    })
    @ProjectServiceProvider(service = ProjectProblemsProvider.class, projectType = "org-netbeans-modules-maven")
    public static ProjectProblemsProvider j2ee(Project project) {
        Set packs = new HashSet();
        packs.add(NbMavenProject.TYPE_WAR);
        packs.add(NbMavenProject.TYPE_EAR);
        packs.add(NbMavenProject.TYPE_EJB);
        return new MissingModulesProblemProvider(project, packs, "org.netbeans.modules.maven.j2ee", "org.netbeans.modules.j2ee.kit", ERR_MissingJ2eeModule(), MSG_MissingJ2eeModule());
    }
    @NbBundle.Messages({
        "ERR_MissingApisupportModule=Maven NetBeans Module Projects support missing",
        "MSG_MissingApisupportModule=You are missing the Maven NetBeans Module Projects module in your installation. "
        + "This means that all NetBeans Platform functionality (for example, API wizards, running Platform applications) is missing. "
        + "The most probable cause is that part of the general Platform development support is missing as well. "
        + "Please go to Tools/Plugins and install the plugins related to NetBeans development."
    })
    @ProjectServiceProvider(service = ProjectProblemsProvider.class, projectType = "org-netbeans-modules-maven")
    public static ProjectProblemsProvider apisupport(Project project) {
        Set packs = new HashSet();
        packs.add(NbMavenProject.TYPE_NBM);
        packs.add(NbMavenProject.TYPE_NBM_APPLICATION);
        return new MissingModulesProblemProvider(project, packs, "org.netbeans.modules.maven.apisupport", "org.netbeans.modules.apisupport.kit", ERR_MissingApisupportModule(), MSG_MissingApisupportModule());
    }
    
    
    private final PropertyChangeSupport support = new PropertyChangeSupport(this);
    private final Project project;
    private EnablementListener listener;
    private String lastPackaging;
    private final AtomicBoolean projectListenerSet = new AtomicBoolean(false);
    private final PropertyChangeListener projectListener = new PropertyChangeListener() {

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            if (NbMavenProject.PROP_PROJECT.equals(evt.getPropertyName())) {
                if (lastPackaging != null) {
                    if (!lastPackaging.equals(project.getLookup().lookup(NbMavenProject.class).getPackagingType())) {
                        //reset only if packaging changed, that's when maybe the missing modules do or don't matter anymore
                        firePropertyChange();
                    }
                }
            }
        }
    };
    private final Set packagings;
    private final String moduleCodenameBase;
    private final String kitCodeNameBase;
    private final String problemDescription;
    private final String problemName;

    private MissingModulesProblemProvider(Project project, Set packagings, String moduleCodenameBase, String kitCodeNameBase, String errorMessage, String errorDescription) {
        this.project = project;
        this.packagings = packagings;
        this.moduleCodenameBase = moduleCodenameBase;
        this.kitCodeNameBase = kitCodeNameBase;
        this.problemName = errorMessage;
        this.problemDescription = errorDescription;
    }

    @Override
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        support.addPropertyChangeListener(listener);
    }

    @Override
    public void removePropertyChangeListener(PropertyChangeListener listener) {
        support.removePropertyChangeListener(listener);
    }

    @Override
    public Collection getProblems() {
        //lazy adding listener only when someone asks for the problems the first time
        if (projectListenerSet.compareAndSet(false, true)) {
            //TODO do we check only when the project is opened?
            project.getLookup().lookup(NbMavenProject.class).addPropertyChangeListener(projectListener);
        }
        return doIDEConfigChecks();
    }

    public synchronized Collection doIDEConfigChecks() {
        Collection toRet = new ArrayList();
        NbMavenProject nbproject = project.getLookup().lookup(NbMavenProject.class);
        String packaging = nbproject.getPackagingType();
        
        if (packagings.contains(packaging)) {
            //TODO check on lastpackaging to prevent re-calculation
            ModuleInfo moduleInfo = listener != null ? listener.info : findModule(moduleCodenameBase);
            boolean foundModule = moduleInfo != null && moduleInfo.isEnabled();
            if (!foundModule) {
                if (listener == null) {
                    ProjectProblem problem = ProjectProblem.createWarning(problemName, problemDescription, new InstallModulesResolver(kitCodeNameBase));
                    listener = new EnablementListener(moduleInfo, problem);
                    listener.startListening();
                }
                toRet.add(listener.problem);
            } else {
                if (listener != null) {
                    listener.stopListening();
                    listener = null;
                }
            }
        }
        lastPackaging = packaging;
        
        return toRet;
    }

    private void firePropertyChange() {
        support.firePropertyChange(ProjectProblemsProvider.PROP_PROBLEMS, null, null);
    }

    private ModuleInfo findModule(@NonNull String codenamebase) {
        Collection infos = Lookup.getDefault().lookupAll(ModuleInfo.class);
        for (ModuleInfo info : infos) {
            if (codenamebase.equals(info.getCodeNameBase())) {
                return info;
            }
        }
        return null;
    }

    private class EnablementListener implements PropertyChangeListener {

        private final @NullAllowed ModuleInfo info;
        private final @NonNull ProjectProblem problem;

        public EnablementListener(@NullAllowed ModuleInfo info, @NonNull ProjectProblem problem) {
            this.info = info;
            this.problem = problem;
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            if (ModuleInfo.PROP_ENABLED.equals(evt.getPropertyName())) {
                if (info != null && info.isEnabled()) {
                    info.removePropertyChangeListener(this);
                    firePropertyChange();
                }
            }
        }
        
        public void stopListening() {
            if (info != null) {
                info.removePropertyChangeListener(this);
            }
        }

        private void startListening() {
            if (info != null) {
                info.addPropertyChangeListener(this);
            }
        }
    }

    private static class InstallModulesResolver implements ProjectProblemResolver {
        private final String codenamebase;

        public InstallModulesResolver(String codenamebase) {
            this.codenamebase = codenamebase;
        }

        @Override
        public Future resolve() {
            FutureTask task = new FutureTask(new Callable() {
                @Override
                public Result call() throws Exception {
                    final Result[] res = new Result[1];
                    try {
                        SwingUtilities.invokeAndWait(new Runnable() {
                            @Override
                            public void run() {
                                Object retval = PluginManager.install(Collections.singleton(codenamebase));
                                res[0] = retval == null ? Result.create(Status.RESOLVED) : Result.create(Status.UNRESOLVED);
                            }
                        });
                    } catch (InterruptedException ex) {
                        res[0] = Result.create(Status.UNRESOLVED);
                    } catch (InvocationTargetException ex) {
                        res[0] = Result.create(Status.UNRESOLVED);
                    }
                    return res[0];
                }
            });
            RP.execute(task);
            return task;
        }

        @Override
        public int hashCode() {
            int hash = 3;
            hash = 67 * hash + (this.codenamebase != null ? this.codenamebase.hashCode() : 0);
            return hash;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final InstallModulesResolver other = (InstallModulesResolver) obj;
            if ((this.codenamebase == null) ? (other.codenamebase != null) : !this.codenamebase.equals(other.codenamebase)) {
                return false;
            }
            return true;
        }
        
        
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy