1 16 package org.apache.cocoon.components.language.markup; 17 18 import org.apache.avalon.framework.activity.Disposable; 19 import org.apache.avalon.framework.configuration.Configurable; 20 import org.apache.avalon.framework.configuration.Configuration; 21 import org.apache.avalon.framework.configuration.ConfigurationException; 22 import org.apache.avalon.framework.logger.AbstractLogEnabled; 23 import org.apache.avalon.framework.parameters.Parameters; 24 import org.apache.avalon.framework.service.ServiceException; 25 import org.apache.avalon.framework.service.ServiceManager; 26 import org.apache.avalon.framework.service.Serviceable; 27 28 import org.apache.avalon.excalibur.pool.Recyclable; 29 import org.apache.excalibur.source.Source; 30 import org.apache.excalibur.source.SourceException; 31 import org.apache.excalibur.source.SourceResolver; 32 33 import org.apache.cocoon.ProcessingException; 34 import org.apache.cocoon.xml.AbstractXMLPipe; 35 import org.apache.cocoon.components.language.programming.ProgrammingLanguage; 36 import org.apache.cocoon.components.source.SourceUtil; 37 import org.apache.excalibur.store.Store; 38 import org.apache.cocoon.util.HashMap; 39 40 import org.xml.sax.Attributes ; 41 import org.xml.sax.SAXException ; 42 43 import java.io.IOException ; 44 import java.net.MalformedURLException ; 45 import java.util.ArrayList ; 46 import java.util.Iterator ; 47 import java.util.LinkedList ; 48 import java.util.List ; 49 import java.util.Map ; 50 51 61 public abstract class AbstractMarkupLanguage 62 extends AbstractLogEnabled 63 implements MarkupLanguage, Serviceable, Configurable, Recyclable, Disposable 64 { 65 69 public static final String ATTR_INTERPOLATION = "attr-interpolation"; 70 71 75 public static final String TEXT_INTERPOLATION = "text-interpolation"; 76 77 78 private static final String FILE = "file:"; 79 80 81 private static final String CACHE_PREFIX = "logicsheet:"; 82 83 84 protected String name; 85 86 87 protected HashMap languages; 88 89 90 protected Store logicsheetCache; 91 92 93 private String uri; 94 95 96 private String prefix; 97 98 99 private boolean attrInterpolation; 100 101 102 private boolean textInterpolation; 103 104 105 protected ServiceManager manager; 106 107 108 private SourceResolver resolver; 109 110 111 115 private final LinkedList logicSheetList = new LinkedList (); 116 117 118 119 public AbstractMarkupLanguage() { 120 this.languages = new HashMap(); 122 } 123 124 131 public void configure(Configuration conf) throws ConfigurationException { 132 try { 133 this.name = conf.getAttribute("name"); 134 135 Parameters params = Parameters.fromConfiguration(conf); 139 this.uri = params.getParameter("uri"); 140 this.prefix = params.getParameter("prefix", null); 141 this.attrInterpolation = 142 params.getParameterAsBoolean(ATTR_INTERPOLATION, false); 143 this.textInterpolation = 144 params.getParameterAsBoolean(TEXT_INTERPOLATION, false); 145 146 Configuration[] l = conf.getChildren("target-language"); 148 for (int i = 0; i < l.length; i++) { 149 LanguageDescriptor language = new LanguageDescriptor(); 150 language.setName(l[i].getAttribute("name")); 151 152 Logicsheet logicsheet = createLogicsheet(l[i], false); 154 language.setLogicsheet(logicsheet.getSystemId()); 155 156 Configuration[] n = l[i].getChildren("builtin-logicsheet"); 158 for (int j = 0; j < n.length; j++) { 159 NamedLogicsheet namedLogicsheet = 161 (NamedLogicsheet) createLogicsheet(n[j], true); 162 163 language.addNamedLogicsheet( 164 namedLogicsheet.getURI(), 165 namedLogicsheet.getPrefix(), 166 namedLogicsheet.getSystemId()); 167 } 168 169 this.languages.put(language.getName(), language); 170 } 171 } catch (Exception e) { 172 getLogger().warn("Configuration Error: " + e.getMessage(), e); 173 throw new ConfigurationException("AbstractMarkupLanguage: " 174 + e.getMessage(), e); 175 } 176 } 177 178 181 private Logicsheet createLogicsheet(Configuration configuration, boolean named) 182 throws Exception 183 { 184 Parameters params = Parameters.fromConfiguration(configuration); 185 186 Logicsheet logicsheet; 187 if (named) { 188 String location = params.getParameter("href", null); 189 String uri = params.getParameter("uri", null); 190 String prefix = params.getParameter("prefix", null); 191 192 NamedLogicsheet namedLogicsheet 193 = new NamedLogicsheet(location, manager, 194 resolver, getLogicsheetFilter()); 195 namedLogicsheet.setURI(uri); 196 namedLogicsheet.setPrefix(prefix); 197 logicsheet = namedLogicsheet; 198 } else { 199 String location = params.getParameter("core-logicsheet", null); 200 logicsheet = new Logicsheet(location, manager, 201 resolver, getLogicsheetFilter()); 202 } 203 204 logicsheet.enableLogging(getLogger()); 205 206 String logicsheetName = logicsheet.getSystemId(); 207 logicsheetCache.store(CACHE_PREFIX + logicsheetName, logicsheet); 208 209 return logicsheet; 210 } 211 212 216 public void service(ServiceManager manager) throws ServiceException { 217 this.manager = manager; 218 219 this.logicsheetCache = (Store) manager.lookup(Store.TRANSIENT_STORE); 221 222 this.resolver = (SourceResolver)this.manager.lookup(SourceResolver.ROLE); 224 } 225 226 229 public void recycle() { 230 this.logicSheetList.clear(); 231 } 232 233 236 public void dispose() { 237 this.manager.release(this.logicsheetCache); 238 this.logicsheetCache = null; 239 240 this.manager.release(this.resolver); 241 this.resolver = null; 242 this.manager = null; 243 this.languages.clear(); 244 } 245 246 252 public String getName() { 253 return this.name; 254 } 255 256 259 public String getURI() { 260 return this.uri; 261 } 262 263 266 public String getPrefix() { 267 return this.prefix; 268 } 269 270 274 public boolean hasAttrInterpolation() { 275 return this.attrInterpolation; 276 } 277 278 282 public boolean hasTextInterpolation() { 283 return this.textInterpolation; 284 } 285 286 298 public String getEncoding() { 299 return null; 300 } 301 302 313 protected TransformerChainBuilderFilter getTransformerChainBuilder( 314 LogicsheetCodeGenerator logicsheetMarkupGenerator) 315 { 316 return new TransformerChainBuilderFilter(logicsheetMarkupGenerator); 317 } 318 319 332 protected AbstractXMLPipe getPreprocessFilter(String filename, 333 AbstractXMLPipe filter, 334 ProgrammingLanguage language) 335 { 336 return filter; 338 } 339 340 350 protected abstract void addDependency(String location); 351 352 370 public String generateCode(Source source, 371 String filename, 372 ProgrammingLanguage programmingLanguage) 373 throws Exception { 374 375 String languageName = programmingLanguage.getLanguageName(); 376 LanguageDescriptor language = (LanguageDescriptor)this.languages.get(languageName); 377 if (language == null) { 378 throw new IllegalArgumentException ("Unsupported programming language: " + languageName); 379 } 380 381 LogicsheetCodeGenerator codeGenerator = new LogicsheetCodeGenerator(); 383 codeGenerator.enableLogging(getLogger()); 384 codeGenerator.initialize(); 385 TransformerChainBuilderFilter tranBuilder = 387 getTransformerChainBuilder(codeGenerator); 388 tranBuilder.setLanguageDescriptor(language); 389 390 AbstractXMLPipe preprocessor = getPreprocessFilter(filename, tranBuilder, programmingLanguage); 392 return codeGenerator.generateCode(source, preprocessor); 393 } 394 395 399 protected void addLogicsheetsToGenerator(LogicsheetCodeGenerator codeGenerator) 400 throws MalformedURLException , IOException , SAXException , ProcessingException { 401 402 if (codeGenerator == null) { 403 getLogger().debug("This should never happen: codeGenerator is null"); 404 throw new SAXException ("codeGenerator must never be null."); 405 } 406 407 LinkedList newLogicSheetList = new LinkedList (); 409 for(int i = logicSheetList.size()-1; i>=0; i--) { 410 Logicsheet logicsheet = (Logicsheet) logicSheetList.get(i); 411 if(newLogicSheetList.indexOf(logicsheet) == -1) 412 newLogicSheetList.addFirst(logicsheet); 413 } 414 415 Iterator iterator = newLogicSheetList.iterator(); 417 while(iterator.hasNext()) { 418 Logicsheet logicsheet = (Logicsheet) iterator.next(); 419 codeGenerator.addLogicsheet(logicsheet); 420 } 421 } 422 423 431 protected void addLogicsheetToList(LanguageDescriptor language, 432 String logicsheetLocation) 433 throws IOException , SAXException , ProcessingException 434 { 435 Logicsheet logicsheet = (Logicsheet)logicsheetCache.get(CACHE_PREFIX + logicsheetLocation); 436 if (logicsheet == null) { 437 Source inputSource = null; 438 try { 439 inputSource = this.resolver.resolveURI(logicsheetLocation); 443 444 logicsheet = new Logicsheet(inputSource, manager, 449 resolver, getLogicsheetFilter()); 450 logicsheetCache.store(CACHE_PREFIX + logicsheet.getSystemId(), logicsheet); 451 } catch (SourceException se) { 452 throw SourceUtil.handle(se); 453 } finally { 454 this.resolver.release( inputSource ); 455 } 456 } 457 String logicsheetName = logicsheet.getSystemId(); 458 459 if (getLogger().isDebugEnabled()) { 460 getLogger().debug("addLogicsheetToList: " 461 + "name: " + logicsheetName 462 + ", location: " + logicsheetLocation 463 + ", instance: " + logicsheet); 464 } 465 466 if (logicsheetName.startsWith(FILE)) { 467 String filename = logicsheetName.substring(FILE.length()); 468 addDependency(filename); 469 getLogger().debug("addLogicsheetToList: " 470 + "adding dependency on file " + filename); 471 } 472 473 logicSheetList.add(logicsheet); 474 475 Map namespaces = logicsheet.getNamespaceURIs(); 476 if(!logicsheetLocation.equals(language.getLogicsheet())) { 477 if(namespaces != null && namespaces.size() > 0) { 478 Iterator iter = namespaces.keySet().iterator(); 479 while(iter.hasNext()) { 480 String namespace = (String ) iter.next(); 481 String namedLogicsheetName = language.getNamedLogicsheetByURI(namespace); 482 if(namedLogicsheetName!= null 483 && !logicsheetLocation.equals(namedLogicsheetName)) { 484 getLogger().debug("Adding embedded logic sheet for " 485 + namespace + ": " + namedLogicsheetName); 486 addLogicsheetToList(language, namedLogicsheetName); 488 } 489 } 490 } 491 } 492 } 493 494 497 protected LogicsheetFilter getLogicsheetFilter() { 498 return new LogicsheetFilter(); 499 } 500 501 505 506 protected static class LanguageDescriptor { 507 508 protected String name; 509 510 511 protected String logicsheet; 512 513 514 protected HashMap namedLogicsheets; 515 516 517 protected LanguageDescriptor() { 518 this.namedLogicsheets = new HashMap(); 519 } 520 521 525 protected void setName(String name) { 526 this.name = name; 527 } 528 529 533 protected String getName() { 534 return this.name; 535 } 536 537 541 protected void setLogicsheet(String logicsheet) { 542 this.logicsheet = logicsheet; 543 } 544 545 549 protected String getLogicsheet() { 550 return this.logicsheet; 551 } 552 553 559 protected void addNamedLogicsheet(String uri, String prefix, String namedLogicsheet) { 560 this.namedLogicsheets.put(uri, namedLogicsheet); 561 } 562 563 567 protected String getNamedLogicsheetByURI(String uri) { 568 return (String )this.namedLogicsheets.get(uri); 569 } 570 } 571 572 573 578 public class TransformerChainBuilderFilter extends AbstractXMLPipe { 579 580 protected LogicsheetCodeGenerator logicsheetMarkupGenerator; 581 582 583 protected LanguageDescriptor language; 584 585 private boolean isRootElem; 586 private List startPrefixes; 587 588 592 protected TransformerChainBuilderFilter(LogicsheetCodeGenerator logicsheetMarkupGenerator) { 593 this.logicsheetMarkupGenerator = logicsheetMarkupGenerator; 594 } 595 596 601 protected void setLanguageDescriptor(LanguageDescriptor language) { 602 this.language = language; 603 } 604 605 606 public void startDocument() throws SAXException { 607 isRootElem = true; 608 startPrefixes = new ArrayList (); 609 } 610 611 612 public void startPrefixMapping(String prefix, String uri) throws SAXException { 613 if (!isRootElem) { 614 super.startPrefixMapping(prefix, uri); 615 } else { 616 String [] prefixNamingArray = new String [2]; 618 prefixNamingArray[0] = prefix; 619 prefixNamingArray[1] = uri; 620 this.startPrefixes.add(prefixNamingArray); 621 } 622 } 623 624 625 public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { 626 if (isRootElem) { 627 isRootElem = false; 628 try { 629 int prefixesCount = this.startPrefixes.size(); 631 for (int i = 0; i < prefixesCount; i++) { 632 String [] prefixNamingArray = (String []) this.startPrefixes.get(i); 633 String namedLogicsheetName = this.language.getNamedLogicsheetByURI(prefixNamingArray[1]); 634 if (namedLogicsheetName != null) { 635 AbstractMarkupLanguage.this.addLogicsheetToList(language, namedLogicsheetName); 636 } 637 } 638 639 AbstractMarkupLanguage.this.addLogicsheetToList(language, this.language.getLogicsheet()); 641 AbstractMarkupLanguage.this.addLogicsheetsToGenerator(this.logicsheetMarkupGenerator); 642 } catch (ProcessingException pe) { 643 throw new SAXException (pe); 644 } catch (IOException ioe) { 645 throw new SAXException (ioe); 646 } 647 648 super.startDocument(); 652 int prefixesCount = this.startPrefixes.size(); 653 for (int i = 0; i < prefixesCount; i++) { 654 String [] prefixNamingArray = (String []) this.startPrefixes.get(i); 655 super.startPrefixMapping(prefixNamingArray[0], prefixNamingArray[1]); 656 } 657 } 658 super.startElement(namespaceURI, localName, qName, atts); 660 } 661 } 662 } 663 | Popular Tags |