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 e37e856fca Proxy autodetection + autoconfiguration for Maven. (#5038)
e37e856fca is described below

commit e37e856fca13c1c0b174a5fb872c5c8f4f74332f
Author: Svatopluk Dedic <[email protected]>
AuthorDate: Wed Dec 7 20:41:42 2022 +0100

    Proxy autodetection + autoconfiguration for Maven. (#5038)
    
    Proxy autodetection + autoconfiguration for Maven. Reset gaps/panels to 
default size.
---
 .../modules/gradle/api/execute/Bundle.properties   |    2 +
 .../modules/maven/api/execute/Bundle.properties    |    1 +
 java/maven/licenseinfo.xml                         |    3 +
 .../modules/maven/api/execute/Bundle.properties    |    4 +-
 .../maven/execute/MavenCommandLineExecutor.java    |   60 +-
 .../modules/maven/execute/MavenProxySupport.java   | 1000 ++++++++++++++++++++
 .../modules/maven/execute/proxies.template.xml     |    9 +
 .../modules/maven/execute/proxy.template.xml       |    7 +
 .../maven/src/org/netbeans/modules/maven/layer.xml |    5 +
 .../modules/maven/options/Bundle.properties        |    1 +
 .../modules/maven/options/MavenSettings.java       |   13 +
 .../maven/options/NetworkProxySettings.java        |   76 ++
 .../modules/maven/options/SettingsPanel.form       |   78 +-
 .../modules/maven/options/SettingsPanel.java       |   63 +-
 .../modules/maven/problems/SanityBuildAction.java  |   30 +
 .../netbeans/modules/maven/settings.template.xml   |   17 +
 16 files changed, 1328 insertions(+), 41 deletions(-)

diff --git 
a/java/java.lsp.server/nbcode/branding/modules/org-netbeans-modules-gradle.jar/org/netbeans/modules/gradle/api/execute/Bundle.properties
 
b/java/java.lsp.server/nbcode/branding/modules/org-netbeans-modules-gradle.jar/org/netbeans/modules/gradle/api/execute/Bundle.properties
index c19939052e..fb601ea76a 100644
--- 
a/java/java.lsp.server/nbcode/branding/modules/org-netbeans-modules-gradle.jar/org/netbeans/modules/gradle/api/execute/Bundle.properties
+++ 
b/java/java.lsp.server/nbcode/branding/modules/org-netbeans-modules-gradle.jar/org/netbeans/modules/gradle/api/execute/Bundle.properties
@@ -18,3 +18,5 @@
 org.netbeans.modules.gradle.api.execute.TrustProjectOption.TrustOnce=1
 org.netbeans.modules.gradle.api.execute.TrustProjectOption.PermanentTrust=-2
 org.netbeans.modules.gradle.api.execute.TrustProjectOption.RunAlways=3
+
+org.netbeans.modules.gradle.api.execute.NetworkProxySettings.allowOverride=false
\ No newline at end of file
diff --git 
a/java/java.lsp.server/nbcode/branding/modules/org-netbeans-modules-maven.jar/org/netbeans/modules/maven/api/execute/Bundle.properties
 
b/java/java.lsp.server/nbcode/branding/modules/org-netbeans-modules-maven.jar/org/netbeans/modules/maven/api/execute/Bundle.properties
index aec63c34af..32382db89c 100644
--- 
a/java/java.lsp.server/nbcode/branding/modules/org-netbeans-modules-maven.jar/org/netbeans/modules/maven/api/execute/Bundle.properties
+++ 
b/java/java.lsp.server/nbcode/branding/modules/org-netbeans-modules-maven.jar/org/netbeans/modules/maven/api/execute/Bundle.properties
@@ -16,3 +16,4 @@
 # under the License.
 
 DEFAULT_COMPILE_ON_SAVE=none
+org.netbeans.modules.maven.api.execute.NetworkProxySettings.allowOverride=false
diff --git a/java/maven/licenseinfo.xml b/java/maven/licenseinfo.xml
index 86205c1d28..467836a522 100644
--- a/java/maven/licenseinfo.xml
+++ b/java/maven/licenseinfo.xml
@@ -82,6 +82,9 @@
     <fileset>
         
<file>src/org/netbeans/modules/maven/resources/AppTest.java.template</file>
         <file>src/org/netbeans/modules/maven/resources/App.java.template</file>
+        
<file>src/org/netbeans/modules/maven/execute/proxies.template.xml</file>
+        <file>src/org/netbeans/modules/maven/execute/proxy.template.xml</file>
+        <file>src/org/netbeans/modules/maven/settings.template.xml</file>
         <license ref="Apache-2.0-ASF" />
         <comment type="TEMPLATE_MINIMAL_IP"/>
     </fileset>
diff --git 
a/java/java.lsp.server/nbcode/branding/modules/org-netbeans-modules-maven.jar/org/netbeans/modules/maven/api/execute/Bundle.properties
 b/java/maven/src/org/netbeans/modules/maven/api/execute/Bundle.properties
similarity index 81%
copy from 
java/java.lsp.server/nbcode/branding/modules/org-netbeans-modules-maven.jar/org/netbeans/modules/maven/api/execute/Bundle.properties
copy to java/maven/src/org/netbeans/modules/maven/api/execute/Bundle.properties
index aec63c34af..d17e291333 100644
--- 
a/java/java.lsp.server/nbcode/branding/modules/org-netbeans-modules-maven.jar/org/netbeans/modules/maven/api/execute/Bundle.properties
+++ b/java/maven/src/org/netbeans/modules/maven/api/execute/Bundle.properties
@@ -15,4 +15,6 @@
 # specific language governing permissions and limitations
 # under the License.
 
-DEFAULT_COMPILE_ON_SAVE=none
+# Branding API
+# Enables on-the-fly override of proxy in maven sttings. Permitted values: 
true, false.
+org.netbeans.modules.maven.api.execute.NetworkProxySettings.allowOverride=true
diff --git 
a/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java
 
b/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java
index b1805f66a9..da5362821c 100644
--- 
a/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java
+++ 
b/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java
@@ -38,6 +38,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.UUID;
+import java.util.concurrent.ExecutionException;
 import java.util.function.Consumer;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -84,6 +85,7 @@ import org.netbeans.modules.maven.runjar.MavenExecuteUtils;
 import org.netbeans.spi.project.ui.support.BuildExecutionSupport;
 import org.openide.LifecycleManager;
 import org.openide.awt.HtmlBrowser;
+import org.openide.awt.NotificationDisplayer;
 import org.openide.execution.ExecutionEngine;
 import org.openide.execution.ExecutorTask;
 import org.openide.filesystems.FileObject;
@@ -92,7 +94,9 @@ import org.openide.modules.InstalledFileLocator;
 import org.openide.modules.Places;
 import org.openide.modules.SpecificationVersion;
 import org.openide.util.Exceptions;
+import org.openide.util.ImageUtilities;
 import org.openide.util.Lookup;
+import org.openide.util.NbBundle;
 import org.openide.util.RequestProcessor;
 import org.openide.util.Task;
 import org.openide.util.TaskListener;
@@ -143,6 +147,8 @@ public class MavenCommandLineExecutor extends 
AbstractMavenExecutor {
     private static final RequestProcessor RP = new 
RequestProcessor(MavenCommandLineExecutor.class.getName(),1);
 
     private static final RequestProcessor UPDATE_INDEX_RP = new 
RequestProcessor(RunUtils.class.getName(), 5);
+
+    private static final String ICON_MAVEN_PROJECT = 
"org/netbeans/modules/maven/resources/Maven2Icon.gif"; // NOI18N
     /**
      * Execute maven build in NetBeans execution engine.
      * Most callers should rather use {@link #run} as this variant does no 
(non-late-bound) prerequisite checks.
@@ -200,6 +206,11 @@ public class MavenCommandLineExecutor extends 
AbstractMavenExecutor {
         this.io = io;
     }
 
+    @NbBundle.Messages({
+        "# {0} - original message",
+        "ERR_CannotOverrideProxy=Could not override the proxy: {0}",
+        "ERR_BuildCancelled=Build cancelled by the user"
+    })
     /**
      * not to be called directly.. use execute();
      */
@@ -225,6 +236,49 @@ public class MavenCommandLineExecutor extends 
AbstractMavenExecutor {
         int executionresult = -10;
         final InputOutput ioput = getInputOutput();
 
+        // TODO: maybe global instance for project-less operation ?
+        MavenProxySupport mps = (clonedConfig.getProject() == null) ? null : 
clonedConfig.getProject().getLookup().lookup(MavenProxySupport.class);
+        if (mps != null) {
+            boolean ok = false;
+            try {
+                MavenProxySupport.ProxyResult res = 
mps.checkProxySettings().get();
+                
+                if (res != null) {
+                    res.configure(clonedConfig);
+                }
+                if (res.getStatus() == MavenProxySupport.Status.ABORT) {
+                    IOException ex = res.getException();
+                    
+                    if (ex == null) {
+                        ioput.getErr().append(Bundle.ERR_BuildCancelled());
+                    } else {
+                        throw ex;
+                    }
+                    
+                } else {
+                    ok = true;
+                }
+            } catch (IOException ex) {
+                
NotificationDisplayer.getDefault().notify(Bundle.TITLE_ProxyUpdateFailed(),
+                        ImageUtilities.loadImageIcon(ICON_MAVEN_PROJECT, 
false),
+                        ex.getLocalizedMessage(), null, 
NotificationDisplayer.Priority.NORMAL, NotificationDisplayer.Category.ERROR);
+                
ioput.getErr().append(Bundle.ERR_CannotOverrideProxy(ex.getLocalizedMessage()));
+                // FIXME: log exception
+            } catch (ExecutionException ex) {
+                // FIXME: log exception
+            } catch (InterruptedException ex) {
+                // FIXME: log exception
+            } finally {
+                if (!ok) {
+                    ioput.getOut().close();
+                    ioput.getErr().close();
+                    actionStatesAtFinish(null, null);
+                    markFreeTab();
+                    return;
+                }
+            }
+        }
+        
         final ProgressHandle handle = 
ProgressHandle.createHandle(clonedConfig.getTaskDisplayName(), this, new 
AbstractAction() {
             @Override
             public void actionPerformed(ActionEvent e) {
@@ -469,7 +523,11 @@ public class MavenCommandLineExecutor extends 
AbstractMavenExecutor {
                 toRet.add(rel != null ? rel : mp.getGroupId() + ':' + 
mp.getArtifactId());
             }
         }
-
+        Object o = config.getInternalProperties().get("NbIde.configOverride"); 
// NOI18N
+        if (o instanceof String) {
+            toRet.add("--settings");
+            toRet.add(o.toString());
+        }
         String opts = MavenSettings.getDefault().getDefaultOptions();
         if (opts != null) {
             try {
diff --git 
a/java/maven/src/org/netbeans/modules/maven/execute/MavenProxySupport.java 
b/java/maven/src/org/netbeans/modules/maven/execute/MavenProxySupport.java
new file mode 100644
index 0000000000..adcd4489da
--- /dev/null
+++ b/java/maven/src/org/netbeans/modules/maven/execute/MavenProxySupport.java
@@ -0,0 +1,1000 @@
+/*
+ * 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.execute;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.SocketAddress;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.StyledDocument;
+import org.apache.maven.settings.Settings;
+import org.codehaus.plexus.util.ReaderFactory;
+import org.codehaus.plexus.util.xml.pull.EntityReplacementMap;
+import org.codehaus.plexus.util.xml.pull.MXParser;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.netbeans.api.editor.document.AtomicLockDocument;
+import org.netbeans.api.editor.document.LineDocument;
+import org.netbeans.api.editor.document.LineDocumentUtils;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.templates.FileBuilder;
+import org.netbeans.modules.maven.api.NbMavenProject;
+import org.netbeans.modules.maven.embedder.EmbedderFactory;
+import org.netbeans.modules.maven.options.MavenSettings;
+import org.netbeans.modules.maven.options.NetworkProxySettings;
+import org.netbeans.spi.project.ProjectServiceProvider;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.awt.NotificationDisplayer;
+import org.openide.cookies.EditorCookie;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.loaders.SaveAsCapable;
+import org.openide.modules.Places;
+import org.openide.util.Exceptions;
+import org.openide.util.ImageUtilities;
+import org.openide.util.Lookup;
+import org.openide.util.MapFormat;
+import org.openide.util.NbBundle;
+
+/**
+ * Checks the proxy settings and possibly reconfigures Maven settings. The 
class checks the effective proxy settings using {@link ProxySelector} API, then 
reads the current Maven
+ * settings using {@link EmbedderFactory#getProjectEmbedder()}. If the maven 
settings do not contain proper proxy setup, maven options ({@link 
MavenSettings#getNetworkProxy()} is consulted:
+ * <ul>
+ * <li>IGNORE - no special handling
+ * <li>NOTICE - a notice is printed into the notifications area informing 
about possible bad proxy setup, no other action taken
+ * <li>UPDATE - maven configuration will be automatically updated (see below)
+ * <li>OVERRIDE - persistent global configuration is not changed, but a new 
settings file will be generated in $nbuser/var/cache/maven and maven {@link 
BeanRunConfig} will be instructed to use it
+ * <li>ASK - asks the user
+ * </ul>
+ * If maven settings are updated, the original contents is preserved as 
<code>settings.xml.old</code> or a numbered <code>settings.xml.old.N</code>, 
first unused N is selected. If the settings file contins
+ * the proxy in effect, but not active, the <code>active</code> property of 
that proxy will be set to true, and the others to false. Otherwise a new proxy 
entry with the desired proxy host/port is created.
+ * To disable proxies, all <code>active</code> entries are set to false.
+ * <p>
+ * The {@link 
ProxyResult#configure(org.netbeans.modules.maven.execute.BeanRunConfig)} should 
be run before each maven online invocation to potentially replace the global 
settings file with a customized one,
+ * that specifies the correct proxy.
+ * <p>
+ * When creating customized settings.xml files, the files are named like 
<code>settings-[hashcode of the oroginal]-[sanitized proxy host].xml. If the 
settings.xml file does not exist at all, "new" is used
+ * instead of the hashcode. Proxy host sanitization just replaces weird 
characters by "_".
+ * 
+ * @author sdedic
+ */
+@ProjectServiceProvider(service = MavenProxySupport.class, projectType = 
NbMavenProject.TYPE)
+public class MavenProxySupport {
+    private static final Logger LOG = 
Logger.getLogger(MavenProxySupport.class.getName());
+    /**
+     * Sample probe URI - google's public DNS server
+     */
+    private static final String PROBE_URI_STRING = "http://search.maven.org";; 
// NOI18N
+    
+    private static final String FILENAME_SUFFIX_OLD = ".old"; // NOI18N
+
+    private static final String ICON_MAVEN_PROJECT = 
"org/netbeans/modules/maven/resources/Maven2Icon.gif"; // NOi18N
+        
+
+    /**
+     * Tag name in settings file.
+     */
+    private static final String TAG_SETTINGS = "settings"; // NOI18N
+
+    /**
+     * Tag name in settings file.
+     */
+    private static final String TAG_PROXIES = "proxies"; // NOI18N
+
+    /**
+     * Tag name in settings file.
+     */
+    private static final String TAG_NAME_ACTIVE = "active"; // NOI18N
+
+    /**
+     * Complete tag start/end. End tag should contain a newline.
+     */
+    private static final String TAG_ACTIVE_START = "<active>"; // NOI18N
+    private static final String TAG_ACTIVE_END = "</active>\n"; // NOI18N
+
+    /**
+     * Tag name in settings file.
+     */
+    private static final String TAG_PROXY = "proxy"; // NOI18N
+
+    /**
+     * Suffix to add to customized settings filename when no proxy is 
configured (all disabled)
+     */
+    private static final String SUFFIX_NONE_PROXY = "-none"; // NOI18N
+    
+    /**
+     * Suffix for custom settings filename if global settings is missing.
+     */
+    private static final String SUFFIX_NEW_PROXY = "-new";
+    
+    /**
+     * Extension for the settings file
+     */
+    private static final String FILENAME_SETTINGS_EXT = ".xml"; // NOI18N
+    
+    /**
+     * Global settings file name
+     */
+    private static final String FILENAME_BASE_SETTINGS = "settings"; // NOI18N
+    private static final String FILENAME_SETTINGS = FILENAME_BASE_SETTINGS + 
FILENAME_SETTINGS_EXT;
+
+    
+    private static final int PORT_DEFAULT_HTTPS = 1080;
+    private static final int PORT_DEFAULT_HTTP = 80;
+    
+    /**
+     * Past decisions made by the user during this session. The Map is used so 
the user si not bothered that often with questions.
+     * If the user chooses 'override' or 'continue' (no action), the Map 
receives the public proxy spec and the result. If the same
+     * effective proxy is detected, the user is not asked again.
+     */
+    // @GuardedBy(this)
+    private Map<String, ProxyResult>    acknowledgedResults = new HashMap<>();
+    
+    public MavenProxySupport(Project project) {
+    }
+    
+    public CompletableFuture<ProxyResult> checkProxySettings() {
+        return new Processor().checkProxy();
+    }
+    
+    public enum Status {
+        UNKNOWN,
+        CONTINUE,
+        RECONFIGURED,
+        OVERRIDE,
+        ABORT
+    }
+    
+    public static final class ProxyResult {
+        private final Proxy proxy;
+        private final String toolProxy;
+        private final String proxyHost;
+        private final String proxySpec;
+        private final int proxyPort;
+        private final Settings mavenSettings;
+        private final boolean nonDefaultPort;
+        private volatile Status status;
+        TextInfo textInfo;
+        FileObject settingsDir;
+        String settingsFileName = FILENAME_SETTINGS;
+        IOException exception;
+        
+        public ProxyResult(Status status, Proxy proxy) {
+            this.status = status;
+            this.proxy = proxy;
+            this.toolProxy = null;
+            this.proxySpec = null;
+            this.proxyHost = null;
+            this.proxyPort = -1;
+            this.mavenSettings = null;
+            this.nonDefaultPort = false;
+        }
+        
+        public ProxyResult(Status status, Proxy proxy, String toolProxy, 
String proxySpec, String proxyHost, int proxyPort, boolean nonDefault, Settings 
mavenSettings) {
+            this.status = status;
+            this.proxy = proxy;
+            this.toolProxy = toolProxy;
+            this.proxySpec = proxySpec;
+            this.proxyHost = proxyHost;
+            this.proxyPort = proxyPort;
+            this.mavenSettings = mavenSettings;
+            this.nonDefaultPort = nonDefault;
+        }
+
+        public Status getStatus() {
+            return status;
+        }
+
+        public Proxy getProxy() {
+            return proxy;
+        }
+
+        public String getToolProxy() {
+            return toolProxy;
+        }
+
+        public String getProxySpec() {
+            return proxySpec;
+        }
+
+        public IOException getException() {
+            return exception;
+        }
+
+        @NbBundle.Messages({
+            "# {0} - settings directory name",
+            "ERR_CannotCreateSettingsDir=Could not create settings directory: 
{0}",
+            "# {0} - settings file name",
+            "ERR_CannoLocateSettings=Could not locate and open settings file: 
{0}",
+            "# {0} - proxy id",
+            "# {1} - proxy host",
+            "ERR_CannotDisableProxy=Could not disable proxy id {0}, host {1}",
+            "# {0} - proxy id",
+            "# {1} - proxy host",
+            "ERR_CannotEnableProxy=Could not enable proxy id {0}, host {1}",
+            "# {0} - proxy host",
+            "ERR_CannotInsertProxy=Could not add proxy host {0}"
+        })
+        private FileObject generateNewSettingsFile(Path settingsPath) throws 
IOException {
+            FileObject settingsDir = this.settingsDir != null ? 
this.settingsDir : FileUtil.toFileObject(settingsPath.getParent().toFile());
+            if (settingsDir == null) {
+                Path dir = Files.createDirectory(settingsPath.getParent());
+                settingsDir = FileUtil.toFileObject(dir.toFile());
+                if (settingsDir == null) {
+                    throw new 
IOException(Bundle.ERROR_ConfigUpdateFailed(settingsPath.getParent()));
+                }
+            }
+            Map<String, Object> params = new HashMap<>();
+            params.put("proxyHost", proxyHost);
+            params.put("proxyPort", proxyPort);
+            return FileBuilder.createFromTemplate(
+                    
FileUtil.getConfigFile("Templates/Project/Maven2/settings.xml"), settingsDir, 
settingsFileName, 
+                    params, FileBuilder.Mode.FAIL);
+        }
+        
+        private File getMavenSettings() {
+            return new File(new File(System.getProperty("user.home"), ".m2"), 
FILENAME_SETTINGS); // NOI18N
+        }
+        
+        public BeanRunConfig configure(BeanRunConfig config) throws 
IOException {
+            if (status != Status.OVERRIDE) {
+                return config;
+            }
+            // compute digest
+            String uniqueString = "";
+            try {
+                Path p = getMavenSettings().toPath();
+                if (!Files.exists(p)) {
+                    uniqueString = SUFFIX_NEW_PROXY; // NOI18N
+                } else {
+                    MessageDigest dg = MessageDigest.getInstance("SHA1");
+                    byte[] bytes = dg.digest(Files.readAllBytes(p));
+                    StringBuilder sb = new StringBuilder("-");
+                    for (int i = 0; i < bytes.length; i++) {
+                        sb.append(Integer.toHexString(bytes[i] & 0xff));
+                    }
+                    uniqueString = sb.toString();
+                }
+            } catch (NoSuchAlgorithmException | IOException ex) {
+                return config;
+            }
+            settingsDir = 
FileUtil.toFileObject(Places.getCacheSubdirectory("maven"));
+            if (settingsDir == null) {
+                return config;
+            }
+            if (proxyHost == null) {
+                uniqueString += SUFFIX_NONE_PROXY;
+            } else {
+                uniqueString += "-" + proxySpec.replace(":", "_");
+            }
+            settingsFileName = FILENAME_BASE_SETTINGS + uniqueString + 
FILENAME_SETTINGS_EXT;
+            FileObject alreadyDone = 
settingsDir.getFileObject(settingsFileName);
+            if (alreadyDone != null) {
+                config.setInternalProperty("NbIde.configOverride", 
alreadyDone.getPath());
+                return config;
+            }
+            
+            updateMavenProxy();
+            alreadyDone = settingsDir.getFileObject(settingsFileName);
+            config.setInternalProperty("NbIde.configOverride", 
alreadyDone.getPath());
+            return config;
+        }
+        
+        private void loadMavenTextInfo() throws IOException, 
IllegalArgumentException {
+            Path settingsPath = getMavenSettings().toPath();
+            if (!Files.isReadable(settingsPath) && 
Files.isRegularFile(settingsPath)) {
+                generateNewSettingsFile(settingsPath);
+                return;
+            }
+            XppDelegate del = new 
XppDelegate(EntityReplacementMap.defaultEntityReplacementMap);
+            
+            try (FileInputStream in = new 
FileInputStream(settingsPath.toFile())) {
+                del.setInput( ReaderFactory.newXmlReader( in ));
+                while (del.next() != XmlPullParser.END_DOCUMENT) {
+                    // empty, just read
+                }
+                textInfo = del.textInfo;
+            } catch (XmlPullParserException ex) {
+                throw new IOException(ex);
+            }
+        }
+        
+        private AtomicLockDocument adoc;
+        private LineDocument settingsLineDoc;
+        private EditorCookie settingsEditor;
+        private Lookup fileLookup;
+        
+        private void loadSettingsContents() throws IOException {
+            if (settingsEditor != null) {
+                return;
+            }
+            Path settingsPath = getMavenSettings().toPath();
+            FileObject fo = FileUtil.toFileObject(settingsPath.toFile());
+            if (fo == null) {
+                return;
+            }
+            fileLookup = fo.getLookup();
+            EditorCookie cake = fileLookup.lookup(EditorCookie.class);
+            if (cake == null) {
+                throw new 
IOException(Bundle.ERR_CannoLocateSettings(settingsPath));
+            }
+            StyledDocument doc = cake.openDocument();
+            settingsLineDoc = LineDocumentUtils.as(doc, LineDocument.class);
+            adoc = LineDocumentUtils.asRequired(doc, AtomicLockDocument.class);
+            if (settingsLineDoc == null) {
+                throw new 
IOException(Bundle.ERR_CannoLocateSettings(settingsPath));
+            }
+            settingsEditor = cake;
+            
+            loadMavenTextInfo();
+        }
+        
+        private String padding(int num) {
+            StringBuffer sb = new StringBuffer();
+            for (int i = 0; i < num; i++) {
+                sb.append(' ');
+            }
+            return sb.toString();
+        }
+        
+        /**
+         * Insert a new proxy:
+         * - if at least one 'proxy' block exists, insert the new definition 
before all the other ones
+         * - if "proxies" element exists, but no proxy definition, insert 
right after "proxies"
+         * - if no proxies element exists insert at the position of the first 
element including the 'proxies' clause.
+         */
+        private void insertNewProxy() throws IOException {
+            int startColumn = 0;
+            LineAndColumn insertAt;
+            
+            StringBuilder textBuilder = new StringBuilder();
+            if (textInfo.proxyTags.isEmpty()) {
+                if (textInfo.proxiesEndTag != null) {
+                    // TODO: obey IDE formatting for xml files ?
+                    insertAt = textInfo.proxiesEndTag;
+                    startColumn = insertAt.column - 1 + 4;
+                    // add 4 spaces, indent between <proxies> and nested 
<proxy>, we're using padding of the </proxies> here.
+                    textBuilder.append("    "); // NOI18N
+                } else {
+                    insertAt = textInfo.firstTag;
+                    startColumn = insertAt.column - 1;
+                }
+            } else {
+                insertAt = 
textInfo.proxyTags.get(0).tags.get(TAG_PROXY).startTag;
+                startColumn = insertAt.column - 1;
+            }
+            
+            // inserting at the position of first "proxy" element: no padding 
in front, add padding at the end.
+            // inserting at the position of </proxies> closing tag: 4-space 
padding at the start, 
+            try (
+                InputStream inputStream = 
getClass().getResourceAsStream(textInfo.proxiesEndTag != null ? 
"proxy.template.xml" : "proxies.template.xml");
+                BufferedReader reader = new BufferedReader(new 
InputStreamReader(inputStream, 
Charset.forName(StandardCharsets.UTF_8.name())))) {
+                String s;
+                boolean first = true;
+                
+                while ((s = reader.readLine()) != null) {
+                    if (!first) {
+                        textBuilder.append(padding(startColumn));
+                    }
+                    first = false;
+                    textBuilder.append(s).append("\n");
+                }
+            }
+            // add necessary padding
+            if (!textInfo.proxyTags.isEmpty()) {
+                textBuilder.append(padding(startColumn));
+            } else if (textInfo.proxiesEndTag != null) {
+                textBuilder.append(padding(textInfo.proxiesEndTag.column - 1));
+            } else {
+                textBuilder.append(padding(startColumn));
+            }
+            Map<String, String> args = new HashMap<>();
+            args.put(FMT_PROXY_HOST, proxyHost);
+            args.put(FMT_PROXY_PORT, Integer.toString(proxyPort));
+            
+            MapFormat fmt = new MapFormat(args);
+            fmt.setLeftBrace("${");
+            String contents = fmt.format(textBuilder.toString());
+            
+            IOException[] err = new IOException[1];
+            adoc.runAtomic(() -> {
+                try {
+                    int lineOffset = 
LineDocumentUtils.getLineStartFromIndex(settingsLineDoc, insertAt.line - 1);
+                    int startOffset = lineOffset + insertAt.column - 1;
+
+                    settingsLineDoc.insertString(startOffset, contents, null);
+                } catch (BadLocationException ex) {
+                    err[0] =  new 
IOException(Bundle.ERR_CannotInsertProxy(proxyHost));
+                }
+            });
+
+            if (err[0] != null) {
+                throw err[0];
+            }
+        }
+        private static final String FMT_PROXY_PORT = "proxyPort"; // NOI18N
+        private static final String FMT_PROXY_HOST = "proxyHost"; // NOI18N
+        
+        private void enableProxy(org.apache.maven.settings.Proxy p, int 
proxyIndex, boolean enable) throws IOException {
+            String failureMsg = enable ? 
Bundle.ERR_CannotEnableProxy(p.getId(), p.getHost()) : 
Bundle.ERR_CannotDisableProxy(p.getId(), p.getHost());
+            if (textInfo.proxyTags.size() < proxyIndex) {
+                throw new IOException(failureMsg);
+            }
+            ProxyInfo pi = textInfo.proxyTags.get(proxyIndex);
+            TagInfo activeTag = pi.tags.get(TAG_NAME_ACTIVE);
+            IOException[] err = new IOException[1];
+            
+            if (activeTag != null) {
+                adoc.runAtomic(() -> {
+                    try {
+                        int lineOffset = 
LineDocumentUtils.getLineStartFromIndex(settingsLineDoc, 
activeTag.startTag.line - 1);
+                        int startOffset = lineOffset + 
activeTag.startTag.column - 1;
+                        
+                        int endLineOffset = 
LineDocumentUtils.getLineStartFromIndex(settingsLineDoc, activeTag.endTag.line 
- 1);
+                        int endOffset = endLineOffset + 
activeTag.endTag.column - 1;
+                        
+                        String content = settingsLineDoc.getText(startOffset, 
endOffset - startOffset);
+                        int endStartTagPos = content.indexOf(">");
+                        if (endStartTagPos == -1 || endStartTagPos >= 
(endOffset - startOffset)) {
+                            // cannot find end of start tag
+                            err[0] =  new 
IOException(Bundle.ERR_CannotDisableProxy(p.getId(), p.getHost()));
+                            return;
+                        }
+                        int from = startOffset + endStartTagPos + 1;
+                        settingsLineDoc.remove(from, endOffset - from);
+                        settingsLineDoc.insertString(from, enable ? "true" : 
"false", null); // NOI18N
+                    } catch (BadLocationException ex) {
+                        err[0] =  new IOException(failureMsg);
+                    }
+                });
+            } else {
+                if (pi.firstTag == null) {
+                    throw new 
IOException(Bundle.ERR_CannotDisableProxy(p.getId(), p.getHost()));
+                }
+                String toInsert = padding(pi.firstTag.column) + 
TAG_ACTIVE_START + enable + TAG_ACTIVE_END; // NOI18N
+                adoc.runAtomic(() -> {
+                    try {
+                        int lineOffset = 
LineDocumentUtils.getLineStartFromIndex(settingsLineDoc, pi.firstTag.line - 1);
+                        settingsLineDoc.insertString(lineOffset, toInsert, 
null);
+                    } catch (BadLocationException ex) {
+                        err[0] =  new IOException(failureMsg);
+                    }
+                });
+            }
+            
+            if (err[0] != null) {
+                throw err[0];
+            }
+        }
+
+        private void updateMavenProxy() throws IOException {
+            loadSettingsContents();
+            
+            if (textInfo == null) {
+                if (settingsDir != null) {
+                    
generateNewSettingsFile(FileUtil.toFile(settingsDir).toPath().resolve(settingsFileName));
+                } else {
+                    generateNewSettingsFile(getMavenSettings().toPath());
+                }
+                return;
+            }
+            
+            // case 1: proxy should not be set, let's deactivate all the 
proxies
+            int pos = 0;
+            if (proxyHost == null) {
+                for (org.apache.maven.settings.Proxy p : 
mavenSettings.getProxies()) {
+                    if (p.isActive()) {
+                        enableProxy(p, pos, false);
+                    }
+                    pos++;
+                }
+            } else {
+
+                // case 2: there MAY be a matching proxy already defined, but 
not active.
+                org.apache.maven.settings.Proxy existingProxy = null;
+
+                for (org.apache.maven.settings.Proxy p : 
mavenSettings.getProxies()) {
+                    if (proxyHost.equals(p.getHost())) {
+                        if (!nonDefaultPort || proxyPort == p.getPort()) {
+                            existingProxy = p;
+                            break;
+                        }
+                    }
+                }
+
+                for (org.apache.maven.settings.Proxy p : 
mavenSettings.getProxies()) {
+                    if (p != existingProxy) {
+                        enableProxy(p, pos, false);
+                    }
+                    pos++;
+                }
+                if (existingProxy != null) {
+                    if (!existingProxy.isActive()) {
+                        int proxyIndex = 
mavenSettings.getProxies().indexOf(existingProxy);
+                        if (proxyIndex == -1) {
+                            throw new 
IOException(Bundle.ERR_CannotEnableProxy(existingProxy.getId(), 
existingProxy.getHost()));
+                        }
+                        enableProxy(existingProxy, proxyIndex, true);
+                    }
+                } else {
+                    insertNewProxy();
+                }
+            }
+            
+            if (settingsEditor.isModified()) {
+                if (settingsDir != null) {
+                    SaveAsCapable saa = fileLookup.lookup(SaveAsCapable.class);
+                    if (saa != null) {
+                        saa.saveAs(settingsDir, settingsFileName);
+                    } else {
+                        // FIXME: log a warning
+                    }
+                } else {
+                    File settings = getMavenSettings();
+                    String base = settings + FILENAME_SUFFIX_OLD;
+                    File f = new File(settings.getParentFile(), base);
+                    int n = 1;
+                    while (f.exists()) {
+                        f = new File(settings.getParentFile(), base + "." + 
n); // NOI18N
+                        n++;
+                    }
+                    settings.renameTo(f);
+                    settingsEditor.saveDocument();
+                }
+            }
+        }
+    }
+
+    @NbBundle.Messages({
+        "TITLE_MavenProxyMismatch=Possible Network Proxy Issue",
+        "# {0} - gradle proxy",
+        "MSG_ProxyMisconfiguredDirect=Maven is configured for a proxy {0}, but 
the system does not require a proxy for network connections. Proxy settings 
should be removed from user gradle.properties.",
+        "# {0} - system proxy",
+        "MSG_ProxyMisconfiguredMissing=Maven is not configured to use a 
network proxy, but the proxy {0} seems to be required for network 
communication. User gradle.properties should be updated to specify a proxy.",
+        "# {0} - system proxy",
+        "# {1} - gradle proxy",
+        "MSG_ProxyMisconfiguredOther=Maven is configured to use a network 
proxy {1}, but the proxy {0} seems to be required for network communication. 
Proxy settings should be updated in user gradle.properties.",
+        "MSG_AppendAskUpdate=\nUpdate Maven configuration ? Choose 
\"Override\" to apply detected proxy only to IDE operations.",
+        "MSG_AppendAskUpdate2=\nUpdate Maven configuration ?",
+        "ACTION_Override=Override",
+        "ACTION_Continue=Keep settings",
+        "# {0} - date/time of the update",
+        "COMMENT_CreatedByNetBeans=# This proxy configuration has been updated 
by Apache NetBeans on {0}",
+        "TITLE_ConfigUpdateFailed=Configuration update failed",
+        "# {0} - error message",
+        "ERROR_ConfigUpdateFailed=Failed to modify Maven user properties: {0}",
+        "# {0} - proxy specification",
+        "MSG_ProxySetTo=Maven Network proxy set to: {0}",
+        "MSG_ProxyCleared=Maven Network proxy removed",
+    })
+    /**
+     * Encapsulates a single check to avoid an enormous method or a ton of 
parameters passed through
+     * a method chain. Should be constructed for each new check separately.
+     */
+    private class Processor {
+        Proxy publicProxy;
+        String publicProxyHost;
+        int publicProxyPort;
+        int publicProxyNonDefaultPort;
+        
+        String proxyAuthority;
+        String proxyHost;
+        String publicProxySpec;
+        
+        int proxyPort;
+        
+        Settings mavenSettings;
+        
+        public CompletableFuture<ProxyResult> checkProxy() {
+            boolean supportOverride = 
NetworkProxySettings.allowProxyOverride();
+            NetworkProxySettings action = 
MavenSettings.getDefault().getNetworkProxy();
+            if (action == NetworkProxySettings.IGNORE) {
+                return 
CompletableFuture.completedFuture(createResult(Status.CONTINUE));
+            }
+            
+            obtainPublicProxy();
+            loadProjectProxy();
+            
+            boolean direct = publicProxy == null || publicProxy.type() == 
Proxy.Type.DIRECT;
+            
+            if (direct && proxyAuthority == null) {
+                LOG.log(Level.FINE, "Project does not specify a proxy and none 
is needed");
+                return 
CompletableFuture.completedFuture(createResult(Status.CONTINUE));
+            }
+            
+            if (publicProxy != null) {
+                if (publicProxyHost == null) {
+                    // unable to decipher proxy address
+                    LOG.log(Level.WARNING, "Unable to decipher proxy: {0}", 
publicProxy);
+                    return CompletableFuture.completedFuture(new 
ProxyResult(Status.UNKNOWN, null));
+                }
+                if (publicProxyHost.equals(proxyHost) && proxyPort == 
publicProxyPort) {
+                    LOG.log(Level.FINE, "Project specifies detected proxy: 
{0}", publicProxySpec);
+                    return CompletableFuture.completedFuture(new 
ProxyResult(Status.CONTINUE, publicProxy));
+                }
+            }
+            
+            // at this point, it's obvious that 
+            
+            String userMessage;
+            
+            if (direct) {
+                userMessage = 
Bundle.MSG_ProxyMisconfiguredDirect(proxyAuthority);
+            } else if (proxyAuthority == null) {
+                userMessage = 
Bundle.MSG_ProxyMisconfiguredMissing(publicProxySpec);
+            } else {
+                userMessage = 
Bundle.MSG_ProxyMisconfiguredOther(publicProxySpec, proxyAuthority);
+            }
+            
+            ProxyResult result;
+            synchronized (this) {
+                result = acknowledgedResults.get(publicProxySpec);
+            }
+            if (result != null) {
+                LOG.log(Level.FINE, "Reusing previous decision: {0} with proxy 
{1}", new Object[] { result.getStatus(), result.proxySpec });
+                switch (result.getStatus()) {
+                    case CONTINUE:
+                        // includes noth NOTICE and IGNORE settings !
+                        action = NetworkProxySettings.IGNORE;
+                        break;
+                    case OVERRIDE: 
+                        action = NetworkProxySettings.OVERRIDE;
+                        break;
+                    case RECONFIGURED:
+                        action = NetworkProxySettings.UPDATE;
+                        break;
+                }
+            }
+
+            switch (action) {
+                case IGNORE:
+                    return 
CompletableFuture.completedFuture(createResult(Status.CONTINUE));
+                    
+                case NOTICE:
+                    
NotificationDisplayer.getDefault().notify(Bundle.TITLE_MavenProxyMismatch(),
+                            ImageUtilities.loadImageIcon(ICON_MAVEN_PROJECT, 
false),
+                            userMessage, null, 
NotificationDisplayer.Priority.NORMAL, NotificationDisplayer.Category.WARNING);
+                    return 
CompletableFuture.completedFuture(createResult(Status.CONTINUE));
+                
+                case OVERRIDE:
+                    return 
CompletableFuture.completedFuture(createResult(Status.OVERRIDE));
+                    
+                case UPDATE:
+                    try {
+                        result = createResult(Status.RECONFIGURED);
+                        result.updateMavenProxy();
+                    } catch (IOException ex) {
+                        result = createResult(ex);
+                    }
+                    return CompletableFuture.completedFuture(result);
+                    
+                case ASK:
+                    if (result != null) {
+                        return CompletableFuture.completedFuture(result);
+                    }
+                    String promptMsg;
+                    
+                    if (supportOverride) {
+                        promptMsg = userMessage + Bundle.MSG_AppendAskUpdate();
+                    } else {
+                        promptMsg = userMessage + 
Bundle.MSG_AppendAskUpdate2();
+                    }
+                    NotifyDescriptor desc = new NotifyDescriptor.Confirmation(
+                            promptMsg, Bundle.TITLE_MavenProxyMismatch(),
+                            NotifyDescriptor.OK_CANCEL_OPTION,  
NotifyDescriptor.WARNING_MESSAGE);
+                    if (supportOverride) {
+                        desc.setAdditionalOptions(new Object[] { 
Bundle.ACTION_Continue(), Bundle.ACTION_Override() });
+                    } else {
+                        desc.setAdditionalOptions(new Object[] { 
Bundle.ACTION_Continue() });
+                    }
+                    desc.setValue(NotifyDescriptor.OK_OPTION);
+                    
+                    return 
DialogDisplayer.getDefault().notifyFuture(desc).thenApply(this::processUserConfirmation).exceptionally(t
 -> {
+                        if ((t instanceof CompletionException) && 
(t.getCause() instanceof CancellationException)) {
+                            return createResult(Status.ABORT);
+                        } else {
+                            return createResult(Status.UNKNOWN);
+                        }
+                    });
+            }
+            
+            return null;
+        }
+
+        ProxyResult createResult(IOException ex) {
+            ProxyResult r = createResult(Status.ABORT);
+            r.exception = ex;
+            LOG.log(Level.WARNING, "Failed to configure proxy", ex);
+            return r;
+        }
+
+        ProxyResult createResult(Status s) {
+            boolean keep = false;
+            switch (s) {
+                case OVERRIDE:
+                    keep = true;
+                    LOG.log(Level.FINE, "Will override proxy to {0}", 
publicProxy);
+                    break;
+                case ABORT:
+                    LOG.log(Level.FINE, "Will abort operation");
+                    break;
+                case CONTINUE:
+                    keep = true;
+                    LOG.log(Level.FINE, "No action will be taken");
+                    break;
+                case RECONFIGURED:
+                    LOG.log(Level.FINE, "User properties were reconfigured to 
{0}", publicProxy);
+                    break;
+            }
+            ProxyResult r = new ProxyResult(s, publicProxy, proxyAuthority, 
publicProxySpec, publicProxyHost, publicProxyPort, publicProxyNonDefaultPort > 
0, mavenSettings);
+            if (keep) {
+                synchronized (this) {
+                    acknowledgedResults.put(publicProxySpec, r);
+                }
+            }
+            return r;
+        }
+        
+        @NbBundle.Messages({
+            "TITLE_ProxyUpdateFailed=Update of proxy configuration failed"
+        })
+        ProxyResult processUserConfirmation(NotifyDescriptor desc) {
+            Object val = desc.getValue();
+            if (val == NotifyDescriptor.CANCEL_OPTION) {
+                return createResult(Status.ABORT);
+            } else if (val == Bundle.ACTION_Continue()) {
+                return createResult(Status.CONTINUE);
+            } else if (val == Bundle.ACTION_Override()) {
+                return createResult(Status.OVERRIDE);
+            } else if (val == NotifyDescriptor.OK_OPTION) {
+                try {
+                    ProxyResult result = createResult(Status.RECONFIGURED);
+                    result.updateMavenProxy();
+                } catch (IOException ex) {
+                    return createResult(ex);
+                }
+            }
+            return createResult(Status.UNKNOWN);
+        }
+        
+        private void obtainPublicProxy() {
+            URI probeUri;
+            try {
+                probeUri = new URI(PROBE_URI_STRING);
+            } catch (URISyntaxException ex) {
+                // this is competely unexpected
+                Exceptions.printStackTrace(ex);
+                return;
+            }
+            List<Proxy> proxies = ProxySelector.getDefault().select(probeUri);
+            LOG.log(Level.FINER, "Detected proxies for URI {0}: {1}", new 
Object[] { probeUri, proxies });
+            for (Proxy p : proxies) {
+                if (p.type() == Proxy.Type.HTTP) {
+                    publicProxy = p;
+                    LOG.log(Level.FINE, "Selected HTTP proxy: {0}", p);
+                    break;
+                } else if (p.type() == Proxy.Type.SOCKS) {
+                    if (publicProxy == null) {
+                        LOG.log(Level.FINE, "Found SOCKS proxy: {0}", p);
+                        publicProxy = p;
+                    }
+                }
+            }
+            if (publicProxy != null) {
+                SocketAddress proxyAddress = publicProxy.address();
+                if (proxyAddress instanceof InetSocketAddress) {
+                    InetSocketAddress iaddr = (InetSocketAddress)proxyAddress;
+                    int port = iaddr.getPort();
+                    int defPort = -1;
+
+                    switch(publicProxy.type()) {
+                        case HTTP:
+                            defPort = PORT_DEFAULT_HTTP; 
+                            break;
+                        case SOCKS:
+                            defPort = PORT_DEFAULT_HTTPS; 
+                            break;
+                    }
+                    
+                    if (port > 1) {
+                        publicProxyPort = port;
+                        if (publicProxyPort != defPort) {
+                            publicProxyNonDefaultPort = port;
+                        }
+                    }
+                    publicProxyHost = ((InetSocketAddress) 
proxyAddress).getHostString();
+                    publicProxySpec = publicProxyHost + 
((publicProxyNonDefaultPort == 0) ? "" : ":" + publicProxyNonDefaultPort);
+                    LOG.log(Level.FINE, "Detected proxy: {0}", 
publicProxySpec);
+                }
+            }
+        }
+
+        private void loadProjectProxy() {
+            mavenSettings = EmbedderFactory.getProjectEmbedder().getSettings();
+            org.apache.maven.settings.Proxy activeProxy = 
mavenSettings.getActiveProxy();
+            if (activeProxy != null) {
+                proxyHost = activeProxy.getHost();
+                proxyPort = activeProxy.getPort();
+                
+                if (proxyPort > 0) {
+                    proxyAuthority = proxyHost + ":" + proxyPort;
+                }
+            } else {
+                proxyAuthority = null;
+                proxyHost = null;
+                proxyPort = -1;
+            }
+        }
+        
+    }
+    
+    static class LineAndColumn {
+        int offset = -1;
+        int line;
+        int column;
+
+        public LineAndColumn(int line, int column) {
+            this.line = line;
+            this.column = column;
+        }
+    }
+    
+    static class TagInfo {
+        String tagName;
+        LineAndColumn  startTag;
+        LineAndColumn  content;
+        LineAndColumn  endTag;
+
+        public TagInfo(String tagName, LineAndColumn start) {
+            this.tagName = tagName;
+            this.startTag = start;
+        }
+    }
+    
+    static class ProxyInfo {
+        LineAndColumn firstTag;
+        Map<String, TagInfo> tags = new HashMap<>();
+    }
+    
+    static class TextInfo {
+        LineAndColumn firstTag;
+        LineAndColumn firstProxyTag;
+        LineAndColumn proxiesEndTag;
+        List<ProxyInfo> proxyTags = new ArrayList<>();
+    }
+
+    static class XppDelegate extends MXParser {
+        private static final int UNKNOWN = 0;
+        private static final int PROXIES = 1;
+        private static final int PROXY = 2;
+        private static final int INSIDE_PROXY = 3;
+        
+        private TextInfo textInfo = new TextInfo();
+        private LinkedList<TagInfo> tagStack = new LinkedList<>();
+        private ProxyInfo current;
+        private int state = UNKNOWN;
+
+        public XppDelegate(EntityReplacementMap entityReplacementMap) {
+            super(entityReplacementMap);
+        }
+        
+        @Override
+        public int nextTag() throws XmlPullParserException, IOException {
+            int t = super.nextTag(); 
+            return processToken(t);
+        }
+
+        @Override
+        public int next() throws XmlPullParserException, IOException {
+            int t = super.next();
+            return processToken(t);
+        }
+        
+        private LineAndColumn startPos() {
+            int ln = getLineNumber();
+            int col = getColumnNumber();
+            col -= (posEnd - posStart);
+            return new LineAndColumn(ln, col);
+        }
+
+        private LineAndColumn pos() {
+            return new LineAndColumn(getLineNumber(), getColumnNumber());
+        }
+        
+        private int processToken(int token) {
+            
+            switch (token) {
+                case XmlPullParser.END_TAG:
+                    String en = getName();
+                    if (state >= PROXY) {
+                        if (TAG_PROXY.equals(en)) {
+                            state = PROXIES;
+                            current = null;
+                            tagStack.clear();
+                            break;
+                        }
+                        if (!tagStack.isEmpty()) {
+                            tagStack.getLast().endTag = startPos();
+                            tagStack.removeLast();
+                        }
+                    } else if (state == PROXIES && TAG_PROXIES.equals(en)) {
+                        state = UNKNOWN;
+                        textInfo.proxiesEndTag = startPos();
+                        break;
+                    }
+                    break;
+                case XmlPullParser.START_TAG:
+                    String n = getName();
+                    if (state == UNKNOWN) {
+                        if (TAG_PROXIES.equals(n)) {
+                            state = 1;
+                        } else if (!TAG_SETTINGS.equals(n) && 
textInfo.firstTag == null) {
+                            textInfo.firstTag = startPos();
+                        }
+                        break;
+                    }
+                    if (state == PROXIES && TAG_PROXY.equals(n)) {
+                        textInfo.firstProxyTag = pos();
+                        state = INSIDE_PROXY;
+                        current = new ProxyInfo();
+                        textInfo.proxyTags.add(current);
+                        // fall through, so proxy is recorded
+                    }
+                    if (state >= PROXY) {
+                        TagInfo ti = new TagInfo(n, startPos());
+                        if (current != null) {
+                            if (current.firstTag == null) {
+                                current.firstTag = ti.startTag;
+                            }
+                            current.tags.putIfAbsent(ti.tagName, ti);
+                        }
+                        tagStack.add(ti);
+                        break;
+                    }
+            }
+            return token;
+        }
+    }
+}
diff --git 
a/java/maven/src/org/netbeans/modules/maven/execute/proxies.template.xml 
b/java/maven/src/org/netbeans/modules/maven/execute/proxies.template.xml
new file mode 100644
index 0000000000..f1b2f3fcbe
--- /dev/null
+++ b/java/maven/src/org/netbeans/modules/maven/execute/proxies.template.xml
@@ -0,0 +1,9 @@
+<proxies>
+    <proxy>
+        <id>netbeans-default-proxy</id>
+        <active>true</active>
+        <protocol>http</protocol>
+        <host>${proxyHost}</host>
+        <port>${proxyPort}</port>
+    </proxy>
+</proxies>
diff --git 
a/java/maven/src/org/netbeans/modules/maven/execute/proxy.template.xml 
b/java/maven/src/org/netbeans/modules/maven/execute/proxy.template.xml
new file mode 100644
index 0000000000..486e867909
--- /dev/null
+++ b/java/maven/src/org/netbeans/modules/maven/execute/proxy.template.xml
@@ -0,0 +1,7 @@
+<proxy>
+    <id>netbeans-default-proxy</id>
+    <active>true</active>
+    <protocol>http</protocol>
+    <host>${proxyHost}</host>
+    <port>${proxyPort}</port>
+</proxy>
diff --git a/java/maven/src/org/netbeans/modules/maven/layer.xml 
b/java/maven/src/org/netbeans/modules/maven/layer.xml
index b23427b7eb..a80ef96dd0 100644
--- a/java/maven/src/org/netbeans/modules/maven/layer.xml
+++ b/java/maven/src/org/netbeans/modules/maven/layer.xml
@@ -49,6 +49,11 @@
                         </folder>
                     </folder>
                 </folder>
+                
+                <file name="settings.xml" url="settings.template.xml">
+                    <attr name="javax.script.ScriptEngine" 
stringvalue="freemarker"/>
+                    <attr name="template.openFile" boolvalue="false"/>
+                </file>
             </folder>
         </folder>
     </folder>
diff --git 
a/java/maven/src/org/netbeans/modules/maven/options/Bundle.properties 
b/java/maven/src/org/netbeans/modules/maven/options/Bundle.properties
index 5a430ebe69..9e300b945b 100644
--- a/java/maven/src/org/netbeans/modules/maven/options/Bundle.properties
+++ b/java/maven/src/org/netbeans/modules/maven/options/Bundle.properties
@@ -91,3 +91,4 @@ SettingsPanel.jLabel5.text=(NOT recommended, many features 
will be limited as a
 SettingsPanel.lblJdkHome.text=Default &JDK
 SettingsPanel.comManageJdks.text=Mana&ge Java Platforms
 SettingsPanel.cbPreferWrapper.text=Prefer Maven Wrapper that comes with project
+SettingsPanel.lbNetworkSettings.text=Network pro&xy:
diff --git 
a/java/maven/src/org/netbeans/modules/maven/options/MavenSettings.java 
b/java/maven/src/org/netbeans/modules/maven/options/MavenSettings.java
index 6fe2a7f1f7..bda5cbabf2 100644
--- a/java/maven/src/org/netbeans/modules/maven/options/MavenSettings.java
+++ b/java/maven/src/org/netbeans/modules/maven/options/MavenSettings.java
@@ -85,6 +85,7 @@ public final class MavenSettings  {
     private static final String PROP_PLUGIN_POLICY = "pluginUpdatePolicy"; 
//NOI18N
     private static final String PROP_FAILURE_BEHAVIOUR = "failureBehaviour"; 
//NOI18N
     private static final String PROP_USE_REGISTRY = "usePluginRegistry"; 
//NOI18N
+    public static final String PROP_NETWORK_PROXY = "networkProxy";
       
     private static final MavenSettings INSTANCE = new MavenSettings();
     
@@ -591,4 +592,16 @@ public final class MavenSettings  {
         }
     }
     
+    public NetworkProxySettings getNetworkProxy() {
+        String s = getPreferences().get(PROP_NETWORK_PROXY, 
NetworkProxySettings.ASK.name());
+        try {
+            return NetworkProxySettings.valueOf(s);
+        } catch (IllegalArgumentException ex) {
+            return NetworkProxySettings.ASK;
+        }
+    }
+    
+    public void setNetworkProxy(NetworkProxySettings s) {
+        getPreferences().put(PROP_NETWORK_PROXY, s.name());
+    }
 }
diff --git 
a/java/maven/src/org/netbeans/modules/maven/options/NetworkProxySettings.java 
b/java/maven/src/org/netbeans/modules/maven/options/NetworkProxySettings.java
new file mode 100644
index 0000000000..5f19dbf7d9
--- /dev/null
+++ 
b/java/maven/src/org/netbeans/modules/maven/options/NetworkProxySettings.java
@@ -0,0 +1,76 @@
+/*
+ * 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.options;
+
+import org.netbeans.modules.maven.api.execute.RunUtils;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ * @author sdedic
+ */
[email protected]({
+    "PROXY_IGNORE=Do not check",
+    "PROXY_NOTICE=Display Mismatch Notice",
+    "PROXY_UPDATE=Update User Properties",
+    "PROXY_ASK=Ask Before Execution",
+    "PROXY_OVERRIDE=Override on execution",
+})
+public enum NetworkProxySettings {
+    /**
+     * Do not verify proxy settings.
+     */
+    IGNORE(Bundle.PROXY_IGNORE()),
+    /**
+     * Display a notice that proxy settings mismatch.
+     */
+    NOTICE(Bundle.PROXY_NOTICE()),
+    /**
+     * Update user's gradle.properties file.
+     */
+    UPDATE(Bundle.PROXY_UPDATE()),
+    /**
+     * Ask the user for confirmation.
+     */
+    ASK(Bundle.PROXY_ASK()),
+    /**
+     * Automatically override on execution, but do not change 
gradle.properties.
+     */
+    OVERRIDE(Bundle.PROXY_OVERRIDE());
+    
+    private String displayName;
+    
+    public String toString() {
+        return displayName;
+    }
+
+    private static final String BRANDING_API_OVERRIDE_ENABLED = 
"org.netbeans.modules.maven.api.execute.NetworkProxySettings.allowOverride"; // 
NOI18N
+    
+    private NetworkProxySettings(String dispName) {
+        this.displayName = dispName;
+    }
+    
+    /**
+     * Determines if override is a valid option.
+     * @return true, if override should be offered as an option
+     */
+    public static boolean allowProxyOverride() {
+        return Boolean.parseBoolean(NbBundle.getMessage(RunUtils.class, 
BRANDING_API_OVERRIDE_ENABLED));
+    }
+}
diff --git 
a/java/maven/src/org/netbeans/modules/maven/options/SettingsPanel.form 
b/java/maven/src/org/netbeans/modules/maven/options/SettingsPanel.form
index 49c6cfbcc3..151e2a9a6e 100644
--- a/java/maven/src/org/netbeans/modules/maven/options/SettingsPanel.form
+++ b/java/maven/src/org/netbeans/modules/maven/options/SettingsPanel.form
@@ -216,7 +216,7 @@
                       </Group>
                       <EmptySpace max="-2" attributes="0"/>
                       <Component id="jLabel3" min="-2" pref="44" max="-2" 
attributes="0"/>
-                      <EmptySpace pref="218" max="32767" attributes="0"/>
+                      <EmptySpace max="32767" attributes="0"/>
                   </Group>
               </Group>
             </DimensionLayout>
@@ -322,7 +322,7 @@
                       <Component id="cbDisableIndex" min="-2" max="-2" 
attributes="0"/>
                       <EmptySpace max="-2" attributes="0"/>
                       <Component id="jLabel5" min="-2" max="-2" 
attributes="0"/>
-                      <EmptySpace pref="290" max="32767" attributes="0"/>
+                      <EmptySpace max="32767" attributes="0"/>
                   </Group>
               </Group>
             </DimensionLayout>
@@ -422,7 +422,7 @@
                           <Component id="txtDirectory" alignment="3" min="-2" 
max="-2" attributes="0"/>
                           <Component id="btnDirectory" alignment="3" min="-2" 
max="-2" attributes="0"/>
                       </Group>
-                      <EmptySpace pref="180" max="32767" attributes="0"/>
+                      <EmptySpace max="32767" attributes="0"/>
                   </Group>
               </Group>
             </DimensionLayout>
@@ -481,12 +481,16 @@
           <Layout>
             <DimensionLayout dim="0">
               <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" alignment="0" attributes="0">
+                      <EmptySpace min="-2" pref="119" max="-2" attributes="0"/>
+                      <Component id="lblExternalVersion" max="32767" 
attributes="0"/>
+                  </Group>
                   <Group type="102" attributes="0">
-                      <EmptySpace min="-2" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
                       <Group type="103" groupAlignment="0" attributes="0">
-                          <Group type="102" attributes="0">
+                          <Group type="102" alignment="0" attributes="0">
                               <Group type="103" groupAlignment="1" 
attributes="0">
-                                  <Group type="102" attributes="0">
+                                  <Group type="102" alignment="1" 
attributes="0">
                                       <Group type="103" groupAlignment="0" 
attributes="0">
                                           <Component id="cbAlwaysShow" 
min="-2" max="-2" attributes="0"/>
                                           <Component id="cbReuse" 
alignment="0" min="-2" max="-2" attributes="0"/>
@@ -496,7 +500,7 @@
                                               <EmptySpace max="-2" 
attributes="0"/>
                                               <Group type="103" 
groupAlignment="0" attributes="0">
                                                   <Component 
id="cbOutputTabShowConfig" min="-2" max="-2" attributes="0"/>
-                                                  <Group type="102" 
attributes="0">
+                                                  <Group type="102" 
alignment="0" attributes="0">
                                                       <Component 
id="rbOutputTabName" min="-2" max="-2" attributes="0"/>
                                                       <EmptySpace max="-2" 
attributes="0"/>
                                                       <Component 
id="rbOutputTabId" min="-2" max="-2" attributes="0"/>
@@ -510,17 +514,10 @@
                                   </Group>
                                   <Component id="cbSkipTests" alignment="0" 
min="-2" max="-2" attributes="0"/>
                               </Group>
-                              <EmptySpace min="0" pref="55" max="32767" 
attributes="0"/>
+                              <EmptySpace min="-2" pref="58" max="-2" 
attributes="0"/>
                           </Group>
                           <Group type="102" attributes="0">
                               <Group type="103" groupAlignment="0" 
attributes="0">
-                                  <Group type="102" alignment="0" 
attributes="0">
-                                      <Component id="lblOptions" min="-2" 
max="-2" attributes="0"/>
-                                      <EmptySpace max="-2" attributes="0"/>
-                                      <Component id="txtOptions" max="32767" 
attributes="0"/>
-                                      <EmptySpace max="-2" attributes="0"/>
-                                      <Component id="btnOptions" min="-2" 
max="-2" attributes="0"/>
-                                  </Group>
                                   <Group type="102" alignment="0" 
attributes="0">
                                       <Group type="103" groupAlignment="0" 
attributes="0">
                                           <Component id="lblCommandLine" 
min="-2" max="-2" attributes="0"/>
@@ -540,15 +537,24 @@
                                           </Group>
                                       </Group>
                                   </Group>
+                                  <Group type="102" alignment="1" 
attributes="0">
+                                      <Group type="103" groupAlignment="0" 
max="-2" attributes="0">
+                                          <Component id="lblOptions" 
max="32767" attributes="0"/>
+                                          <Component id="lbNetworkSettings" 
max="32767" attributes="0"/>
+                                      </Group>
+                                      <EmptySpace max="-2" attributes="0"/>
+                                      <Group type="103" groupAlignment="0" 
attributes="0">
+                                          <Component id="cbNetworkProxy" 
max="32767" attributes="0"/>
+                                          <Component id="txtOptions" 
max="32767" attributes="0"/>
+                                      </Group>
+                                      <EmptySpace max="-2" attributes="0"/>
+                                      <Component id="btnOptions" min="-2" 
max="-2" attributes="0"/>
+                                  </Group>
                               </Group>
                               <EmptySpace max="-2" attributes="0"/>
                           </Group>
                       </Group>
                   </Group>
-                  <Group type="102" alignment="0" attributes="0">
-                      <EmptySpace min="-2" pref="119" max="-2" attributes="0"/>
-                      <Component id="lblExternalVersion" max="32767" 
attributes="0"/>
-                  </Group>
               </Group>
             </DimensionLayout>
             <DimensionLayout dim="1">
@@ -575,7 +581,15 @@
                           <Component id="txtOptions" alignment="3" min="-2" 
max="-2" attributes="0"/>
                           <Component id="btnOptions" alignment="3" min="-2" 
max="-2" attributes="0"/>
                       </Group>
-                      <EmptySpace type="unrelated" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Group type="103" groupAlignment="1" attributes="0">
+                          <Component id="cbNetworkProxy" alignment="1" 
min="-2" max="-2" attributes="0"/>
+                          <Group type="102" alignment="1" attributes="0">
+                              <Component id="lbNetworkSettings" min="-2" 
pref="16" max="-2" attributes="0"/>
+                              <EmptySpace min="3" pref="3" max="-2" 
attributes="0"/>
+                          </Group>
+                      </Group>
+                      <EmptySpace type="separate" max="-2" attributes="0"/>
                       <Component id="cbSkipTests" min="-2" max="-2" 
attributes="0"/>
                       <EmptySpace type="separate" max="-2" attributes="0"/>
                       <Component id="btnGoals" min="-2" max="-2" 
attributes="0"/>
@@ -591,11 +605,11 @@
                           <Component id="rbOutputTabName" alignment="3" 
min="-2" max="-2" attributes="0"/>
                           <Component id="rbOutputTabId" alignment="3" min="-2" 
max="-2" attributes="0"/>
                       </Group>
-                      <EmptySpace max="-2" attributes="0"/>
+                      <EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
                       <Component id="cbOutputTabShowConfig" min="-2" max="-2" 
attributes="0"/>
                       <EmptySpace type="unrelated" max="-2" attributes="0"/>
                       <Component id="cbCollapseSuccessFolds" min="-2" max="-2" 
attributes="0"/>
-                      <EmptySpace max="32767" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
                   </Group>
               </Group>
             </DimensionLayout>
@@ -759,6 +773,26 @@
                 </Property>
               </Properties>
             </Component>
+            <Component class="javax.swing.JComboBox" name="cbNetworkProxy">
+              <Properties>
+                <Property name="model" type="javax.swing.ComboBoxModel" 
editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
+                  <StringArray count="0"/>
+                </Property>
+              </Properties>
+              <AuxValues>
+                <AuxValue name="JavaCodeGenerator_TypeParameters" 
type="java.lang.String" value="&lt;NetworkProxySettings&gt;"/>
+              </AuxValues>
+            </Component>
+            <Component class="javax.swing.JLabel" name="lbNetworkSettings">
+              <Properties>
+                <Property name="labelFor" type="java.awt.Component" 
editor="org.netbeans.modules.form.ComponentChooserEditor">
+                  <ComponentRef name="cbNetworkProxy"/>
+                </Property>
+                <Property name="text" type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString 
bundle="org/netbeans/modules/maven/options/Bundle.properties" 
key="SettingsPanel.lbNetworkSettings.text" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
           </SubComponents>
         </Container>
       </SubComponents>
diff --git 
a/java/maven/src/org/netbeans/modules/maven/options/SettingsPanel.java 
b/java/maven/src/org/netbeans/modules/maven/options/SettingsPanel.java
index fe3a3ecad7..b960bfcf38 100644
--- a/java/maven/src/org/netbeans/modules/maven/options/SettingsPanel.java
+++ b/java/maven/src/org/netbeans/modules/maven/options/SettingsPanel.java
@@ -229,6 +229,13 @@ public class SettingsPanel extends javax.swing.JPanel {
                 return super.getListCellRendererComponent(list, value, index, 
isSelected, cellHasFocus);
             }
         });
+
+        DefaultComboBoxModel mdl = new 
DefaultComboBoxModel<>(NetworkProxySettings.values());
+        if (!NetworkProxySettings.allowProxyOverride()) {
+            mdl.removeElement(NetworkProxySettings.OVERRIDE);
+        }
+        cbNetworkProxy.setModel(mdl);
+        cbNetworkProxy.addActionListener(listener);
     }
 
     /** XXX update for M3 from {@link 
org.apache.maven.cli.CLIManager#CLIManager} */
@@ -397,6 +404,8 @@ public class SettingsPanel extends javax.swing.JPanel {
         comJdkHome = new javax.swing.JComboBox();
         comManageJdks = new javax.swing.JButton();
         cbPreferWrapper = new javax.swing.JCheckBox();
+        cbNetworkProxy = new javax.swing.JComboBox<>();
+        lbNetworkSettings = new javax.swing.JLabel();
         jScrollPane1 = new javax.swing.JScrollPane();
         lstCategory = new javax.swing.JList();
         lblCategory = new javax.swing.JLabel();
@@ -516,7 +525,7 @@ public class SettingsPanel extends javax.swing.JPanel {
                     .addComponent(comSource, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE))
                 
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                 .addComponent(jLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, 
44, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addContainerGap(218, Short.MAX_VALUE))
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, 
Short.MAX_VALUE))
         );
 
         pnlCards.add(pnlDependencies, "dependencies");
@@ -576,7 +585,7 @@ public class SettingsPanel extends javax.swing.JPanel {
                 .addComponent(cbDisableIndex)
                 
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                 .addComponent(jLabel5)
-                .addContainerGap(290, Short.MAX_VALUE))
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, 
Short.MAX_VALUE))
         );
 
         pnlCards.add(pnlIndex, "index");
@@ -632,7 +641,7 @@ public class SettingsPanel extends javax.swing.JPanel {
                     .addComponent(lblDirectory)
                     .addComponent(txtDirectory, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
                     .addComponent(btnDirectory))
-                .addContainerGap(180, Short.MAX_VALUE))
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, 
Short.MAX_VALUE))
         );
 
         pnlCards.add(plnExperimental, "experimental");
@@ -690,10 +699,16 @@ public class SettingsPanel extends javax.swing.JPanel {
 
         org.openide.awt.Mnemonics.setLocalizedText(cbPreferWrapper, 
org.openide.util.NbBundle.getMessage(SettingsPanel.class, 
"SettingsPanel.cbPreferWrapper.text")); // NOI18N
 
+        lbNetworkSettings.setLabelFor(cbNetworkProxy);
+        org.openide.awt.Mnemonics.setLocalizedText(lbNetworkSettings, 
org.openide.util.NbBundle.getMessage(SettingsPanel.class, 
"SettingsPanel.lbNetworkSettings.text")); // NOI18N
+
         javax.swing.GroupLayout pnlExecutionLayout = new 
javax.swing.GroupLayout(pnlExecution);
         pnlExecution.setLayout(pnlExecutionLayout);
         pnlExecutionLayout.setHorizontalGroup(
             
pnlExecutionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(pnlExecutionLayout.createSequentialGroup()
+                .addGap(119, 119, 119)
+                .addComponent(lblExternalVersion, 
javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
Short.MAX_VALUE))
             .addGroup(pnlExecutionLayout.createSequentialGroup()
                 .addContainerGap()
                 
.addGroup(pnlExecutionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@@ -717,15 +732,9 @@ public class SettingsPanel extends javax.swing.JPanel {
                                     .addComponent(btnGoals))
                                 .addGap(18, 18, 18))
                             .addComponent(cbSkipTests, 
javax.swing.GroupLayout.Alignment.LEADING))
-                        .addGap(0, 55, Short.MAX_VALUE))
+                        .addGap(58, 58, 58))
                     .addGroup(pnlExecutionLayout.createSequentialGroup()
                         
.addGroup(pnlExecutionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                            
.addGroup(pnlExecutionLayout.createSequentialGroup()
-                                .addComponent(lblOptions)
-                                
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                                .addComponent(txtOptions)
-                                
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                                .addComponent(btnOptions))
                             
.addGroup(pnlExecutionLayout.createSequentialGroup()
                                 
.addGroup(pnlExecutionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                     .addComponent(lblCommandLine)
@@ -739,11 +748,18 @@ public class SettingsPanel extends javax.swing.JPanel {
                                     
.addGroup(pnlExecutionLayout.createSequentialGroup()
                                         .addComponent(comJdkHome, 0, 
javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                         
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                                        .addComponent(comManageJdks)))))
+                                        .addComponent(comManageJdks))))
+                            
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, 
pnlExecutionLayout.createSequentialGroup()
+                                
.addGroup(pnlExecutionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING,
 false)
+                                    .addComponent(lblOptions, 
javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
Short.MAX_VALUE)
+                                    .addComponent(lbNetworkSettings, 
javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
Short.MAX_VALUE))
+                                
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                                
.addGroup(pnlExecutionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                                    .addComponent(cbNetworkProxy, 0, 
javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                                    .addComponent(txtOptions))
+                                
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                                .addComponent(btnOptions)))
                         .addContainerGap())))
