View Javadoc

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 }