/*
 * 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.felix.cm.file;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.BitSet;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import java.util.Stack;

import org.apache.felix.cm.PersistenceManager;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;


/**
 * The <code>FilePersistenceManager</code> class stores configuration data in
 * properties-like files inside a given directory. All configuration files are
 * located in the same directory.
 * <p>
 * The configuration directory is set by either the
 * {@link #FilePersistenceManager(String)} constructor or the
 * {@link #FilePersistenceManager(BundleContext, String)} constructor. Refer
 * to the respective JavaDocs for more information.
 * <p>
 * When this persistence manager is used by the Configuration Admin Service,
 * the location may be configured using the
 * {@link org.apache.felix.cm.impl.ConfigurationManager#CM_CONFIG_DIR} bundle
 * context property. That is the Configuration Admin Service creates an instance
 * of this class calling
 * <code>new FilePersistenceManager(bundleContext, bundleContext.getProperty(CM_CONFIG_DIR))</code>.
 * <p>
 * If the location is not set, the <code>config</code> directory in the current
 * working directory (as set in the <code>user.dir</code> system property) is
 * used. If the the location is set but, no such directory exists, the directory
 * and any missing parent directories are created. If a file exists at the given
 * location, the constructor fails.
 * <p>
 * Configuration files are created in the configuration directory by appending
 * the extension <code>.config</code> to the PID of the configuration. The PID
 * is converted into a relative path name by replacing enclosed dots to slashes.
 * Non-<code>symbolic-name</code> characters in the PID are encoded with their
 * Unicode character code in hexadecimal.
 * <p>
 * <table border="0" cellspacing="3" cellpadding="0">
 * <tr><td colspan="2"><b>Examples of PID to name conversion:</td></tr>
 * <tr><th>PID</th><th>Configuration File Name</th></tr>
 * <tr><td><code>sample</code><td><code>sample.config</code></tr>
 * <tr><td><code>org.apache.felix.log.LogService</code><td><code>org/apache/felix/log/LogService.config</code></tr>
 * <tr><td><code>sample.fl&auml;che</code><td><code>sample/fl%00e8che.config</code></tr>
 * </table>
 * <p>
 * <b>Mulithreading Issues</b>
 * <p>
 * In a multithreaded environment the {@link #store(String, Dictionary)} and
 * {@link #load(File)} methods may be called at the the quasi-same time for the
 * same configuration PID. It may no happen, that the store method starts
 * writing the file and the load method might at the same time read from the
 * file currently being written and thus loading corrupt data (if data is
 * available at all).
 * <p>
 * To prevent this situation from happening, the methods use synchronization
 * and temporary files as follows:
 * <ul>
 * <li>The {@link #store(String, Dictionary)} method writes a temporary file
 * with file extension <code>.tmp</code>. When done, the file is renamed to
 * actual configuration file name as implied by the PID. This last step of
 * renaming the file is synchronized on the FilePersistenceManager instance.</li>
 * <li>The {@link #load(File)} method is completeley synchronized on the
 * FilePersistenceManager instance such that the {@link #store} method might
 * inadvertantly try to replace the file while it is being read.</li>
 * <li>Finally the <code>Iterator</code> returned by {@link #getDictionaries()}
 * is implemented such that any temporary configuration file is just ignored.</li>
 * </ul>
 */
public class FilePersistenceManager implements PersistenceManager
{

    /**
     * The default configuration data directory if no location is configured
     * (value is "config").
     */
    public static final String DEFAULT_CONFIG_DIR = "config";

    /**
     * The extension of the configuration files.
     */
    private static final String FILE_EXT = ".config";

    /**
     * The extension of the configuration files, while they are being written
     * (value is ".tmp").
     *
     * @see #store(String, Dictionary)
     */
    private static final String TMP_EXT = ".tmp";

    private static final BitSet VALID_PATH_CHARS;

    /**
     * The access control context we use in the presence of a security manager.
     */
    private final AccessControlContext acc;

    /**
     * The abstract path name of the configuration files.
     */
    private final File location;

