/*******************************************************************************
 * Copyright (c) 2007 Standards for Technology in Automotive Retail
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     David Carver - STAR - bug 224197 - initial API and implementation
 *                    based on work from Apache Xalan 2.7.0
 *******************************************************************************/

/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed 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.
 */
/*
 * $Id: ExtensionHandlerJavaPackage.java,v 1.3 2008/03/28 02:38:17 dacarver Exp $
 */
package org.eclipse.wst.xsl.core.internal.compiler.xslt10.extensions;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Vector;

import javax.xml.transform.TransformerException;

import org.eclipse.wst.xsl.core.compiler.xslt10.res.Messages;
import org.eclipse.wst.xsl.core.compiler.xslt10.res.XSLTErrorResources;
import org.eclipse.wst.xsl.core.internal.compiler.xslt10.templates.ElemTemplateElement;
import org.eclipse.wst.xsl.core.internal.compiler.xslt10.templates.Stylesheet;
import org.eclipse.wst.xsl.core.internal.compiler.xslt10.trace.ExtensionEvent;
import org.eclipse.wst.xsl.core.internal.compiler.xslt10.transformer.TransformerImpl;
import org.apache.xpath.functions.FuncExtFunction;
import org.apache.xpath.objects.XObject;

/**
 * Represents an extension namespace for XPath that handles java packages that
 * may be fully or partially specified. It is recommended that the class URI be
 * of one of the following forms:
 * 
 * <pre>
 *   xalan://partial.class.name
 *   xalan://
 *   http://xml.apache.org/xalan/java (which is the same as xalan://)
 * </pre>
 * 
 * However, we do not enforce this. If the class name contains a a /, we only
 * use the part to the right of the rightmost slash. In addition, we ignore any
 * "class:" prefix. Provides functions to test a function's existence and call a
 * function. Also provides functions to test an element's existence and call an
 * element.
 * 
 * @author <a href="mailto:garyp@firstech.com">Gary L Peskin</a>
 * 
 * @xsl.usage internal
 */

public class ExtensionHandlerJavaPackage extends ExtensionHandlerJava {

	/**
	 * Construct a new extension namespace handler given all the information
	 * needed.
	 * 
	 * @param namespaceUri
	 *            the extension namespace URI that I'm implementing
	 * @param scriptLang
	 *            language of code implementing the extension
	 * @param className
	 *            the beginning of the class name of the class. This should be
	 *            followed by a dot (.)
	 */
	public ExtensionHandlerJavaPackage(String namespaceUri, String scriptLang,
			String className) {
		super(namespaceUri, scriptLang, className);
	}

	/**
	 * Tests whether a certain function name is known within this namespace.
	 * Since this is for a package, we concatenate the package name used when
	 * this handler was created and the function name specified in the argument.
	 * There is no information regarding the arguments to the function call or
	 * whether the method implementing the function is a static method or an
	 * instance method.
	 * 
	 * @param function
	 *            name of the function being tested
	 * @return true if its known, false if not.
	 */

	@Override
	public boolean isFunctionAvailable(String function) {
		try {
			String fullName = m_className + function;
			int lastDot = fullName.lastIndexOf(".");
			if (lastDot >= 0) {
				Class myClass = getClassForName(fullName.substring(0, lastDot));
				Method[] methods = myClass.getMethods();
				int nMethods = methods.length;
				function = fullName.substring(lastDot + 1);
				for (int i = 0; i < nMethods; i++) {
					if (methods[i].getName().equals(function))
						return true;
				}
			}
		} catch (ClassNotFoundException cnfe) {
		}

		return false;
	}

	/**
	 * Tests whether a certain element name is known within this namespace.
	 * Looks for a method with the appropriate name and signature. This method
	 * examines both static and instance methods.
	 * 
	 * @param element
	 *            name of the element being tested
	 * @return true if its known, false if not.
	 */

