package org.apache.fulcrum.intake;

/*
 * 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.
 */

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.Unmarshaller.Listener;
import javax.xml.bind.helpers.DefaultValidationEventHandler;
import javax.xml.validation.SchemaFactory;

import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.LogEnabled;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.commons.pool2.KeyedObjectPool;
import org.apache.commons.pool2.KeyedPooledObjectFactory;
import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
import org.apache.fulcrum.intake.model.AppData;
import org.apache.fulcrum.intake.model.Field;
import org.apache.fulcrum.intake.model.Group;

/**
 * This service provides access to input processing objects based on an XML
 * specification.
 *
 * avalon.component name="intake"
 * avalon.service type="org.apache.fulcrum.intake.IntakeService"
 *
 * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
 * @version $Id$
 */
public class IntakeServiceImpl extends AbstractLogEnabled implements
        IntakeService, Configurable, Initializable, Contextualizable,
        Serviceable
{
    /** Map of groupNames -> appData elements */
    private Map<String, AppData> groupNames;

    /** The cache of group names. */
    private Map<String, String> groupNameMap;

    /** The cache of group keys. */
    private Map<String, String> groupKeyMap;

    /** The cache of property getters. */
    private Map<String, Map<String, Method>> getterMap;

    /** The cache of property setters. */
    private Map<String, Map<String, Method>> setterMap;

    /** AppData -> keyed Pools Map */
    private Map<AppData, KeyedObjectPool<String, Group>> keyedPools;

    /** The Avalon Container root directory */
    private String applicationRoot;

    /** List of configured xml specification files */
    private List<String> xmlPathes = null;

    /** Configured location of the serialization file */
    private String serialDataPath = null;

    /**
     * Local Class to enable Avalon logging on the model classes
     *
     */
    private class AvalonLogEnabledListener extends Listener
    {
		/**
		 * @see javax.xml.bind.Unmarshaller.Listener#beforeUnmarshal(java.lang.Object, java.lang.Object)
		 */
		@Override
		public void beforeUnmarshal(Object target, Object parent)
		{
			super.beforeUnmarshal(target, parent);

			if (target instanceof LogEnabled)
			{
				((LogEnabled)target).enableLogging(getLogger());
			}
		}

    }

    /**
     * Registers a given group name in the system
     *
     * @param groupName
     *            The name to register the group under
     * @param group
     *            The Group to register in
     * @param appData
     *            The app Data object where the group can be found
     * @param checkKey
     *            Whether to check if the key also exists.
     *
     * @return true if successful, false if not
     */
    private boolean registerGroup(String groupName, Group group,
            AppData appData, boolean checkKey)
    {
        if (groupNames.containsKey(groupName))
        {
            // This name already exists.
            return false;
        }

        boolean keyExists = groupNameMap.containsKey(group.getGID());

        if (checkKey && keyExists)
        {
            // The key for this package is already registered for another group
            return false;
        }

        groupNames.put(groupName, appData);
        groupKeyMap.put(groupName, group.getGID());

        if (!keyExists)
        {
            // This key does not exist. Add it to the hash.
            groupNameMap.put(group.getGID(), groupName);
        }

        List<Field<?>> fields = group.getFields();
        for (Field<?> field : fields)
        {
            String className = field.getMapToObject();
            if (!getterMap.containsKey(className))
            {
                getterMap.put(className, new HashMap<String, Method>());
                setterMap.put(className, new HashMap<String, Method>());
            }
        }
        return true;
    }

    /**
     * Tries to load a serialized Intake Group file. This can reduce the startup
     * time of Turbine.
     *
     * @param serialDataPath
     *            The path of the File to load.
     *
     * @return A map with appData objects loaded from the file or null if the
     *         map could not be loaded.
     */
    private Map<AppData, File> loadSerialized(String serialDataPath, long timeStamp)
    {
        getLogger().debug(
                "Entered loadSerialized(" + serialDataPath + ", " + timeStamp
                        + ")");

        long timer = System.currentTimeMillis();

        if (serialDataPath == null)
        {
            return null;
        }

        File serialDataFile = new File(serialDataPath);

        if (!serialDataFile.exists())
        {
            getLogger().info("No serialized file found, parsing XML");
            return null;
        }

        if (serialDataFile.lastModified() <= timeStamp)
        {
            getLogger().info("serialized file too old, parsing XML");
            return null;
        }

        ObjectInputStream in = null;
        Map<AppData, File> serialData = null;

        try
        {
        	FileInputStream fin = new FileInputStream(serialDataFile);
            in = new ObjectInputStream(fin);
            Object o = in.readObject();

            if (o instanceof Map)
            {
                @SuppressWarnings("unchecked") // checked with instanceof
				Map<AppData, File> map = (Map<AppData, File>) o;
				serialData = map;
            }
            else
            {
                // This could be old file from intake. Try to delete it
                getLogger().info("serialized object is not an intake map, ignoring");
                in.close();
                in = null;
                
                // Try to delete the file
                boolean result = serialDataFile.delete();
                if ( result == false )
                {
                	getLogger().error("Unknown serialized file could not be removed");
                }
            }
        }
        catch (IOException e)
        {
            getLogger().error("Serialized File could not be read.", e);

            // We got a corrupt file for some reason.
            // Null out serialData to be sure
            serialData = null;
        }
        catch (ClassNotFoundException e)
        {
            getLogger().error("Objects could not be read from serialized file.", e);

            // This should not happen
            // Null out serialData to be sure
            serialData = null;
        }
        finally
        {
            // Could be null if we opened a file, didn't find it to be a
            // Map object and then nuked it away.
            try
            {
                if (in != null)
                {
                    in.close();
                }
            }
            catch (IOException e)
            {
                getLogger().error("Exception while closing file", e);
            }
        }

        // Recreate transient loggers
        if (serialData != null)
        {
        	for (AppData appData : serialData.keySet())
        	{
        		for (Group group : appData.getGroups())
        		{
        			if (group instanceof LogEnabled)
        			{
        				((LogEnabled)group).enableLogging(getLogger());
        			}

    				for (Field<?> field : group.getFields())
    				{
            			if (field instanceof LogEnabled)
            			{
            				((LogEnabled)field).enableLogging(getLogger());
            			}
    				}
        		}
        	}
        }
        getLogger().info("Loaded serialized map object, ignoring XML");
        getLogger().debug("Loading took " + (System.currentTimeMillis() - timer));
        return serialData;
    }

    /**
     * Writes a parsed XML map with all the appData groups into a file. This
     * will speed up loading time when you restart the Intake Service because it
     * will only unserialize this file instead of reloading all of the XML files
     *
     * @param serialDataPath
     *            The path of the file to write to
     * @param appDataElements
     *            A Map containing all of the XML parsed appdata elements
     */
    private void saveSerialized(String serialDataPath, Map<AppData, File> appDataElements)
    {

        getLogger().debug(
                "Entered saveSerialized(" + serialDataPath
                        + ", appDataElements)");

        long timer = System.currentTimeMillis();

        if (serialDataPath == null)
        {
            return;
        }

        File serialData = new File(serialDataPath);

        try
        {
            boolean result = serialData.createNewFile();
            if ( result == false )
            {
            	getLogger().error("Could not create new serialized file");
            }

            // Try to delete the file
            result = serialData.delete();
            if ( result == false )
            {
            	getLogger().error("Serialized file could not be removed");
            }
            
        }
        catch (IOException e)
        {
            getLogger().info(
                    "Could not create serialized file " + serialDataPath
                            + ", not serializing the XML data", e);
            return;
        }

        ObjectOutputStream out = null;
        ObjectInputStream in = null;

        try
        {
            // write the appData file out
        	FileOutputStream fout = new FileOutputStream(serialDataPath);
            out = new ObjectOutputStream(fout);
            out.writeObject(appDataElements);
            out.flush();

            // read the file back in. for some reason on OSX 10.1
            // this is necessary.
            FileInputStream fin = new FileInputStream(serialDataPath);
            in = new ObjectInputStream(fin);
            /* Map dummy = (Map) */ in.readObject();

            getLogger().debug("Serializing successful");
        }
        catch (IOException e)
        {
            getLogger().info(
                    "Could not write serialized file to " + serialDataPath
                            + ", not serializing the XML data", e);
        }
        catch (ClassNotFoundException e)
        {
            getLogger().info(
                    "Could not re-read serialized file from " + serialDataPath, e);
        }
        finally
        {
            try
            {
                if (out != null)
                {
                    out.close();
                }
            }
            catch (IOException e)
            {
                getLogger().error("Exception while closing file", e);
            }
            try
            {
                if (in != null)
                {
                    in.close();
                }
            }
            catch (IOException e)
            {
                getLogger().error("Exception while closing file", e);
            }
        }

        getLogger().debug("Saving took " + (System.currentTimeMillis() - timer));
    }

    /**
     * Gets an instance of a named group either from the pool or by calling the
     * Factory Service if the pool is empty.
     *
     * @param groupName
     *            the name of the group.
     * @return a Group instance.
     * @throws IntakeException
     *             if recycling fails.
     */
    @Override
    public Group getGroup(String groupName) throws IntakeException
    {
        Group group = null;

        AppData appData = groupNames.get(groupName);

        if (groupName == null)
        {
            throw new IntakeException(
                    "Intake IntakeServiceImpl.getGroup(groupName) is null");
        }

        if (appData == null)
        {
            throw new IntakeException(
                    "Intake IntakeServiceImpl.getGroup(groupName): No XML definition for Group "
                            + groupName + " found");
        }
        try
        {
            group = keyedPools.get(appData).borrowObject(groupName);
        }
        catch (Exception e)
        {
            throw new IntakeException("Could not get group " + groupName, e);
        }
        return group;
    }

    /**
     * Puts a Group back to the pool.
     *
     * @param instance
     *            the object instance to recycle.
     *
     * @throws IntakeException
     *             The passed group name does not exist.
     */
    @Override
    public void releaseGroup(Group instance) throws IntakeException
    {
        if (instance != null)
        {
            String groupName = instance.getIntakeGroupName();
            AppData appData = groupNames.get(groupName);

            if (appData == null)
            {
                throw new IntakeException(
                        "Intake IntakeServiceImpl.releaseGroup(groupName): "
                                + "No XML definition for Group " + groupName
                                + " found");
            }

            try
            {
                keyedPools.get(appData).returnObject(groupName, instance);
            }
            catch (Exception e)
            {
                throw new IntakeException("Could not get group " + groupName, e);
            }
        }
    }

    /**
     * Gets the current size of the pool for a group.
     *
     * @param groupName
     *            the name of the group.
     *
     * @throws IntakeException
     *             The passed group name does not exist.
     */
    @Override
    public int getSize(String groupName) throws IntakeException
    {
        AppData appData = groupNames.get(groupName);
        if (appData == null)
        {
            throw new IntakeException(
                    "Intake IntakeServiceImpl.Size(groupName): No XML definition for Group "
                            + groupName + " found");
        }

        KeyedObjectPool<String, Group> kop = keyedPools.get(appData);

        return kop.getNumActive(groupName) + kop.getNumIdle(groupName);
    }

    /**
     * Names of all the defined groups.
     *
     * @return array of names.
     */
    @Override
    public String[] getGroupNames()
    {
        return groupNames.keySet().toArray(new String[0]);
    }

    /**
     * Gets the key (usually a short identifier) for a group.
     *
     * @param groupName
     *            the name of the group.
     * @return the the key.
     */
    @Override
    public String getGroupKey(String groupName)
    {
        return groupKeyMap.get(groupName);
    }

    /**
     * Gets the group name given its key.
     *
     * @param groupKey
     *            the key.
     * @return groupName the name of the group.
     */
    @Override
    public String getGroupName(String groupKey)
    {
        return groupNameMap.get(groupKey);
    }

    /**
     * Gets the Method that can be used to set a property.
     *
     * @param className
     *            the name of the object.
     * @param propName
     *            the name of the property.
     * @return the setter.
     * @throws ClassNotFoundException if the class specified could not be loaded
     * @throws IntrospectionException if the property setter could not be called
     */
    @Override
    public Method getFieldSetter(String className, String propName)
            throws ClassNotFoundException, IntrospectionException
    {
        Map<String, Method> settersForClassName = setterMap.get(className);

        if (settersForClassName == null)
        {
            throw new IntrospectionException("No setter Map for " + className
                    + " available!");
        }

        Method setter = settersForClassName.get(propName);

        if (setter == null)
        {
            PropertyDescriptor pd = new PropertyDescriptor(propName, Class
                    .forName(className));
            synchronized (setterMap)
            {
                setter = pd.getWriteMethod();
                settersForClassName.put(propName, setter);
                if (setter == null)
                {
                    getLogger().error(
                            "Intake: setter for '" + propName + "' in class '"
                                    + className + "' could not be found.");
                }
            }
            // we have already completed the reflection on the getter, so
            // save it so we do not have to repeat
            synchronized (getterMap)
            {
                Map<String, Method> gettersForClassName = getterMap.get(className);

                if (gettersForClassName != null)
                {
                    Method getter = pd.getReadMethod();
                    if (getter != null)
                    {
                        gettersForClassName.put(propName, getter);
                    }
                }
            }
        }
        return setter;
    }

    /**
     * Gets the Method that can be used to get a property value.
     *
     * @param className
     *            the name of the object.
     * @param propName
     *            the name of the property.
     * @return the getter.
     * @throws ClassNotFoundException if the class specified could not be loaded
     * @throws IntrospectionException if the property getter could not be called
     */
    @Override
    public Method getFieldGetter(String className, String propName)
            throws ClassNotFoundException, IntrospectionException
    {
        Map<String, Method> gettersForClassName = getterMap.get(className);

        if (gettersForClassName == null)
        {
            throw new IntrospectionException("No getter Map for " + className
                    + " available!");
        }

        Method getter = gettersForClassName.get(propName);

        if (getter == null)
        {
            PropertyDescriptor pd = null;
            synchronized (getterMap)
            {
                pd = new PropertyDescriptor(propName, Class.forName(className));
                getter = pd.getReadMethod();
                gettersForClassName.put(propName, getter);
                if (getter == null)
                {
                    getLogger().error(
                            "Intake: getter for '" + propName + "' in class '"
                                    + className + "' could not be found.");
                }
            }
            // we have already completed the reflection on the setter, so
            // save it so we do not have to repeat
            synchronized (setterMap)
            {
                Map<String, Method> settersForClassName = getterMap.get(className);

                if (settersForClassName != null)
                {
                    Method setter = pd.getWriteMethod();
                    if (setter != null)
                    {
                        settersForClassName.put(propName, setter);
                    }
                }
            }
        }
        return getter;
    }

    // ---------------- Avalon Lifecycle Methods ---------------------
    /**
     * Avalon component lifecycle method
     */
    @Override
    public void configure(Configuration conf) throws ConfigurationException
    {
        final Configuration xmlPaths = conf.getChild(XML_PATHS, false);

        xmlPathes = new ArrayList<String>();

        if (xmlPaths == null)
        {
            xmlPathes.add(XML_PATH_DEFAULT);
        }
        else
        {
            Configuration[] nameVal = xmlPaths.getChildren();
            for (int i = 0; i < nameVal.length; i++)
            {
                String val = nameVal[i].getValue();
                xmlPathes.add(val);
            }
        }

        serialDataPath = conf.getChild(SERIAL_XML, false).getValue(SERIAL_XML_DEFAULT);

        if (!serialDataPath.equalsIgnoreCase("none"))
        {
            serialDataPath = new File(applicationRoot, serialDataPath).getAbsolutePath();
        }
        else
        {
            serialDataPath = null;
        }

        getLogger().debug("Path for serializing: " + serialDataPath);
    }

    /**
     * Avalon component lifecycle method Initializes the service by loading
     * xml rule files and creating the Intake groups.
     *
     * @throws Exception
     *             if initialization fails.
     */
    @Override
    public void initialize() throws Exception
    {
        Map<AppData, File> appDataElements = null;

        groupNames = new HashMap<String, AppData>();
        groupKeyMap = new HashMap<String, String>();
        groupNameMap = new HashMap<String, String>();
        getterMap = new HashMap<String, Map<String,Method>>();
        setterMap = new HashMap<String, Map<String,Method>>();
        keyedPools = new HashMap<AppData, KeyedObjectPool<String, Group>>();

        Set<File> xmlFiles = new HashSet<File>();

        long timeStamp = 0;
        
        getLogger().debug("logger is " + getLogger().getClass().getSimpleName());

        for (String xmlPath : xmlPathes)
        {
            // Files are webapp.root relative
            File xmlFile = new File(applicationRoot, xmlPath).getAbsoluteFile();

            getLogger().debug("Path for XML File: " + xmlFile);

            if (!xmlFile.canRead())
            {
                String READ_ERR = "Could not read input file with path "
                        + xmlPath + ".  Looking for file " + xmlFile;

                getLogger().error(READ_ERR);
                throw new Exception(READ_ERR);
            }

            xmlFiles.add(xmlFile);

            getLogger().debug("Added " + xmlPath + " as File to parse");

            // Get the timestamp of the youngest file to be compared with
            // a serialized file. If it is younger than the serialized file,
            // then we have to parse the XML anyway.
            timeStamp = xmlFile.lastModified() > timeStamp ? xmlFile
                    .lastModified() : timeStamp;
        }

        Map<AppData, File> serializedMap = loadSerialized(serialDataPath, timeStamp);

        if (serializedMap != null)
        {
            // Use the serialized data as XML groups. Don't parse.
            appDataElements = serializedMap;
            getLogger().debug("Using the serialized map");
        }
        else
        {
        	long timer = System.currentTimeMillis();

            // Parse all the given XML files
            JAXBContext jaxb = JAXBContext.newInstance(AppData.class);
            Unmarshaller um = jaxb.createUnmarshaller();

            // Debug mapping
            um.setEventHandler(new DefaultValidationEventHandler());

            // Enable logging
            Listener logEnabledListener = new AvalonLogEnabledListener();
            um.setListener(logEnabledListener);

            URL schemaURL = getClass().getResource("/intake.xsd");
            SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
            um.setSchema(schemaFactory.newSchema(schemaURL));
            appDataElements = new HashMap<AppData, File>();

            for (File xmlFile : xmlFiles)
            {
                getLogger().debug("Now parsing: " + xmlFile);
                FileInputStream fis = null;
                try
                {
                    fis = new FileInputStream(xmlFile);
                    AppData appData = (AppData) um.unmarshal(fis);

                    appDataElements.put(appData, xmlFile);
                    getLogger().debug("Saving AppData for " + xmlFile);
                }
                finally
                {
                    if (fis != null)
                    {
                        try
                        {
                            fis.close();
                        }
                        catch (IOException e)
                        {
                            getLogger().warn("Could not close file " + xmlFile);
                        }
                    }
                }
            }

            getLogger().debug("Parsing took " + (System.currentTimeMillis() - timer));
            saveSerialized(serialDataPath, appDataElements);
        }

        int counter = 0;
        AppData appData;
        File dataFile;
        for ( Entry<AppData, File> entry : appDataElements.entrySet() )
        {
        	// Set the entry pair
        	appData = entry.getKey();
        	dataFile = entry.getValue();
        	
            int maxPooledGroups = 0;
            List<Group> glist = appData.getGroups();

            String groupPrefix = appData.getGroupPrefix();

            for (ListIterator<Group> i = glist.listIterator(glist.size()); i.hasPrevious();)
            {
                Group g = i.previous();
                String groupName = g.getIntakeGroupName();

                boolean registerUnqualified = registerGroup(groupName, g, appData, true);

                if (!registerUnqualified)
                {
                    getLogger().info(
                            "Ignored redefinition of Group " + groupName
                                    + " or Key " + g.getGID() + " from "
                                    + dataFile);
                }

                if (groupPrefix != null)
                {
                    StringBuilder qualifiedName = new StringBuilder();
                    qualifiedName.append(groupPrefix).append(':').append(groupName);

                    // Add the fully qualified group name. Do _not_ check
                    // for
                    // the existence of the key if the unqualified
                    // registration succeeded
                    // (because then it was added by the registerGroup
                    // above).
                    if (!registerGroup(qualifiedName.toString(), g,
                            appData, !registerUnqualified))
                    {
                        getLogger().error(
                            "Could not register fully qualified name "
                                    + qualifiedName
                                    + ", maybe two XML files have the same prefix. Ignoring it.");
                    }
                }

                // Init fields
                for (Field<?> f : g.getFields())
                {
                    f.initGetterAndSetter();
                }

                maxPooledGroups = Math.max(maxPooledGroups, g.getPoolCapacity());
            }

            KeyedPooledObjectFactory<String, Group> factory =
                new Group.GroupFactory(appData);

            GenericKeyedObjectPoolConfig<Group> poolConfig = new GenericKeyedObjectPoolConfig<Group>();
            poolConfig.setMaxTotalPerKey(maxPooledGroups);
            poolConfig.setJmxEnabled(true);
            poolConfig.setJmxNamePrefix("fulcrum-intake-pool-" + counter++);

            keyedPools.put(appData,
                new GenericKeyedObjectPool<String, Group>(factory, poolConfig));
        }

        if (getLogger().isInfoEnabled())
        {
            getLogger().info("Intake Service is initialized now.");
        }
    }

    /**
     * Note that the avalon.entry key="urn:avalon:home" 
     * and the type is {@link java.io.File}
     * 
     * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
     * 
     * @param context the Context to use
     * @throws ContextException if the context is not found
     */
    @Override
    public void contextualize(Context context) throws ContextException
    {
        this.applicationRoot = context.get("urn:avalon:home").toString();
    }

    /**
     * Avalon component lifecycle method
     *
     * avalon.dependency type="org.apache.fulcrum.localization.LocalizationService"
     * 
     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
     * 
     * @param manager the service manager
     * @throws ServiceException generic exception
     */
    @Override
    public void service(ServiceManager manager) throws ServiceException
    {
        IntakeServiceFacade.setIntakeService(this);
    }
}
