1 9 10 package org.jboss.portal.format.template; 11 12 import java.io.Writer ; 13 import java.util.Iterator ; 14 import java.util.LinkedList ; 15 import java.util.Set ; 16 17 import javassist.CannotCompileException; 18 import javassist.ClassPool; 19 import javassist.CtClass; 20 import javassist.CtConstructor; 21 import javassist.CtField; 22 import javassist.CtMethod; 23 import javassist.CtNewMethod; 24 import javassist.LoaderClassPath; 25 import javassist.Modifier; 26 import javassist.NotFoundException; 27 28 import org.apache.log4j.Logger; 29 import org.dom4j.Document; 30 import org.dom4j.Element; 31 import org.dom4j.Node; 32 import org.dom4j.Text; 33 34 37 public class TemplateBuilder 38 { 39 40 private static final String CONTEXT = Context.class.getName(); 41 private static final String ITERATOR = Iterator .class.getName(); 42 43 private final ClassPool pool; 44 private final Element node; 45 private final int index; 46 private final Logger log; 47 private final Set propertyNames; 48 private CtClass cc; 49 50 public static int classNameCounter = 0; 51 52 public TemplateBuilder(Document doc, Set propertyNames) 53 { 54 this(doc.getRootElement(), propertyNames); 55 } 56 57 public TemplateBuilder(Element node, Set propertyNames) 58 { 59 this(new ClassPool(null), node, propertyNames); 60 pool.appendClassPath(new LoaderClassPath(Thread.currentThread().getContextClassLoader())); 61 } 62 63 public TemplateBuilder(ClassPool pool, Document doc, Set names) 64 { 65 this(pool, doc.getRootElement(), names); 66 } 67 68 public TemplateBuilder(ClassPool pool, Element node, Set names) 69 { 70 this.index = classNameCounter++; 71 this.pool = pool; 72 this.node = node; 73 this.propertyNames = names; 74 this.log = Logger.getLogger(getClass() + "." + index); 75 } 76 77 public CtClass getGeneratedClass() 78 { 79 return cc; 80 } 81 82 public void build() throws BuildException 83 { 84 try 85 { 86 cc = pool.makeClass("org.jboss.nukes.common.template.Generated" + index); 87 cc.setSuperclass(pool.get(Template.class.getName())); 88 cc.setModifiers(Modifier.PUBLIC); 89 90 addConstructor(); 91 implementRender(); 92 } 93 catch(CannotCompileException e) 94 { 95 throw new BuildException("Unexpected error, cannot build template", e); 96 } 97 catch(NotFoundException e) 98 { 99 throw new BuildException("Unexpected error, cannot build template", e); 100 } 101 } 102 103 private void addConstructor() throws CannotCompileException, NotFoundException 104 { 105 CtConstructor ctor = new CtConstructor(new CtClass[]{pool.get(CONTEXT)}, cc); 106 ctor.setBody("{ super($1); }"); 107 cc.addConstructor(ctor); 108 log.debug("Added constructor on template " + cc.getName()); 109 } 110 111 private void implementRender() throws CannotCompileException, NotFoundException 112 { 113 LinkedList stack = new LinkedList (); 114 stack.add(""); 115 StringBuffer buffer = new StringBuffer (); 116 buffer.append("public void render(").append(Context.class.getName()).append(" ctx, ").append(Writer .class.getName()).append(" writer)\n"). 117 append("{\n"). 118 append(" ").append(CONTEXT).append(" ctx_ = $1;\n"); 119 generateRender(stack, buffer, " ", node); 120 buffer.append("}\n"); 121 String code = buffer.toString(); 122 CtMethod method = CtNewMethod.make(code, cc); 123 cc.addMethod(method); 124 CtField gc = new CtField(pool.get(String .class.getName()), "_generated_code", cc); 125 gc.setModifiers(Modifier.PUBLIC | Modifier.STATIC); 126 CtField.Initializer initializer = CtField.Initializer.constant(code); 127 cc.addField(gc, initializer); 128 log.debug("Created render method on template " + cc.getName() + " with body " + code); 129 } 130 131 private void generateRender(LinkedList stack, StringBuffer buffer, String indent, Element node) 132 { 133 buffer.append(indent).append("String s_").append(stack.size()).append(" = null;\n"); 134 for (Iterator i = node.content().iterator();i.hasNext();) 135 { 136 Node item = (Node)i.next(); 137 if (item instanceof Text) 138 { 139 String text = item.getText().trim(); 140 text = org.jboss.portal.common.util.Tools.replace(text, "\n", "\\n"); 141 text = org.jboss.portal.common.util.Tools.replace(text, "\"", "\\\""); 142 buffer.append(indent).append("$2.write(\"").append(text).append("\");\n"); 143 } 144 else if (item instanceof Element) 145 { 146 Element elt = (Element)item; 147 if ("loop".equals(elt.getName())) 148 { 149 String name = elt.attributeValue("name"); 150 String iterator = "it_" + name; 151 String context = "ctx_" + name; 152 buffer.append(indent).append("for (").append(ITERATOR).append(" ").append(iterator).append(" = ").append("ctx_").append(stack.getLast()).append(".childIterator(\"").append(name).append("\");"). 153 append(iterator).append(".hasNext();"). 154 append(")\n"). 155 append(indent).append("{\n"). 156 append(indent).append(" ").append(CONTEXT).append(" ").append(context).append(" = (").append(CONTEXT).append(")").append(iterator).append(".next();\n"); 157 stack.add(name); 158 generateRender(stack, buffer, indent + " ", elt.element("node")); 159 stack.removeLast(); 160 buffer.append(indent).append("}\n"); 161 } 162 else if ("ref".equals(elt.getName())) 163 { 164 String name = elt.attributeValue("name"); 165 int depth = Integer.parseInt(elt.attributeValue("depth")); 166 String target = null; 167 if (depth == 0) 168 { 169 target = propertyNames.contains(name) ? "$0.local" : "ctx_"; 170 } 171 else 172 { 173 target = "ctx_" + (String )stack.get(depth); 174 } 175 if (target != null) 176 { 177 buffer.append(indent).append("s_").append(stack.size()).append(" = (java.lang.String)").append(target).append(".get(\"").append(name).append("\");\n"). 178 append(indent).append("if (s_").append(stack.size()).append(" != null)\n"). 179 append(indent).append("{\n"). 180 append(indent).append(" $2.write(s_").append(stack.size()).append(");\n"). 181 append(indent).append("}\n"). 182 append(indent).append("else if (log.isDebugEnabled())\n"). 183 append(indent).append("{\n"). 184 append(indent).append(" log.debug(\"field ").append(name).append(" is null\");\n"). 185 append(indent).append("}\n"); 186 } 187 else 188 { 189 } 191 } 192 } 193 } 194 } 195 196 } 197 | Popular Tags |