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;
        }

        Map<AppData, File> serialData = null;

        try (FileInputStream fin = new FileInputStream(serialDataFile);
             ObjectInputStream 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();

                // 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;
        }

        // 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;
        }

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

            // read the file back in. for some reason on OSX 10.1
            // this is necessary.
            /* 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);
        }

        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 release 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())
            {
                throw new Exception("Could not read input file with path "
                        + xmlPath + ".  Looking for file " + xmlFile);
            }

            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);
                try (FileInputStream fis = new FileInputStream(xmlFile))
                {
                    AppData appData = (AppData) um.unmarshal(fis);
                    appDataElements.put(appData, xmlFile);
                    getLogger().debug("Saving AppData for " + 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);
    }
}
