1. Sebastian Sdorra
  2. scm-manager

Commits

Sebastian Sdorra  committed 8201365 Merge

merge with branch issue-281

  • Participants
  • Parent commits 66d6be4, 9822fb0
  • Branches default

Comments (0)

Files changed (7)

File scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java

View file
 
 //~--- non-JDK imports --------------------------------------------------------
 
+import com.google.common.collect.Sets;
 import com.google.inject.Singleton;
 
 import org.slf4j.Logger;
 @XmlRootElement(name = "scm-config")
 @XmlAccessorType(XmlAccessType.FIELD)
 public class ScmConfiguration
-        implements ListenerSupport<ConfigChangedListener<ScmConfiguration>>
+  implements ListenerSupport<ConfigChangedListener<ScmConfiguration>>
 {
 
   /** Default JavaScript date format */
    */
   @Override
   public void addListeners(
-          Collection<ConfigChangedListener<ScmConfiguration>> listeners)
+    Collection<ConfigChangedListener<ScmConfiguration>> listeners)
   {
     listeners.addAll(listeners);
   }
     this.proxyServer = other.proxyServer;
     this.proxyUser = other.proxyUser;
     this.proxyPassword = other.proxyPassword;
+    this.proxyExcludes = other.proxyExcludes;
     this.forceBaseUrl = other.forceBaseUrl;
     this.baseUrl = other.baseUrl;
     this.disableGroupingGrid = other.disableGroupingGrid;
   }
 
   /**
+   * Returns a set of glob patterns for urls which should excluded from
+   * proxy settings.
+   *
+   *
+   * @return set of glob patterns
+   * @since 1.23
+   */
+  public Set<String> getProxyExcludes()
+  {
+    if (proxyExcludes == null)
+    {
+      proxyExcludes = Sets.newHashSet();
+    }
+
+    return proxyExcludes;
+  }
+
+  /**
    * Method description
    *
    *
   }
 
   /**
+   * Set glob patterns for urls which are should be excluded from proxy
+   * settings.
+   *
+   *
+   * @param proxyExcludes glob patterns
+   * @since 1.23
+   */
+  public void setProxyExcludes(Set<String> proxyExcludes)
+  {
+    this.proxyExcludes = proxyExcludes;
+  }
+
+  /**
    * Method description
    *
    *
   @XmlElement(name = "plugin-url")
   private String pluginUrl = DEFAULT_PLUGINURL;
 
+  /** glob patterns for urls which are excluded from proxy */
+  @XmlElement(name = "proxy-excludes")
+  @XmlJavaTypeAdapter(XmlSetStringAdapter.class)
+  private Set<String> proxyExcludes;
+
   /** Field description */
   private String proxyPassword;
 

File scm-core/src/main/java/sonia/scm/net/Proxies.java

View file
+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.net;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.config.ScmConfiguration;
+import sonia.scm.util.GlobUtil;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.net.URL;
+
+/**
+ * Util class for proxy settings.
+ *
+ * @author Sebastian Sdorra
+ * @since 1.23
+ */
+public class Proxies
+{
+
+  /**
+   * the logger for Proxies
+   */
+  private static final Logger logger = LoggerFactory.getLogger(Proxies.class);
+
+  //~--- get methods ----------------------------------------------------------
+
+  /**
+   * Returns true if proxy settings should be used to access the given url.
+   *
+   *
+   * @param configuration scm-manager main configuration
+   * @param url url to check
+   *
+   * @return true if proxy settings should be used
+   */
+  public static boolean isEnabled(ScmConfiguration configuration, String url)
+  {
+    boolean result = false;
+
+    if (configuration.isEnableProxy())
+    {
+      result = true;
+
+      int index = url.indexOf("://");
+
+      if (index > 0)
+      {
+        url = url.substring(index + 3);
+      }
+
+      index = url.indexOf("/");
+
+      if (index > 0)
+      {
+        url = url.substring(0, index);
+      }
+
+      for (String exclude : configuration.getProxyExcludes())
+      {
+        if (GlobUtil.matches(exclude, url))
+        {
+          logger.debug(
+            "disable proxy settings for url {}, because exclude {} matches",
+            url, exclude);
+          result = false;
+
+          break;
+        }
+      }
+    }
+    else
+    {
+      logger.trace("proxy settings are disabled");
+    }
+
+    return result;
+  }
+
+  /**
+   * Returns true if proxy settings should be used to access the given url.
+   *
+   *
+   * @param configuration scm-manager main configuration
+   * @param url url to check
+   *
+   * @return true if proxy settings should be used
+   */
+  public static boolean isEnabled(ScmConfiguration configuration, URL url)
+  {
+    return isEnabled(configuration, url.getHost());
+  }
+}

