Working on utility to update maven refs
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java
index c0ffd6c..721db48 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java
@@ -41,7 +41,6 @@
 import java.nio.file.Path;
 import java.nio.file.StandardOpenOption;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -86,26 +85,6 @@
     private static final String EXITING_LICENSE_NOT_ACKNOWLEDGED = "Exiting: license not acknowledged!";
     private static final int EXIT_USAGE = 1;
 
-    public static String join(Collection<?> objs, String delim)
-    {
-        if (objs==null)
-        {
-            return "";
-        }
-        StringBuilder str = new StringBuilder();
-        boolean needDelim = false;
-        for (Object obj : objs)
-        {
-            if (needDelim)
-            {
-                str.append(delim);
-            }
-            str.append(obj);
-            needDelim = true;
-        }
-        return str.toString();
-    }
-
     public static void main(String[] args)
     {
         try
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Modules.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Modules.java
index 2731ef3..1958cfa 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/Modules.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Modules.java
@@ -327,7 +327,7 @@
         if (sources != null)
         {
             module.addSources(sources);
-            via = Main.join(sources, ", ");
+            via = Utils.join(sources, ", ");
         }
         
         // If already enabled, nothing else to do
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Utils.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Utils.java
index 3e7ffa8..8aa99cb 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/Utils.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Utils.java
@@ -18,8 +18,58 @@
 
 package org.eclipse.jetty.start;
 
+import java.util.Collection;
+
 public final class Utils
 {
+    public static String join(Object[] arr, String delim)
+    {
+        if (arr == null)
+        {
+            return "";
+        }
+
+        return join(arr,0,arr.length,delim);
+    }
+
+    public static String join(Object[] arr, int start, int end, String delim)
+    {
+        if (arr == null)
+        {
+            return "";
+        }
+        StringBuilder str = new StringBuilder();
+        for (int i = start; i < end; i++)
+        {
+            if (i > start)
+            {
+                str.append(delim);
+            }
+            str.append(arr[i]);
+        }
+        return str.toString();
+    }
+
+    public static String join(Collection<?> objs, String delim)
+    {
+        if (objs == null)
+        {
+            return "";
+        }
+        StringBuilder str = new StringBuilder();
+        boolean needDelim = false;
+        for (Object obj : objs)
+        {
+            if (needDelim)
+            {
+                str.append(delim);
+            }
+            str.append(obj);
+            needDelim = true;
+        }
+        return str.toString();
+    }
+
     /**
      * Is String null, empty, or consisting of only whitespace.
      * 
@@ -44,7 +94,7 @@
         }
         return true;
     }
-    
+
     /**
      * Is String valid and has something other than whitespace
      * 
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/BaseHomeTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/BaseHomeTest.java
index 861972c..0d4c66f 100644
--- a/jetty-start/src/test/java/org/eclipse/jetty/start/BaseHomeTest.java
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/BaseHomeTest.java
@@ -57,7 +57,7 @@
                 System.out.printf(" %s%n",path);

             }

         }

-        Assert.assertThat(message + ": " + Main.join(actual,", "),actual,containsInAnyOrder(expected.toArray()));

+        Assert.assertThat(message + ": " + Utils.join(actual,", "),actual,containsInAnyOrder(expected.toArray()));

     }

     

     public static void assertPathList(BaseHome hb, String message, List<String> expected, List<Path> paths)

@@ -81,7 +81,7 @@
                 System.out.printf(" %s%n",path);

             }

         }

-        Assert.assertThat(message + ": " + Main.join(actual,", "),actual,containsInAnyOrder(expected.toArray()));

+        Assert.assertThat(message + ": " + Utils.join(actual,", "),actual,containsInAnyOrder(expected.toArray()));

     }

 

     public static void assertFileList(BaseHome hb, String message, List<String> expected, List<File> files)

@@ -91,7 +91,7 @@
         {

             actual.add(hb.toShortForm(file));

         }

-        Assert.assertThat(message + ": " + Main.join(actual,", "),actual,containsInAnyOrder(expected.toArray()));

+        Assert.assertThat(message + ": " + Utils.join(actual,", "),actual,containsInAnyOrder(expected.toArray()));

     }

 

     @Test

diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/util/CorrectMavenCentralRefs.java b/jetty-start/src/test/java/org/eclipse/jetty/start/util/CorrectMavenCentralRefs.java
new file mode 100644
index 0000000..ba35077
--- /dev/null
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/util/CorrectMavenCentralRefs.java
@@ -0,0 +1,256 @@
+//
+//  ========================================================================
+//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+//  ------------------------------------------------------------------------
+//  All rights reserved. This program and the accompanying materials
+//  are made available under the terms of the Eclipse Public License v1.0
+//  and Apache License v2.0 which accompanies this distribution.
+//
+//      The Eclipse Public License is available at
+//      http://www.eclipse.org/legal/epl-v10.html
+//
+//      The Apache License v2.0 is available at
+//      http://www.opensource.org/licenses/apache2.0.php
+//
+//  You may elect to redistribute this code under either of these licenses.
+//  ========================================================================
+//
+
+package org.eclipse.jetty.start.util;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.FileVisitOption;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.jetty.start.PathFinder;
+import org.eclipse.jetty.start.PathMatchers;
+import org.eclipse.jetty.start.Utils;
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+
+/**
+ * Simple utility to scan all of the mod files and correct references
+ * to maven central URL in [files] sections to the new maven:// syntax
+ */
+public class CorrectMavenCentralRefs
+{
+    public static void main(String[] args)
+    {
+        Path buildRoot = MavenTestingUtils.getProjectDir("..").toPath();
+        buildRoot = buildRoot.normalize().toAbsolutePath();
+
+        // Test to make sure we are in right directory
+        Path rootPomXml = buildRoot.resolve("pom.xml");
+        Path distPomXml = buildRoot.resolve("jetty-distribution/pom.xml");
+        if (!Files.exists(rootPomXml) || !Files.exists(distPomXml))
+        {
+            System.err.println("Not build root directory: " + buildRoot);
+            System.exit(-1);
+        }
+
+        try
+        {
+            new CorrectMavenCentralRefs().fix(buildRoot);
+        }
+        catch (Throwable t)
+        {
+            t.printStackTrace(System.err);
+        }
+    }
+
+    public void fix(Path buildRoot) throws IOException
+    {
+        // Find all of the *.mod files
+        PathFinder finder = new PathFinder();
+        finder.setFileMatcher("glob:**/*.mod");
+        finder.setBase(buildRoot);
+
+        // Matcher for target directories
+        PathMatcher targetMatcher = PathMatchers.getMatcher("glob:**/target/**");
+        PathMatcher testMatcher = PathMatchers.getMatcher("glob:**/test/**");
+
+        System.out.printf("Walking path: %s%n",buildRoot);
+        Set<FileVisitOption> options = Collections.emptySet();
+        Files.walkFileTree(buildRoot,options,30,finder);
+
+        System.out.printf("Found: %d hits%n",finder.getHits().size());
+        int count = 0;
+        for (Path path : finder.getHits())
+        {
+            if (Files.isDirectory(path))
+            {
+                // skip
+                continue;
+            }
+
+            if (targetMatcher.matches(path))
+            {
+                // skip
+                continue;
+            }
+
+            if (testMatcher.matches(path))
+            {
+                // skip
+                continue;
+            }
+
+            if (processModFile(path))
+            {
+                count++;
+            }
+        }
+
+        System.out.printf("Processed %,d modules",count);
+    }
+
+    private boolean processFileRefs(List<String> lines)
+    {
+        Pattern section = Pattern.compile("\\s*\\[([^]]*)\\]\\s*");
+        int filesStart = -1;
+        int filesEnd = -1;
+
+        // Find [files] section
+        String sectionId = null;
+        int lineCount = lines.size();
+        for (int i = 0; i < lineCount; i++)
+        {
+            String line = lines.get(i).trim();
+
+            Matcher sectionMatcher = section.matcher(line);
+
+            if (sectionMatcher.matches())
+            {
+                sectionId = sectionMatcher.group(1).trim().toUpperCase(Locale.ENGLISH);
+            }
+            else
+            {
+                if ("FILES".equals(sectionId))
+                {
+                    if (filesStart < 0)
+                    {
+                        filesStart = i;
+                    }
+                    filesEnd = i;
+                }
+            }
+        }
+
+        if (filesStart == (-1))
+        {
+            // no [files] section
+            return false;
+        }
+
+        // process lines, only in files section
+        int updated = 0;
+        for (int i = filesStart; i <= filesEnd; i++)
+        {
+            String line = lines.get(i);
+            String keyword = "maven.org/maven2/";
+            int idx = line.indexOf(keyword);
+            if (idx > 0)
+            {
+                int pipe = line.indexOf('|');
+                String rawpath = line.substring(idx + keyword.length(),pipe);
+                String destpath = line.substring(pipe + 1);
+
+                String parts[] = rawpath.split("/");
+                int rev = parts.length;
+                String filename = parts[--rev];
+
+                String type = "jar";
+                int ext = filename.lastIndexOf('.');
+                if (ext > 0)
+                {
+                    type = filename.substring(ext + 1);
+                }
+                String version = parts[--rev];
+                String artifactId = parts[--rev];
+                String groupId = Utils.join(parts,0,rev,".");
+
+                String classifier = filename.replaceFirst(artifactId + '-' + version,"");
+                classifier = classifier.replaceFirst('.' + type + '$',"");
+                if (Utils.isNotBlank(classifier) && (classifier.charAt(0) == '-'))
+                {
+                    classifier = classifier.substring(1);
+                }
+
+                StringBuilder murl = new StringBuilder();
+                murl.append("maven://");
+                murl.append(groupId).append('/');
+                murl.append(artifactId).append('/');
+                murl.append(version);
+                if (!"jar".equals(type) || Utils.isNotBlank(classifier))
+                {
+                    murl.append('/').append(type);
+                    if (Utils.isNotBlank(classifier))
+                    {
+                        murl.append('/').append(classifier);
+                    }
+                }
+
+                lines.set(i,murl.toString()+'|'+destpath);
+
+                updated++;
+            }
+        }
+
+        return (updated > 0);
+    }
+
+    private boolean processModFile(Path path) throws IOException
+    {
+        List<String> lines = readLines(path);
+        if (processFileRefs(lines))
+        {
+            // the lines are now dirty, save them.
+            System.out.printf("Updating: %s%n",path);
+            saveLines(path,lines);
+            return true;
+        }
+
+        // no update performed
+        return false;
+    }
+
+    private List<String> readLines(Path path) throws IOException
+    {
+        List<String> lines = new ArrayList<>();
+
+        try (BufferedReader reader = Files.newBufferedReader(path,StandardCharsets.UTF_8))
+        {
+            String line;
+            while ((line = reader.readLine()) != null)
+            {
+                lines.add(line);
+            }
+        }
+
+        return lines;
+    }
+
+    private void saveLines(Path path, List<String> lines) throws IOException
+    {
+        try (BufferedWriter writer = Files.newBufferedWriter(path,StandardCharsets.UTF_8,StandardOpenOption.TRUNCATE_EXISTING))
+        {
+            for (String line : lines)
+            {
+                writer.write(line);
+                writer.write(System.lineSeparator());
+            }
+        }
+    }
+}
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/RebuildTestResources.java b/jetty-start/src/test/java/org/eclipse/jetty/start/util/RebuildTestResources.java
similarity index 99%
rename from jetty-start/src/test/java/org/eclipse/jetty/start/RebuildTestResources.java
rename to jetty-start/src/test/java/org/eclipse/jetty/start/util/RebuildTestResources.java
index 9679ba4..ebd99fe 100644
--- a/jetty-start/src/test/java/org/eclipse/jetty/start/RebuildTestResources.java
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/util/RebuildTestResources.java
@@ -16,7 +16,7 @@
 //  ========================================================================
 //
 
-package org.eclipse.jetty.start;
+package org.eclipse.jetty.start.util;
 
 import java.io.File;
 import java.io.IOException;