    // sets up this class defining the set of valid characters in path
    // set getFile(String) for details.
    static
    {
        VALID_PATH_CHARS = new BitSet();

        for ( int i = 'a'; i <= 'z'; i++ )
        {
            VALID_PATH_CHARS.set( i );
        }
        for ( int i = 'A'; i <= 'Z'; i++ )
        {
            VALID_PATH_CHARS.set( i );
        }
        for ( int i = '0'; i <= '9'; i++ )
        {
            VALID_PATH_CHARS.set( i );
        }
        VALID_PATH_CHARS.set( File.separatorChar );
        VALID_PATH_CHARS.set( ' ' );
        VALID_PATH_CHARS.set( '-' );
        VALID_PATH_CHARS.set( '_' );
    }


    /**
     * Encodes a Service PID to a filesystem path as described in the class
     * JavaDoc above.
     * <p>
     * This method is not part of the API of this class and is declared package
     * private to enable JUnit testing on it. This method may be removed or
     * modified at any time without notice.
     *
     * @param pid The Service PID to encode into a relative path name.
     *
     * @return The relative path name corresponding to the Service PID.
     */
    static String encodePid( String pid )
    {

        // replace dots by File.separatorChar
        pid = pid.replace( '.', File.separatorChar );

        // replace slash by File.separatorChar if different
        if ( File.separatorChar != '/' )
        {
            pid = pid.replace( '/', File.separatorChar );
        }

        // scan for first non-valid character (if any)
        int first = 0;
        while ( first < pid.length() && VALID_PATH_CHARS.get( pid.charAt( first ) ) )
        {
            first++;
        }

        // check whether we exhausted
        if ( first < pid.length() )
        {
            StringBuffer buf = new StringBuffer( pid.substring( 0, first ) );

            for ( int i = first; i < pid.length(); i++ )
            {
                char c = pid.charAt( i );
                if ( VALID_PATH_CHARS.get( c ) )
                {
                    buf.append( c );
                }
                else
                {
                    String val = "000" + Integer.toHexString( c );
                    buf.append( '%' );
                    buf.append( val.substring( val.length() - 4 ) );
                }
            }

            pid = buf.toString();
        }

        return pid;
    }


    /**
     * Creates an instance of this persistence manager using the given location
     * as the directory to store and retrieve the configuration files.
     * <p>
     * This constructor resolves the configuration file location as follows:
     * <ul>
     * <li>If <code>location</code> is <code>null</code>, the <code>config</code>
     * directory in the current working directory as specified in the
     * <code>user.dir</code> system property is assumed.</li>
     * <li>Otherwise the named directory is used.</li>
     * <li>If the directory name resolved in the first or second step is not an
     * absolute path, it is resolved to an absolute path calling the
     * <code>File.getAbsoluteFile()</code> method.</li>
     * <li>If a non-directory file exists as the location found in the previous
     * step or the named directory (including any parent directories) cannot be
     * created, an <code>IllegalArgumentException</code> is thrown.</li>
     * </ul>
     * <p>
     * This constructor is equivalent to calling
     * {@link #FilePersistenceManager(BundleContext, String)} with a
     * <code>null</code> <code>BundleContext</code>.
     *
     * @param location The configuration file location. If this is
     *      <code>null</code> the <code>config</code> directory below the current
     *      working directory is used.
     *
     * @throws IllegalArgumentException If the <code>location</code> exists but
     *      is not a directory or does not exist and cannot be created.
     */
    public FilePersistenceManager( String location )
    {
        this( null, location );
    }


