You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by sd...@apache.org on 2022/03/21 13:12:06 UTC

[netbeans] branch master updated: Maven error/warnings refactored to use Parsing API.

This is an automated email from the ASF dual-hosted git repository.

sdedic pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new 413e442  Maven error/warnings refactored to use Parsing API.
     new e26276d  Merge pull request #3793 from sdedic/maven/editor-error-hints
413e442 is described below

commit 413e44285f53225b9ee87bf7ee83ee981e45eccd
Author: Svata Dedic <sv...@oracle.com>
AuthorDate: Wed Mar 16 15:56:23 2022 +0100

    Maven error/warnings refactored to use Parsing API.
---
 java/maven.embedder/nbproject/project.xml          |   1 +
 java/maven.hints/nbproject/project.properties      |   2 +
 java/maven.hints/nbproject/project.xml             |  19 ++
 .../maven/hints/pom/MavenFileHintsTask.java        |  89 ++++++
 .../modules/maven/hints/pom/MavenPOMParser.java    | 118 ++++++++
 .../pom/{PomModelUtils.java => MavenResult.java}   |  50 +--
 .../maven/hints/pom/MavenSelectionHintsTask.java   | 159 ++++++++++
 .../modules/maven/hints/pom/PomModelUtils.java     | 228 ++++++++++++++
 .../modules/maven/hints/pom/StatusProvider.java    | 335 ---------------------
 .../modules/maven/hints/pom/TaskListBridge.java    |   2 +-
 .../maven/hints/pom/StatusProviderTest.java        |  20 +-
 .../modules/maven/hints/pom/pom-with-warnings.xml  | 241 +++++++++++++++
 12 files changed, 902 insertions(+), 362 deletions(-)

diff --git a/java/maven.embedder/nbproject/project.xml b/java/maven.embedder/nbproject/project.xml
index 4cdbc30..48192c7 100644
--- a/java/maven.embedder/nbproject/project.xml
+++ b/java/maven.embedder/nbproject/project.xml
@@ -198,6 +198,7 @@
                 <package>org.apache.maven.artifact.resolver.filter</package>
                 <package>org.apache.maven.artifact.resolver</package>
                 <package>org.apache.maven.artifact.versioning</package>
+                <package>org.apache.maven.building</package>
                 <package>org.apache.maven.cli</package>
                 <package>org.apache.maven.cli.configuration</package>
                 <package>org.apache.maven.embedder</package>
diff --git a/java/maven.hints/nbproject/project.properties b/java/maven.hints/nbproject/project.properties
index 84e1499..b1ac481 100644
--- a/java/maven.hints/nbproject/project.properties
+++ b/java/maven.hints/nbproject/project.properties
@@ -21,3 +21,5 @@ javac.source=1.8
 
 test.config.stableBTD.includes=**/*Test.class
 requires.nb.javac=true
+
+test-unit-sys-prop.test.netbeans.dest.dir=${netbeans.dest.dir}
diff --git a/java/maven.hints/nbproject/project.xml b/java/maven.hints/nbproject/project.xml
index 8695d77..b2ca2ec 100644
--- a/java/maven.hints/nbproject/project.xml
+++ b/java/maven.hints/nbproject/project.xml
@@ -159,6 +159,15 @@
                     </run-dependency>
                 </dependency>
                 <dependency>
+                    <code-name-base>org.netbeans.modules.parsing.api</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>9.23</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
                     <code-name-base>org.netbeans.modules.projectapi</code-name-base>
                     <build-prerequisite/>
                     <compile-dependency/>
@@ -307,6 +316,16 @@
                         <compile-dependency/>
                         <test/>
                     </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.openide.modules</code-name-base>
+                        <compile-dependency/>
+                        <test/>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.openide.util.lookup</code-name-base>
+                        <compile-dependency/>
+                        <test/>
+                    </test-dependency>
                 </test-type>
             </test-dependencies>
             <public-packages/>
diff --git a/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/MavenFileHintsTask.java b/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/MavenFileHintsTask.java
new file mode 100644
index 0000000..60d1550
--- /dev/null
+++ b/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/MavenFileHintsTask.java
@@ -0,0 +1,89 @@
+/*
+ * 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.hints.pom;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.api.editor.mimelookup.MimeRegistration;
+import org.netbeans.api.project.FileOwnerQuery;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.maven.hints.pom.spi.POMErrorFixProvider;
+import org.netbeans.modules.maven.model.pom.POMModel;
+import org.netbeans.modules.parsing.api.Snapshot;
+import org.netbeans.modules.parsing.spi.ParserResultTask;
+import org.netbeans.modules.parsing.spi.Scheduler;
+import org.netbeans.modules.parsing.spi.SchedulerEvent;
+import org.netbeans.modules.parsing.spi.SchedulerTask;
+import org.netbeans.modules.parsing.spi.TaskFactory;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+import org.netbeans.spi.editor.hints.HintsController;
+import org.openide.filesystems.FileObject;
+
+/**
+ * A ParserResult task that should be run on POM file changes. It validates the
+ * POM, reports possible errors. If no errors, it runs {@link POMErrorFixProvider}s
+ * to provide additional hints for Maven's POM model.
+ *
+ * @author sdedic
+ */
+public class MavenFileHintsTask extends ParserResultTask<MavenResult> {
+
+    @Override
+    public void run(MavenResult result, SchedulerEvent event) {
+        FileObject fo = result.getPomFile();
+        Project p = FileOwnerQuery.getOwner(fo);
+        if (fo == null || p == null || p.getProjectDirectory() != fo.getParent()) {
+            // ?? pom file ought to form a project!
+            return;
+        }
+        List<ErrorDescription> errors = PomModelUtils.findHints(result.getProjectModel(), p);
+        HintsController.setErrors(fo, PomModelUtils.LAYER_POM, errors);
+    }
+
+    @Override
+    public int getPriority() {
+        return 100;
+    }
+
+    @Override
+    public Class<? extends Scheduler> getSchedulerClass() {
+        return Scheduler.EDITOR_SENSITIVE_TASK_SCHEDULER;
+    }
+
+    @Override
+    public void cancel() {
+        // 
+    }
+
+    @MimeRegistration(mimeType = "text/x-maven-pom+xml", service = TaskFactory.class)
+    public static class F extends TaskFactory {
+        @Override
+        public Collection<? extends SchedulerTask> create(Snapshot snapshot) {
+            return Arrays.asList(
+                    new MavenFileHintsTask(),
+                    new MavenSelectionHintsTask()
+            );
+        }
+    }
+    
+}
diff --git a/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/MavenPOMParser.java b/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/MavenPOMParser.java
new file mode 100644
index 0000000..e426f6f
--- /dev/null
+++ b/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/MavenPOMParser.java
@@ -0,0 +1,118 @@
+/*
+ * 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.hints.pom;
+
+import java.util.Collection;
+import java.util.prefs.PreferenceChangeEvent;
+import java.util.prefs.PreferenceChangeListener;
+import java.util.prefs.Preferences;
+import javax.swing.event.ChangeListener;
+import org.netbeans.api.editor.mimelookup.MimeRegistration;
+import org.netbeans.editor.BaseDocument;
+import org.netbeans.modules.maven.embedder.EmbedderFactory;
+import org.netbeans.modules.maven.model.Utilities;
+import org.netbeans.modules.maven.model.pom.POMModel;
+import org.netbeans.modules.maven.model.pom.POMModelFactory;
+import org.netbeans.modules.parsing.api.Snapshot;
+import org.netbeans.modules.parsing.api.Task;
+import org.netbeans.modules.parsing.spi.ParseException;
+import org.netbeans.modules.parsing.spi.Parser;
+import org.netbeans.modules.parsing.spi.ParserFactory;
+import org.netbeans.modules.parsing.spi.SourceModificationEvent;
+import org.netbeans.modules.xml.xam.ModelSource;
+import org.openide.filesystems.FileObject;
+import org.openide.loaders.DataObject;
+import org.openide.util.ChangeSupport;
+import org.openide.util.NbPreferences;
+import org.openide.util.WeakListeners;
+
+/**
+ * Parses POM files.
+ *
+ * @author sdedic
+ */
+public class MavenPOMParser extends Parser implements PreferenceChangeListener {
+    private final ChangeSupport chs = new ChangeSupport(this);
+    private POMModel    theModel;
+    private Snapshot    lastSnapshot;
+
+    public MavenPOMParser() {
+        Preferences prefs = NbPreferences.root().node("org/netbeans/modules/maven");
+        prefs.addPreferenceChangeListener(
+                WeakListeners.create(PreferenceChangeListener.class, this, prefs));
+    }
+
+    @Override
+    public void preferenceChange(PreferenceChangeEvent evt) {
+        if(EmbedderFactory.PROP_COMMANDLINE_PATH.equals(evt.getKey())) {
+            chs.fireChange();
+        }
+    }
+    
+    @Override
+    public void parse(Snapshot snapshot, Task task, SourceModificationEvent event) throws ParseException {
+        final FileObject sFile = snapshot.getSource().getFileObject();
+        if (sFile == null) {
+            synchronized (this) {
+                theModel = null;
+                lastSnapshot = snapshot;
+            }
+            return;
+        }
+        //#236116 passing document protects from looking it up later and causing a deadlock.
+        final BaseDocument document = (BaseDocument)snapshot.getSource().getDocument(false);
+        final DataObject d = sFile.getLookup().lookup(DataObject.class);
+        ModelSource ms = Utilities.createModelSource(sFile, d, document);
+        synchronized (this) {
+            theModel = POMModelFactory.getDefault().getModel(ms);
+            lastSnapshot = snapshot;
+        }
+    }
+
+    @Override
+    public Result getResult(Task task) throws ParseException {
+        synchronized (this) {
+            if (lastSnapshot == null) {
+                return null;
+            }
+            return new MavenResult(theModel, lastSnapshot.getSource().getFileObject(), lastSnapshot);
+        }
+    }
+
+    @Override
+    public void addChangeListener(ChangeListener changeListener) {
+        chs.addChangeListener(changeListener);
+    }
+
+    @Override
+    public void removeChangeListener(ChangeListener changeListener) {
+        chs.removeChangeListener(changeListener);
+    }
+
+    
+    @MimeRegistration(mimeType = "text/x-maven-pom+xml", service = ParserFactory.class)
+    public static class F extends ParserFactory {
+
+        @Override
+        public Parser createParser(Collection<Snapshot> snapshots) {
+            return new MavenPOMParser();
+        }
+    }
+    
+}
diff --git a/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/PomModelUtils.java b/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/MavenResult.java
similarity index 51%
copy from java/maven.hints/src/org/netbeans/modules/maven/hints/pom/PomModelUtils.java
copy to java/maven.hints/src/org/netbeans/modules/maven/hints/pom/MavenResult.java
index 751c020..f3cbd6b 100644
--- a/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/PomModelUtils.java
+++ b/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/MavenResult.java
@@ -18,30 +18,38 @@
  */
 package org.netbeans.modules.maven.hints.pom;
 
