1 23 24 package org.objectweb.fractal.adl.xml; 25 26 import org.objectweb.fractal.adl.NodeClassLoader; 27 28 import org.objectweb.asm.Type; 29 import org.objectweb.asm.ClassWriter; 30 import org.objectweb.asm.CodeVisitor; 31 import org.objectweb.asm.Label; 32 33 import java.util.Map ; 34 import java.util.HashMap ; 35 import java.util.Set ; 36 import java.util.HashSet ; 37 import java.lang.reflect.Method ; 38 39 42 43 class XMLNodeClassLoader extends NodeClassLoader { 44 45 49 53 54 private Map astItfs; 55 56 60 64 65 private Map astNodes; 66 67 71 72 private Map xmlElements; 73 74 78 79 private Map astAttributes; 80 81 85 86 private Map xmlAttributes; 87 88 92 public XMLNodeClassLoader (final ClassLoader parent) { 93 super(parent); 94 astItfs = new HashMap (); 95 astNodes = new HashMap (); 96 xmlElements = new HashMap (); 97 astAttributes = new HashMap (); 98 xmlAttributes = new HashMap (); 99 } 100 101 105 void addASTNodeInterface (final String astNode, final String itf) { 106 Set s = (Set )astItfs.get(astNode); 107 if (s == null) { 108 s = new HashSet (); 109 astItfs.put(astNode, s); 110 } 111 s.add(itf.replace('.', '/')); 112 } 113 114 void addASTNodeMapping (final String astName, final String xmlName) { 115 xmlElements.put(astName, xmlName); 116 astNodes.put(xmlName, astName); 117 } 118 119 void addASTAttributeMapping (final String astName, final String xmlName) { 120 xmlAttributes.put(astName, xmlName.substring(xmlName.indexOf('.') + 1)); 121 astAttributes.put(xmlName, astName.substring(astName.indexOf('.') + 1)); 122 } 123 124 String getASTName (final String xmlElement) { 125 String astName = (String )astNodes.get(xmlElement); 126 return astName == null ? xmlElement : astName; 127 } 128 129 String getXMLElement (final String astNode) { 130 String xmlElement = (String )xmlElements.get(astNode); 131 return xmlElement == null ? astNode : xmlElement; 132 } 133 134 String getASTAttribute (final String xmlNode, final String xmlAttr) { 135 String astAttribute = (String )astAttributes.get(xmlNode + "." + xmlAttr); 136 return astAttribute == null ? xmlAttr : astAttribute; 137 } 138 139 String getXMLAttribute (final String astNode, final String astAttr) { 140 String xmlAttribute = (String )xmlAttributes.get(astNode + "." + astAttr); 141 return xmlAttribute == null ? astAttr : xmlAttribute; 142 } 143 144 String getASTClassName (final String xmlElement) { 145 String astNode = (String )astNodes.get(xmlElement); 146 if (astNode == null) { 147 astNode = xmlElement; 148 } 149 return getASTClass(astNode); 150 } 151 152 156 protected Class findClass (final String name) throws ClassNotFoundException { 157 if (isASTClass(name)) { 158 byte[] b = generateClass(getASTNode(name)); 159 168 return defineClass(name, b); 169 } 170 return super.findClass(name); 171 } 172 173 177 private byte[] generateClass (final String astNodeName) 178 throws ClassNotFoundException 179 { 180 String owner = getASTClass(astNodeName).replace('.', '/'); 181 String xmlNode = Type.getInternalName(XMLNode.class); 182 Set itfSet = (Set )astItfs.get(astNodeName); 183 String [] itfs = (String [])itfSet.toArray(new String [itfSet.size()]); 184 185 ClassWriter cw = generateClass(getASTClassName(astNodeName), astNodeName, xmlNode, itfs); 186 187 CodeVisitor xsa = cw.visitMethod( 188 ACC_PUBLIC, 189 "xmlSetAttributes", 190 "(Lorg/xml/sax/Attributes;)V", 191 null, 192 null); 193 194 CodeVisitor xan = cw.visitMethod( 195 ACC_PUBLIC, 196 "xmlAddNode", 197 "(Ljava/lang/String;L" + xmlNode + ";)V", 198 null, 199 null); 200 Label xanEnd = new Label(); 201 202 Set methods = new HashSet (); 203 for (int i = 0; i < itfs.length; ++i) { 204 Method [] meths = loadClass(itfs[i].replace('/', '.')).getMethods(); 205 for (int j = 0; j < meths.length; ++j) { 206 Method meth = meths[j]; 207 String name = meth.getName(); 208 String desc = Type.getMethodDescriptor(meth); 209 210 if (methods.contains(name + desc)) { 211 continue; 212 } 213 methods.add(name + desc); 214 215 if (name.startsWith("get")) { 216 String field = getFieldName(name, 3); 217 218 if (desc.startsWith("()[")) { 219 String fieldDesc = "Ljava/util/List;"; 221 generateAddNodesMethod( 222 xan, owner, name, field, fieldDesc, xanEnd, true); 223 } else { 224 String fieldDesc = desc.substring(2); 226 227 if (fieldDesc.equals("Ljava/lang/String;")) { 228 xsa.visitVarInsn(ALOAD, 0); 231 xsa.visitVarInsn(ALOAD, 1); 232 xsa.visitLdcInsn( 233 getXMLAttribute(astNodeName, getASTName(name, true))); 234 xsa.visitMethodInsn( 235 INVOKEINTERFACE, 236 "org/xml/sax/Attributes", 237 "getValue", 238 "(Ljava/lang/String;)Ljava/lang/String;"); 239 xsa.visitFieldInsn(PUTFIELD, owner, field, fieldDesc); 240 } else { 241 generateAddNodeMethod( 243 xan, owner, name, field, fieldDesc, xanEnd, true); 244 } 245 } 246 } 247 } 248 } 249 250 xsa.visitInsn(RETURN); 251 xsa.visitMaxs(0, 0); 252 253 xan.visitLabel(xanEnd); 254 xan.visitInsn(RETURN); 255 xan.visitMaxs(0, 0); 256 257 return cw.toByteArray(); 258 } 259 260 private void generateAddNodeMethod ( 261 final CodeVisitor cv, 262 final String owner, final String name, 263 final String field, final String fieldDesc, 264 final Label end, final boolean add) 265 { 266 String s = getASTName(name, true); 267 Label l = generateIf(cv, getXMLElement(s)); 268 cv.visitVarInsn(ALOAD, 0); 269 if (add) { 270 cv.visitVarInsn(ALOAD, 2); 271 cv.visitTypeInsn( 272 CHECKCAST, fieldDesc.substring(1, fieldDesc.length() - 1)); 273 } else { 274 cv.visitInsn(ACONST_NULL); 275 } 276 cv.visitFieldInsn(PUTFIELD, owner, field, fieldDesc); 277 cv.visitJumpInsn(GOTO, end); 278 cv.visitLabel(l); 279 } 280 281 private void generateAddNodesMethod ( 282 final CodeVisitor cv, 283 final String owner, final String name, 284 final String field, final String fieldDesc, 285 final Label end, final boolean add) 286 { 287 String s = getASTName(name, false); 288 Label l = generateIf(cv, getXMLElement(s)); 289 cv.visitVarInsn(ALOAD, 0); 290 cv.visitFieldInsn(GETFIELD, owner, field, fieldDesc); 291 cv.visitVarInsn(ALOAD, 2); 292 cv.visitMethodInsn( 293 INVOKEINTERFACE, 294 "java/util/List", 295 add ? "add" : "remove", 296 add ? "(Ljava/lang/Object;)Z" : "(Ljava/lang/Object;)Z"); 297 cv.visitInsn(POP); 298 cv.visitJumpInsn(GOTO, end); 299 cv.visitLabel(l); 300 } 301 302 private Label generateIf (final CodeVisitor cv, final String name) { 303 Label l = new Label(); 304 cv.visitVarInsn(ALOAD, 1); 305 cv.visitLdcInsn(name); 306 cv.visitMethodInsn( 307 INVOKEVIRTUAL, 308 "java/lang/Object", 309 "equals", 310 "(Ljava/lang/Object;)Z"); 311 cv.visitJumpInsn(IFEQ, l); 312 return l; 313 } 314 315 319 private final static String PKG = "org.objectweb.fractal.adl.ast.xml."; 320 321 private static String getASTClass (final String astNodeName) { 322 return PKG + astNodeName + "Impl"; 323 } 324 325 private static boolean isASTClass (final String name) { 326 return name.startsWith(PKG) && name.endsWith("Impl"); 327 } 328 329 private static String getASTNode (final String astClassName) { 330 return astClassName.substring(PKG.length(), astClassName.length() - 4); 331 } 332 } 333 | Popular Tags |