/*
 * 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 flex.messaging.config;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 *
 */
public class LocalFileResolver implements ConfigurationFileResolver
{
    public static final int CLIENT = 0;
    public static final int SERVER = 1;
    public static final int LIVECYCLE = 2;

    private static final int ERR_MSG_INVALID_PATH_CLIENT = 11106;
    private static final int ERR_MSG_INVALID_PATH_SERVER = 11108;
    private static final int ERR_MSG_INVALID_PATH_LIVECYCLE = 11122;

    private Stack configurationPathStack = new Stack();
    int version = CLIENT;

    public LocalFileResolver()
    {
    }

    public LocalFileResolver(int version)
    {
        this.version = version;
    }

    public void setErrorMessage(ConfigurationException e, String path)
    {
        if (version == LIVECYCLE)
        {
            // Invalid location: ''{0}''. Please specify a valid LiveCycle Data Services Configuration file via the LiveCycle Admin UI.
            e.setMessage(ERR_MSG_INVALID_PATH_LIVECYCLE, new Object[] {path});
        }
        else if (version == SERVER)
        {
            // Please specify a valid ''services.configuration.file'' in web.xml. You specified ''{0}''. This is not a valid file system path reachable via the app server and is also not a path to a resource in your J2EE application archive.
            e.setMessage(ERR_MSG_INVALID_PATH_SERVER, new Object[]{path});
        }
        else
        {
            // Please specify a valid <services/> file path in flex-config.xml.
            e.setMessage(ERR_MSG_INVALID_PATH_CLIENT);
        }
    }

    public InputStream getConfigurationFile(String path)
    {
        File f = new File(path);
        try
        {
            if (f != null && f.exists() && f.isAbsolute())
            {
                FileInputStream fin = new FileInputStream(f);
                pushConfigurationFile(f.getParent());
                return fin;
            }
            else
            {
                ConfigurationException e = new ConfigurationException();
                setErrorMessage(e, path);
                throw e;
            }
        }
        catch (FileNotFoundException ex)
        {
            ConfigurationException e = new ConfigurationException();
            setErrorMessage(e, path);
            e.setRootCause(ex);
            throw e;
        }
        catch (SecurityException se)
        {
            ConfigurationException e = new ConfigurationException();
            setErrorMessage(e, path);
            e.setRootCause(se);
            throw e;
        }
    }

    public InputStream getIncludedFile(String src)
    {
        String path = configurationPathStack.peek() + File.separator + src;
        File f = new File(path);
        try
        {
            if (f != null && f.exists() && f.isAbsolute())
            {
                FileInputStream fin = new FileInputStream(f);
                pushConfigurationFile(f.getParent());
                return fin;
            }
            else
            {
                // Please specify a valid include file. ''{0}'' is invalid.
                ConfigurationException e = new ConfigurationException();
                e.setMessage(11107, new Object[] {path});
                throw e;
            }
        }
        catch (FileNotFoundException ex)
        {
            // Please specify a valid include file. ''{0}'' is invalid.
            ConfigurationException e = new ConfigurationException();
            e.setMessage(11107, new Object[] {path});
            e.setRootCause(ex);
            throw e;
        }
        catch (SecurityException se)
        {
            // Please specify a valid include file. ''{0}'' is invalid.
            ConfigurationException e = new ConfigurationException();
            e.setMessage(11107, new Object[] {path});
            e.setRootCause(se);
            throw e;
        }
    }

    public void popIncludedFile()
    {
        configurationPathStack.pop();
    }

    /**
     * Returns the list of XML files (denoted by .xml extension) in the directory
     * relative to the current configuration file.
     *
     * @param dir a directory relative to the current configuration file
     * @return a (possibly empty) list of file names
     */
    public List getFiles(String dir)
    {
        List result = new ArrayList();
        File f = new File(configurationPathStack.peek().toString(), dir);
        if (f.exists() && f.isDirectory())
        {
            String[] xmlFiles = f.list(new FilenameFilter()
            {
                public boolean accept(File dir, String name)
                {
                    return name.endsWith(".xml");
                }
            });

            // prepend the directory to each filename
            for (int i = 0; i < xmlFiles.length; i++)
            {
                String file = xmlFiles[i];
                result.add(dir +  File.separator + file);
            }
            return result;
        }
        else
        {
            // Please specify a valid include directory. ''{0}'' is invalid.
            ConfigurationException e = new ConfigurationException();
            e.setMessage(11113, new Object[]{dir});
            throw e;
        }
    }

    private void pushConfigurationFile(String topLevelPath)
    {
        configurationPathStack.push(topLevelPath);
    }

    public String getIncludedPath(String src)
    {
        return configurationPathStack.peek() + File.separator + src;
    }

    public long getIncludedLastModified(String src)
    {
        String path = configurationPathStack.peek() + File.separator + src;
        File f = new File(path);
        return f.lastModified();
    }
}