📄 proxygenerator.java
字号:
/** * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 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 name "Exolab" must not be used to endorse or promote * products derived from this Software without prior written * permission of Exoffice Technologies. For written permission, * please contact info@exolab.org. * * 4. Products derived from this Software may not be called "Exolab" * nor may "Exolab" appear in their names without prior written * permission of Exoffice Technologies. Exolab is a registered * trademark of Exoffice Technologies. * * 5. Due credit should be given to the Exolab Project * (http://www.exolab.org/). * * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS * ``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 * EXOFFICE TECHNOLOGIES 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. * * Copyright 2003-2005 (C) Exoffice Technologies Inc. All Rights Reserved. * * $Id: ProxyGenerator.java,v 1.6 2005/05/24 13:38:20 tanderson Exp $ */package org.exolab.jms.plugins.proxygen;import java.io.IOException;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.lang.reflect.Method;import java.rmi.RemoteException;import java.util.Arrays;import java.util.Comparator;import java.util.HashMap;import java.util.Iterator;/** * Generates source code for a <code>Proxy</code> implementation of a class. * * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a> * @version $Revision: 1.6 $ $Date: 2005/05/24 13:38:20 $ */public class ProxyGenerator { /** * The class to generate a proxy source for. */ private final Class _clazz; /** * The package. */ private final String _package; /** * The class name. */ private final String _className; /** * A map of adapters of {@link Throwable}. The key is the target * exception type, the value the adapter class. The adapter class must * implement <code>ThrowableAdapter</code>. It is accessed via * introspection to avoid circular build dependencies. */ private HashMap _adapters = new HashMap(); /** * Interfaces implemented by the class. */ private Class[] _interfaces; /** * The methods implemented by the class. */ private Method[] _methods; /** * Primitive mappings. */ private static final Class[][] MAPPINGS = new Class[][]{ {boolean.class, Boolean.class}, {byte.class, Byte.class}, {short.class, Short.class}, {char.class, Character.class}, {int.class, Integer.class}, {long.class, Long.class}, {float.class, Float.class}, {double.class, Double.class}}; /** * The fully qualified Delegate class name. */ private static final String DELEGATE = "org.exolab.jms.net.proxy.Delegate"; /** * The fully qualified Proxy class name. */ private static final String PROXY = "org.exolab.jms.net.proxy.Proxy"; /** * The suffix for generated proxies. */ private static final String PROXY_SUFFIX = "__Proxy"; /** * The fully qualified RemoteInvocationException class name. */ private static final String REMOTE_INVOCATION_EXCEPTION = "org.exolab.jms.net.proxy.RemoteInvocationException"; /** * The fully qualified ThrowableAdapter class name. */ private static final String THROWABLE_ADAPTER = "org.exolab.jms.net.proxy.ThrowableAdapter"; /** * Construct a new <code>ProxyGenerator</code>. * * @param clazz the class to generate proxy code for * @param adapters adapter classes for {@link RemoteException}. May be * <code>null</code> * @throws Exception if <code>adapter</code> is specified but can't be * instantiated */ public ProxyGenerator(Class clazz, Class[] adapters) throws Exception { if (clazz == null) { throw new IllegalArgumentException("Argument 'clazz' is null"); } if (clazz.isArray()) { throw new IllegalArgumentException( "Can't generate proxies for array types"); } if (clazz.isPrimitive()) { throw new IllegalArgumentException( "Can't generate proxies for primitive types"); } _clazz = clazz; _package = ClassHelper.getPackage(_clazz); String name; if (_package != null) { name = _clazz.getName().substring(_package.length() + 1); } else { name = _clazz.getName(); } _className = name + PROXY_SUFFIX; _interfaces = _clazz.getInterfaces(); if (_interfaces.length == 0) { if (MethodHelper.getAllInterfaces(clazz).length == 0) { throw new IllegalArgumentException( "Cannot generate proxy for class " + _clazz.getName() + ": class doesn't implement any interfaces"); } } if (adapters != null && adapters.length != 0) { _adapters = getAdapters(adapters); } _methods = MethodHelper.getInterfaceMethods(_clazz); Arrays.sort(_methods, new MethodComparator()); } /** * Generates the code for the proxy implementation. * * @param stream the stream to write to * @throws IOException for any I/O error */ public void generate(OutputStream stream) throws IOException { SourceWriter writer = new SourceWriter(new OutputStreamWriter(stream)); if (_package != null) { writer.writeln("package " + _package + ";"); } writer.writelnInc("public class " + _className); writer.writeln("extends " + getSuperclassProxy(_clazz)); if (_interfaces.length != 0) { writer.write("implements "); for (int i = 0; i < _interfaces.length; ++i) { if (i > 0) { writer.write(", "); } writer.write(_interfaces[i].getName()); } } writer.writeln(" {"); generateStaticDeclarations(writer); generateConstructor(writer); generateMethods(writer); generateStaticInitialiser(writer); writer.writelnDec(); writer.writeln("}"); writer.flush(); } /** * Generates static declarations. * * @param writer the writer to write to * @throws IOException for any I/O error */ protected void generateStaticDeclarations(SourceWriter writer) throws IOException { if (_methods.length > 0) { writer.writeln(); for (int i = 0; i < _methods.length; ++i) { Method method = _methods[i]; String name = getMethodVarName(method); writer.writeln("private static final java.lang.reflect.Method " + name + ";"); } writer.writeln(); Iterator iterator = _adapters.values().iterator(); while (iterator.hasNext()) { Class adapter = (Class) iterator.next(); String name = getAdapterInstanceName(adapter); writer.writeln("private static final " + THROWABLE_ADAPTER + " " + name + " = new " + adapter.getName()+ "();"); } writer.writeln(); } } /** * Generates the constructor. * * @param writer the writer to write to * @throws IOException for any I/O error */ protected void generateConstructor(SourceWriter writer) throws IOException { writer.writelnInc("public " + _className + "(" + DELEGATE + " delegate) {"); writer.writelnDec("super(delegate);"); writer.writeln("}"); } /** * Generates the public methods. * * @param writer the writer to write to * @throws IOException for any I/O error */ protected void generateMethods(SourceWriter writer) throws IOException { for (int i = 0; i < _methods.length; ++i) { writer.writeln(); Method method = _methods[i]; generateMethod(method, writer); } } /** * Generates a method. * * @param method the method to generate code for * @param writer the writer to write to * @throws IOException for any I/O error */ protected void generateMethod(Method method, SourceWriter writer) throws IOException { Class returnType = method.getReturnType(); Class[] argTypes = method.getParameterTypes(); Class[] exceptionTypes = method.getExceptionTypes(); boolean declaresThrowable = false; boolean declaresException = false; boolean declaresRuntimeException = false; boolean declaresRemoteException = false; boolean declaresRemoteInvocationException = false; boolean adaptThrowable = false; Class adaptType = null; for (int i = 0; i < exceptionTypes.length; ++i) { Class exceptionType = exceptionTypes[i]; if (exceptionType.equals(Throwable.class)) { declaresThrowable = true; } else if (exceptionType.equals(Exception.class)) { declaresException = true; } else if (exceptionType.equals(RuntimeException.class)) { declaresRuntimeException = true; } else if (exceptionType.equals(RemoteException.class)) { declaresRemoteException = true; } else if (exceptionType.getName().equals( REMOTE_INVOCATION_EXCEPTION)) { declaresRemoteInvocationException = true; } else if (_adapters.get(exceptionType) != null) { adaptType = exceptionType; } } if (!declaresThrowable && adaptType != null) { // rethrow all uncaught exceptions as an instance of adaptType adaptThrowable = true; } // determine the set of exceptions to catch. Class[] catchTypes = method.getExceptionTypes(); Arrays.sort(catchTypes, new ClassComparator()); // generate the method signature String returnClass = ClassHelper.getQualifiedName(returnType); writer.write("public " + returnClass + " " + method.getName() + "("); for (int i = 0; i < argTypes.length; ++i) { if (i > 0) { writer.write(", ");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -