| | |
| | +/** |
| | + * MIT License |
| | + * |
| | + * Copyright 2015 White Magic Software, Ltd. |
| | + */ |
| | +package to.discuss.util; |
| | + |
| | +import java.io.IOException; |
| | +import java.io.Reader; |
| | +import java.io.StringReader; |
| | + |
| | +import java.net.URI; |
| | + |
| | +import javax.xml.transform.Source; |
| | +import javax.xml.transform.TransformerException; |
| | +import javax.xml.transform.URIResolver; |
| | +import javax.xml.transform.stream.StreamSource; |
| | + |
| | +import to.discuss.App; |
| | +import to.discuss.Base; |
| | + |
| | +/** |
| | + * Extends java.util.Properties to recursively parse ${property} values. This |
| | + */ |
| | +public class AppURIResolver implements URIResolver, Base { |
| | + private URIResolver delegate; |
| | + private App app; |
| | + |
| | + public AppURIResolver( App app, URIResolver delegate ) { |
| | + setApp( app ); |
| | + setDelegate( delegate ); |
| | + } |
| | + |
| | + /** |
| | + * Dynamically resolve the path to the include file based on the app name. |
| | + */ |
| | + @Override |
| | + public Source resolve( String href, String base ) |
| | + throws TransformerException { |
| | + Source result = null; |
| | + URI uri = null; |
| | + |
| | + try { |
| | + uri = new URI( href ); |
| | + } |
| | + catch( Exception e ) { |
| | + throw new TransformerException( e ); |
| | + } |
| | + |
| | + // The XSLT file has a URI path that allows for a file to be included |
| | + // dynamically. |
| | + if( "import".equalsIgnoreCase( uri.getScheme() ) && |
| | + "discuss.to".equalsIgnoreCase( uri.getAuthority() ) ) { |
| | + result = openAppTemplate(); |
| | + } |
| | + else { |
| | + result = getDelegate().resolve( href, base ); |
| | + } |
| | + |
| | + return result; |
| | + } |
| | + |
| | + /** |
| | + * Guaranteed to open an XSL template that corresponds to the app name. |
| | + * If no template is found, or the default template file is missing, this |
| | + * will return a hard-coded string as a StreamSource. |
| | + * |
| | + * @return A valid StreamSource containing a stylesheet DOM. |
| | + */ |
| | + private Source openAppTemplate() { |
| | + Source result = null; |
| | + |
| | + try { |
| | + result = new StreamSource( open( getStylesheetFilename() ) ); |
| | + } |
| | + catch( IOException ioe ) { |
| | + try { |
| | + result = new StreamSource( open( "xsl/template.xsl" ) ); |
| | + } |
| | + catch( Exception e ) { |
| | + result = new StreamSource( getDefaultTemplate() ); |
| | + } |
| | + } |
| | + |
| | + return result; |
| | + } |
| | + |
| | + /** |
| | + * If the file-based template cannot be found, then use a hard-coded, |
| | + * fail-safe version. |
| | + */ |
| | + private Reader getDefaultTemplate() { |
| | + return new StringReader( |
| | + "<?xml version='1.0' encoding='utf-8'?>" + |
| | + "<xsl:stylesheet version='2.0' " + |
| | + "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>" + |
| | + "</xsl:stylesheet>" ); |
| | + } |
| | + |
| | + private String getStylesheetFilename() { |
| | + return String.format( "xsl/%s.xsl", getApp().getAppName() ); |
| | + } |
| | + |
| | + private void setApp( App app ) { |
| | + this.app = app; |
| | + } |
| | + |
| | + private App getApp() { |
| | + return this.app; |
| | + } |
| | + |
| | + private void setDelegate( URIResolver delegate ) { |
| | + this.delegate = delegate; |
| | + } |
| | + |
| | + private URIResolver getDelegate() { |
| | + return this.delegate; |
| | + } |
| | +} |
| | + |
| | + |