1 14 15 package com.sun.facelets.compiler; 16 17 import java.util.ArrayList ; 18 import java.util.List ; 19 import java.util.Stack ; 20 import java.util.logging.Level ; 21 import java.util.logging.Logger ; 22 23 import com.sun.facelets.FaceletHandler; 24 import com.sun.facelets.tag.Tag; 25 import com.sun.facelets.tag.TagAttribute; 26 import com.sun.facelets.tag.TagAttributeException; 27 import com.sun.facelets.tag.TagAttributes; 28 import com.sun.facelets.tag.TagDecorator; 29 import com.sun.facelets.tag.TagException; 30 import com.sun.facelets.tag.TagLibrary; 31 import com.sun.facelets.tag.ui.ComponentRefHandler; 32 import com.sun.facelets.tag.ui.CompositionHandler; 33 import com.sun.facelets.tag.ui.UILibrary; 34 35 44 final class CompilationManager { 45 46 private final static Logger log = Logger.getLogger("facelets.compiler"); 47 48 private final Compiler compiler; 49 50 private final TagLibrary tagLibrary; 51 52 private final TagDecorator tagDecorator; 53 54 private final NamespaceManager namespaceManager; 55 56 private final Stack units; 57 58 private int tagId; 59 60 private boolean finished; 61 62 private final String alias; 63 64 public CompilationManager(String alias, Compiler compiler) { 65 66 this.alias = alias; 68 69 this.compiler = compiler; 71 this.tagDecorator = compiler.createTagDecorator(); 72 this.tagLibrary = compiler.createTagLibrary(); 73 74 this.namespaceManager = new NamespaceManager(); 76 77 this.tagId = 0; 79 80 this.finished = false; 82 83 this.units = new Stack (); 85 this.units.push(new CompilationUnit()); 86 } 87 88 public void writeInstruction(String value) { 89 if (this.finished) { 90 return; 91 } 92 93 if (value.length() == 0) { 95 return; 96 } 97 98 TextUnit unit; 99 if (this.currentUnit() instanceof TextUnit) { 100 unit = (TextUnit) this.currentUnit(); 101 } else { 102 unit = new TextUnit(this.alias); 103 this.startUnit(unit); 104 } 105 unit.writeInstruction(value); 106 } 107 108 public void writeText(String value) { 109 110 if (this.finished) { 111 return; 112 } 113 114 if (value.length() == 0) { 116 return; 117 } 118 119 TextUnit unit; 120 if (this.currentUnit() instanceof TextUnit) { 121 unit = (TextUnit) this.currentUnit(); 122 } else { 123 unit = new TextUnit(this.alias); 124 this.startUnit(unit); 125 } 126 unit.write(value); 127 } 128 129 public void writeComment(String text) { 130 if (this.compiler.isTrimmingComments()) 131 return; 132 133 if (this.finished) { 134 return; 135 } 136 137 if (text.length() == 0) { 139 return; 140 } 141 142 TextUnit unit; 143 if (this.currentUnit() instanceof TextUnit) { 144 unit = (TextUnit) this.currentUnit(); 145 } else { 146 unit = new TextUnit(this.alias); 147 this.startUnit(unit); 148 } 149 150 unit.writeComment(text); 151 } 152 153 public void writeWhitespace(String text) { 154 if (!this.compiler.isTrimmingWhitespace()) { 155 this.writeText(text); 156 } 157 } 158 159 private String nextTagId() { 160 return Integer.toHexString(Math.abs(this.alias.hashCode() ^ 13 * this.tagId++)); 161 } 162 163 public void pushTag(Tag orig) { 164 165 if (this.finished) { 166 return; 167 } 168 169 if (log.isLoggable(Level.FINE)) { 170 log.fine("Tag Pushed: " + orig); 171 } 172 173 Tag t = this.tagDecorator.decorate(orig); 174 String [] qname = this.determineQName(t); 175 t = this.trimAttributes(t); 176 177 boolean handled = false; 178 179 if (isTrimmed(qname[0], qname[1])) { 180 log.fine("Composition Found, Popping Parent Tags"); 181 this.units.clear(); 182 NamespaceUnit nsUnit = this.namespaceManager 183 .toNamespaceUnit(this.tagLibrary); 184 this.units.push(nsUnit); 185 this.startUnit(new TrimmedTagUnit(this.tagLibrary, qname[0], qname[1], t, this 186 .nextTagId())); 187 log.fine("New Namespace and [Trimmed] TagUnit pushed"); 188 } else if (isRemove(qname[0], qname[1])) { 189 this.units.push(new RemoveUnit()); 190 } else if (this.tagLibrary.containsTagHandler(qname[0], qname[1])) { 191 this.startUnit(new TagUnit(this.tagLibrary, qname[0], qname[1], t, this.nextTagId())); 192 } else if (this.tagLibrary.containsNamespace(qname[0])) { 193 throw new TagException(orig, "Tag Library supports namespace: "+qname[0]+", but no tag was defined for name: "+qname[1]); 194 } else { 195 TextUnit unit; 196 if (this.currentUnit() instanceof TextUnit) { 197 unit = (TextUnit) this.currentUnit(); 198 } else { 199 unit = new TextUnit(this.alias); 200 this.startUnit(unit); 201 } 202 unit.startTag(t); 203 } 204 } 205 206 public void popTag() { 207 208 if (this.finished) { 209 return; 210 } 211 212 CompilationUnit unit = this.currentUnit(); 213 214 if (unit instanceof TextUnit) { 215 TextUnit t = (TextUnit) unit; 216 if (t.isClosed()) { 217 this.finishUnit(); 218 } else { 219 t.endTag(); 220 return; 221 } 222 } 223 224 unit = this.currentUnit(); 225 if (unit instanceof TagUnit) { 226 TagUnit t = (TagUnit) unit; 227 if (t instanceof TrimmedTagUnit) { 228 this.finished = true; 229 return; 230 } 231 } 232 233 this.finishUnit(); 234 } 235 236 public void popNamespace(String ns) { 237 this.namespaceManager.popNamespace(ns); 238 if (this.currentUnit() instanceof NamespaceUnit) { 239 this.finishUnit(); 240 } 241 } 242 243 public void pushNamespace(String prefix, String uri) { 244 245 if (log.isLoggable(Level.FINE)) { 246 log.fine("Namespace Pushed " + prefix + ": " + uri); 247 } 248 249 this.namespaceManager.pushNamespace(prefix, uri); 250 NamespaceUnit unit; 251 if (this.currentUnit() instanceof NamespaceUnit) { 252 unit = (NamespaceUnit) this.currentUnit(); 253 } else { 254 unit = new NamespaceUnit(this.tagLibrary); 255 this.startUnit(unit); 256 } 257 unit.setNamespace(prefix, uri); 258 } 259 260 public FaceletHandler createFaceletHandler() { 261 return ((CompilationUnit) this.units.get(0)).createFaceletHandler(); 262 } 263 264 private CompilationUnit currentUnit() { 265 if (!this.units.isEmpty()) { 266 return (CompilationUnit) this.units.peek(); 267 } 268 return null; 269 } 270 271 private void finishUnit() { 272 Object obj = this.units.pop(); 273 274 if (log.isLoggable(Level.FINE)) { 275 log.fine("Finished Unit: " + obj); 276 } 277 } 278 279 private CompilationUnit searchUnits(Class type) { 280 CompilationUnit unit = null; 281 int i = this.units.size(); 282 while (unit == null && --i >= 0) { 283 if (type.isAssignableFrom(this.units.get(i).getClass())) { 284 unit = (CompilationUnit) this.units.get(i); 285 } 286 } 287 return unit; 288 } 289 290 private void startUnit(CompilationUnit unit) { 291 292 if (log.isLoggable(Level.FINE)) { 293 log.fine("Starting Unit: " + unit + " and adding it to parent: " 294 + this.currentUnit()); 295 } 296 297 this.currentUnit().addChild(unit); 298 this.units.push(unit); 299 } 300 301 private Tag trimAttributes(Tag tag) { 302 Tag t = this.trimJSFCAttribute(tag); 303 t = this.trimNSAttributes(t); 304 return t; 305 } 306 307 protected static boolean isRemove(String ns, String name) { 308 return UILibrary.Namespace.equals(ns) 309 && "remove".equals(name); 310 } 311 312 protected static boolean isTrimmed(String ns, String name) { 313 return UILibrary.Namespace.equals(ns) 314 && (CompositionHandler.Name.equals(name) || ComponentRefHandler.Name.equals(name)); 315 } 316 317 private String [] determineQName(Tag tag) { 318 TagAttribute attr = tag.getAttributes().get("jsfc"); 319 if (attr != null) { 320 if (log.isLoggable(Level.FINE)) { 321 log.fine(attr + " JSF Facelet Compile Directive Found"); 322 } 323 String value = attr.getValue(); 324 String namespace, localName; 325 int c = value.indexOf(':'); 326 if (c == -1) { 327 namespace = this.namespaceManager.getNamespace(""); 328 localName = value; 329 } else { 330 String prefix = value.substring(0, c); 331 namespace = this.namespaceManager.getNamespace(prefix); 332 if (namespace == null) { 333 throw new TagAttributeException(tag, attr, 334 "No Namespace matched for: " + prefix); 335 } 336 localName = value.substring(c + 1); 337 } 338 return new String [] { namespace, localName }; 339 } else { 340 return new String [] { tag.getNamespace(), tag.getLocalName() }; 341 } 342 } 343 344 private Tag trimJSFCAttribute(Tag tag) { 345 TagAttribute attr = tag.getAttributes().get("jsfc"); 346 if (attr != null) { 347 TagAttribute[] oa = tag.getAttributes().getAll(); 348 TagAttribute[] na = new TagAttribute[oa.length - 1]; 349 int p = 0; 350 for (int i = 0; i < oa.length; i++) { 351 if (!"jsfc".equals(oa[i].getLocalName())) { 352 na[p++] = oa[i]; 353 } 354 } 355 return new Tag(tag, new TagAttributes(na)); 356 } 357 return tag; 358 } 359 360 private Tag trimNSAttributes(Tag tag) { 361 TagAttribute[] attr = tag.getAttributes().getAll(); 362 int remove = 0; 363 for (int i = 0; i < attr.length; i++) { 364 if (attr[i].getQName().startsWith("xmlns") 365 && this.tagLibrary.containsNamespace(attr[i].getValue())) { 366 remove |= 1 << i; 367 if (log.isLoggable(Level.FINE)) { 368 log.fine(attr[i] + " Namespace Bound to TagLibrary"); 369 } 370 } 371 } 372 if (remove == 0) { 373 return tag; 374 } else { 375 List attrList = new ArrayList (attr.length); 376 int p = 0; 377 for (int i = 0; i < attr.length; i++) { 378 p = 1 << i; 379 if ((p & remove) == p) { 380 continue; 381 } 382 attrList.add(attr[i]); 383 } 384 attr = (TagAttribute[]) attrList.toArray(new TagAttribute[attrList 385 .size()]); 386 return new Tag(tag.getLocation(), tag.getNamespace(), tag 387 .getLocalName(), tag.getQName(), new TagAttributes(attr)); 388 } 389 } 390 } 391 | Popular Tags |