1 package it.imolinfo.jbi4corba.webservice.generator.typedef;
2
3 import it.imolinfo.jbi4corba.Logger;
4 import it.imolinfo.jbi4corba.LoggerFactory;
5 import it.imolinfo.jbi4corba.exception.ClassGenerationException;
6 import it.imolinfo.jbi4corba.webservice.generator.Util;
7 import it.imolinfo.jbi4corba.webservice.generator.bcm.ByteCodeManipulationUtil;
8
9 import java.io.File;
10
11 import javax.xml.bind.annotation.XmlAccessType;
12 import javax.xml.bind.annotation.XmlAccessorType;
13 import javax.xml.bind.annotation.XmlElement;
14 import javax.xml.bind.annotation.XmlTransient;
15
16 import org.objectweb.asm.AnnotationVisitor;
17 import org.objectweb.asm.ClassWriter;
18 import org.objectweb.asm.FieldVisitor;
19 import org.objectweb.asm.Label;
20 import org.objectweb.asm.MethodVisitor;
21 import org.objectweb.asm.Opcodes;
22 import org.objectweb.asm.Type;
23
24 /**
25 * Complex Array TypeDef class generator.
26 *
27 * The class generated is:
28 *
29 * <pre>
30 * {@code
31 *
32 *
33 * @XmlAccessorType(XmlAccessType.FIELD)
34 * public class MyComplexTypeSeq{
35 * @XmlTransient
36 * final static private MyComplexTypeHelper helperClass = MyComplexTypeSeqHelper.class;
37 * @XmlElement(required=true, nillable=false)
38 * MyComplexType[] value;
39 * }
40 * }
41 * </pre>
42 *
43 * @author <a href="mailto:mpiraccini@imolinfo.it">Marco Piraccini</a>
44 */
45 public class ComplexArrayTypeDef extends SimpleTypeDef {
46
47 /**
48 * Class logger
49 */
50 private static final Logger LOG = LoggerFactory
51 .getLogger(ComplexArrayTypeDef.class);
52
53 @SuppressWarnings("unchecked")
54 protected ComplexArrayTypeDef(String className, String helperClassName, Class aliasedClass, String id) {
55 super(className, helperClassName, aliasedClass, id);
56 }
57
58 @SuppressWarnings("unchecked")
59 public void createTypeDefClass(String classesDir) throws ClassGenerationException {
60 // I have to calculate this values (i cannot load the class...doesn't exist yet)
61 String classInternalName = this.getClassName().replace('.','/');
62 String classDescriptor = "L" + classInternalName + ";";
63 String aliasedClassDescriptor = Type.getDescriptor(aliasedClass);
64
65 // helper class
66 Class helperClass = this.getHelperClass(classesDir);
67 String helperDescriptor = Type.getDescriptor(helperClass);
68
69 // Class, Object and jaxb annotations
70 String javaLangClassDescriptor = Type.getDescriptor(Class.class);
71 String javaLangObjectInternalName = Type.getInternalName(java.lang.Object.class);
72 String xmlAccessorTypeDescriptor = Type.getDescriptor(XmlAccessorType.class);
73 String xmlElementDescriptor = Type.getDescriptor(XmlElement.class);
74 String xmlAccessTypeDescriptor = Type.getDescriptor(XmlAccessType.class);
75 String xmlTransientDescriptor = Type.getDescriptor(XmlTransient.class);
76
77 ClassWriter cw = new ClassWriter(true);
78
79 // The class
80 cw.visit(Opcodes.V1_5, ACC_PUBLIC + ACC_SUPER, classInternalName ,null, javaLangObjectInternalName, null);
81
82 // The class XmlType Annotation
83 // The class XmlAccessorType Annotation: @XmlAccessorType(XmlAccessType.FIELD)
84 AnnotationVisitor av = cw.visitAnnotation(xmlAccessorTypeDescriptor, true);
85 //the Annotations was changed for generate WSDL with Union Type
86 av.visitEnum("value", xmlAccessTypeDescriptor, "FIELD");
87 av.visitEnd();
88
89 /*
90 * @XmlTransient
91 * final static private Class helperClass = null; // cannot be inited (null)
92 */
93 /*
94 FieldVisitor fvHelperClass = cw.visitField(ACC_PUBLIC + ACC_STATIC + ACC_FINAL
95 , "helperClass", javaLangClassDescriptor, null, null);
96 AnnotationVisitor avHelper = fvHelperClass.visitAnnotation(xmlTransientDescriptor, true);
97 avHelper.visitEnd();
98 fvHelperClass.visitEnd();
99 */
100
101 /* The field with the XmlElement
102 * For example:
103 * @XmlElement(required=true, nillable=false)
104 * public int value;
105 */
106 FieldVisitor fv = cw.visitField(ACC_PUBLIC, "value", aliasedClassDescriptor, null, null);
107 AnnotationVisitor avValue = fv.visitAnnotation(xmlElementDescriptor, true);
108 avValue.visit("required", true);
109 avValue.visit("nillable", false);
110 avValue.visitEnd();
111 fv.visitEnd();
112
113
114 // Class init. Inits the statoc "helperClass" field.
115 /*
116 MethodVisitor mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
117 mv.visitCode();
118 Label lclinit = new Label();
119 mv.visitLabel(lclinit);
120 mv.visitLineNumber(10, lclinit);
121 mv.visitLdcInsn(Type.getType(helperDescriptor));
122 mv.visitFieldInsn(PUTSTATIC, classInternalName, "helperClass", javaLangClassDescriptor);
123 Label lclinit1 = new Label();
124 mv.visitLabel(lclinit1);
125 mv.visitLineNumber(7, lclinit1);
126 mv.visitInsn(RETURN);
127 mv.visitMaxs(1, 0);
128 mv.visitEnd();
129 */
130
131 ByteCodeManipulationUtil bcmUtil = new ByteCodeManipulationUtil();
132 // SETTER
133 bcmUtil.createSetter(cw, classInternalName, "value", aliasedClassDescriptor);
134
135 // GETTER
136 // bcmUtil.createGetter(cw, classInternalName, "value", aliasedClassDescriptor, false);
137
138
139 // Default constructor
140 MethodVisitor mvinit = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
141 mvinit.visitCode();
142 Label linit = new Label();
143 mvinit.visitLabel(linit);
144 mvinit.visitLineNumber(7, linit);
145 mvinit.visitVarInsn(ALOAD, 0);
146 mvinit.visitMethodInsn(INVOKESPECIAL, javaLangObjectInternalName, "<init>", "()V");
147 mvinit.visitInsn(RETURN);
148 Label linit1 = new Label();
149 mvinit.visitLabel(linit1);
150 mvinit.visitLocalVariable("this", classDescriptor, null, linit, linit1, 0);
151 mvinit.visitMaxs(1, 1);
152 mvinit.visitEnd();
153
154 cw.visitEnd();
155 byte[] bytecode = cw.toByteArray();
156
157 String relativeClassName = getClassRelativeFileName();
158
159 if (LOG.isDebugEnabled()) {
160 LOG.debug("Writing out TypeDef class:" + classesDir + File.separatorChar + relativeClassName);
161 }
162 // Writes out the class
163 Util.saveAsJavaClass(classesDir, relativeClassName, bytecode);
164 }
165
166 public String toString() {
167 return "ComplexArrayTypeDef: " + super.toString();
168 }
169
170
171 // // The same of SimpeTypeDef...probably it make more sense to have only TWO typedef sublclasses
172 // // (inheritance vs wrapper).
173 // @Override
174 // public Object getTypeDefObject(ClassLoader classLoader, Object obj) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SecurityException, NoSuchFieldException {
175 // Class classDefinition = classLoader.loadClass(getClassName());
176 // Object typeDefObject = classDefinition.newInstance();
177 // Field value = typeDefObject.getClass().getField("value");
178 // LOG.info("Trying to set: " + obj + " of object: " + obj + " on object:" + typeDefObject);
179 // // This seems the only way to cast a Object[] to a String[]!!!!!
180 // if (obj.getClass().isArray()) {
181 //
182 // if (LOG.isDebugEnabled()) {
183 // LOG.debug("Input: " + ArrayUtils.toString(obj));
184 // }
185 // Class aliasedClassCorrectCL = Class.forName(this.getAliasedClassName(), false, classLoader);
186 // Object ob = TypeDefUtil.fillArray(obj, null, aliasedClassCorrectCL.getComponentType());
187 // if (LOG.isDebugEnabled()) {
188 // LOG.debug("Returned: " + ArrayUtils.toString(ob));
189 // }
190 // value.set(typeDefObject,ob);
191 //
192 // /*
193 // Vector v = new Vector();
194 // Object[] myarr = (Object[]) obj;
195 // for (int i = 0; i < myarr.length; i++) {
196 // v.add(myarr[i]);
197 // }
198 // Object[] ob = (Object[])Array.newInstance(aliasedClassCorrectCL.getComponentType(), 0);
199 // value.set(typeDefObject,v.toArray(ob));
200 // */
201 //
202 // } else {
203 // value.set(typeDefObject, obj);
204 // }
205 // return typeDefObject;
206 // }
207 //
208 // @Override
209 // public Object getAliasedObject(Object obj) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
210 // Field value = obj.getClass().getField("value");
211 // Object objValue = value.get(obj);
212 // return objValue;
213 // }
214
215
216
217 }