	@Override
	public boolean isElementAvailable(String element) {
		try {
			String fullName = m_className + element;
			int lastDot = fullName.lastIndexOf(".");
			if (lastDot >= 0) {
				Class myClass = getClassForName(fullName.substring(0, lastDot));
				Method[] methods = myClass.getMethods();
				int nMethods = methods.length;
				element = fullName.substring(lastDot + 1);
				for (int i = 0; i < nMethods; i++) {
					if (methods[i].getName().equals(element)) {
						Class[] paramTypes = methods[i].getParameterTypes();
						if ((paramTypes.length == 2)
								&& paramTypes[0]
										.isAssignableFrom(org.apache.xalan.extensions.XSLProcessorContext.class)
								&& paramTypes[1]
										.isAssignableFrom(org.eclipse.wst.xsl.core.internal.compiler.xslt10.templates.ElemExtensionCall.class)) {
							return true;
						}
					}
				}
			}
		} catch (ClassNotFoundException cnfe) {
		}

		return false;
	}

	/**
	 * Process a call to a function in the package java namespace. There are
	 * three possible types of calls:
	 * 
	 * <pre>
	 *   Constructor:
	 *     packagens:class.name.new(arg1, arg2, ...)
	 * 
	 *   Static method:
	 *     packagens:class.name.method(arg1, arg2, ...)
	 * 
	 *   Instance method:
	 *     packagens:method(obj, arg1, arg2, ...)
	 * </pre>
	 * 
	 * We use the following rules to determine the type of call made:
	 * <ol type="1">
	 * <li>If the function name ends with a ".new", call the best constructor
	 * for class whose name is formed by concatenating the value specified on
	 * the namespace with the value specified in the function invocation before
	 * ".new".</li>
	 * <li>If the function name contains a period, call the best static method
	 * "method" in the class whose name is formed by concatenating the value
	 * specified on the namespace with the value specified in the function
	 * invocation.</li>
	 * <li>Otherwise, call the best instance method "method" in the class whose
	 * name is formed by concatenating the value specified on the namespace with
	 * the value specified in the function invocation. Note that a static method
	 * of the same name will <i>not</i> be called in the current
	 * implementation. This module does not verify that the obj argument is a
	 * member of the package namespace.</li>
	 * </ol>
	 * 
	 * @param funcName
	 *            Function name.
	 * @param args
	 *            The arguments of the function call.
	 * @param methodKey
	 *            A key that uniquely identifies this class and method call.
	 * @param exprContext
	 *            The context in which this expression is being executed.
	 * @return the return value of the function evaluation.
	 * 
	 * @throws TransformerException
	 *             if parsing trouble
	 */