-            .addGroup(pnlExecutionLayout.createSequentialGroup()
-                .addGap(119, 119, 119)
-                .addComponent(lblExternalVersion, 
javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
Short.MAX_VALUE))
         );
         pnlExecutionLayout.setVerticalGroup(
             
pnlExecutionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@@ -766,7 +782,13 @@ public class SettingsPanel extends javax.swing.JPanel {
                     .addComponent(lblOptions)
                     .addComponent(txtOptions, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
                     .addComponent(btnOptions))
-                
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                
.addGroup(pnlExecutionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+                    .addComponent(cbNetworkProxy, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addGroup(pnlExecutionLayout.createSequentialGroup()
+                        .addComponent(lbNetworkSettings, 
javax.swing.GroupLayout.PREFERRED_SIZE, 16, 
javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addGap(3, 3, 3)))
+                .addGap(18, 18, 18)
                 .addComponent(cbSkipTests)
                 .addGap(18, 18, 18)
                 .addComponent(btnGoals)
@@ -781,11 +803,11 @@ public class SettingsPanel extends javax.swing.JPanel {
                     .addComponent(lblOutputTab)
                     .addComponent(rbOutputTabName)
                     .addComponent(rbOutputTabId))
-                
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGap(6, 6, 6)
                 .addComponent(cbOutputTabShowConfig)
                 
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                 .addComponent(cbCollapseSuccessFolds)
-                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, 
Short.MAX_VALUE))
+                .addContainerGap())
         );
 
         pnlCards.add(pnlExecution, "execution");