    /**
     * Creates an instance of this persistence manager using the given location
     * as the directory to store and retrieve the configuration files.
     * <p>
     * This constructor resolves the configuration file location as follows:
     * <ul>
     * <li>If <code>location</code> is <code>null</code>, the <code>config</code>
     * directory in the persistent storage area of the bundle identified by
     * <code>bundleContext</code> is used.</li>
     * <li>If the framework does not support persistent storage area for bundles
     * in the filesystem or if <code>bundleContext</code> is <code>null</code>,
     * the <code>config</code> directory in the current working directory as
     * specified in the <code>user.dir</code> system property is assumed.</li>
     * <li>Otherwise the named directory is used.</li>
     * <li>If the directory name resolved in the first, second or third step is
     * not an absolute path and a <code>bundleContext</code> is provided which
     * provides access to persistent storage area, the directory name is
     * resolved as being inside the persistent storage area. Otherwise the
     * directory name is resolved to an absolute path calling the
     * <code>File.getAbsoluteFile()</code> method.</li>
     * <li>If a non-directory file exists as the location found in the previous
     * step or the named directory (including any parent directories) cannot be
     * created, an <code>IllegalArgumentException</code> is thrown.</li>
     * </ul>
     *
     * @param bundleContext The <code>BundleContext</code> to optionally get
     *      the data location for the configuration files. This may be
     *      <code>null</code>, in which case this constructor acts exactly the
     *      same as calling {@link #FilePersistenceManager(String)}.
     * @param location The configuration file location. If this is
     *      <code>null</code> the <code>config</code> directory below the current
     *      working directory is used.
     *
     * @throws IllegalArgumentException If the location exists but is not a
     *      directory or does not exist and cannot be created.
     * @throws IllegalStateException If the <code>bundleContext</code> is not
     *      valid.
     */
    public FilePersistenceManager( BundleContext bundleContext, String location )
    {
        // setup the access control context from the calling setup
        if ( System.getSecurityManager() != null )
        {
            acc = AccessController.getContext();
        }
        else
        {
            acc = null;
        }

        // no configured location, use the config dir in the bundle persistent
        // area
        if ( location == null && bundleContext != null )
        {
            File locationFile = bundleContext.getDataFile( DEFAULT_CONFIG_DIR );
            if ( locationFile != null )
            {
                location = locationFile.getAbsolutePath();
            }
        }

        // fall back to the current working directory if the platform does
        // not support filesystem based data area
        if ( location == null )
        {
            location = System.getProperty( "user.dir" ) + "/config";
        }

        // ensure the file is absolute
        File locationFile = new File( location );
        if ( !locationFile.isAbsolute() )
        {
            if ( bundleContext != null )
            {
                File bundleLocationFile = bundleContext.getDataFile( locationFile.getPath() );
                if ( bundleLocationFile != null )
                {
                    locationFile = bundleLocationFile;
                }
            }

            // ensure the file object is an absolute file object
            locationFile = locationFile.getAbsoluteFile();
        }

        // check the location
        if ( !locationFile.isDirectory() )
        {
            if ( locationFile.exists() )
            {
                throw new IllegalArgumentException( location + " is not a directory" );
            }

            if ( !locationFile.mkdirs() )
            {
                throw new IllegalArgumentException( "Cannot create directory " + location );
            }
        }

        this.location = locationFile;
    }


    /**
     * Returns the directory in which the configuration files are written as
     * a <code>File</code> object.
     *
     * @return The configuration file location.
     */
    public File getLocation()
    {
        return location;
    }


    /**
     * Loads configuration data from the configuration location and returns
     * it as <code>Dictionary</code> objects.
     * <p>
     * This method is a lazy implementation, which is just one configuration
     * file ahead of the current enumeration location.
     *
     * @return an enumeration of configuration data returned as instances of
     *      the <code>Dictionary</code> class.
     */
    public Enumeration getDictionaries()
    {
        return new DictionaryEnumeration();
    }


    /**
     * Deletes the file for the given identifier.
     *
     * @param pid The identifier of the configuration file to delete.
     */
    public void delete( final String pid )
    {
        if ( System.getSecurityManager() != null )
        {
            _privilegedDelete( pid );
        }
        else
        {
            _delete( pid );
        }
    }


    private void _privilegedDelete( final String pid )
    {
        AccessController.doPrivileged( new PrivilegedAction()
        {
            public Object run()
            {
                _delete( pid );
                return null;
            }
        }, acc );
    }


    private void _delete( final String pid )
    {
        synchronized ( this )
        {
            getFile( pid ).delete();
        }
    }


    /**
     * Returns <code>true</code> if a (configuration) file exists for the given
     * identifier.
     *
     * @param pid The identifier of the configuration file to check.
     *
     * @return <code>true</code> if the file exists
     */
    public boolean exists( final String pid )
    {
        if ( System.getSecurityManager() != null )
        {
            return _privilegedExists( pid );
        }

        return _exists( pid );
    }