	@Override
	public Object callFunction(String funcName, Vector args, Object methodKey,
			ExpressionContext exprContext) throws TransformerException {

		String className;
		String methodName;
		Class classObj;
		Object targetObject;
		int lastDot = funcName.lastIndexOf(".");
		Object[] methodArgs;
		Object[][] convertedArgs;
		Class[] paramTypes;

		try {
			TransformerImpl trans = (exprContext != null) ? (TransformerImpl) exprContext
					.getXPathContext().getOwnerObject()
					: null;
			if (funcName.endsWith(".new")) { // Handle constructor call

				methodArgs = new Object[args.size()];
				convertedArgs = new Object[1][];
				for (int i = 0; i < methodArgs.length; i++) {
					methodArgs[i] = args.elementAt(i);
				}

				Constructor c = (methodKey != null) ? (Constructor) getFromCache(
						methodKey, null, methodArgs)
						: null;

				if (c != null) {
					try {
						paramTypes = c.getParameterTypes();
						MethodResolver.convertParams(methodArgs, convertedArgs,
								paramTypes, exprContext);
						return c.newInstance(convertedArgs[0]);
					} catch (InvocationTargetException ite) {
						throw ite;
					} catch (Exception e) {
						// Must not have been the right one
					}
				}
				className = m_className + funcName.substring(0, lastDot);
				try {
					classObj = getClassForName(className);
				} catch (ClassNotFoundException e) {
					throw new TransformerException(e);
				}
				c = MethodResolver.getConstructor(classObj, methodArgs,
						convertedArgs, exprContext);
				if (methodKey != null)
					putToCache(methodKey, null, methodArgs, c);

				if (trans != null && trans.getDebug()) {
					trans.getTraceManager().fireExtensionEvent(
							new ExtensionEvent(trans, c, convertedArgs[0]));
					Object result;
					try {
						result = c.newInstance(convertedArgs[0]);
					} catch (Exception e) {
						throw e;
					} finally {
						trans.getTraceManager().fireExtensionEndEvent(
								new ExtensionEvent(trans, c, convertedArgs[0]));
					}
					return result;
				} else
					return c.newInstance(convertedArgs[0]);
			}

			else if (-1 != lastDot) { // Handle static method call

				methodArgs = new Object[args.size()];
				convertedArgs = new Object[1][];
				for (int i = 0; i < methodArgs.length; i++) {
					methodArgs[i] = args.elementAt(i);
				}
				Method m = (methodKey != null) ? (Method) getFromCache(
						methodKey, null, methodArgs) : null;

				if (m != null && !trans.getDebug()) {
					try {
						paramTypes = m.getParameterTypes();
						MethodResolver.convertParams(methodArgs, convertedArgs,
								paramTypes, exprContext);
						return m.invoke(null, convertedArgs[0]);
					} catch (InvocationTargetException ite) {
						throw ite;
					} catch (Exception e) {
						// Must not have been the right one
					}
				}
				className = m_className + funcName.substring(0, lastDot);
				methodName = funcName.substring(lastDot + 1);
				try {
					classObj = getClassForName(className);
				} catch (ClassNotFoundException e) {
					throw new TransformerException(e);
				}
				m = MethodResolver.getMethod(classObj, methodName, methodArgs,
						convertedArgs, exprContext, MethodResolver.STATIC_ONLY);
				if (methodKey != null)
					putToCache(methodKey, null, methodArgs, m);

				if (trans != null && trans.getDebug()) {
					trans.getTraceManager().fireExtensionEvent(m, null,
							convertedArgs[0]);
					Object result;
					try {
						result = m.invoke(null, convertedArgs[0]);
					} catch (Exception e) {
						throw e;
					} finally {
						trans.getTraceManager().fireExtensionEndEvent(m, null,
								convertedArgs[0]);
					}
					return result;
				} else
					return m.invoke(null, convertedArgs[0]);
			}

			else { // Handle instance method call

				if (args.size() < 1) {
					throw new TransformerException(Messages.createMessage(
							XSLTErrorResources.ER_INSTANCE_MTHD_CALL_REQUIRES,
							new Object[] { funcName })); // "Instance method
															// call to method "
															// + funcName
					// + " requires an Object instance as first argument");
				}
				targetObject = args.elementAt(0);
				if (targetObject instanceof XObject) // Next level down for
														// XObjects
					targetObject = ((XObject) targetObject).object();
				methodArgs = new Object[args.size() - 1];
				convertedArgs = new Object[1][];
				for (int i = 0; i < methodArgs.length; i++) {
					methodArgs[i] = args.elementAt(i + 1);
				}
				Method m = (methodKey != null) ? (Method) getFromCache(
						methodKey, targetObject, methodArgs) : null;

				if (m != null) {
					try {
						paramTypes = m.getParameterTypes();
						MethodResolver.convertParams(methodArgs, convertedArgs,
								paramTypes, exprContext);
						return m.invoke(targetObject, convertedArgs[0]);
					} catch (InvocationTargetException ite) {
						throw ite;
					} catch (Exception e) {
						// Must not have been the right one
					}
				}
				classObj = targetObject.getClass();
				m = MethodResolver.getMethod(classObj, funcName, methodArgs,
						convertedArgs, exprContext,
						MethodResolver.INSTANCE_ONLY);
				if (methodKey != null)
					putToCache(methodKey, targetObject, methodArgs, m);

				if (trans != null && trans.getDebug()) {
					trans.getTraceManager().fireExtensionEvent(m, targetObject,
							convertedArgs[0]);
					Object result;
					try {
						result = m.invoke(targetObject, convertedArgs[0]);
					} catch (Exception e) {
						throw e;
					} finally {
						trans.getTraceManager().fireExtensionEndEvent(m,
								targetObject, convertedArgs[0]);
					}
					return result;
				} else
					return m.invoke(targetObject, convertedArgs[0]);
			}
		} catch (InvocationTargetException ite) {
			Throwable resultException = ite;
			Throwable targetException = ite.getTargetException();

			if (targetException instanceof TransformerException)
				throw ((TransformerException) targetException);
			else if (targetException != null)
				resultException = targetException;

			throw new TransformerException(resultException);
		} catch (Exception e) {
			// e.printStackTrace();
			throw new TransformerException(e);
		}
	}