File scm-core/src/test/java/sonia/scm/net/ProxiesTest.java

View file
+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.net;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.collect.Sets;
+
+import org.junit.Test;
+
+import sonia.scm.config.ScmConfiguration;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class ProxiesTest
+{
+
+  /**
+   * Method description
+   *
+   */
+  @Test
+  public void testDisabledWithoutExcludes()
+  {
+    ScmConfiguration config = createConfiguration(false);
+
+    assertFalse(Proxies.isEnabled(config, "localhost"));
+    assertFalse(Proxies.isEnabled(config, "download.scm-manager.org"));
+    assertFalse(Proxies.isEnabled(config, "http://127.0.0.1"));
+    assertFalse(Proxies.isEnabled(config, "http://127.0.0.1/test/ka"));
+  }
+
+  /**
+   * Method description
+   *
+   */
+  @Test
+  public void testEnabledWithoutExcludes()
+  {
+    ScmConfiguration config = createConfiguration(true);
+
+    assertTrue(Proxies.isEnabled(config, "localhost"));
+    assertTrue(Proxies.isEnabled(config, "download.scm-manager.org"));
+    assertTrue(Proxies.isEnabled(config, "http://127.0.0.1"));
+    assertTrue(Proxies.isEnabled(config, "http://127.0.0.1/test/ka"));
+  }
+
+  /**
+   * Method description
+   *
+   */
+  @Test
+  public void testWithExcludes()
+  {
+    ScmConfiguration config = createConfiguration(true, "127.0.0.1",
+                                "localhost");
+
+    assertFalse(Proxies.isEnabled(config, "localhost"));
+    assertTrue(Proxies.isEnabled(config, "download.scm-manager.org"));
+    assertFalse(Proxies.isEnabled(config, "http://127.0.0.1"));
+    assertFalse(Proxies.isEnabled(config, "http://127.0.0.1/test/ka"));
+  }
+
+  /**
+   * Method description
+   *
+   */
+  @Test
+  public void testWithGlobExcludes()
+  {
+    ScmConfiguration config = createConfiguration(true, "127.*", "*host");
+
+    assertFalse(Proxies.isEnabled(config, "localhost"));
+    assertTrue(Proxies.isEnabled(config, "download.scm-manager.org"));
+    assertFalse(Proxies.isEnabled(config, "http://127.0.0.1"));
+    assertFalse(Proxies.isEnabled(config, "http://127.0.0.1/test/ka"));
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @param enabled
+   * @param excludes
+   *
+   * @return
+   */
+  private ScmConfiguration createConfiguration(boolean enabled,
+    String... excludes)
+  {
+    ScmConfiguration configuration = new ScmConfiguration();
+
+    configuration.setEnableProxy(enabled);
+    configuration.setProxyExcludes(Sets.newHashSet(excludes));
+
+    return configuration;
+  }
+}

File scm-webapp/src/main/java/sonia/scm/net/URLHttpClient.java

View file
    */
   @Inject
   public URLHttpClient(SCMContextProvider context,
-                       ScmConfiguration configuration)
+    ScmConfiguration configuration)
   {
     this.context = context;
     this.configuration = configuration;
    */
   @Override
   public HttpResponse post(String url, Map<String, List<String>> parameters)
-          throws IOException
+    throws IOException
   {
     HttpURLConnection connection = (HttpURLConnection) openConnection(null,
                                      url);
    */
   @Override
   public HttpResponse get(String url, Map<String, List<String>> parameters)
-          throws IOException
+    throws IOException
   {
     url = createGetUrl(url, parameters);
 
     String url = createGetUrl(request.getUrl(), request.getParameters());
 
     return new URLHttpResponse(openConnection(request, url),
-                               request.isDecodeGZip());
+      request.isDecodeGZip());
   }
 
   //~--- methods --------------------------------------------------------------
    * @param password
    */
   private void appendBasicAuthHeader(HttpURLConnection connection,
-                                     String header, String username,
-                                     String password)
+    String header, String username, String password)
   {
     if (Util.isNotEmpty(username) || Util.isNotEmpty(password))
     {
 
       auth = new String(Base64.encode(auth.getBytes()));
       connection.addRequestProperty(header,
-                                    PREFIX_BASIC_AUTHENTICATION.concat(auth));
+        PREFIX_BASIC_AUTHENTICATION.concat(auth));
     }
   }
 
    * @param connection
    */
   private void appendHeaders(Map<String, List<String>> headers,
-                             URLConnection connection)
+    URLConnection connection)
   {
     if (Util.isNotEmpty(headers))
     {
    * @throws IOException
    */
   private void appendPostParameter(HttpURLConnection connection,
-                                   Map<String, List<String>> parameters)
-          throws IOException
+    Map<String, List<String>> parameters)
+    throws IOException
   {
     if (Util.isNotEmpty(parameters))
     {
    * @param connection
    */
   private void applySSLSettings(HttpRequest request,
-                                HttpsURLConnection connection)
+    HttpsURLConnection connection)
   {
     if (request.isDisableCertificateValidation())
     {
    * @throws IOException
    */
   private HttpURLConnection openConnection(HttpRequest request, String spec)
-          throws IOException
+    throws IOException
   {
     return openConnection(request, new URL(spec));
   }
    * @throws IOException
    */
   private HttpURLConnection openConnection(HttpRequest request, URL url)
-          throws IOException
+    throws IOException
   {
     if (request == null)
     {
+
       // TODO improve
       request = new HttpRequest(url.toExternalForm());
     }
 
     HttpURLConnection connection = null;
 
-    if (!request.isIgnoreProxySettings() && configuration.isEnableProxy())
+    if (!request.isIgnoreProxySettings()
+      && Proxies.isEnabled(configuration, url))
     {
       if (logger.isDebugEnabled())
       {
         logger.debug("fetch '{}' using proxy {}:{}",
-                     new Object[] { url.toExternalForm(),
-                                    configuration.getProxyServer(),
-                                    configuration.getProxyPort() });
+          new Object[] { url.toExternalForm(),
+          configuration.getProxyServer(), configuration.getProxyPort() });
       }
 
       SocketAddress address =
         new InetSocketAddress(configuration.getProxyServer(),
-                              configuration.getProxyPort());
+          configuration.getProxyPort());
 
       connection =
         (HttpURLConnection) url.openConnection(new Proxy(Proxy.Type.HTTP,
       String password = request.getPassword();
 
       appendBasicAuthHeader(connection, HEADER_AUTHORIZATION, username,
-                            password);
+        password);
     }
 
     connection.setRequestProperty(HEADER_ACCEPT_ENCODING,
-                                  HEADER_ACCEPT_ENCODING_VALUE);
-    connection.setRequestProperty(
-        HEADER_USERAGENT, HEADER_USERAGENT_VALUE.concat(context.getVersion()));
+      HEADER_ACCEPT_ENCODING_VALUE);
+    connection.setRequestProperty(HEADER_USERAGENT,
+      HEADER_USERAGENT_VALUE.concat(context.getVersion()));
 
     String username = configuration.getProxyUser();
     String password = configuration.getProxyPassword();
 
     appendBasicAuthHeader(connection, HEADER_PROXY_AUTHORIZATION, username,
-                          password);
+      password);
 
     return connection;
   }

File scm-webapp/src/main/java/sonia/scm/plugin/AetherPluginHandler.java

View file
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBException;
 import javax.xml.bind.Marshaller;
+import sonia.scm.net.Proxies;
 
 /**
  *
       RemoteRepository rr = new RemoteRepository(repository.getId(), "default",
                               repository.getUrl());
 
-      if (configuration.isEnableProxy())
+      if (Proxies.isEnabled(configuration, rr.getHost()))
       {
         Proxy proxy = DefaultProxySelector.createProxy(configuration);
 

File scm-webapp/src/main/webapp/resources/js/config/sonia.config.scmconfigpanel.js

View file
   proxyPortText: 'Proxy Port',
   proxyUserText: 'Proxy User',
   proxyPasswordText: 'Proxy Password',
+  proxyExcludesText: 'Proxy Excludes',
   baseUrlText: 'Base Url',
   forceBaseUrlText: 'Force Base Url',
   disableGroupingGridText: 'Disable repository Groups',
   proxyPortHelpText: 'The proxy port',
   proxyUserHelpText: 'The username for the proxy server authentication.',
   proxyPasswordHelpText: 'The password for the proxy server authentication.',
+  proxyExcludesHelpText: 'A comma separated list of glob patterns for hostnames which should be excluded from proxy settings.',
   baseUrlHelpText: 'The url of the application (with context path) i.e. http://localhost:8080/scm',
   forceBaseUrlHelpText: 'Redirects to the base url if the request comes from a other url',
   disableGroupingGridHelpText: 'Disable repository Groups. A complete page reload is required after a change of this value.',
               Ext.getCmp('proxyPort').setDisabled( ! this.checked );
               Ext.getCmp('proxyUser').setDisabled( ! this.checked );
               Ext.getCmp('proxyPassword').setDisabled( ! this.checked );
+              Ext.getCmp('proxyExcludes').setDisabled( ! this.checked );
             }
           }
         },{
           helpText: this.proxyPasswordHelpText,
           allowBlank: true
         },{
+          id: 'proxyExcludes',
+          xtype: 'textfield',
+          fieldLabel: this.proxyExcludesText,
+          name: 'proxy-excludes',
+          disabled: true,
+          helpText: this.proxyExcludesHelpText,
+          allowBlank: true
+        },{
           xtype : 'textfield',
           fieldLabel : this.adminGroupsText,
           name : 'admin-groups',
               if ( obj.enableProxy ){
                 Ext.getCmp('proxyServer').setDisabled(false);
                 Ext.getCmp('proxyPort').setDisabled(false);
+                Ext.getCmp('proxyUser').setDisabled(false);
+                Ext.getCmp('proxyPassword').setDisabled(false);
+                Ext.getCmp('proxyExcludes').setDisabled(false);
               }
               clearTimeout(tid);
               el.unmask();

File scm-webapp/src/main/webapp/resources/js/i18n/de.js

View file
     proxyPortText: 'Proxy Port',
     proxyUserText: 'Proxy User',
     proxyPasswordText: 'Proxy Passwort',
+    proxyExcludesText: 'Proxy Ausnahmen',
     baseUrlText: 'Basis-URL',
     forceBaseUrlText: 'Basis-URL forcieren',
     disableGroupingGridText: 'Repository-Gruppierung deaktivieren',
     proxyPortHelpText: 'Der Proxy-Port',
     proxyUserHelpText: 'Der Benutzername für die Authentifizierung am Proxy-Server.',
     proxyPasswordHelpText: 'Das Passwort für die Authentifizierung am Proxy-Server.',
+    proxyExcludesHelpText: 'Eine Komma-separierte liste von Glob-Patterns für servername die von den Proxy-Einstellungen ausgenommen werden sollen',
     baseUrlHelpText: 'Die vollständige URL des Server, inclusive Context-Pfad z.B.: http://localhost:8080/scm.',
     forceBaseUrlHelpText: 'Leitet alle Zugriffe die nicht von der Basis-URL kommen auf die Basis-URL um.',
     disableGroupingGridHelpText: 'Repository grupierung deaktivieren. Wenn dieser Wert verändert wird muss die Seite neu geladen werden.',