@@ -935,6 +957,7 @@ public class SettingsPanel extends javax.swing.JPanel {
     private javax.swing.JCheckBox cbAlwaysShow;
     private javax.swing.JCheckBox cbCollapseSuccessFolds;
     private javax.swing.JCheckBox cbDisableIndex;
+    private javax.swing.JComboBox<NetworkProxySettings> cbNetworkProxy;
     private javax.swing.JCheckBox cbOutputTabShowConfig;
     private javax.swing.JCheckBox cbPreferWrapper;
     private javax.swing.JComboBox cbProjectNodeNameMode;
@@ -955,6 +978,7 @@ public class SettingsPanel extends javax.swing.JPanel {
     private javax.swing.JLabel jLabel4;
     private javax.swing.JLabel jLabel5;
     private javax.swing.JScrollPane jScrollPane1;
+    private javax.swing.JLabel lbNetworkSettings;
     private javax.swing.JLabel lblBinaries;
     private javax.swing.JLabel lblCategory;
     private javax.swing.JLabel lblCommandLine;
@@ -1157,6 +1181,8 @@ public class SettingsPanel extends javax.swing.JPanel {
             }
         }
         
+         
cbNetworkProxy.setSelectedItem(MavenSettings.getDefault().getNetworkProxy());
+        
         changed = false;  //#163955 - do not fire change events on load
     }
     