    private boolean _privilegedExists( final String pid )
    {
        final Object result = AccessController.doPrivileged( new PrivilegedAction()
        {
            public Object run()
            {
                return Boolean.valueOf( _exists( pid ) );
            }
        } );
        return ( ( Boolean ) result ).booleanValue();
    }


    private boolean _exists( final String pid )
    {
        synchronized ( this )
        {
            return getFile( pid ).isFile();
        }
    }


    /**
     * Reads the (configuration) for the given identifier into a
     * <code>Dictionary</code> object.
     *
     * @param pid The identifier of the configuration file to delete.
     *
     * @return The configuration read from the file. This <code>Dictionary</code>
     *      may be empty if the file contains no configuration information
     *      or is not properly formatted.
     */
    public Dictionary load( String pid ) throws IOException
    {
        final File cfgFile = getFile( pid );

        if ( System.getSecurityManager() != null )
        {
            return _privilegedLoad( cfgFile );
        }

        return _load( cfgFile );
    }


    private Dictionary _privilegedLoad( final File cfgFile ) throws IOException
    {
        try
        {
            Object result = AccessController.doPrivileged( new PrivilegedExceptionAction()
            {
                public Object run() throws IOException
                {
                    return _load( cfgFile );
                }
            } );

            return ( Dictionary ) result;
        }
        catch ( PrivilegedActionException pae )
        {
            throw ( IOException ) pae.getCause();
        }
    }


    /**
     * Loads the contents of the <code>cfgFile</code> into a new
     * <code>Dictionary</code> object.
     *
     * @param cfgFile
     *            The file from which to load the data.
     * @return A new <code>Dictionary</code> object providing the file contents.
     * @throws java.io.FileNotFoundException
     *             If the given file does not exist.
     * @throws IOException
     *             If an error occurrs reading the configuration file.
     */
    Dictionary _load( File cfgFile ) throws IOException
    {
        // this method is not part of the API of this class but is made
        // package private to prevent the creation of a synthetic method
        // for use by the DictionaryEnumeration._seek method

        // synchronize this instance to make at least sure, the file is
        // not at the same time accessed by another thread (see store())
        // we have to synchronize the complete load time as the store
        // method might want to replace the file while we are reading and
        // still have the file open. This might be a problem e.g. in Windows
        // environments, where files may not be removed which are still open
        synchronized ( this )
        {
            InputStream ins = null;
            try
            {
                ins = new FileInputStream( cfgFile );
                return ConfigurationHandler.read( ins );
            }
            finally
            {
                if ( ins != null )
                {
                    try
                    {
                        ins.close();
                    }
                    catch ( IOException ioe )
                    {
                        // ignore
                    }
                }
            }
        }
    }


    /**
     * Stores the contents of the <code>Dictionary</code> in a file denoted
     * by the given identifier.
     *
     * @param pid The identifier of the configuration file to which to write
     *      the configuration contents.
     * @param props The configuration data to write.
     *
     * @throws IOException If an error occurrs writing the configuration data.
     */
    public void store( final String pid, final Dictionary props ) throws IOException
    {
        if ( System.getSecurityManager() != null )
        {
            _privilegedStore( pid, props );
        }
        else
        {
            _store( pid, props );
        }
    }


    private void _privilegedStore( final String pid, final Dictionary props ) throws IOException
    {
        try
        {
            AccessController.doPrivileged( new PrivilegedExceptionAction()
            {
                public Object run() throws IOException
                {
                    _store( pid, props );
                    return null;
                }
            } );
        }
        catch ( PrivilegedActionException pae )
        {
            throw ( IOException ) pae.getCause();
        }
    }


