Package com.caucho.ejb.hessian

Source Code of com.caucho.ejb.hessian.MarshalGenerator

/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT.  See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*   Free SoftwareFoundation, Inc.
*   59 Temple Place, Suite 330
*   Boston, MA 02111-1307  USA
*
* @author Scott Ferguson
*/

package com.caucho.ejb.hessian;

import com.caucho.java.AbstractGenerator;
import com.caucho.loader.DynamicClassLoader;
import com.caucho.util.CharBuffer;
import com.caucho.util.IntMap;
import com.caucho.vfs.Path;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;

/**
* Base class for generating code to marshal and unmarshal sml-rpc calls.
*/
abstract class MarshalGenerator extends AbstractGenerator {
  // Classes which can be safely passed by reference because they're
  // immutable and part of the JDK
  static IntMap immutableClasses;
 
  protected static Class readerClass;
  protected static Class inputStreamClass;
  protected static Class remoteClass;
  protected static Class nodeClass;
 
  static {
    readerClass = java.io.Reader.class;
    inputStreamClass = java.io.InputStream.class;
    remoteClass = java.rmi.Remote.class;
    nodeClass = org.w3c.dom.Node.class;
  }
 
  protected Class _cl;
  String objClass;
  String fullName;
  String pkg;
  String className;

  protected int unique;
 
  protected ArrayList marshallClasses;
  protected ArrayList unmarshallClasses;
 
  protected ArrayList marshallArrays;
  protected ArrayList unmarshallArrays;

  /**
   * Initialize the generated classname.
   *
   * @param beanClass the bean which needs the stub/skeleton
   *
   * @return the path to the file to be generated
   */
  Path initClassNames(Class beanClass, String suffix)
    throws Exception
  {
    ClassLoader parentLoader = getParentLoader();
   
    if (parentLoader instanceof DynamicClassLoader) {
      DynamicClassLoader dcl = (DynamicClassLoader) parentLoader;

      dcl.make();
    }

    Path workPath = getClassDir();

    _cl = beanClass;

    fullName = _cl.getName() + suffix;

    objClass = _cl.getName();
    int p = objClass.lastIndexOf('.');
    if (p > 0)
      objClass = objClass.substring(p + 1);
   
    p = fullName.lastIndexOf('.');
    if (p > 0) {
      pkg = fullName.substring(0, p);
      className = fullName.substring(p + 1);
    }
    else
      className = fullName;

    Path path = workPath.lookup(fullName.replace('.', '/') + ".java");
    path.getParent().mkdirs();

    return path;
  }

  /**
   * Creates a unique mangled method name based on the method name and
   * the method parameters.
   *
   * @param name the base method name
   * @param method the method to mangle
   * @param isFull if true, mangle the full classname
   *
   * @return a mangled string.
   */
  protected String mangleMethodName(String name, Method method, boolean isFull)
  {
    CharBuffer cb = CharBuffer.allocate();
   
    cb.append(name);
   
    Class []params = method.getParameterTypes();
    for (int i = 0; i < params.length; i++) {
      cb.append('_');
      mangleClass(cb, params[i], isFull);
    }

    return cb.close();
  }

  /**
   * Creates a unique mangled method name based on the method name and
   * the method parameters.
   *
   * @param name the base method name
   * @param method the method to mangle
   * @param isFull if true, mangle the full classname
   *
   * @return a mangled string.
   */
  protected String mangleMethodName(String name, Class []param, boolean isFull)
  {
    CharBuffer cb = CharBuffer.allocate();
   
    cb.append(name);
   
    for (int i = 0; i < param.length; i++) {
      cb.append('_');
      mangleClass(cb, param[i], isFull);
    }

    return cb.close();
  }

  /**
   * Mangles a classname.
   */
  private void mangleClass(CharBuffer cb, Class cl, boolean isFull)
  {
    String name = cl.getName();

    if (name.equals("boolean"))
      cb.append("boolean");
    else if (name.equals("int") ||
             name.equals("short") ||
             name.equals("byte"))
      cb.append("int");
    else if (name.equals("long"))
      cb.append("long");
    else if (name.equals("double") || name.equals("float"))
      cb.append("double");
    else if (name.equals("java.lang.String") ||
             name.equals("com.caucho.util.CharBuffer") ||
             name.equals("char") ||
             name.equals("java.io.Reader"))
      cb.append("string");
    else if (name.equals("java.util.Date") ||
             name.equals("com.caucho.util.QDate"))
      cb.append("date");
    else if (inputStreamClass.isAssignableFrom(cl) ||
             name.equals("[B"))
      cb.append("binary");
    else if (cl.isArray()) {
      cb.append("[");
      mangleClass(cb, cl.getComponentType(), isFull);
    }
    else if (name.equals("org.w3c.dom.Node") ||
             name.equals("org.w3c.dom.Element") ||
             name.equals("org.w3c.dom.Document"))
      cb.append("xml");
    else if (isFull)
      cb.append(name);
    else {
      int p = name.lastIndexOf('.');
      if (p > 0)
        cb.append(name.substring(p + 1));
      else
        cb.append(name);
    }
  }