@@ -1215,6 +1241,8 @@ public class SettingsPanel extends javax.swing.JPanel {
             //a predefined pattern entry was selected
             
MavenSettings.getDefault().setProjectNodeNamePattern(cbProjectNodeNameMode.getSelectedItem().toString());
         } 
+        
+        
MavenSettings.getDefault().setNetworkProxy((NetworkProxySettings)cbNetworkProxy.getSelectedItem());
         changed = false;
     }
     
@@ -1283,6 +1311,7 @@ public class SettingsPanel extends javax.swing.JPanel {
                 isChanged |= (projectNodeNamePattern == null ? 
!cbProjectNodeNameMode.getSelectedItem().toString().isEmpty() : 
!projectNodeNamePattern.equals(cbProjectNodeNameMode.getSelectedItem().toString()));
             }
         }
+        isChanged |= MavenSettings.getDefault().getNetworkProxy() != 
cbNetworkProxy.getSelectedItem();
         changed = isChanged;
     }
 
diff --git 
a/java/maven/src/org/netbeans/modules/maven/problems/SanityBuildAction.java 
b/java/maven/src/org/netbeans/modules/maven/problems/SanityBuildAction.java
index dea2d9340f..c0f88d3347 100644
--- a/java/maven/src/org/netbeans/modules/maven/problems/SanityBuildAction.java
+++ b/java/maven/src/org/netbeans/modules/maven/problems/SanityBuildAction.java
@@ -21,6 +21,7 @@ package org.netbeans.modules.maven.problems;
 
 import java.util.Arrays;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -30,11 +31,14 @@ import org.netbeans.modules.maven.api.NbMavenProject;
 import org.netbeans.modules.maven.api.execute.RunConfig.ReactorStyle;
 import org.netbeans.modules.maven.api.execute.RunUtils;
 import org.netbeans.modules.maven.execute.BeanRunConfig;
