From bdd0a41aed7edf21ec2a65cfa17a86af2ef8c48a Mon Sep 17 00:00:00 2001 From: dims Date: Tue, 17 Jun 2008 00:23:01 +0000 Subject: Move Tuscany from Incubator to top level. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@668359 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/tuscany/sdo/impl/TypeHelperImpl.java | 236 +++++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 sandbox/jboynes/sdoproxy/src/main/java/org/apache/tuscany/sdo/impl/TypeHelperImpl.java (limited to 'sandbox/jboynes/sdoproxy/src/main/java/org/apache/tuscany/sdo/impl/TypeHelperImpl.java') diff --git a/sandbox/jboynes/sdoproxy/src/main/java/org/apache/tuscany/sdo/impl/TypeHelperImpl.java b/sandbox/jboynes/sdoproxy/src/main/java/org/apache/tuscany/sdo/impl/TypeHelperImpl.java new file mode 100644 index 0000000000..bb5c2561d8 --- /dev/null +++ b/sandbox/jboynes/sdoproxy/src/main/java/org/apache/tuscany/sdo/impl/TypeHelperImpl.java @@ -0,0 +1,236 @@ +/** + * + * Copyright 2005 BEA Systems Inc. + * Copyright 2005 International Business Machines Corporation + * + * Licensed 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.sdo.impl; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import javax.xml.namespace.QName; + +import org.osoa.sdo.DuplicateTypeException; +import org.osoa.sdo.Property; +import org.osoa.sdo.Type; +import org.osoa.sdo.helper.TypeHelper; + +/** + * @version $Rev$ $Date$ + */ +public class TypeHelperImpl implements TypeHelper { + private final Map> typesByClass; + private final Map> typesByName; + private final ProxyClassLoader cl; + + @SuppressWarnings({"ClassLoader2Instantiation"}) + public TypeHelperImpl(ClassLoader cl) { + this.cl = new ProxyClassLoader(cl); + typesByName = new HashMap>(); + typesByClass = new HashMap>(); + mapType(DataTypeImpl.BOOLEAN); + mapType(DataTypeImpl.BYTE); + mapType(DataTypeImpl.BYTES); + mapType(DataTypeImpl.CHARACTER); + mapType(DataTypeImpl.DATE); + mapType(DataTypeImpl.DOUBLE); + mapType(DataTypeImpl.FLOAT); + mapType(DataTypeImpl.INT); + mapType(DataTypeImpl.LONG); + mapType(DataTypeImpl.SHORT); + mapType(DataTypeImpl.STRING); + + mapType(DataTypeImpl.BOOLEAN_OBJECT); + mapType(DataTypeImpl.CHARACTER_OBJECT); + } + + private void mapType(Type type) { + typesByName.put(type.getName(), type); + + java.lang.reflect.Type javaType = type.getJavaType(); + if (javaType != null) { + typesByClass.put(javaType, type); + } + } + + public Type define(Class interfaceClass) { + if (typesByClass.containsKey(interfaceClass)) { + throw new DuplicateTypeException(interfaceClass.getName()); + } + + String namespace; + String name; + org.osoa.sdo.annotation.Type ann = interfaceClass.getAnnotation(org.osoa.sdo.annotation.Type.class); + if (ann != null) { + namespace = ann.namespace(); + name = ann.name(); + } else { + namespace = Type.JAVA_NAMESPACE; + name = interfaceClass.getName(); + } + return define(new QName(namespace, name), interfaceClass); + } + + public Type define(QName typeName, Class interfaceClass) { + if (!interfaceClass.isInterface()) { + throw new IllegalArgumentException("Not an interface: " + interfaceClass); + } + + Method[] methods = interfaceClass.getMethods(); + Map props = new LinkedHashMap(methods.length >> 1); + for (Method method : methods) { + String methodName = method.getName(); + Class[] params = method.getParameterTypes(); + String propName; + java.lang.reflect.Type propType; + if (Void.TYPE.equals(method.getReturnType()) && + methodName.startsWith("set") && + methodName.length() > 3 && + params.length == 1) { + propName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4); + propType = params[0]; + } else if (Boolean.TYPE.equals(method.getReturnType()) && + methodName.startsWith("is") && + methodName.length() > 2 && + params.length == 0) { + propName = Character.toLowerCase(methodName.charAt(2)) + methodName.substring(3); + propType = Boolean.TYPE; + } else if (!Void.TYPE.equals(method.getReturnType()) && + methodName.startsWith("get") && + methodName.length() > 3 && + params.length == 0) { + propName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4); + propType = method.getGenericReturnType(); + } else { + throw new IllegalArgumentException("Non-accessor method on interface: " + method); + } + + defineProperty(props, propName, propType); + } + return define(typeName, interfaceClass, new ArrayList(props.values())); + } + + private void defineProperty(Map props, String propName, java.lang.reflect.Type propType) { + Property prop = props.get(propName); + if (prop != null) { + /* TODO should check this + if (!propClass.equals(prop.getType().getInstanceClass())) { + throw new IllegalArgumentException("set/get types do not match for property: " + propName); + } + */ + return; + } + + int index = props.size(); + + if (propType instanceof Class) { + prop = getPropertyFromClass(propName, index, propType); + } else if (propType instanceof ParameterizedType) { + prop = getPropertyFromParameterizedType(propName, index, propType); + } else { + throw new UnsupportedOperationException(); + } + props.put(propName, prop); + } + + private Property getPropertyFromParameterizedType(String propName, int index, java.lang.reflect.Type propType) { + ParameterizedType parameterizedType = (ParameterizedType) propType; + if (List.class.equals(parameterizedType.getRawType())) { + java.lang.reflect.Type actualPropType = parameterizedType.getActualTypeArguments()[0]; + if (!(actualPropType instanceof Class)) { + throw new IllegalArgumentException("Actual type of list property must not be generic: " + propName); + } + Class propClass = (Class) actualPropType; + Type type = getType(propClass); + if (type == null) { + type = define(propClass); + } + return new ListPropertyImpl(propName, type, parameterizedType,index); + } else { + throw new IllegalArgumentException("Invalid generic type: " + parameterizedType); + } + } + + private Property getPropertyFromClass(String propName, int index, java.lang.reflect.Type propType) { + Class propClass = (Class) propType; + if (propClass.isArray() && !byte[].class.equals(propClass)) { + throw new IllegalArgumentException("Property cannot be an array type: " + propName); + } + + Type type = getType(propClass); + if (type == null) { + type = define(propClass); + } + return new PropertyImpl(propName, type, index); + } + + private Type define(QName typeName, Class instanceClass, List properties) { + if (typeName == null) { + throw new IllegalArgumentException("typeName is null"); + } + String namespace = typeName.getNamespaceURI(); + String name = typeName.getLocalPart(); + if (namespace == null || Type.SDO_NAMESPACE.equals(namespace)) { + throw new IllegalArgumentException("Invalid namespace: " + namespace); + } + if (name == null) { + throw new IllegalArgumentException("name is null"); + } + if (Type.JAVA_NAMESPACE.equals(namespace) && !instanceClass.getName().equals(name)) { + throw new IllegalArgumentException("in Java namespace, name must equal instanceClass name"); + } + + SDOInstanceFactory instanceFactory = new SDOInstanceFactory(); + Type type = new TypeImpl(typeName, instanceClass, properties, instanceFactory); + + SDOGenerator gen = new SDOGenerator(instanceClass); + for (Property property : properties) { + gen.addProperty(property); + } + byte[] bytes = gen.toByteArray(); +// dumpClass(typeName.getLocalPart(), bytes); + Class implementationClass = (Class) cl.addProxy(null, bytes); + instanceFactory.setImplementationClass(implementationClass); + + mapType(type); + return type; + } + + public Type getType(Class interfaceClass) { + return (Type) typesByClass.get(interfaceClass); + } + + public Type getType(QName name) { + return typesByName.get(name); + } + + private static void dumpClass(String name, byte[] bytes) { + File file = new File("/tmp/dump/" + name.replace('.', '/') + ".class"); + file.getParentFile().mkdirs(); + try { + FileOutputStream fos = new FileOutputStream(file); + fos.write(bytes); + fos.close(); + } catch (IOException e) { + } + } +} -- cgit v1.2.3