alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Glassfish example source code file (Descriptor.java)

This example Glassfish source code file (Descriptor.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Glassfish tags/keywords

b, c, d, i, insnerror, insnerror, j, l, l, noi18n, noi18n, string, string, util, z

The Glassfish Descriptor.java source code

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package com.sun.jdo.api.persistence.enhancer.classfile;

import java.util.Stack;
import java.util.Map;

//@olsen: subst: Hashtable -> Map, HashMap


/**
 * A collection of static methods which manipulate type descriptors
 */

public class Descriptor implements VMConstants {
  /** 
   * Return the number of words of arguments to the method 
   * based on the method signature
   */
  public static int countMethodArgWords(String sig) {
    if (sig.charAt(0) != '(')
        throw new InsnError ("not a method signature");//NOI18N
    int count = 0;
    for (int idx = 1; sig.charAt(idx) != ')'; idx++) {
      switch (sig.charAt(idx)) {
      case 'B': /* byte */
      case 'C': /* char */
      case 'S': /* short */
      case 'I': /* int */
      case 'F': /* float */
      case 'Z': /* boolean */
	count++;
	break;
      case 'J': /* long */
      case 'D': /* double */
	count += 2;
	break;
      case 'L':
	count++;
	idx = sig.indexOf(';', idx);
	break;
      case '[':
	count++;
	while (sig.charAt(idx) == '[' || sig.charAt(idx) == ']')
	  idx++;
	if (sig.charAt(idx) == 'L')
	  idx = sig.indexOf(';', idx);
	/* else, let idx++ at loop iteration skip primitive descriptor */
	break;
      default:
          throw new InsnError("missing case");//NOI18N
      }
    }
    return count;
  }

  /** 
   * Return the number of words of return value for the method
   * based on the method signature
   */
  public static int countMethodReturnWords(String sig) {
    int idx = sig.lastIndexOf(')') + 1;
    if (idx == 0)
        throw new InsnError ("not a method signature");//NOI18N
    switch (sig.charAt(idx)) {
    case 'J': /* long */
    case 'D': /* double */
      return 2;
    case 'B': /* byte */
    case 'C': /* char */
    case 'S': /* short */
    case 'I': /* int */
    case 'F': /* float */
    case 'Z': /* boolean */
    case 'L': /* object */
    case '[': /* array */
      return 1;
    case 'V': /* void */
      return 0;
    default:
        throw new InsnError("missing case");//NOI18N
    }
  }

  /**
   * Return the stack descriptor for the result of a method
   * invocation.  Void return values yield "V".
   */
  public static String extractResultSig(String methodSig) {
    return methodSig.substring(methodSig.indexOf(')')+1);
  }

  /**
   * Return the stack descriptor for the arguments to a method
   * invocation (not including any "this" argument)
   */
  public static String extractArgSig(String methodSig) {
    return methodSig.substring(1, methodSig.indexOf(')'));
  }

  /**
   * Return the reversed stack descriptor for the arguments to a method
   * invocation (not including any "this" argument).  The top of stack
   * element will be first.
   */
  public static String extractReversedArgSig(String methodSig) {
    StringBuffer buf = new StringBuffer();;
    reverseArgSig(buf, methodSig, 1);
    return buf.toString();
  }

  /**
   * Given a StringBuffer, a method descriptor, and a index to the 
   * start of an argument descriptor, append the arguments to the
   * string buffer in reverse order.
   */
  private static void reverseArgSig(StringBuffer buf, String methodSig, 
				    int idx) {
    char c = methodSig.charAt(idx);
    if (c == ')')
      return;
    int startIdx = idx;

    switch(c) {
    case 'B':
    case 'C':
    case 'S':
    case 'I':
    case 'F':
    case 'J':
    case 'D':
    case 'Z':
      idx = idx+1;
      break;
    case '[':
      while (methodSig.charAt(idx) == '[' || methodSig.charAt(idx) == ']')
	idx++;
      if (methodSig.charAt(idx) != 'L') {
	idx++;
	break;
      }
      /* fall through */
    case 'L':
      idx = methodSig.indexOf(';', idx) + 1;
      break;
    default:
        throw new InsnError("bad signature char");//NOI18N
    }

    reverseArgSig(buf, methodSig, idx);
    while (startIdx < idx)
      buf.append(methodSig.charAt(startIdx++));
  }

  /** 
   * Return the number of words of a field based on its signature.
   */
  //@olsen: added method
  public static int countFieldWords(String sig) {
    if (sig == null || sig.length() < 1)
        throw new InsnError ("not a field signature");//NOI18N
    switch (sig.charAt(0)) {
    case 'J': /* long */
    case 'D': /* double */
      return 2;
    case 'B': /* byte */
    case 'C': /* char */
    case 'S': /* short */
    case 'I': /* int */
    case 'F': /* float */
    case 'Z': /* boolean */
    case 'L': /* object */
    case '[': /* array */
      return 1;
    default:
        throw new InsnError("missing case");//NOI18N
    }
  }

  /**
   * Return the element type for the first char in the type descriptor string.
   */
  //@olsen: added method
  public static int elementType(String sig) {
    if (sig == null || sig.length() < 1)
        throw new InsnError ("not a value signature");//NOI18N
    switch(sig.charAt(0)) {
      case 'B':
        return T_BOOLEAN;
      case 'C':
	return T_CHAR;
      case 'Z':
	return T_BYTE;
      case 'S':
	return T_SHORT;
      case 'I':
	return T_INT;
      case 'J':
	return T_LONG;
      case 'F':
	return T_FLOAT;
      case 'D':
	return T_DOUBLE;
      case '[':
	return TC_OBJECT;
      case 'L':
	return TC_OBJECT;
      default:
          throw new InsnError("bad signature char");//NOI18N
    }
  }

  /**
   * Return the element type descriptor char for the element type.
   * The element type must be one of the T_ or TC_OBJECT.
   */
  public static String elementSig(int valueType) {
    switch(valueType) {
    case T_BYTE:
        return "B";//NOI18N
    case T_CHAR:
        return "C";//NOI18N
    case T_BOOLEAN:
        return "Z";//NOI18N
    case T_SHORT:
        return "S";//NOI18N
    case T_INT:
        return "I";//NOI18N
    case T_LONG:
        return "J";//NOI18N
    case T_FLOAT:
        return "F";//NOI18N
    case T_DOUBLE:
        return "D";//NOI18N
    case TC_OBJECT:
        return "Ljava/lang/Object;";//NOI18N
    default:
        throw new InsnError("bad element type");//NOI18N
    }
  }

  /**
   * Return the number of stack words required for a value of the specified
   * type on the operand stack.
   */
  public static int elementSize(int elementType) {
    switch(elementType) {
    case T_LONG:
    case T_DOUBLE:
    case T_TWOWORD:
      return 2;
    default:
      return 1;
    }
  }

  /**
   * stackSig is a signature for a list of types on the JVM stack with the
   * last type in the signature intended to be on the top of JVM stack.
   * For each type in the signature, pushes an Integer objects identifying
   * the types on top of the input Stack object.
   */
  public static void computeStackTypes(String stackSig, Stack stack) {
    for (int idx = 0; idx < stackSig.length(); idx++) {
      int tp = 0;
      switch(stackSig.charAt(idx)) {
      case 'B':
      case 'C':
      case 'Z':
      case 'S':
      case 'I':
	tp = T_INT;
	break;
      case 'F':
	tp = T_FLOAT;
	break;
      case 'J':
	tp = T_LONG;
	break;
      case 'D':
	tp = T_DOUBLE;
	break;
      case '?':
	tp = T_UNKNOWN;
	break;
      case 'W':
	tp = T_WORD;
	break;
      case 'X':
	tp = T_TWOWORD;
	break;
      case 'A':
	/* This isn't a real type, but any object refrence */
	tp = TC_OBJECT;
	break;
      case '[':
	tp = TC_OBJECT;
	while (stackSig.charAt(idx) == '[' || stackSig.charAt(idx) == ']')
	  idx++;
	if (stackSig.charAt(idx) != 'L')
	    break;
	/* fall through */
      case 'L':
	tp = TC_OBJECT;
	idx = stackSig.indexOf(';', idx);
	break;
      default:
          throw new InsnError("bad signature char");//NOI18N
      }
      stack.push(new Integer(tp));
    }
  }

  /**
   * stackSig is a signature for the types on the stack with the last
   * type in the signature on the top of stack.  idx is the index of
   * the start of a valid signature type element.  Return the index of
   * the next element (which may be past the end of the string).
   */
  public static int nextSigElement(String stackSig, int idx) {
    switch(stackSig.charAt(idx)) {
    case 'B':
    case 'C':
    case 'Z':
    case 'S':
    case 'I':
    case 'F':
    case 'J':
    case 'D':
      break;
    case '[':
      while (stackSig.charAt(idx) == '[' || stackSig.charAt(idx) == ']')
	idx++;
      if (stackSig.charAt(idx) != 'L')
	break;
      /* fall through */
    case 'L':
      idx = stackSig.indexOf(';', idx);
      break;
    default:
        throw new InsnError("bad signature char");//NOI18N
    }

    idx++;
    return idx;
  }

  /**
   * classTranslations contains a set of mappings of class names.
   * For any types within the input signature which appear as keys
   * in the translation table, change the signature to replace the
   * original type with the translation.  Return a string containing
   * the original signature with any translations applied.
   */
  public static String remapTypes(String sig, Map classTranslations) {
    /* Defer allocation of the string buffer until it's needed */
    StringBuffer buf = null;

    for (int idx = 0; idx < sig.length(); idx++) {
      char c;
      switch(c = sig.charAt(idx)) {
      case '[':
	/* An array - skip through the [] pairs, copying to buf if not null */
	while ((c = sig.charAt(idx)) == '[' || c == ']') {
	  idx++;
	  if (buf != null)
	    buf.append(c);
	}

	/* If the next char isnt 'L', the next char is a simple type and
	   will be handled by the default 1 char translation */
	if (sig.charAt(idx) != 'L')
	  break;
	/* fall through to type name translation */
      case 'L':
	/* This is a type name */
	idx++;
	int endIdx = sig.indexOf(';', idx);
	String typeName = sig.substring(idx, endIdx);
	String mapTo = (String) classTranslations.get(typeName);
	if (mapTo != null) {
	  /* This type needs translation - allocate the string buffer
	     now if needed and copy in all up to this type name. */
	  if (buf == null) {
	    buf = new StringBuffer(sig.length() + 20);
	    buf.append(sig.substring(0,idx-1));
	  }
	  typeName = mapTo;
	}

	if (buf != null) {
	  buf.append('L');
	  buf.append(typeName);
	}
	idx = endIdx;
	c = ';';
	break;
      }

      if (buf != null)
	buf.append(c);
    }
    return (buf == null) ? sig : (buf.toString());
  }

  /**
   * classTranslations contains a set of mappings of class names.
   * Translate the class name (which may be an array class) according
   * to the entries in the translation table.
   * Return either the original string if no translation applies or
   * else the translated string.
   */
  public static String translateClass(
	String cls, Map classTranslations) {
    if (cls.charAt(0) == '[')
      return remapTypes(cls, classTranslations);
    else {
      String mapTo = (String) classTranslations.get(cls);
      if (mapTo != null)
	return mapTo;
      return cls;
    }
  }

  /**
   * Translates a VM type field signature into a  user-format signature.
   * Just a front for the two argument overload of this method.
   */
  public static String userFieldSig(String vmSig) {
    return userFieldSig(vmSig, 0);
  }

  /**
   * Translates a VM type field signature into a  user-format signature.
   */
  public static String userFieldSig(String vmSig, int idx) {
      String sigElement = "";//NOI18N
    int arrayDims = 0;
    boolean moreSig = true;
    while (moreSig) {
      moreSig = false;
      char c = vmSig.charAt(idx);
      switch (c) {
      case 'B':
          sigElement = "byte";//NOI18N
	break;
      case 'C':
          sigElement = "char";//NOI18N
	break;
      case 'Z':
          sigElement = "boolean";//NOI18N
	break;
      case 'S':
          sigElement = "short";//NOI18N
	break;
      case 'I':
          sigElement = "int";//NOI18N
	break;
      case 'F':
          sigElement = "float";//NOI18N
	break;
      case 'J':
          sigElement = "long";//NOI18N
	break;
      case 'D':
          sigElement = "double";//NOI18N
	break;
      case 'V':
	/* void isn't really valid as a field signature but this method
	   might be useful in implementing method signature conversion and
	   void is a valid return type. */
          sigElement = "void";//NOI18N
	break;
      case '[':
	idx++;
	arrayDims++;
	moreSig = true;
	break;
      case 'L':
	int nextIdx = vmSig.indexOf(';', idx);
	sigElement = vmSig.substring(idx+1,nextIdx).replace('/','.');
	break;
      default:
          throw new InsnError("bad signature char");//NOI18N
      }
    }

    /* If a non-array type, we already have the answer */
    if (arrayDims == 0)
      return sigElement;

    /* array types need a little more work */
    StringBuffer buf = new StringBuffer(sigElement.length() + 2 * arrayDims);
    buf.append(sigElement);
    while (arrayDims-- > 0) 
        buf.append("[]");//NOI18N

    return buf.toString();
  }

  /**
   * Produce a user consumable representation of a method argument list
   * from the method signature.  The return value is ignored.
   */
  public static String userMethodArgs(String methodSig) {
    /* This better be a method signature */
    if (methodSig.charAt(0) != '(')
        throw new InsnError("Invalid method signature");//NOI18N

    StringBuffer buf = new StringBuffer();

    buf.append('(');

    int idx = 1;
    boolean firstArg = true;
    while (methodSig.charAt(idx) != ')') {
      if (firstArg)
	firstArg = false;
      else
          buf.append(", ");//NOI18N
	
      buf.append(userFieldSig(methodSig, idx));
      idx = nextSigElement(methodSig, idx);
    }

    buf.append(')');
    return buf.toString();
  }

}

Other Glassfish examples (source code examples)

Here is a short list of links related to this Glassfish Descriptor.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.