-import org.netbeans.modules.xml.xam.Model;
-import org.openide.awt.StatusDisplayer;
-import org.openide.util.Exceptions;
-import org.openide.util.NbBundle;
+import org.netbeans.modules.maven.model.pom.POMModel;
+import org.netbeans.modules.parsing.api.Snapshot;
+import org.netbeans.modules.parsing.spi.Parser;
+import org.openide.filesystems.FileObject;
 
 /**
- *
+ * Result of POM 'parsing'. Contains {@link POMModel} build from the pom file or
+ * editor contents.
+ * 
  * @author sdedic
  */
-public final class PomModelUtils {
-    public static boolean implementInTransaction(Model m, Runnable r) {
-        m.startTransaction();
-        try {
-            r.run();
-        } finally {
-            try {
-                m.endTransaction();
-            } catch (IllegalStateException ex) {
-                StatusDisplayer.getDefault().setStatusText(
-                        NbBundle.getMessage(PomModelUtils.class, "ERR_UpdatePomModel",
-                        Exceptions.findLocalizedMessage(ex)));
-                return false;
-            }
-        }
-        return true;
+public final class MavenResult extends Parser.Result {
+    
+    private final POMModel projectModel;
+    private final FileObject pomFile;
+
+    public MavenResult(POMModel projectModel, FileObject pomFile, Snapshot _snapshot) {
+        super(_snapshot);
+        this.projectModel = projectModel;
+        this.pomFile = pomFile;
+    }
+
+    public FileObject getPomFile() {
+        return pomFile;
+    }
+
+    public POMModel getProjectModel() {
+        return projectModel;
+    }
+
+    @Override
+    protected void invalidate() {
     }
+    
 }
diff --git a/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/MavenSelectionHintsTask.java b/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/MavenSelectionHintsTask.java
new file mode 100644
index 0000000..9ec4bf6
--- /dev/null
+++ b/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/MavenSelectionHintsTask.java
@@ -0,0 +1,159 @@
+/*
+ * 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.hints.pom;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import javax.swing.text.Position;
+import javax.swing.text.StyledDocument;
+import org.netbeans.api.project.FileOwnerQuery;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.maven.hints.pom.spi.SelectionPOMFixProvider;
+import org.netbeans.modules.maven.model.pom.POMModel;
+import org.netbeans.modules.maven.model.pom.Parent;
+import org.netbeans.modules.parsing.spi.CursorMovedSchedulerEvent;
+import org.netbeans.modules.parsing.spi.ParserResultTask;
+import org.netbeans.modules.parsing.spi.Scheduler;
+import org.netbeans.modules.parsing.spi.SchedulerEvent;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+import org.netbeans.spi.editor.hints.HintsController;
+import org.openide.filesystems.FileObject;
+import org.openide.text.Annotation;
+import org.openide.text.NbDocument;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+
+/**
+ * A ParserResult task that should be run on caret/selection changes. It runs 
+ * {@link SelectionPOMFixProvider}s to provide suggestions appropriate for the
+ * current caret location.
+ * It also adds gutter annotation for parent POM reference.
+ *
+ * @author sdedic
+ */
+public class MavenSelectionHintsTask extends ParserResultTask<MavenResult> {
+
+    @Override
+    public void run(MavenResult result, SchedulerEvent event) {
+        if (!(event instanceof CursorMovedSchedulerEvent)) {
+            return;
+        }
+        CursorMovedSchedulerEvent cursorEvent = (CursorMovedSchedulerEvent)event;
+        FileObject fo = result.getPomFile();
+        Project project = FileOwnerQuery.getOwner(fo);
+        Document document = result.getSnapshot().getSource().getDocument(false);
+        if (fo == null || project == null || project.getProjectDirectory() != fo.getParent()) {
+            // ?? pom file ought to form a project!
+            return;
+        }
+        final POMModel model = result.getProjectModel();
+        final List<ErrorDescription> errors = new ArrayList<ErrorDescription>();
+        // clear selection hints in case of an error; validation errors are handled by 
+        // MavenFileHintsTask.
+        StyledDocument styled = null;
+        Annotation[] old = null;
+        
+        if (document instanceof StyledDocument) {
+            styled = (StyledDocument)document;
+            old = (Annotation[]) styled.getProperty("maven_annot");
+        }
+        if (PomModelUtils.checkModelValid(model)) {
+            int ss = cursorEvent.getCaretOffset();
+            int se = cursorEvent.getMarkOffset();
+            if (ss > se) {
+                // swap min/max
+                int x = se;
+                se = ss;
+                ss = x;
+            }
+
+            for (SelectionPOMFixProvider prov : PomModelUtils.hintProviders(project, SelectionPOMFixProvider.class)) {
+                List<ErrorDescription> lst = prov.getErrorsForDocument(model, project, 
+                        ss, se, cursorEvent.getCaretOffset());
+                if (lst != null) {
+                    errors.addAll(lst);
+                }
+            }
+            if (styled != null) {
+                List<Annotation> anns = new ArrayList<Annotation>();
+                try {
+                    Parent p = model.findComponent(ss, Parent.class, true);
+                    if (p != null && p.getArtifactId() != null && p.getGroupId() != null && p.getVersion() != null) { //217741
+                        Annotation ann = new ParentPomAnnotation();
+                        anns.add(ann);
+                        Position position = NbDocument.createPosition(document, ss, Position.Bias.Forward);
+                        NbDocument.addAnnotation(styled, position, se - ss, ann);
+                    }
+                } catch (BadLocationException ex) {
+                    Exceptions.printStackTrace(ex);
+                }
+                
+                if (old != null) {
+                }
+
+                styled.putProperty("maven_annot", anns.toArray(new Annotation[0]));
+            } else {
+                // clear on error
+                if (styled != null) {
+                    styled.putProperty("maven_annot", null); //217741
+                }
+            }
+            // remove old annotations
+            if (styled != null && old != null) {
+                for (Annotation ann : old) {
+                    NbDocument.removeAnnotation(styled, ann);
+                }
+            }
+        }
+        HintsController.setErrors(fo, PomModelUtils.LAYER_POM_SELECTION, errors);
+    }
+
+    @Override
+    public int getPriority() {
+        return 100;
+    }
+
+    @Override
+    public Class<? extends Scheduler> getSchedulerClass() {
+        return Scheduler.CURSOR_SENSITIVE_TASK_SCHEDULER;
+    }
+
+    @Override
+    public void cancel() {
+        // 
+    }
+
+    public static class ParentPomAnnotation extends Annotation {
+
+        @Override
+        public String getAnnotationType() {
+            return "org-netbeans-modules-editor-annotations-implements";
+        }
+
+        @NbBundle.Messages({
+            "ParentPOMAnnotation_Description=Go to parent POM declaration"
+        })
+        @Override
+        public String getShortDescription() {
+            return Bundle.ParentPOMAnnotation_Description();
+        }
+    }
+}
diff --git a/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/PomModelUtils.java b/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/PomModelUtils.java
index 751c020..9df5022 100644
--- a/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/PomModelUtils.java
+++ b/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/PomModelUtils.java
@@ -18,16 +18,66 @@
  */
 package org.netbeans.modules.maven.hints.pom;
 
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import org.apache.maven.DefaultMaven;
+import org.apache.maven.Maven;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.building.Source;
+import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.model.building.ModelBuildingException;
+import org.apache.maven.model.building.ModelBuildingRequest;
+import org.apache.maven.model.building.ModelProblem;
+import org.apache.maven.model.building.ModelSource2;
+import org.apache.maven.model.resolution.UnresolvableModelException;
+import org.apache.maven.project.ProjectBuilder;
+import org.apache.maven.project.ProjectBuildingException;
+import org.apache.maven.project.ProjectBuildingRequest;
+import org.apache.maven.project.ProjectBuildingResult;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectManager;
+import org.netbeans.modules.maven.api.ModelUtils;
+import org.netbeans.modules.maven.embedder.EmbedderFactory;
+import org.netbeans.modules.maven.embedder.MavenEmbedder;
+import org.netbeans.modules.maven.hints.pom.spi.POMErrorFixBase;
+import org.netbeans.modules.maven.hints.pom.spi.POMErrorFixProvider;
+import org.netbeans.modules.maven.indexer.api.RepositoryPreferences;
+import org.netbeans.modules.maven.model.pom.POMModel;
 import org.netbeans.modules.xml.xam.Model;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
+import org.netbeans.spi.editor.hints.Severity;
 import org.openide.awt.StatusDisplayer;
 import org.openide.util.Exceptions;
+import org.openide.util.Lookup;
+import org.openide.util.Mutex;
 import org.openide.util.NbBundle;
+import org.openide.util.lookup.Lookups;
 
 /**
  *
  * @author sdedic
  */
 public final class PomModelUtils {
+    private static final Logger LOG = Logger.getLogger(PomModelUtils.class.getName());
+    
+    static final String LAYER_POM = "pom"; //NOI18N
+    static final String LAYER_POM_SELECTION = "pom-selection"; //NOI18N
+
     public static boolean implementInTransaction(Model m, Runnable r) {
         m.startTransaction();
         try {
@@ -44,4 +94,182 @@ public final class PomModelUtils {
         }
         return true;
     }
+
+    static boolean checkModelValid(POMModel model) {
+        assert model != null;
+        if (!model.getModelSource().isEditable()) {
+            return false;
+        }
+        try {
+            model.getBaseDocument(); // #187615
+            model.sync();
+            // model.refresh();
+        } catch (IOException ex) {
+            LOG.log(Level.FINE, "Error while syncing pom model.", ex);
+        }
+
+        if (!model.getState().equals(Model.State.VALID)) {
+            LOG.log(Level.FINE, "Pom model document is not valid, is {0}", model.getState());
+            return false;
+        }
+        if (model.getProject() == null) {
+            LOG.log(Level.FINE, "Pom model root element missing");
+            return false;
+        }
+        return true;
+    }
+
+
+    static void runMavenValidation(final POMModel model, final List<ErrorDescription> err) {
+        File pom = model.getModelSource().getLookup().lookup(File.class);
+        if (pom == null) {
+            return;
+        }
+        
+        List<ModelProblem> problems = runMavenValidationImpl(pom, model.getModelSource().getLookup().lookup(Document.class));
+        for (ModelProblem problem : problems) {
+            if (!problem.getSource().equals(pom.getAbsolutePath())) {
+                LOG.log(Level.FINE, "found problem not in {0}: {1}", new Object[] {pom, problem.getSource()});
+                continue;
+            }
+            int line = problem.getLineNumber();
+            if (line <= 0) { // probably from a parent POM
+                continue;
+            }
+            if (problem.getException() instanceof UnresolvableModelException) {
+                // If a <parent> reference cannot be followed because e.g. no projects are opened (so no repos registered), just ignore it.
+                continue;
+            }
+            try {
+                err.add(ErrorDescriptionFactory.createErrorDescription(problem.getSeverity() == ModelProblem.Severity.WARNING ? Severity.WARNING : Severity.ERROR, problem.getMessage(), model.getBaseDocument(), line));
+            } catch (IndexOutOfBoundsException x) {
+                LOG.log(Level.WARNING, "improper line number: {0}", problem);
+            }
+        }
+        
+    }
+    
+    public static List<ErrorDescription> findHints(final @NonNull POMModel model, final Project project) {
+        final List<ErrorDescription> err = new ArrayList<ErrorDescription>();
+        //before checkModelValid because of #216093
+        runMavenValidation(model, err);
+        if (!checkModelValid(model)) {
+            return err;
+        }
+
+        for (POMErrorFixProvider prov : PomModelUtils.hintProviders(project, POMErrorFixProvider.class)) {
+            List<ErrorDescription> lst = prov.getErrorsForDocument(model, project);
+            if (lst != null) {
+                err.addAll(lst);
+            }
+        }
+        return err;
+    }
+
+    /**
+     * Source for maven model that can serve both editor contents and file contents.
+     */
+    private static class M2S implements ModelSource2, Source {
+        private final File pomFile;
+        private final Document doc;
+
+        public M2S(File pomFile, Document doc) {
+            this.pomFile = pomFile;
+            this.doc = doc;
+        }
+
+        @Override
+        public ModelSource2 getRelatedSource(String relative) {
+            return new M2S(new File(pomFile, relative), null);
+        }
+
+        @Override
+        public URI getLocationURI() {
+            return pomFile.toURI();
+        }
+
+        @Override
+        public InputStream getInputStream() throws IOException {
+            AtomicReference<String> content = new AtomicReference<>();
+            AtomicReference<BadLocationException> err = new AtomicReference<>();
+            if (doc != null) {
+                doc.render(() -> {
+                    try {
+                        content.set(doc.getText(0, doc.getLength()));
+                    } catch (BadLocationException ex) {
+                        err.set(ex);
+                    }
+                });
+                if (err.get() != null) {
+                    throw new IOException(err.get());
+                } else {
+                    return new ByteArrayInputStream(content.get().getBytes("UTF-8"));
+                }
+            }
+            return new FileInputStream(pomFile);
+        }
+
+        @Override
+        public String getLocation() {
+            return pomFile.getPath();
+        }
+    }
+    
+    static List<ModelProblem> runMavenValidationImpl(final File pom, Document doc) {
+        MavenEmbedder embedder = EmbedderFactory.getProjectEmbedder();
+        MavenExecutionRequest meReq = embedder.createMavenExecutionRequest();
+        ProjectBuildingRequest req = meReq.getProjectBuildingRequest();
+        req.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_0); // 3.1 currently enables just <reporting> warning, see issue 223562 for details on why it's bad to show.
+        req.setLocalRepository(embedder.getLocalRepository());
+        List<ArtifactRepository> remoteRepos = RepositoryPreferences.getInstance().remoteRepositories(embedder);
+        req.setRemoteRepositories(remoteRepos);
+        req.setRepositorySession(((DefaultMaven) embedder.lookupComponent(Maven.class)).newRepositorySession(meReq));
+        List<ModelProblem> problems;
+        long t = System.currentTimeMillis();
+        try {
+            problems = embedder.lookupComponent(ProjectBuilder.class).build(new M2S(pom, doc), req).getProblems();
+        } catch (ProjectBuildingException x) {
+            problems = new ArrayList<ModelProblem>();
+            List<ProjectBuildingResult> results = x.getResults();
+            if (results != null) { //one code point throwing ProjectBuildingException contains results,
+                for (ProjectBuildingResult result : results) {
+                    problems.addAll(result.getProblems());
+                }
+            } else {
+                // another code point throwing ProjectBuildingException doesn't contain results..
+                Throwable cause = x.getCause();
+                if (cause instanceof ModelBuildingException) {
+                    problems.addAll(((ModelBuildingException) cause).getProblems());
+                }
+            }
+        }
+        List<ModelProblem> toRet = new LinkedList<ModelProblem>();
+        for (ModelProblem problem : problems) {
+            if(ModelUtils.checkByCLIMavenValidationLevel(problem)) {
+                toRet.add(problem);
+            }
+        }
+        long d = System.currentTimeMillis() - t;
+        LOG.info("Maven validation of " + pom.getPath() + " run for: " + d);
+        return toRet;
+    }
+    
+    static <T extends POMErrorFixBase> List<T> hintProviders(Project project, Class<T> providerType) {
+        List<T> providers =  ProjectManager.mutex().readAccess(new Mutex.Action<List<T>>() {
+            public @Override List<T> run() {
+                Lookup lkp = Lookups.forPath("org-netbeans-modules-maven-hints"); //NOI18N
+                Lookup.Result<T> res = lkp.lookupResult(providerType);
+                List<T> r = new ArrayList<>(res.allInstances());
+                for (Iterator<T> it = r.iterator(); it.hasNext(); ) {
+                    T prov = it.next();
+                    if (!prov.getConfiguration().isEnabled(prov.getConfiguration().getPreferences())) {
+                        it.remove();
+                    }
+                }
+                return r;
+            }
+        });
+        return providers;
+    }
+    
 }
diff --git a/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/StatusProvider.java b/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/StatusProvider.java
index 23b7b9b..d59bdb8 100644
--- a/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/StatusProvider.java
+++ b/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/StatusProvider.java
@@ -19,75 +19,24 @@
 
 package org.netbeans.modules.maven.hints.pom;
 
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.logging.Level;
 import java.util.logging.Logger;
-import java.util.prefs.PreferenceChangeEvent;
-import java.util.prefs.PreferenceChangeListener;
-import java.util.prefs.Preferences;
-import javax.swing.JEditorPane;
-import javax.swing.text.BadLocationException;
 import javax.swing.text.Document;
-import javax.swing.text.Position;
-import javax.swing.text.StyledDocument;
-import org.apache.maven.DefaultMaven;
-import org.apache.maven.Maven;
-import org.apache.maven.artifact.repository.ArtifactRepository;
-import org.apache.maven.execution.MavenExecutionRequest;
-import org.apache.maven.model.building.ModelBuildingException;
-import org.apache.maven.model.building.ModelBuildingRequest;
-import org.apache.maven.model.building.ModelProblem;
-import org.apache.maven.model.resolution.UnresolvableModelException;
-import org.apache.maven.project.ProjectBuilder;
-import org.apache.maven.project.ProjectBuildingException;
-import org.apache.maven.project.ProjectBuildingRequest;
-import org.apache.maven.project.ProjectBuildingResult;
-import org.netbeans.api.annotations.common.NonNull;
 import org.netbeans.api.annotations.common.NullAllowed;
 import org.netbeans.api.editor.mimelookup.MimeRegistration;
 import org.netbeans.api.project.FileOwnerQuery;
 import org.netbeans.api.project.Project;
-import org.netbeans.api.project.ProjectManager;
 import org.netbeans.editor.BaseDocument;
 import org.netbeans.modules.editor.NbEditorUtilities;
 import org.netbeans.modules.maven.api.Constants;
-import org.netbeans.modules.maven.api.ModelUtils;
-import org.netbeans.modules.maven.embedder.EmbedderFactory;
-import org.netbeans.modules.maven.embedder.MavenEmbedder;
-import org.netbeans.modules.maven.hints.pom.spi.POMErrorFixProvider;
-import org.netbeans.modules.maven.hints.pom.spi.SelectionPOMFixProvider;
-import org.netbeans.modules.maven.indexer.api.RepositoryPreferences;
 import org.netbeans.modules.maven.model.Utilities;
 import org.netbeans.modules.maven.model.pom.POMModel;
 import org.netbeans.modules.maven.model.pom.POMModelFactory;
-import org.netbeans.modules.maven.model.pom.Parent;
-import org.netbeans.modules.xml.xam.Model;
 import org.netbeans.modules.xml.xam.ModelSource;
 import org.netbeans.spi.editor.errorstripe.UpToDateStatus;
 import org.netbeans.spi.editor.errorstripe.UpToDateStatusProvider;
 import org.netbeans.spi.editor.errorstripe.UpToDateStatusProviderFactory;
-import org.netbeans.spi.editor.hints.ErrorDescription;
-import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
-import org.netbeans.spi.editor.hints.HintsController;
-import org.netbeans.spi.editor.hints.Severity;
-import org.openide.cookies.EditorCookie;
 import org.openide.filesystems.*;
-import org.openide.loaders.DataObject;
-import org.openide.loaders.DataObjectNotFoundException;
-import org.openide.text.Annotation;
-import org.openide.text.NbDocument;
-import org.openide.util.Exceptions;
-import org.openide.util.Lookup;
-import org.openide.util.Mutex;
-import org.openide.util.NbPreferences;
 import org.openide.util.RequestProcessor;
-import org.openide.util.WeakListeners;
-import org.openide.util.lookup.Lookups;
 
 /**
  *
@@ -95,9 +44,6 @@ import org.openide.util.lookup.Lookups;
  */
 @MimeRegistration(mimeType=Constants.POM_MIME_TYPE, service=UpToDateStatusProviderFactory.class)
 public final class StatusProvider implements UpToDateStatusProviderFactory {
-
-    private static final String LAYER_POM = "pom"; //NOI18N
-    private static final String LAYER_POM_SELECTION = "pom-selection"; //NOI18N
     private static final RequestProcessor RP = new RequestProcessor("StatusProvider"); //NOI18N
     private static final Logger LOG = Logger.getLogger(StatusProvider.class.getName());
 
@@ -110,115 +56,17 @@ public final class StatusProvider implements UpToDateStatusProviderFactory {
         private final Document document;
         private @NullAllowed POMModel model;
         private Project project;
-        private final FileChangeListener listener;
-        private final PreferenceChangeListener prefListener;
         
         StatusProviderImpl(Document doc) {
             this.document = doc;
-            listener = new FileChangeAdapter() {
-                @Override
-                public void fileChanged(FileEvent fe) {
-                    // XXX fire PROP_UP_TO_DATE
-                    RP.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            checkHints();
-                        }
-                    });
-                }
-            };
-            prefListener = new PreferenceChangeListener() {
-                @Override
-                public void preferenceChange(PreferenceChangeEvent evt) {
-                    if(EmbedderFactory.PROP_COMMANDLINE_PATH.equals(evt.getKey())) {
-                        // given by the registered mvn client, the pom validation result may change ...
-                        checkHints();
-                    }
-                }
-            };
-            Preferences prefs = NbPreferences.root().node("org/netbeans/modules/maven");
-            prefs.addPreferenceChangeListener(WeakListeners.create(PreferenceChangeListener.class, prefListener, prefs));
-            
             RP.post(new Runnable() {
                 @Override
                 public void run() {
                     initializeModel(); //#204067 moved to RP 
-                    checkHints();
                 }
             });
         }
 
-
-        private void checkHints() {
-            if (model == null) {
-                return;
-            }
-            HintsController.setErrors(document, LAYER_POM, findHints(model, project, -1, -1, -1));
-        }
-
-        static List<ErrorDescription> findHints(final @NonNull POMModel model, final Project project, final int selectionStart, final int selectionEnd, final int caretPosition) {
-            final List<ErrorDescription> err = new ArrayList<ErrorDescription>();
-            //before checkModelValid because of #216093
-            runMavenValidation(model, err);
-            if (!checkModelValid(model)) {
-                return err;
-            }
-
-            return ProjectManager.mutex().readAccess(new Mutex.Action<List<ErrorDescription>>() {
-                public @Override List<ErrorDescription> run() {
-                        Lookup lkp = Lookups.forPath("org-netbeans-modules-maven-hints"); //NOI18N
-                        if (selectionStart == -1 && selectionEnd == -1) {
-                            Lookup.Result<POMErrorFixProvider> res = lkp.lookupResult(POMErrorFixProvider.class);
-                            for (POMErrorFixProvider prov : res.allInstances()) {
-                                if (!prov.getConfiguration().isEnabled(prov.getConfiguration().getPreferences())) {
-                                    continue;
-                                }
-                                List<ErrorDescription> lst = prov.getErrorsForDocument(model, project);
-                                if (lst != null) {
-                                    err.addAll(lst);
-                                }
-                            }
-                        } else {
-                            Lookup.Result<SelectionPOMFixProvider> res = lkp.lookupResult(SelectionPOMFixProvider.class);
-                            for (SelectionPOMFixProvider prov : res.allInstances()) {
-                                if (!prov.getConfiguration().isEnabled(prov.getConfiguration().getPreferences())) {
-                                    continue;
-                                }
-                                List<ErrorDescription> lst = prov.getErrorsForDocument(model, project, selectionStart, selectionEnd, caretPosition);
-                                if (lst != null) {
-                                    err.addAll(lst);
-                                }
-                            }
-                        }
-                        return err;
-                }
-            });
-        }
-        
-        private static boolean checkModelValid(POMModel model) {
-            assert model != null;
-            if (!model.getModelSource().isEditable()) {
-                return false;
-            }
-            try {
-                model.getBaseDocument(); // #187615
-                model.sync();
-                // model.refresh();
-            } catch (IOException ex) {
-                LOG.log(Level.FINE, "Error while syncing pom model.", ex);
-            }
-
-            if (!model.getState().equals(Model.State.VALID)) {
-                LOG.log(Level.FINE, "Pom model document is not valid, is {0}", model.getState());
-                return false;
-            }
-            if (model.getProject() == null) {
-                LOG.log(Level.FINE, "Pom model root element missing");
-                return false;
-            }
-            return true;
-        }
-
         private void initializeModel() {
             FileObject fo = NbEditorUtilities.getFileObject(document);
             if (fo != null) {
@@ -226,195 +74,12 @@ public final class StatusProvider implements UpToDateStatusProviderFactory {
                 ModelSource ms = Utilities.createModelSource(fo, null, document instanceof BaseDocument ? (BaseDocument)document : null);
                 model = POMModelFactory.getDefault().createFreshModel(ms);
                 project = FileOwnerQuery.getOwner(fo);
-                fo.addFileChangeListener(FileUtil.weakFileChangeListener(listener, fo));
             }
         }
 
         @Override
         public UpToDateStatus getUpToDate() {
-            if (model == null) {
-                return UpToDateStatus.UP_TO_DATE_OK;
-            }
-            FileObject fo = NbEditorUtilities.getFileObject(document);
-            boolean ok = false;
-            try {
-                if (fo.isValid()) {
-                    DataObject dobj = DataObject.find(fo);
-                    EditorCookie ed = dobj.getLookup().lookup(EditorCookie.class);
-                    if (ed != null) {
-                        JEditorPane[] panes = ed.getOpenedPanes();
-                        if (panes != null && panes.length > 0) {
-                            //#214527
-                            JEditorPane pane = panes[0];
-                            if (panes.length > 1) {
-                                for (JEditorPane p : panes) {
-                                    if (p.isFocusOwner()) {
-                                        pane = p;
-                                        break;
-                                    }
-                                }
-                            }
-                            //TODO this code is called very often apparently.
-                            //we should only run the checks if something changed..
-                            //something means file + selection start + selection end.
-                            final int selectionStart = pane.getSelectionStart();
-                            final int selectionEnd = pane.getSelectionEnd();
-                            final int caretPosition = pane.getCaretPosition();
-                            RP.post(new Runnable() {
-                                @Override
-                                public void run() {
-                                    refreshLinkAnnotations(document, model, selectionStart, selectionEnd);
-                                }
-                            });
-                            if (selectionStart != selectionEnd) { //maybe we want to remove the condition?
-                                RP.post(new Runnable() {
-                                    @Override public void run() {
-                                        //this condition is important in order not to break any running hints
-                                        //the model sync+refresh renders any existing POMComponents people
-                                        // might be holding useless
-                                        if (!model.isIntransaction()) {
-                                            HintsController.setErrors(document, LAYER_POM_SELECTION, findHints(model, project, selectionStart, selectionEnd, caretPosition));
-                                        } else {
-                                            HintsController.setErrors(document, LAYER_POM_SELECTION, Collections.<ErrorDescription>emptyList());
-                                        }
-                                        
-                                    }
-                                });
-                                ok = true;
-                                return UpToDateStatus.UP_TO_DATE_PROCESSING;
-                            }
-                        }
-                    }
-                }
-            } catch (DataObjectNotFoundException ex) {
-                //#166011 just a minor issue, just log, but don't show to user directly
-                LOG.log(Level.INFO, "Touched somehow invalidated FileObject", ex);
-            } finally {
-                if (!ok) {
-                    HintsController.setErrors(document, LAYER_POM_SELECTION, Collections.<ErrorDescription>emptyList());
-                }
-            }
             return UpToDateStatus.UP_TO_DATE_OK; // XXX should use UP_TO_DATE_PROCESSING if checkHints task is currently running
         }
-
-        private void refreshLinkAnnotations(Document document, POMModel model, final int selectionStart, int selectionEnd) {
-            if (document instanceof StyledDocument) {
-                StyledDocument styled = (StyledDocument) document;
-                Annotation[] old = (Annotation[]) styled.getProperty("maven_annot");
-                if (old != null) {
-                    for (Annotation ann : old) {
-                        NbDocument.removeAnnotation(styled, ann);
-                    }
-                    styled.putProperty("maven_annot", null); //217741
-                }
-                if (checkModelValid(model)) {
-                    try {
-                        List<Annotation> anns = new ArrayList<Annotation>();
-                        //now add a link to parent pom.
-                        Parent p = model.findComponent(selectionStart, Parent.class, true);
-                        if (p != null && p.getArtifactId() != null && p.getGroupId() != null && p.getVersion() != null) { //217741
-                            Annotation ann = new ParentPomAnnotation();
-                            anns.add(ann);
-                            Position position = NbDocument.createPosition(document, selectionStart, Position.Bias.Forward);
-                            NbDocument.addAnnotation(styled, position, selectionEnd - selectionStart, ann);
-                        }
-                        styled.putProperty("maven_annot", anns.toArray(new Annotation[0]));
-                    } catch (BadLocationException ex) {
-                        Exceptions.printStackTrace(ex);
-                    }                    
-                }
-            }
- 
-        }
-
-    }
-
-    private static void runMavenValidation(final POMModel model, final List<ErrorDescription> err) {
-        File pom = model.getModelSource().getLookup().lookup(File.class);
-        if (pom == null) {
-            return;
-        }
-        
-        List<ModelProblem> problems = runMavenValidationImpl(pom);
-        for (ModelProblem problem : problems) {
-            if (!problem.getSource().equals(pom.getAbsolutePath())) {
-                LOG.log(Level.FINE, "found problem not in {0}: {1}", new Object[] {pom, problem.getSource()});
-                continue;
-            }
-            int line = problem.getLineNumber();
-            if (line <= 0) { // probably from a parent POM
-                /* probably more irritating than helpful:
-                line = 1; // fallback
-                Parent parent = model.getProject().getPomParent();
-                if (parent != null) {
-                    Line l = NbEditorUtilities.getLine(model.getBaseDocument(), parent.findPosition(), false);
-                    if (l != null) {
-                        line = l.getLineNumber() + 1;
-                    }
-                }
-                */
-                continue;
-            }
-            if (problem.getException() instanceof UnresolvableModelException) {
-                // If a <parent> reference cannot be followed because e.g. no projects are opened (so no repos registered), just ignore it.
-                continue;
-            }
-            try {
-                err.add(ErrorDescriptionFactory.createErrorDescription(problem.getSeverity() == ModelProblem.Severity.WARNING ? Severity.WARNING : Severity.ERROR, problem.getMessage(), model.getBaseDocument(), line));
-            } catch (IndexOutOfBoundsException x) {
-                LOG.log(Level.WARNING, "improper line number: {0}", problem);
-            }
-        }
-        
-    }
-    
-    //non-private because of tests..   
-    static List<ModelProblem> runMavenValidationImpl(final File pom) {
-        MavenEmbedder embedder = EmbedderFactory.getProjectEmbedder();
-        MavenExecutionRequest meReq = embedder.createMavenExecutionRequest();
-        ProjectBuildingRequest req = meReq.getProjectBuildingRequest();
-        req.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_0); // 3.1 currently enables just <reporting> warning, see issue 223562 for details on why it's bad to show.
-        req.setLocalRepository(embedder.getLocalRepository());
-        List<ArtifactRepository> remoteRepos = RepositoryPreferences.getInstance().remoteRepositories(embedder);
-        req.setRemoteRepositories(remoteRepos);
-        req.setRepositorySession(((DefaultMaven) embedder.lookupComponent(Maven.class)).newRepositorySession(meReq));
-        List<ModelProblem> problems;
-        try {
-            problems = embedder.lookupComponent(ProjectBuilder.class).build(pom, req).getProblems();
-        } catch (ProjectBuildingException x) {
-            problems = new ArrayList<ModelProblem>();
-            List<ProjectBuildingResult> results = x.getResults();
-            if (results != null) { //one code point throwing ProjectBuildingException contains results,
-                for (ProjectBuildingResult result : results) {
-                    problems.addAll(result.getProblems());
-                }
-            } else {
-                // another code point throwing ProjectBuildingException doesn't contain results..
-                Throwable cause = x.getCause();
-                if (cause instanceof ModelBuildingException) {
-                    problems.addAll(((ModelBuildingException) cause).getProblems());
-                }
-            }
-        }
-        List<ModelProblem> toRet = new LinkedList<ModelProblem>();
-        for (ModelProblem problem : problems) {
-            if(ModelUtils.checkByCLIMavenValidationLevel(problem)) {
-                toRet.add(problem);
-            }
-        }
-        return toRet;
-    }
-    
-    public static class ParentPomAnnotation extends Annotation {
-
-        @Override
-        public String getAnnotationType() {
-            return "org-netbeans-modules-editor-annotations-implements";
-        }
-
-        @Override
-        public String getShortDescription() {
-            return "Go to parent POM declaration";
-        }
     }
 }