  /**
   * Prints a method declaration with a given name.
   *
   * @param name the name to use for the generated method
   * @param method the method to override
   */
  protected void printMethodDeclaration(String name, Method method)
    throws IOException
  {
    Class ret = method.getReturnType();
    Class []params = method.getParameterTypes();

    Class []exns = method.getExceptionTypes();

    println();
    print("public ");
    printClass(ret);
    print(" " + name + "(");
    for (int i = 0; i < params.length; i++) {
      if (i != 0)
        print(", ");
      printClass(params[i]);
      print(" _arg" + i);
    }
    println(")");
    if (exns.length > 0)
      print("  throws ");
    for (int i = 0; i < exns.length; i++) {
      if (i != 0)
        print(", ");
      printClass(exns[i]);
    }
    if (exns.length > 0)
      println();
  }

  /**
   * Unmarshal the reading of a single variable, knowing the result
   * type.
   *
   * @param var the generated java variable which will receive the data.
   * @param cl the class of the target variable.
   */
  protected void printUnmarshalType(Class cl)
    throws IOException
  {
    String name = cl.getName();

    if (cl.equals(boolean.class)) {
      println("in.readBoolean();");
    }
    else if (cl.equals(int.class)) {
      println("in.readInt();");
    }
    else if (cl.equals(short.class) ||
             cl.equals(char.class) ||
             cl.equals(byte.class)) {
      println("(" + name + ") in.readInt();");
    }
    else if (cl.equals(long.class)) {
      println("in.readLong();");
    }
    else if (cl.equals(double.class)) {
      println("in.readDouble();");
    }
    else if (cl.equals(float.class)) {
      println("(" + name + ") in.readDouble();");
    }
    else if (cl.equals(String.class))
      println("in.readString();");
    else if (cl.equals(java.util.Date.class)) {
      println("new java.util.Date(in.readUTCDate());");
    }
    else if (cl.equals(byte[].class)) {
      println("in.readBytes();");
    }
    else if (org.w3c.dom.Node.class.isAssignableFrom(cl)) {
      println("in.readNode();");
    }
    else if (cl.equals(java.lang.Object.class)) {
      println("in.readObject();");
    }
    else {
      print("(");
      printClass(cl);
      print(") in.readObject(");
      printClass(cl);
      println(".class);");
    }
  }

  protected void printMarshalType(Class cl, String var)
    throws IOException
  {
    String name = cl.getName();

    if (cl.equals(void.class)) {
      println("out.writeNull();");
    }
    else if (cl.equals(boolean.class)) {
      println("out.writeBoolean(" + var + ");");
    }
    else if (cl.equals(int.class) ||
             cl.equals(short.class) ||
             cl.equals(char.class) ||
             cl.equals(byte.class)) {
      println("out.writeInt(" + var + ");");
    }
    else if (cl.equals(long.class)) {
      println("out.writeLong(" + var + ");");
    }
    else if (cl.equals(double.class) || cl.equals(float.class)) {
      println("out.writeDouble(" + var + ");");
    }
    else if (cl.equals(String.class)) {
      println("out.writeString(" + var + ");");
    }
    else if (cl.equals(java.util.Date.class)) {
      println("out.writeUTCDate(" + var + " == null ? 0 : " + var + ".getTime());");
    }
    else if (org.w3c.dom.Node.class.isAssignableFrom(cl)) {
      println("out.writeXml(" + var + ");");
    }
    else if (cl.equals(byte[].class)) {
      println("out.writeBytes(" + var + ");");
    }
    else {
      println("out.writeObject(" + var + ");");
    }
  }

  /**
   * Returns true if the class needs serialization.
   *
   * @param cl the class to test.
   *
   * @return true if the class needs serialization
   */
  boolean needsSerialization(Class cl)
  {
    if (cl.isPrimitive())
      return false;
    else
      return immutableClasses.get(cl) < 0;
  }

  public void printClass(Class cl)
    throws IOException
  {
    if (! cl.isArray())
      print(cl.getName());
    else {
      printClass(cl.getComponentType());
      print("[]");
    }
  }

  protected void printNewArray(Class cl)
    throws IOException
  {
    if (! cl.isArray()) {
      print(cl.getName());
      print("[length]");
    }
    else {
      printNewArray(cl.getComponentType());
      print("[]");
    }
  }

  static {
    immutableClasses = new IntMap();
    immutableClasses.put(String.class, 1);
    immutableClasses.put(Byte.class, 1);
    immutableClasses.put(Character.class, 1);
    immutableClasses.put(Short.class, 1);
    immutableClasses.put(Integer.class, 1);
    immutableClasses.put(Long.class, 1);
    immutableClasses.put(Float.class, 1);
    immutableClasses.put(Double.class, 1);
    immutableClasses.put(Class.class, 1);
  }
}
TOP

Related Classes of com.caucho.ejb.hessian.MarshalGenerator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.