/* * The Apache Software License, Version 1.1 * * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Xalan" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation and was * originally based on software copyright (c) 1999, Lotus * Development Corporation., http://www.lotus.com. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.apache.xml.utils.synthetic.reflection; import java.lang.reflect.InvocationTargetException; import org.apache.xml.utils.synthetic.SynthesisException; /* * OPEN ISSUES: * Reflection doesn't tell us about deprecation; if we want * that info, MFC advises mousing our way into the class (ugh). * Should we at least model that for synthetics? */ /** * <meta name="usage" content="internal"/> * API/behaviors shared between Constructors and Methods. * They're mostly similar, except for what they proxy and * a few specific calls (name, invoke/getInstance). */ abstract public class EntryPoint implements Member { /** Field realep */ protected Object realep; /** Field declaringclass */ private org.apache.xml.utils.synthetic.Class declaringclass = null; /** Field returntype */ protected org.apache.xml.utils.synthetic.Class returntype = null; /** Field parameternames */ private String[] parameternames = new String[0]; /** Field parametertypes */ private org.apache.xml.utils.synthetic.Class[] parametertypes = new org.apache.xml.utils.synthetic.Class[0]; /** Field exceptiontypes */ private org.apache.xml.utils.synthetic.Class[] exceptiontypes = new org.apache.xml.utils.synthetic.Class[0]; ; /** Field modifiers */ private int modifiers; /** Field name */ protected String name = null; // for Methods // For synthesis: /** Field body */ private StringBuffer body = null; /** Field language */ private String language = null; // For reifying: /** Field realE, realP */ Class[] realE, realP; /** * Insert the method's description here. * <p> * Creation date: (12-27-99 2:31:39 PM) * @param realConstructor java.lang.reflect.Constructor * * @param declaringclass */ public EntryPoint(org.apache.xml.utils.synthetic.Class declaringclass) { this.declaringclass = declaringclass; } /** * Nonpublic constructor. Wrap this to appropriate "real" type * * @param ep * @param declaringclass * * @throws IllegalArgumentException */ protected EntryPoint( Object ep, org.apache.xml.utils.synthetic.Class declaringclass) throws IllegalArgumentException { realep = ep; this.declaringclass = declaringclass; if (ep instanceof java.lang.reflect.Method) { java.lang.reflect.Method m = (java.lang.reflect.Method) ep; if (declaringclass == null) { declaringclass = org.apache.xml.utils.synthetic.Class.forClass( m.getDeclaringClass()); } name = m.getName(); modifiers = m.getModifiers(); returntype = org.apache.xml.utils.synthetic.Class.forClass(m.getReturnType()); realP = m.getParameterTypes(); realE = m.getExceptionTypes(); } else if (ep instanceof java.lang.reflect.Constructor) { java.lang.reflect.Constructor c = (java.lang.reflect.Constructor) ep; if (declaringclass == null) { declaringclass = org.apache.xml.utils.synthetic.Class.forClass( c.getDeclaringClass()); } name = declaringclass.getShortName(); modifiers = c.getModifiers(); returntype = declaringclass; realP = c.getParameterTypes(); realE = c.getExceptionTypes(); } else throw new IllegalArgumentException(); } /** * Nonpublic constructor. Wrap this to appropriate "real" type * * @param ep * * @throws IllegalArgumentException */ protected EntryPoint(Object ep) throws IllegalArgumentException { this(ep, null); } /** * Compares this against the specified * object. Returns true if the objects are the same. * Two EntryPoints are the same if they were * declared by the same class, have the same name * (or are both ctors) and have the same * formal parameter types. * * @param obj * */ public boolean equals(Object obj) { EntryPoint otherep = null; if (obj instanceof EntryPoint) otherep = (EntryPoint) obj; else if (obj instanceof java.lang.reflect.Constructor || obj instanceof java.lang.reflect.Method) otherep = (EntryPoint) obj; return (otherep != null && ((this instanceof Constructor && otherep instanceof Constructor) || (this instanceof Method && otherep instanceof Method && this.getName().equals( otherep.getName()))) && otherep.getDeclaringClass().equals( declaringclass) && otherep.getParameterTypes().equals( parametertypes)); } /** * Returns the Class object representing the class that * declares the constructor represented by this * Constructor object. * */ public org.apache.xml.utils.synthetic.Class getDeclaringClass() { return declaringclass; } /** * Returns the Class object representing the class that * will be returned by this EntryPoint. Needed by the Method * API, but made meaningful for Constructors as well. * */ public org.apache.xml.utils.synthetic.Class getReturnType() { return returntype; } /** * Returns an array of Class objects that represent the * types of the checked exceptions thrown by the * underlying constructor represented by this * Constructor object. Returns an array of length 0 if * the constructor throws no checked exceptions. * */ public org.apache.xml.utils.synthetic.Class[] getExceptionTypes() { if (realep != null && exceptiontypes == null) { exceptiontypes = new org.apache.xml.utils.synthetic.Class[realE.length]; for (int i = 0; i < realE.length; ++i) { exceptiontypes[i] = org.apache.xml.utils.synthetic.Class.forClass(realE[i]); } realE = null; } return exceptiontypes; } /** * Method addExceptionType * * * @param exception * * @throws SynthesisException */ public void addExceptionType( org.apache.xml.utils.synthetic.Class exception) throws SynthesisException { if (realep != null) throw new SynthesisException(SynthesisException.REIFIED); org.apache.xml.utils.synthetic.Class[] e = new org.apache.xml.utils.synthetic.Class[exceptiontypes.length + 1]; System.arraycopy(exceptiontypes, 0, e, 0, exceptiontypes.length); e[exceptiontypes.length] = exception; exceptiontypes = e; } /** * Returns the Java language modifiers for the * constructor represented by this Constructor object, * as an integer. The Modifier class should be used to * decode the modifiers. * */ public int getModifiers() { return modifiers; } /** * Member method. C'tor's name is always that of the defining class. * Methods have a "real" name. * Creation date: (12-25-99 1:32:06 PM) * @return java.lang.String */ public java.lang.String getName() { if (this instanceof Constructor) return declaringclass.getShortName(); return name; } /** * Member method. C'tor's name is always that of the defining class. * Methods have a "real" name. * Creation date: (12-25-99 1:32:06 PM) * * @param name * @return java.lang.String * * @throws SynthesisException */ public void setName(String name) throws SynthesisException { if (realep != null) throw new SynthesisException(SynthesisException.REIFIED); this.name = name; } /** * Returns an array of Class objects that represent the * formal parameter types, in declaration order, of the * constructor represented by this Constructor object. * Returns an array of length 0 if the underlying * constructor takes no parameters. * */ public org.apache.xml.utils.synthetic.Class[] getParameterTypes() { if (realep != null && parametertypes == null) { parametertypes = new org.apache.xml.utils.synthetic.Class[realP.length]; for (int i = 0; i < realP.length; ++i) { parametertypes[i] = org.apache.xml.utils.synthetic.Class.forClass(realP[i]); } realP = null; } return parametertypes; } /** * Method getParameterNames * * * (getParameterNames) @return */ public String[] getParameterNames() { return parameternames; } /** * Method addParameter * * * @param type * @param name * * @throws SynthesisException */ public void addParameter( org.apache.xml.utils.synthetic.Class type, String name) throws SynthesisException { if (realep != null) throw new SynthesisException(SynthesisException.REIFIED); org.apache.xml.utils.synthetic.Class[] types = new org.apache.xml.utils.synthetic.Class[parametertypes.length + 1]; System.arraycopy(parametertypes, 0, types, 0, parametertypes.length); types[parametertypes.length] = type; parametertypes = types; String[] names = new String[parameternames.length + 1]; System.arraycopy(parameternames, 0, names, 0, parameternames.length); names[parameternames.length] = name; parameternames = names; } /** * Returns a hashcode for this Constructor. The * hashcode is the same as the hashcode for the * underlying constructor's declaring class name, * xor'ed (for Methods) with the method name. * (Implemented in the subclasses rather than here.) * */ abstract public int hashCode(); /** * Assert the Class object representing the class that * declares the constructor represented by this * Constructor object. * * @param declaringClass * * @throws SynthesisException */ public void setDeclaringClass( org.apache.xml.utils.synthetic.Class declaringClass) throws SynthesisException { if (realep != null) throw new SynthesisException(SynthesisException.REIFIED); this.declaringclass = declaringClass; } /** * Should only be accepted before a "real" entrypoint is bound. * Creation date: (12-25-99 1:28:28 PM) * @return int * @param modifiers int * * @throws SynthesisException */ public void setModifiers(int modifiers) throws SynthesisException { if (realep != null) throw new SynthesisException(SynthesisException.REIFIED); this.modifiers = modifiers; } /** * Return a string describing this Constructor. The * string is formatted as the constructor access * modifiers, if any, followed by the fully-qualified * name of the declaring class, followed by a * parenthesized, comma-separated list of the * constructor's formal parameter types. For example: * <code> * public java.util.Hashtable(int,float) * </code> * <p> * The only possible modifiers for constructors are * the access modifiers public, protected or * private. Only one of these may appear, or none * if the constructor has default (package) access. * <p> * Methods will also display their checked exceptions. * */ public String toString() { StringBuffer sb = new StringBuffer(java.lang.reflect.Modifier.toString(getModifiers())); if (this instanceof org.apache.xml.utils.synthetic.reflection.Method) sb.append(' ').append(getReturnType()).append( getDeclaringClass().getName()).append('.').append(getName()); else sb.append(getDeclaringClass().getName()); sb.append('('); org.apache.xml.utils.synthetic.Class[] p = getParameterTypes(); if (p != null && p.length > 0) { sb.append(p[0].getName()); for (int i = 1; i < p.length; ++i) { sb.append(',').append(p[i].getName()); } } sb.append(')'); if (this instanceof org.apache.xml.utils.synthetic.reflection.Method) { p = getExceptionTypes(); if (p != null && p.length > 0) { sb.append(" throws ").append(p[0].getName()); for (int i = 1; i < p.length; ++i) { sb.append(',').append(p[i].getName()); } } } return sb.toString(); } /** * Extension: For synthesis, we need a place to hang a * method body. * * @param language * @param body * * @throws SynthesisException */ public void setBody(String language, StringBuffer body) throws SynthesisException { if (realep != null) throw new SynthesisException(SynthesisException.REIFIED); this.language = language; this.body = body; } /** * Extension: For synthesis, we need a place to hang a * method body. Note that this returns a mutable object, * for editing etc. Slightly sloppy first cut. * */ public StringBuffer getBody() { if (body == null) body = new StringBuffer(); return body; } /** * Extension: For synthesis, we need a place to hang a * method body. * */ public String getLanguage() { return language; } /** * Generate Java code * * @param basetab * */ public String toSource(String basetab) { StringBuffer sb = new StringBuffer(); sb.append(basetab).append( java.lang.reflect.Modifier.toString(getModifiers())); if (this instanceof org.apache.xml.utils.synthetic.reflection.Method) { if (returntype != null) sb.append(" ").append(getReturnType().getJavaName()); else sb.append(" void"); } sb.append(" ").append(getName()).append("("); org.apache.xml.utils.synthetic.Class[] types = getParameterTypes(); if (types != null & types.length > 0) { sb.append(types[0].getJavaName()); if (parameternames != null) sb.append(' ').append(parameternames[0]); for (int i = 1; i < types.length; ++i) { sb.append(',').append(types[i].getJavaName()); if (parameternames != null) sb.append(' ').append(parameternames[i]); } } sb.append(')'); types = getExceptionTypes(); if (types != null & types.length > 0) { sb.append(" throws ").append(types[0].getJavaName()); for (int i = 1; i < types.length; ++i) { sb.append(',').append(types[i].getJavaName()); } } if (body == null) sb.append("; // No method body available\n"); else { sb.append("\n" + basetab + "{\n"); if (language == null || "java".equals(language)) { sb.append(basetab + "// ***** Should prettyprint this code...\n"); sb.append(basetab + body + "\n"); } else { sb.append(basetab + "// ***** Generate BSF invocation!?\n"); } sb.append(basetab + "}\n"); } return sb.toString(); } }