diff --git a/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/TaskListBridge.java b/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/TaskListBridge.java
index 0dd15ab..b772d87 100644
--- a/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/TaskListBridge.java
+++ b/java/maven.hints/src/org/netbeans/modules/maven/hints/pom/TaskListBridge.java
@@ -62,7 +62,7 @@ public class TaskListBridge extends FileTaskScanner {
                 ModelSource ms = Utilities.createModelSource(resource);
                 POMModel model = POMModelFactory.getDefault().getModel(ms);
                 model.setAutoSyncActive(false);
-                List<ErrorDescription> errs = StatusProvider.StatusProviderImpl.findHints(model, prj, -1, -1, -1);
+                List<ErrorDescription> errs = PomModelUtils.findHints(model, prj);
                 List<Task> tasks = new ArrayList<Task>();
 
                 for (ErrorDescription error : errs) {
diff --git a/java/maven.hints/test/unit/src/org/netbeans/modules/maven/hints/pom/StatusProviderTest.java b/java/maven.hints/test/unit/src/org/netbeans/modules/maven/hints/pom/StatusProviderTest.java
index 01ca395..468b167 100644
--- a/java/maven.hints/test/unit/src/org/netbeans/modules/maven/hints/pom/StatusProviderTest.java
+++ b/java/maven.hints/test/unit/src/org/netbeans/modules/maven/hints/pom/StatusProviderTest.java
@@ -24,6 +24,8 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import org.netbeans.junit.NbTestCase;
 import org.openide.filesystems.FileUtil;
+import org.openide.modules.DummyInstalledFileLocator;
+import org.openide.util.test.MockLookup;
 
 /**
  *
@@ -39,12 +41,20 @@ public class StatusProviderTest extends NbTestCase {
         clearWorkDir();
     }
 
+    //@org.openide.util.lookup.ServiceProvider(service=org.openide.modules.InstalledFileLocator.class, position = 1000)
+    public static class InstalledFileLocator extends DummyInstalledFileLocator {
+        public InstalledFileLocator() {
+            registerDestDir(new File(System.getProperty("test.netbeans.dest.dir")));
+        }
+    }
+
     public void testModelLoading() throws Exception { // #212152
+        MockLookup.setLayersAndInstances(new InstalledFileLocator());
         // new File(StatusProviderTest.class.getResource(...).toURI()) may not work in all environments, e.g. testdist
         File pom = new File(getWorkDir(), "pom.xml");
         InputStream is = StatusProviderTest.class.getResourceAsStream("pom-with-warnings.xml");
         try {
-            OutputStream os = new FileOutputStream(pom);
+            OutputStream os = new FileOutputStream(pom); 
             try {
                 FileUtil.copy(is, os);
             } finally {
@@ -53,11 +63,11 @@ public class StatusProviderTest extends NbTestCase {
         } finally {
             is.close();
         }
-        String warnings = StatusProvider.runMavenValidationImpl(pom).toString().replace(pom.getAbsolutePath(), "pom.xml");
+        String warnings = PomModelUtils.runMavenValidationImpl(pom, null).toString().replace(pom.getAbsolutePath(), "pom.xml");
         assertEquals("["
-                + "[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-compiler-plugin is missing. @ test:mavenproject4:1.0-SNAPSHOT, pom.xml, line 22, column 12, "
-                + "[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-surefire-plugin is missing. @ test:mavenproject4:1.0-SNAPSHOT, pom.xml, line 72, column 12, "
-                + "[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-war-plugin is missing. @ test:mavenproject4:1.0-SNAPSHOT, pom.xml, line 64, column 12]"
+                + "[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-compiler-plugin is missing. @ test:mavenproject4:1.0-SNAPSHOT, pom.xml, line 41, column 12, "
+                + "[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-surefire-plugin is missing. @ test:mavenproject4:1.0-SNAPSHOT, pom.xml, line 91, column 12, "
+                + "[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-war-plugin is missing. @ test:mavenproject4:1.0-SNAPSHOT, pom.xml, line 83, column 12]"
 //#223562                + "[WARNING] The <reporting> section is deprecated, please move the reports to the <configuration> section of the new Maven Site Plugin. @ test:mavenproject4:1.0-SNAPSHOT, pom.xml, line 102, column 13, "
                 // not reported since upgrade to 3.3.9 + "[WARNING] 'reporting.plugins.plugin.version' for org.apache.maven.plugins:maven-surefire-report-plugin is missing. @ test:mavenproject4:1.0-SNAPSHOT, pom.xml, line 127, column 12]"
                 , warnings);
diff --git a/java/maven.hints/test/unit/src/org/netbeans/modules/maven/hints/pom/pom-with-warnings.xml b/java/maven.hints/test/unit/src/org/netbeans/modules/maven/hints/pom/pom-with-warnings.xml
new file mode 100644
index 0000000..455db6f
--- /dev/null
+++ b/java/maven.hints/test/unit/src/org/netbeans/modules/maven/hints/pom/pom-with-warnings.xml
@@ -0,0 +1,241 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>test</groupId>
+	<artifactId>mavenproject4</artifactId>
+	<packaging>war</packaging>
+	<version>1.0-SNAPSHOT</version>
+	<name>mavenproject4 - My Tynamo project</name>
+	<url>http://tynamo.org/</url>
+
+	<properties>
+		<tynamo-version>0.1.0</tynamo-version>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+	</properties>
+
+	<build>
+		<finalName>mavenproject4</finalName>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+					<optimize>true</optimize>
+				</configuration>
+			</plugin>
+
+			<!-- Run the application using "mvn jetty:run" -->
+			<plugin>
+				<groupId>org.mortbay.jetty</groupId>
+				<artifactId>maven-jetty-plugin</artifactId>
+				<version>6.1.26</version>
+				<configuration>
+					<contextPath>/</contextPath>
+					<!-- Log to the console. -->
+					<requestLog implementation="org.mortbay.jetty.NCSARequestLog">
+						<!-- This doesn't do anything for Jetty, but is a workaround for a Maven bug
+							 that prevents the requestLog from being set. -->
+						<append>true</append>
+					</requestLog>
+					<systemProperties>
+						<systemProperty>
+							<name>tapestry.compress-whitespace</name>
+							<value>false</value>
+						</systemProperty>
+						<systemProperty>
+							<name>tapestry.production-mode</name>
+							<value>false</value>
+						</systemProperty>
+					</systemProperties>
+				</configuration>
+			</plugin>
+
+			<!-- This changes the WAR file packaging so that what would normally go into WEB-INF/classes
+				 is instead packaged as WEB-INF/lib/mavenproject4.jar. This is necessary for Tapestry
+				 to be able to search for page and component classes at startup. Only
+				 certain application servers require this configuration, please see the documentation
+				 at the Tapestry 5 project page (http://tapestry.apache.org/tapestry5/).
+			 -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-war-plugin</artifactId>
+				<configuration>
+					<archiveClasses>true</archiveClasses>
+				</configuration>
+			</plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-surefire-plugin</artifactId>
+				<configuration>
+					<suiteXmlFiles>
+						<suiteXmlFile>src/test/conf/testng.xml</suiteXmlFile>
+					</suiteXmlFiles>
+					<argLine>-Xmx500m</argLine>
+					<redirectTestOutputToFile>false</redirectTestOutputToFile>
+				</configuration>
+			</plugin>
+
+			<!-- This gets the plugin to clean up the cobertura.ser file left
+		in the root directory. -->
+			<plugin>
+				<groupId>org.codehaus.mojo</groupId>
+				<artifactId>cobertura-maven-plugin</artifactId>
+				<version>2.2</version>
+				<executions>
+					<execution>
+						<id>clean</id>
+						<goals>
+							<goal>clean</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+
+	<reporting>
+		<!-- Adds a report detailing the components, mixins and base classes defined by this module. -->
+		<plugins>
+			<plugin>
+				<groupId>org.apache.tapestry</groupId>
+				<artifactId>tapestry-component-report</artifactId>
+				<version>5.2.4</version>
+				<configuration>
+					<rootPackage>test.mavenproject4</rootPackage>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-project-info-reports-plugin</artifactId>
+				<version>2.1.2</version>
+				<configuration>
+					<dependencyDetailsEnabled>false</dependencyDetailsEnabled>
+					<dependencyLocationsEnabled>false</dependencyLocationsEnabled>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.codehaus.mojo</groupId>
+				<artifactId>cobertura-maven-plugin</artifactId>
+				<version>2.2</version>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-surefire-report-plugin</artifactId>
+			</plugin>
+		</plugins>
+	</reporting>
+
+	<dependencies>
+
+		<dependency>
+			<groupId>org.tynamo</groupId>
+			<artifactId>tapestry-model-hibernate</artifactId>
+			<version>${tynamo-version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.tynamo</groupId>
+			<artifactId>tapestry-model-test</artifactId>
+			<version>${tynamo-version}</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.tynamo</groupId>
+			<artifactId>tapestry-model-web</artifactId>
+			<version>${tynamo-version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>com.h2database</groupId>
+			<artifactId>h2</artifactId>
+			<version>1.2.125</version>
+		</dependency>
+
+	</dependencies>
+
+	<!--
+	IMPORTANT NOTE:
+
+	Configuring repositories is against Maven best practices. If you have
+	a repository manager in use, remove this section and configure your
+	repository manager to proxy these repositories instead.
+	-->
+	<repositories>
+		<!-- Don't use snapshots unless absolutely necessary -->
+		<repository>
+			<id>codehaus-ci</id>
+			<name>Official snapshot repository available from Codehaus' Bamboo server</name>
+			<url>http://ci.repository.codehaus.org</url>
+			<snapshots>
+				<enabled>true</enabled>
+			</snapshots>
+			<releases>
+		 		<enabled>false</enabled>
+			</releases>
+		</repository>
+
+		<repository>
+			<id>repository.jboss.org</id>
+			<url>https://repository.jboss.org/nexus/content/repositories/releases</url>
+			<releases>
+				<enabled>true</enabled>
+			</releases>
+			<snapshots>
+				<enabled>false</enabled>
+			</snapshots>
+		</repository>
+
+		<!--
+			little hack to disable java.net repositories because they are not working
+			and they corrupt your local repo.
+		-->
+		<repository>
+			<id>maven-repository.dev.java.net</id>
+			<url>https://maven-repository.dev.java.net/nonav/repository</url>
+			<releases>
+				<enabled>false</enabled>
+			</releases>
+			<snapshots>
+				<enabled>false</enabled>
+			</snapshots>
+		</repository>
+		<repository>
+			<id>java.net</id>
+			<url>https://maven-repository.dev.java.net/nonav/repository</url>
+			<releases>
+				<enabled>false</enabled>
+			</releases>
+			<snapshots>
+				<enabled>false</enabled>
+			</snapshots>
+		</repository>
+
+	</repositories>
+
+</project>

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists