/*
 * 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.apache.commons.net.ftp.parser;

import java.util.regex.Pattern;

import org.apache.commons.net.ftp.Configurable;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFileEntryParser;


/**
 * This is the default implementation of the
 * FTPFileEntryParserFactory interface.  This is the
 * implementation that will be used by
 * org.apache.commons.net.ftp.FTPClient.listFiles()
 * if no other implementation has been specified.
 *
 * @see org.apache.commons.net.ftp.FTPClient#listFiles
 * @see org.apache.commons.net.ftp.FTPClient#setParserFactory
 */
public class DefaultFTPFileEntryParserFactory
    implements FTPFileEntryParserFactory
{

    // Match a plain Java Identifier
    private static final String JAVA_IDENTIFIER = "\\p{javaJavaIdentifierStart}(\\p{javaJavaIdentifierPart})*";
    // Match a qualified name, e.g. a.b.c.Name - but don't allow the default package as that would allow "VMS"/"UNIX" etc.
    private static final String JAVA_QUALIFIED_NAME  = "("+JAVA_IDENTIFIER+"\\.)+"+JAVA_IDENTIFIER;
    // Create the pattern, as it will be reused many times
    private static final Pattern JAVA_QUALIFIED_NAME_PATTERN = Pattern.compile(JAVA_QUALIFIED_NAME);

    /**
     * This default implementation of the FTPFileEntryParserFactory
     * interface works according to the following logic:
     * First it attempts to interpret the supplied key as a fully
     * qualified classname (default package is not allowed) of a class implementing the
     * FTPFileEntryParser interface.  If that succeeds, a parser
     * object of this class is instantiated and is returned;
     * otherwise it attempts to interpret the key as an identirier
     * commonly used by the FTP SYST command to identify systems.
     * <p>
     * If <code>key</code> is not recognized as a fully qualified
     * classname known to the system, this method will then attempt
     * to see whether it <b>contains</b> a string identifying one of
     * the known parsers.  This comparison is <b>case-insensitive</b>.
     * The intent here is where possible, to select as keys strings
     * which are returned by the SYST command on the systems which
     * the corresponding parser successfully parses.  This enables
     * this factory to be used in the auto-detection system.
     *
     * @param key    should be a fully qualified classname corresponding to
     *               a class implementing the FTPFileEntryParser interface<br>
     *               OR<br>
     *               a string containing (case-insensitively) one of the
     *               following keywords:
     *               <ul>
     *               <li>{@link FTPClientConfig#SYST_UNIX UNIX}</li>
     *               <li>{@link FTPClientConfig#SYST_NT WINDOWS}</li>
     *               <li>{@link FTPClientConfig#SYST_OS2 OS/2}</li>
     *               <li>{@link FTPClientConfig#SYST_OS400 OS/400}</li>
     *               <li>{@link FTPClientConfig#SYST_AS400 AS/400}</li>
     *               <li>{@link FTPClientConfig#SYST_VMS VMS}</li>
     *               <li>{@link FTPClientConfig#SYST_MVS MVS}</li>
     *               <li>{@link FTPClientConfig#SYST_NETWARE NETWARE}</li>
     *               <li>{@link FTPClientConfig#SYST_L8 TYPE:L8}</li>
     *               </ul>
     * @return the FTPFileEntryParser corresponding to the supplied key.
     * @throws ParserInitializationException thrown if for any reason the factory cannot resolve
     *                   the supplied key into an FTPFileEntryParser.
     * @see FTPFileEntryParser
     */
//    @Override
    @Override
    public FTPFileEntryParser createFileEntryParser(String key)
    {
        if (key == null) {
            throw new ParserInitializationException("Parser key cannot be null");
        }
        return createFileEntryParser(key, null);
    }

    // Common method to process both key and config parameters.
    private FTPFileEntryParser createFileEntryParser(String key, FTPClientConfig config) {
        FTPFileEntryParser parser = null;

        // Is the key a possible class name?
        if (JAVA_QUALIFIED_NAME_PATTERN.matcher(key).matches()) {
            try
            {
                Class<?> parserClass = Class.forName(key);
                try {
                    parser = (FTPFileEntryParser) parserClass.newInstance();
                } catch (ClassCastException e) {
                    throw new ParserInitializationException(parserClass.getName()
                        + " does not implement the interface "
                        + "org.apache.commons.net.ftp.FTPFileEntryParser.", e);
                } catch (Exception e) {
                    throw new ParserInitializationException("Error initializing parser", e);
                } catch (ExceptionInInitializerError e) {
                    throw new ParserInitializationException("Error initializing parser", e);
                }
            } catch (ClassNotFoundException e) {
                // OK, assume it is an alias
            }
        }

        if (parser == null) { // Now try for aliases
            String ukey = key.toUpperCase(java.util.Locale.ENGLISH);
            if (ukey.indexOf(FTPClientConfig.SYST_UNIX) >= 0)
            {
                parser = new UnixFTPEntryParser(config, false);
            }
            else if (ukey.indexOf(FTPClientConfig.SYST_UNIX_TRIM_LEADING) >= 0)
            {
                parser = new UnixFTPEntryParser(config, true);
            }
            else if (ukey.indexOf(FTPClientConfig.SYST_VMS) >= 0)
            {
                parser = new VMSVersioningFTPEntryParser(config);
            }
            else if (ukey.indexOf(FTPClientConfig.SYST_NT) >= 0)
            {
                parser = createNTFTPEntryParser(config);
            }
            else if (ukey.indexOf(FTPClientConfig.SYST_OS2) >= 0)
            {
                parser = new OS2FTPEntryParser(config);
            }
            else if (ukey.indexOf(FTPClientConfig.SYST_OS400) >= 0 ||
                    ukey.indexOf(FTPClientConfig.SYST_AS400) >= 0)
            {
                parser = createOS400FTPEntryParser(config);
            }
            else if (ukey.indexOf(FTPClientConfig.SYST_MVS) >= 0)
            {
                parser = new MVSFTPEntryParser(); // Does not currently support config parameter
            }
            else if (ukey.indexOf(FTPClientConfig.SYST_NETWARE) >= 0)
            {
                parser = new NetwareFTPEntryParser(config);
            }
            else if (ukey.indexOf(FTPClientConfig.SYST_MACOS_PETER) >= 0)
            {
                parser = new MacOsPeterFTPEntryParser(config);
            }
            else if (ukey.indexOf(FTPClientConfig.SYST_L8) >= 0)
            {
                // L8 normally means Unix, but move it to the end for some L8 systems that aren't.
                // This check should be last!
                parser = new UnixFTPEntryParser(config);
            }
            else
            {
                throw new ParserInitializationException("Unknown parser type: " + key);
            }
        }

        if (parser instanceof Configurable) {
            ((Configurable)parser).configure(config);
        }
        return parser;
    }

    /**
     * <p>Implementation extracts a key from the supplied
     * {@link  FTPClientConfig FTPClientConfig}
     * parameter and creates an object implementing the
     * interface FTPFileEntryParser and uses the supplied configuration
     * to configure it.
     * </p><p>
     * Note that this method will generally not be called in scenarios
     * that call for autodetection of parser type but rather, for situations
     * where the user knows that the server uses a non-default configuration
     * and knows what that configuration is.
     * </p>
     * @param config  A {@link  FTPClientConfig FTPClientConfig}
     * used to configure the parser created
     *
     * @return the @link  FTPFileEntryParser FTPFileEntryParser} so created.
     * @exception ParserInitializationException
     *                   Thrown on any exception in instantiation
     * @throws NullPointerException if {@code config} is {@code null}
     * @since 1.4
     */
//    @Override
    @Override
    public FTPFileEntryParser createFileEntryParser(FTPClientConfig config)
    throws ParserInitializationException
    {
        String key = config.getServerSystemKey();
        return createFileEntryParser(key, config);
    }


    public FTPFileEntryParser createUnixFTPEntryParser()
    {
        return new UnixFTPEntryParser();
    }

    public FTPFileEntryParser createVMSVersioningFTPEntryParser()
    {
        return new VMSVersioningFTPEntryParser();
    }

    public FTPFileEntryParser createNetwareFTPEntryParser() {
        return new NetwareFTPEntryParser();
    }

    public FTPFileEntryParser createNTFTPEntryParser()
    {
        return createNTFTPEntryParser(null);
    }

    /**
     * Creates an NT FTP parser: if the config exists, and the system key equals
     * {@link FTPClientConfig.SYST_NT} then a plain {@link NTFTPEntryParser} is used,
     * otherwise a composite of {@link NTFTPEntryParser} and {@link UnixFTPEntryParser} is used.
     * @param config the config to use, may be {@code null}
     * @return the parser
     */
    private FTPFileEntryParser createNTFTPEntryParser(FTPClientConfig config)
    {
        if (config != null && FTPClientConfig.SYST_NT.equals(
                config.getServerSystemKey()))
        {
            return new NTFTPEntryParser(config);
        } else {
            return new CompositeFileEntryParser(new FTPFileEntryParser[]
                   {
                       new NTFTPEntryParser(config),
                       new UnixFTPEntryParser(config,
                               config != null && FTPClientConfig.SYST_UNIX_TRIM_LEADING.equals(config.getServerSystemKey()))
                   });
        }
    }

     public FTPFileEntryParser createOS2FTPEntryParser()
    {
        return new OS2FTPEntryParser();
    }

    public FTPFileEntryParser createOS400FTPEntryParser()
    {
        return createOS400FTPEntryParser(null);
    }

    /**
     * Creates an OS400 FTP parser: if the config exists, and the system key equals
     * {@link FTPClientConfig.SYST_OS400} then a plain {@link OS400FTPEntryParser} is used,
     * otherwise a composite of {@link OS400FTPEntryParser} and {@link UnixFTPEntryParser} is used.
     * @param config the config to use, may be {@code null}
     * @return the parser
     */
    private FTPFileEntryParser createOS400FTPEntryParser(FTPClientConfig config)
        {
        if (config != null &&
                FTPClientConfig.SYST_OS400.equals(config.getServerSystemKey()))
        {
            return new OS400FTPEntryParser(config);
        } else {
            return new CompositeFileEntryParser(new FTPFileEntryParser[]
                {
                    new OS400FTPEntryParser(config),
                    new UnixFTPEntryParser(config,
                            config != null && FTPClientConfig.SYST_UNIX_TRIM_LEADING.equals(config.getServerSystemKey()))
                });
        }
    }

    public FTPFileEntryParser createMVSEntryParser()
    {
        return new MVSFTPEntryParser();
    }

}

