/*
 * Copyright 2014-present Facebook, Inc.
 *
 * Licensed 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 com.facebook.buck.file;

import com.facebook.buck.util.HumanReadableException;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Responsible for converting a maven URL to an HTTP or HTTPS url. The format of a maven URL is:
 * <pre>
 *   mvn:optionalServer:group:id:type:classifier:version
 * </pre>
 * If the {@code optionalServer} is omitted, the default one configured in "download -&gt;
 * maven_repo" in the project's {@code .buckconfig} is used, or an exception is thrown. The
 * optionalServer URL is expected to be a valid {@link java.net.URL}.
 * <p>
 * Examples of valid mvn URLs:
 * <pre>
 *   mvn:org.seleniumhq.selenium:selenium-java:jar:2.42.2
 *   mvn:http://repo1.maven.org/maven2:org.seleniumhq.selenium:selenium-java:jar:2.42.2
 * </pre>
 */
public class MavenUrlDecoder {
  @VisibleForTesting
  private static final Pattern URL_PATTERN =
      Pattern.compile("((.+):)?([^:]+):([^:]+):([^:]+):([^:]+)");

  private MavenUrlDecoder() {
    // Utility class
  }

  public static URI toHttpUrl(Optional<String> mavenRepo, URI uri) {
    Preconditions.checkArgument("mvn".equals(uri.getScheme()), "URI must start with mvn: " + uri);
    Preconditions.checkArgument(
        mavenRepo.isPresent(),
        "You must specify the maven repo in the \"download->maven_repo\" section of your " +
            ".buckconfig");

    String repo = mavenRepo.get();

    if (!repo.endsWith("/")) {
      repo += "/";
    }

    Matcher matcher = URL_PATTERN.matcher(uri.getSchemeSpecificPart());

    if (!matcher.matches()) {
      throw new HumanReadableException("Unable to parse: " + uri);
    }

    String host = matcher.group(2);
    if (Strings.isNullOrEmpty(host)) {
      host = repo;
    }
    String group = matcher.group(3).replace('.', '/');
    String artifactId = matcher.group(4);
    String type = matcher.group(5);
    String version = matcher.group(6);

    if (!host.endsWith("/")) {
      host += "/";
    }

    try {
      String plainUri = String.format(
          "%s%s/%s/%s/%s-%s%s",
          host,
          group,
          artifactId,
          version,
          artifactId,
          version,
          fileExtensionFor(type));
      URI generated = new URI(plainUri);
      if ("https".equals(generated.getScheme()) || "http".equals(generated.getScheme())) {
        return generated;
      }
      throw new HumanReadableException(
          "Can only download maven artifacts over HTTP or HTTPS: %s", generated);
    } catch (URISyntaxException e) {
      throw new HumanReadableException("Unable to parse URL: " + uri);
    }
  }

  private static String fileExtensionFor(String type) {
    switch (type) {
      case "jar":
        return ".jar";

      case "aar":
        return ".aar";

      case "src":
        return "-sources.jar";

      default:
        return String.format("-%s.jar", type);
    }
  }
}

@@ -1710,21 +1710,16 @@
 ATTERN =
-%0A    
   Patter
@@ -1732,26 +1732,48 @@
 ile(
-%22((.+):)?(
+%0A      %22((?%3Chost%3E.+):)?(?%3Cgroup%3E
 %5B%5E:%5D+):(
 %5B%5E:%5D
@@ -1764,32 +1764,37 @@
 oup%3E%5B%5E:%5D+):(
+?%3Cid%3E
 %5B%5E:%5D+):(
 %5B%5E:%5D+):(%5B%5E:%5D
@@ -1781,24 +1781,31 @@
 %5B%5E:%5D+):(
+?%3Ctype%3E
 %5B%5E:%5D+):(
 %5B%5E:%5D+)%22)
@@ -1800,15 +1800,28 @@
 +):(
+?%3Cversion%3E
 %5B%5E:%5D+)%22
+%0A  
 );%0A%0A
@@ -2532,17 +2532,22 @@
 r.group(
-2
+%22host%22
 );%0A    i
@@ -2642,9 +2642,15 @@
 oup(
-3
+%22group%22
 ).re
@@ -2704,17 +2704,20 @@
 r.group(
-4
+%22id%22
 );%0A    S
@@ -2747,9 +2747,14 @@
 oup(
-5
+%22type%22
 );%0A 
@@ -2791,9 +2791,17 @@
 oup(
-6
+%22version%22
 );%0A%0A
@@ -2934,13 +2934,8 @@
 s/%25s
--%25s%25s
 %22,%0A 
@@ -3021,66 +3021,41 @@
     
-artifactId,%0A          version,%0A          fileExtensionFor(
+fileNameFor(artifactId, version, 
 type
@@ -3450,24 +3450,24 @@
 : %22 + uri);%0A
-
     %7D%0A  %7D%0A%0A 
@@ -3465,16 +3465,189 @@
  %7D%0A  %7D%0A%0A
+  private static String fileNameFor(String artifactId, String version, String type) %7B%0A    return String.format(%22%25s-%25s%25s%22, artifactId, version, fileExtensionFor(type));%0A  %7D%0A%0A
   privat

Refactor URL pattern for better readability