blob: b05715b54e84331ec03d6e29952f637611e54c0c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.tuscany.sca.interfacedef.java.jaxws;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.objectweb.asm.Opcodes;
/**
* @version $Rev$ $Date$
*/
public class CodeGenerationHelper {
/**
* @param type
* @return
*/
public static Class<?> getErasure(Type type) {
if (type instanceof Class) {
return (Class<?>)type;
} else if (type instanceof GenericArrayType) {
GenericArrayType arrayType = (GenericArrayType)type;
Class<?> componentType = getErasure(arrayType.getGenericComponentType());
return Array.newInstance(componentType, 0).getClass();
} else if (type instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType)type;
return getErasure(pType.getRawType());
} else if (type instanceof WildcardType) {
WildcardType wType = (WildcardType)type;
Type[] types = wType.getUpperBounds();
if (types.length == 0) {
return Object.class;
}
return getErasure(types[0]);
} else if (type instanceof TypeVariable) {
TypeVariable<?> var = (TypeVariable<?>)type;
Type[] types = var.getBounds();
if (types.length == 0) {
return Object.class;
}
return getErasure(types[0]);
}
return null;
}
/**
* @param type
* @return
*/
public static String getJAXWSSignature(Type type) {
Class<?> cls = getErasure(type);
if (Collection.class.isAssignableFrom(cls) && (type instanceof ParameterizedType)) {
ParameterizedType pType = (ParameterizedType)type;
Type p = pType.getActualTypeArguments()[0];
StringBuffer sb = new StringBuffer();
sb.append(getSignature(cls));
sb.deleteCharAt(sb.length() - 1); // Remove ;
sb.append('<').append(getSignature(getErasure(p))).append(">;");
return sb.toString();
} else if (Map.class.isAssignableFrom(cls) && (type instanceof ParameterizedType)) {
ParameterizedType pType = (ParameterizedType)type;
Type key = pType.getActualTypeArguments()[0];
Type value = pType.getActualTypeArguments()[1];
StringBuffer sb = new StringBuffer();
sb.append(getSignature(cls));
sb.deleteCharAt(sb.length() - 1); // Remove ;
sb.append('<').append(getSignature(getErasure(key))).append(getSignature(getErasure(value))).append(">;");
return sb.toString();
} else {
return getSignature(cls);
}
}
/**
* @param type
* @return
*/
public static String getSignature(Type type) {
if (!(type instanceof Class)) {
if (type instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType)type;
StringBuffer sb = new StringBuffer();
String rawType = getSignature(pType.getRawType());
sb.append(rawType.substring(0, rawType.length() - 1));
sb.append('<');
for (Type t : pType.getActualTypeArguments()) {
String argType = getSignature(t);
sb.append(argType);
}
sb.append('>');
sb.append(rawType.substring(rawType.length() - 1));
return sb.toString();
}
if (type instanceof TypeVariable) {
return "T" + ((TypeVariable<?>)type).getName() + ";";
}
if (type instanceof GenericArrayType) {
GenericArrayType arrayType = (GenericArrayType)type;
return "[" + getSignature(arrayType.getGenericComponentType());
}
if (type instanceof WildcardType) {
WildcardType wType = (WildcardType)type;
Type[] types = wType.getUpperBounds();
StringBuffer sb = new StringBuffer();
if (types.length == 0 || !(types.length == 1 && types[0] == Object.class)) {
sb.append('+');
for (Type t : types) {
sb.append(getSignature(t));
}
}
types = wType.getLowerBounds();
if (types.length != 0) {
sb.append('-');
for (Type t : wType.getLowerBounds()) {
sb.append(getSignature(t));
}
}
if (sb.length() == 0) {
return "*";
}
return sb.toString();
}
}
Class<?> cls = (Class<?>)type;
return org.objectweb.asm.Type.getDescriptor(cls);
}
/**
* Get the actual type arguments a child class has used to extend a generic base class.
*
* @param baseClass the base class
* @param childClass the child class
* @return a list of the raw classes for the actual type arguments.
*/
public static <T> List<Class<?>> resovleTypeArguments(Class<T> baseClass, Class<? extends T> childClass) {
Map<Type, Type> resolvedTypes = new HashMap<Type, Type>();
Type type = childClass;
// start walking up the inheritance hierarchy until we hit baseClass
while (!getErasure(type).equals(baseClass)) {
if (type instanceof Class) {
// there is no useful information for us in raw types, so just keep going.
type = ((Class<?>)type).getGenericSuperclass();
} else {
ParameterizedType parameterizedType = (ParameterizedType)type;
Class<?> rawType = getErasure(parameterizedType.getRawType());
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
TypeVariable<?>[] typeParameters = rawType.getTypeParameters();
for (int i = 0; i < actualTypeArguments.length; i++) {
resolvedTypes.put(typeParameters[i], actualTypeArguments[i]);
}
if (!rawType.equals(baseClass)) {
type = rawType.getGenericSuperclass();
}
}
}
// finally, for each actual type argument provided to baseClass, determine (if possible)
// the raw class for that type argument.
Type[] actualTypeArguments;
if (type instanceof Class) {
actualTypeArguments = ((Class<?>)type).getTypeParameters();
} else {
actualTypeArguments = ((ParameterizedType)type).getActualTypeArguments();
}
List<Class<?>> typeArgumentsAsClasses = new ArrayList<Class<?>>();
// resolve types by chasing down type variables.
for (Type baseType : actualTypeArguments) {
while (resolvedTypes.containsKey(baseType)) {
baseType = resolvedTypes.get(baseType);
}
typeArgumentsAsClasses.add(getErasure(baseType));
}
return typeArgumentsAsClasses;
}
/*
signatures.put(boolean.class, "Z");
signatures.put(byte.class, "B");
signatures.put(char.class, "C");
signatures.put(short.class, "S");
signatures.put(int.class, "I");
signatures.put(long.class, "J");
signatures.put(float.class, "F");
signatures.put(double.class, "D");
*/
public static int getLoadOPCode(String signature) {
if ("Z".equals(signature) || "B".equals(signature)
|| "C".equals(signature)
|| "S".equals(signature)
|| "I".equals(signature)) {
return Opcodes.ILOAD;
}
if ("J".equals(signature)) {
return Opcodes.LLOAD;
}
if ("F".equals(signature)) {
return Opcodes.FLOAD;
}
if ("D".equals(signature)) {
return Opcodes.DLOAD;
}
return Opcodes.ALOAD;
}
public static int getReturnOPCode(String signature) {
if ("Z".equals(signature) || "B".equals(signature)
|| "C".equals(signature)
|| "S".equals(signature)
|| "I".equals(signature)) {
return Opcodes.IRETURN;
}
if ("J".equals(signature)) {
return Opcodes.LRETURN;
}
if ("F".equals(signature)) {
return Opcodes.FRETURN;
}
if ("D".equals(signature)) {
return Opcodes.DRETURN;
}
if ("V".equals(signature)) {
return Opcodes.RETURN;
}
return Opcodes.ARETURN;
}
/**
* Get the package prefix for generated JAXWS artifacts
* @param cls
* @return
*/
public static String getPackagePrefix(Class<?> cls) {
String name = cls.getName();
int index = name.lastIndexOf('.');
if (index == -1) {
return "jaxws.";
} else {
return name.substring(0, index) + ".jaxws.";
}
}
}