+import org.netbeans.modules.maven.execute.MavenProxySupport;
+import org.netbeans.modules.maven.execute.MavenProxySupport.ProxyResult;
 import static org.netbeans.modules.maven.problems.Bundle.*;
 import org.netbeans.spi.project.ui.ProjectProblemResolver;
 import org.netbeans.spi.project.ui.ProjectProblemsProvider;
 import org.openide.execution.ExecutorTask;
 import org.openide.filesystems.FileUtil;
+import org.openide.util.NbBundle;
 import org.openide.util.NbBundle.Messages;
 
 /**
@@ -67,6 +71,11 @@ public class SanityBuildAction implements 
ProjectProblemResolver {
         return this.pendingResult;
     }
 
+    @NbBundle.Messages({
+        "ERR_SanityBuildCancalled=Sanity build cancelled",
+        "# {0} - message",
+        "ERR_ProxyUpdateFailed=Proxy setup failed: {0}"
+    })
     @Override
     public CompletableFuture<ProjectProblemsProvider.Result> resolve() {
         CompletableFuture<ProjectProblemsProvider.Result> pr = pendingResult;
@@ -97,6 +106,27 @@ public class SanityBuildAction implements 
ProjectProblemResolver {
                     String label = 
build_label(nbproject.getProjectDirectory().getNameExt());
                     config.setExecutionName(label);
                     config.setTaskDisplayName(label);
+                    
+                    MavenProxySupport mps = 
nbproject.getLookup().lookup(MavenProxySupport.class);
+                    if (mps != null) {
+                        ProxyResult res;
+                        try {
+                            res = mps.checkProxySettings().get();
+                            if (res.getStatus() == 
MavenProxySupport.Status.ABORT) {
+                                ProjectProblemsProvider.Result r = 
ProjectProblemsProvider.Result.create(ProjectProblemsProvider.Status.UNRESOLVED,
 ERR_SanityBuildCancalled());
+                                publicResult.complete(r);
+                                return;
+                            }
+                        } catch (ExecutionException ex) {
+                            ProjectProblemsProvider.Result r = 
ProjectProblemsProvider.Result.create(ProjectProblemsProvider.Status.UNRESOLVED,
 ERR_ProxyUpdateFailed(ex.getLocalizedMessage()));
+                            publicResult.complete(r);
+                            return;
+                        } catch (InterruptedException ex) {
+                            ProjectProblemsProvider.Result r = 
ProjectProblemsProvider.Result.create(ProjectProblemsProvider.Status.UNRESOLVED,
 ERR_SanityBuildCancalled());
+                            publicResult.complete(r);
+                            return;
+                        }
+                    }
                     LOG.log(Level.FINE, "Executing sanity build: goals = {0}, 
properties = {1}", new Object[] { config.getGoals(), config.getProperties() });
                     ExecutorTask et = RunUtils.run(config);
                     et.addTaskListener(t -> {
diff --git a/java/maven/src/org/netbeans/modules/maven/settings.template.xml 
b/java/maven/src/org/netbeans/modules/maven/settings.template.xml
new file mode 100644
index 0000000000..84150288c3
--- /dev/null
+++ b/java/maven/src/org/netbeans/modules/maven/settings.template.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<settings>
+<#if proxyHost?? && proxyHost != "">
+    <proxies>
+        <!-- Proxy defined by NetBeans IDE -->
+        <proxy>
+            <id>netbeans-default-proxy</id>
+            <active>true</active>
+            <protocol>http</protocol>
+            <host>${proxyHost}</host>
+            <port>${proxyPort}</port>
+            <!-- Proxy exclusion list: separate by pipe-symbol, e.g. 
127.0.0.8|localhost -->
+            
<nonProxyHosts>localhost|127.0.0.0/8|localhost.localdomain|127.0.0.1|[::1]</nonProxyHosts>
 
+        </proxy>
+    </proxies>
+</#if>
+</settings>


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

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


Reply via email to