/*
 *  eXist Open Source Native XML Database
 *  Copyright (C) 2001-06 The eXist Project
 *  http://exist-db.org
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * $Id$
 */

package org.exist.start;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This class uses regex pattern matching to find the latest version of a
 * particular jar file. 
 * 
 * @see LatestFileResolver#getResolvedFileName(String)
 * 
 * @author Ben Schmaus (exist@benschmaus.com)
 * @version $Revision$
 */
public class LatestFileResolver {

    // Pattern that can be used to indicate that the
    // latest version of a particular file should be added to the classpath.
    // E.g., commons-fileupload-%latest%.jar would resolve to something like
    // commons-fileupload-1.1.jar.
    private final static Pattern latestVersionPattern = Pattern.compile(
        "(%latest%)"
    );

    // Set debug mode for each file resolver instance based on whether or
    // not the system was started with debugging turned on.
    private static boolean _debug = Boolean.getBoolean("exist.start.debug");
            
    /**
     * If the passed file name contains a %latest% token,
     * find the latest version of that file. Otherwise, return
     * the passed file name unmodified.
     * 
     * @param filename Path relative to exist home dir of
     * a jar file that should be added to the classpath.
     */
    public String getResolvedFileName(final String filename) {
        final Matcher matches = latestVersionPattern.matcher(filename);
        if (!matches.find()) {
            return filename;
        }
        final String[] fileinfo = filename.split("%latest%");
        // Path of file up to the beginning of the %latest% token.
        final String uptoToken = fileinfo[0];

        // Dir that should contain our jar.
        final String containerDirName = uptoToken.substring(
            0, uptoToken.lastIndexOf(File.separatorChar)
        );

        final Path containerDir = Paths.get(containerDirName);

        final String artifactId = Pattern.quote(uptoToken.substring(uptoToken.lastIndexOf(File.separatorChar) + 1));
        final String suffix = Pattern.quote(fileinfo[1]);
        final String patternString = '^' + artifactId + "(?:(?:[0-9]+(?:(?:\\.|_)[0-9]+)*)(?:-SNAPSHOT)?(?:-[0-9a-f]{7})?)" + suffix + '$';
        final Pattern pattern = Pattern.compile(patternString);
        final Matcher matcher = pattern.matcher("");

        List<Path> jars;
        try {
             jars = Main.list(containerDir, p -> {
                matcher.reset(Main.fileName(p));
                return matcher.find();
            });
        } catch (final IOException e) {
            System.err.println("ERROR: No jars found in " + containerDir.toAbsolutePath());
            e.printStackTrace();
            jars = Collections.emptyList();
        }

        if (!jars.isEmpty()) {
            final String actualFileName = jars.get(0).toAbsolutePath().toString();
            if (_debug) {
                System.err.println(
                    "Found match: " + actualFileName
                    + " for jar file pattern: " + filename
                );
            }
            return actualFileName;
        } else {
            if (_debug) {
                System.err.println(
                    "WARN: No latest version found for JAR file: '"
                    + filename + "'"
                );
            }
        }
        return filename;
    }    
}

@@ -3163,16 +3163,29 @@
 OT)?(?:-
+patched)?(?:-
 %5B0-9a-f%5D

Fix a regression with loading the XML:DB API introduced in 3814547