    private void _store( final String pid, final Dictionary props ) throws IOException
    {
        OutputStream out = null;
        File tmpFile = null;
        try
        {
            File cfgFile = getFile( pid );

            // ensure parent path
            File cfgDir = cfgFile.getParentFile();
            cfgDir.mkdirs();

            // write the configuration to a temporary file
            tmpFile = File.createTempFile( cfgFile.getName(), TMP_EXT, cfgDir );
            out = new FileOutputStream( tmpFile );
            ConfigurationHandler.write( out, props );
            out.close();

            // after writing the file, rename it but ensure, that no other
            // might at the same time open the new file
            // see load(File)
            synchronized ( this )
            {
                // make sure the cfg file does not exists (just for sanity)
                if ( cfgFile.exists() )
                {
                    cfgFile.delete();
                }

                // rename the temporary file to the new file
                if ( !tmpFile.renameTo( cfgFile ) )
                {
                    throw new IOException( "Failed to rename configuration file from '" + tmpFile + "' to '" + cfgFile );
                }
            }
        }
        finally
        {
            if ( out != null )
            {
                try
                {
                    out.close();
                }
                catch ( IOException ioe )
                {
                    // ignore
                }
            }

            if (tmpFile != null && tmpFile.exists())
            {
                tmpFile.delete();
            }
        }
    }


    /**
     * Creates an abstract path name for the <code>pid</code> encoding it as
     * follows:
     * <ul>
     * <li>Dots (<code>.</code>) are replaced by <code>File.separatorChar</code>
     * <li>Characters not matching [a-zA-Z0-9 _-] are encoded with a percent
     *  character (<code>%</code>) and a 4-place hexadecimal unicode value.
     * </ul>
     * Before returning the path name, the parent directory and any ancestors
     * are created.
     *
     * @param pid The identifier for which to create the abstract file name.
     *
     * @return The abstract path name, which the parent directory path created.
     */
    File getFile( String pid )
    {
        // this method is not part of the API of this class but is made
        // package private to prevent the creation of a synthetic method
        // for use by the DictionaryEnumeration._seek method

        return new File( location, encodePid( pid ) + FILE_EXT );
    }

    /**
     * The <code>DictionaryEnumeration</code> class implements the
     * <code>Enumeration</code> returning configuration <code>Dictionary</code>
     * objects on behalf of the {@link FilePersistenceManager#getDictionaries()}
     * method.
     * <p>
     * This enumeration loads configuration lazily with a look ahead of one
     * dictionary.
     */
    class DictionaryEnumeration implements Enumeration
    {
        private Stack dirStack;
        private File[] fileList;
        private int idx;
        private Dictionary next;


        DictionaryEnumeration()
        {
            dirStack = new Stack();
            fileList = null;
            idx = 0;

            dirStack.push( getLocation() );
            next = seek();
        }


        public boolean hasMoreElements()
        {
            return next != null;
        }


        public Object nextElement()
        {
            if ( next == null )
            {
                throw new NoSuchElementException();
            }

            Dictionary toReturn = next;
            next = seek();
            return toReturn;
        }


        private Dictionary seek()
        {
            if ( System.getSecurityManager() != null )
            {
                return _privilegedSeek();
            }

            return _seek();
        }


        protected Dictionary _privilegedSeek()
        {
            Object result = AccessController.doPrivileged( new PrivilegedAction()
            {
                public Object run()
                {
                    return _seek();
                }
            } );
            return ( Dictionary ) result;
        }


        protected Dictionary _seek()
        {
            while ( ( fileList != null && idx < fileList.length ) || !dirStack.isEmpty() )
            {
                if ( fileList == null || idx >= fileList.length )
                {
                    File dir = ( File ) dirStack.pop();
                    fileList = dir.listFiles();
                    idx = 0;
                }
                else
                {

                    File cfgFile = fileList[idx++];
                    if ( cfgFile.isFile() && !cfgFile.getName().endsWith( TMP_EXT ))
                    {
                        try
                        {
                            Dictionary dict =  _load( cfgFile );

                            // use the dictionary if it has no PID or the PID
                            // derived file name matches the source file name
                            if ( dict.get( Constants.SERVICE_PID ) == null
                                || cfgFile.equals( getFile( ( String ) dict.get( Constants.SERVICE_PID ) ) ) )
                            {
                                return dict;
                            }
                        }
                        catch ( IOException ioe )
                        {
                            // ignore, check next file
                        }
                    }
                    else if ( cfgFile.isDirectory() )
                    {
                        dirStack.push( cfgFile );
                    }
                }
            }

            // exhausted
            return null;
        }
    }

}