	/**
	 * Process a call to an XPath extension function
	 * 
	 * @param extFunction
	 *            The XPath extension function
	 * @param args
	 *            The arguments of the function call.
	 * @param exprContext
	 *            The context in which this expression is being executed.
	 * @return the return value of the function evaluation.
	 * @throws TransformerException
	 */
	@Override
	public Object callFunction(FuncExtFunction extFunction, Vector args,
			ExpressionContext exprContext) throws TransformerException {
		return callFunction(extFunction.getFunctionName(), args, extFunction
				.getMethodKey(), exprContext);
	}

	/**
	 * Process a call to this extension namespace via an element. As a side
	 * effect, the results are sent to the TransformerImpl's result tree. For
	 * this namespace, only static element methods are currently supported. If
	 * instance methods are needed, please let us know your requirements.
	 * 
	 * @param localPart
	 *            Element name's local part.
	 * @param element
	 *            The extension element being processed.
	 * @param transformer
	 *            Handle to TransformerImpl.
	 * @param stylesheetTree
	 *            The compiled stylesheet tree.
	 * @param methodKey
	 *            A key that uniquely identifies this element call.
	 * @throws IOException
	 *             if loading trouble
	 * @throws TransformerException
	 *             if parsing trouble
	 */

	@Override
	public void processElement(String localPart, ElemTemplateElement element,
			TransformerImpl transformer, Stylesheet stylesheetTree,
			Object methodKey) throws TransformerException, IOException {
		Object result = null;
		Class classObj;

		Method m = (Method) getFromCache(methodKey, null, null);
		if (null == m) {
			try {
				String fullName = m_className + localPart;
				int lastDot = fullName.lastIndexOf(".");
				if (lastDot < 0)
					throw new TransformerException(Messages.createMessage(
							XSLTErrorResources.ER_INVALID_ELEMENT_NAME,
							new Object[] { fullName })); // "Invalid element
															// name specified "
															// + fullName);
				try {
					classObj = getClassForName(fullName.substring(0, lastDot));
				} catch (ClassNotFoundException e) {
					throw new TransformerException(e);
				}
				localPart = fullName.substring(lastDot + 1);
				m = MethodResolver.getElementMethod(classObj, localPart);
				if (!Modifier.isStatic(m.getModifiers()))
					throw new TransformerException(Messages.createMessage(
							XSLTErrorResources.ER_ELEMENT_NAME_METHOD_STATIC,
							new Object[] { fullName })); // "Element name
															// method must be
															// static " +
															// fullName);
			} catch (Exception e) {
				// e.printStackTrace ();
				throw new TransformerException(e);
			}
			putToCache(methodKey, null, null, m);
		}

		XSLProcessorContext xpc = new XSLProcessorContext(transformer,
				stylesheetTree);

		try {
			if (transformer.getDebug()) {
				transformer.getTraceManager().fireExtensionEvent(m, null,
						new Object[] { xpc, element });
				try {
					result = m.invoke(null, new Object[] { xpc, element });
				} catch (Exception e) {
					throw e;
				} finally {
					transformer.getTraceManager().fireExtensionEndEvent(m,
							null, new Object[] { xpc, element });
				}
			} else
				result = m.invoke(null, new Object[] { xpc, element });
		} catch (InvocationTargetException ite) {
			Throwable resultException = ite;
			Throwable targetException = ite.getTargetException();

			if (targetException instanceof TransformerException)
				throw ((TransformerException) targetException);
			else if (targetException != null)
				resultException = targetException;

			throw new TransformerException(resultException);
		} catch (Exception e) {
			// e.printStackTrace ();
			throw new TransformerException(e);
		}

		if (result != null) {
			xpc.outputToResultTree(stylesheetTree, result);
		}

	}

}
