Changeset 2783
- Timestamp:
- 19/06/07 13:35:26 (5 years ago)
- Files:
-
- trunk (modified) (1 prop)
- trunk/.classpath (modified) (1 diff)
- trunk/build.xml (modified) (1 diff)
- trunk/ivy.xml (modified) (1 diff)
- trunk/src/main/java/org/sarugo/xtc/Template.java (modified) (1 diff)
- trunk/src/main/java/org/sarugo/xtc/TemplateClient.java (modified) (1 diff)
- trunk/src/main/java/org/sarugo/xtc/TemplateContext.java (modified) (1 diff)
- trunk/src/main/java/org/sarugo/xtc/TemplateFactory.java (modified) (2 diffs)
- trunk/src/main/java/org/sarugo/xtc/TemplateHandler.java (modified) (1 diff)
- trunk/src/main/java/org/sarugo/xtc/compiler/Compiler.java (modified) (3 diffs)
- trunk/src/main/java/org/sarugo/xtc/impl/DefaultResourceResolver.java (deleted)
- trunk/src/main/java/org/sarugo/xtc/impl/DefaultTemplateContext.java (modified) (3 diffs)
- trunk/src/main/java/org/sarugo/xtc/impl/DefaultTemplateFactory.java (modified) (2 diffs)
- trunk/src/main/java/org/sarugo/xtc/impl/ResourceResolver.java (modified) (1 diff)
- trunk/src/main/java/org/sarugo/xtc/package.html (modified) (1 diff)
- trunk/src/main/java/org/sarugo/xtc/render.uxf (added)
- trunk/src/main/java/org/sarugo/xtc/restlet/XtcResourceHandler.java (modified) (3 diffs)
- trunk/src/main/java/org/sarugo/xtc/restlet/XtcRestApplication.java (modified) (1 diff)
- trunk/src/main/java/org/sarugo/xtc/util/Classpath.java (modified) (3 diffs)
- trunk/src/main/resources/META-INF/services (added)
- trunk/src/main/resources/META-INF/services/org.sarugo.xtc.TemplateFactory (added)
- trunk/src/main/resources/META-INF/services/org.sarugo.xtc.compiler.Compiler (added)
- trunk/src/main/resources/default.dtd (added)
- trunk/src/test/java/org/sarugo/xtc/BasicTests.java (modified) (1 diff)
- trunk/src/test/java/org/sarugo/xtc/UITests.java (modified) (1 diff)
- trunk/src/test/java/org/sarugo/xtc/XtcTestFixture.java (added)
- trunk/src/test/resources/component.xhtml (added)
- trunk/src/test/resources/composition.xhtml.result (added)
- trunk/src/test/resources/decorate.xhtml (modified) (1 diff)
- trunk/src/test/resources/decorate.xhtml.result (added)
- trunk/src/test/resources/include.xhtml.result (added)
- trunk/src/test/resources/jstl-core.xhtml.result (added)
- trunk/src/test/resources/jstl-fn.xhtml.result (added)
- trunk/src/test/resources/plain.xhtml.result (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk
- Property svn:ignore set to
ant
build
dist
lib
- Property svn:ignore set to
trunk/.classpath
r2777 r2783 3 3 <classpathentry kind="src" output="build/main/java" path="src/main/java"/> 4 4 <classpathentry kind="src" output="build/test/java" path="src/test/java"/> 5 <classpathentry kind="src" output="build/test/resources" path="src/test/resources"/> 6 <classpathentry kind="src" output="build/main/resources" path="src/main/resources"/> 5 7 <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> 6 8 <classpathentry kind="lib" path="lib/com.noelios.restlet-1.0.1.jar"/> 7 9 <classpathentry kind="lib" path="lib/com.noelios.restlet.ext.simple-1.0.1.jar"/> 8 10 <classpathentry kind="lib" path="lib/juel-2.1.0.jar"/> 9 <classpathentry kind="lib" path="lib/junit-3.8.2.jar"/>10 11 <classpathentry kind="lib" path="lib/org.restlet-1.0.1.jar"/> 11 12 <classpathentry kind="lib" path="lib/org.simpleframework-3.1.3.jar"/> 13 <classpathentry kind="lib" path="lib/xmlunit-1.0.jar"/> 14 <classpathentry kind="lib" path="lib/junit-3.8.1.jar"/> 12 15 <classpathentry kind="output" path="bin"/> 13 16 </classpath> trunk/build.xml
r2776 r2783 1 1 <project name="xtc" default="help" xmlns:ivy="antlib:org.apache.ivy.ant"> 2 <!-- Sarugo common ant configuration --> 3 <property name="ant.lib.dir" value="ant"/> 4 <property name="ant.server" value="http://ant.sarugo.org"/> 5 <property name="sarugo.ant.file" value="${ant.lib.dir}/common-build.xml"/> 6 <!-- Ivy configuration --> 7 <property name="ivy.server" value="${ant.server}/ivy"/> 8 <property name="ivy.version" value="2.0.0-alpha-1-incubating"/> 9 <property name="ivy.dest.file" value="${ant.lib.dir}/ivy-${ivy.version}.jar"/> 10 <condition property="download-ivy.required"> 11 <not><available file="${ivy.dest.file}" type="file"/></not> 12 </condition> 13 <!-- Project directories --> 14 <property name="src.dir" value="src"/> 15 <property name="build.dir" value="build"/> 16 <property name="dist.dir" value="dist"/> 17 <property name="lib.dir" value="lib"/> 18 <condition property="bootstrap.required"> 19 <not><and> 20 <available file="${ant.lib.dir}" type="dir"/> 21 <available file="${lib.dir}" type="dir"/> 22 </and></not> 23 </condition> 24 25 <target name="download-ivy" if="download-ivy.required"> 26 <!-- download Ivy from web site so that it can be used even without any special installation --> 27 <get src="${ivy.server}/${ivy.version}/ivy-${ivy.version}.jar" dest="${ivy.dest.file}" usetimestamp="true"/> 28 </target> 29 30 <target name="bootstrap" description="Downloads common ant scripts and libraries"> 31 <mkdir dir="${ant.lib.dir}"/> 32 <antcall target="download-ivy"/> 33 <path id="ivy.lib.path"> 34 <fileset file="${ivy.dest.file}"/> 35 </path> 36 <taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/> 37 <ivy:configure file="ivysettings.xml"/> 38 <ivy:resolve file="ivy.xml"/> 39 <ivy:retrieve pattern="${lib.dir}/[artifact]-[revision].[ext]"/> 40 </target> 41 42 <target name="init" if="bootstrap.required"> 43 <fail message="You need to run ant bootstrap"/> 44 </target> 45 46 <target name="compile" depends="init" description="Compile the library"> 47 <mkdir dir="${build.dir}/main/java" /> 48 <javac source="1.5" target="1.5" destdir="${build.dir}/main/java"> 49 <src path="${src.dir}/main/java"/> 50 <classpath> 51 <pathelement path="${build.dir}/main/java"/> 52 <fileset dir="${lib.dir}" includes="**/*.jar"/> 53 </classpath> 54 </javac> 55 </target> 56 57 <target name="test" depends="compile" description="Build and run unit tests"> 58 <mkdir dir="${build.dir}/test/java" /> 59 <javac source="1.5" target="1.5" destdir="${build.dir}/test/java"> 60 <src path="${src.dir}/test/java"/> 61 <classpath> 62 <pathelement path="${build.dir}/main/java"/> 63 <pathelement path="${build.dir}/test/java"/> 64 <fileset dir="${lib.dir}" includes="**/*.jar"/> 65 </classpath> 66 </javac> 67 </target> 68 69 <target name="package" depends="compile" description="Build distribution files"> 70 <mkdir dir="${dist.dir}"/> 71 <jar destfile="${dist.dir}/xtc.jar"> 72 <fileset dir="${build.dir}/main/java" /> 73 <fileset dir="${src.dir}/main/resources" /> 74 </jar> 75 <!-- Use ivy to copy the runtime dependencies to distribution directory --> 76 <path id="ivy.lib.path"> 77 <fileset file="${ivy.dest.file}"/> 78 </path> 79 <taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/> 80 <ivy:configure file="ivysettings.xml"/> 81 <ivy:resolve file="ivy.xml"/> 82 <ivy:retrieve pattern="${dist.dir}/[artifact]-[revision].[ext]" conf="default"/> 83 </target> 84 85 <target name="integration-test" depends="package" description="Test distribution files"> 86 </target> 87 88 <target name="clean" description="Clean the project built files (not dist)"> 89 <delete includeemptydirs="true" failonerror="false"> 90 <fileset dir="${build.dir}"/> 91 </delete> 92 </target> 93 94 <target name="clean-dist" depends="clean" description="Clean compiled, packaged and downloaded library files"> 95 <delete includeemptydirs="true" failonerror="false"> 96 <fileset dir="${dist.dir}"/> 97 </delete> 98 </target> 99 100 <target name="clean-all" depends="clean-dist" description="Clean all generated (or downloaded) files"> 101 <delete includeemptydirs="true" failonerror="false"> 102 <fileset dir="${ant.lib.dir}"/> 103 <fileset dir="${lib.dir}"/> 104 </delete> 105 </target> 106 107 <target name="help"> 108 <echo message="Run ant -p to see a list of targets."/> 109 <echo message="Most likely you want to test or package."/> 110 </target> 111 2 <!-- Sarugo common ant configuration --> 3 <property name="ant.lib.dir" value="ant" /> 4 <property name="ant.server" value="http://ant.sarugo.org" /> 5 <property name="sarugo.ant.file" value="${ant.lib.dir}/common-build.xml" /> 6 <!-- Ivy configuration --> 7 <property name="ivy.server" value="${ant.server}/ivy" /> 8 <property name="ivy.version" value="2.0.0-alpha-1-incubating" /> 9 <property name="ivy.dest.file" value="${ant.lib.dir}/ivy-${ivy.version}.jar" /> 10 <condition property="download-ivy.required"> 11 <not> 12 <available file="${ivy.dest.file}" type="file" /> 13 </not> 14 </condition> 15 <!-- Project directories --> 16 <property name="src.dir" value="src" /> 17 <property name="build.dir" value="build" /> 18 <property name="dist.dir" value="dist" /> 19 <property name="lib.dir" value="lib" /> 20 <condition property="bootstrap.required"> 21 <not> 22 <and> 23 <available file="${ant.lib.dir}" type="dir" /> 24 <available file="${lib.dir}" type="dir" /> 25 </and> 26 </not> 27 </condition> 28 29 <target name="download-ivy" if="download-ivy.required"> 30 <!-- download Ivy from web site so that it can be used even without any special installation --> 31 <get src="${ivy.server}/${ivy.version}/ivy-${ivy.version}.jar" dest="${ivy.dest.file}" usetimestamp="true" /> 32 </target> 33 34 <target name="bootstrap" description="Downloads common ant scripts and libraries"> 35 <mkdir dir="${ant.lib.dir}" /> 36 <antcall target="download-ivy" /> 37 <path id="ivy.lib.path"> 38 <fileset file="${ivy.dest.file}" /> 39 </path> 40 <taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path" /> 41 <ivy:configure file="ivysettings.xml" /> 42 <ivy:resolve file="ivy.xml" /> 43 <ivy:retrieve pattern="${lib.dir}/[artifact]-[revision].[ext]" /> 44 </target> 45 46 <target name="init" if="bootstrap.required"> 47 <fail message="You need to run ant bootstrap" /> 48 </target> 49 50 <target name="compile" depends="init" description="Compile the library"> 51 <mkdir dir="${build.dir}/main/java" /> 52 <javac source="1.5" target="1.5" destdir="${build.dir}/main/java"> 53 <src path="${src.dir}/main/java" /> 54 <classpath> 55 <dirset dir="${build.dir}"> 56 <include name="main/*" /> 57 </dirset> 58 <fileset dir="${lib.dir}" includes="**/*.jar" /> 59 </classpath> 60 </javac> 61 <copy todir="${build.dir}/main"> 62 <fileset dir="${src.dir}/main" excludes="java/**"/> 63 </copy> 64 </target> 65 66 <target name="test" depends="compile" description="Build and run unit tests"> 67 <mkdir dir="${build.dir}/test/java" /> 68 <javac source="1.5" target="1.5" destdir="${build.dir}/test/java"> 69 <src path="${src.dir}/test/java" /> 70 <classpath> 71 <dirset dir="${build.dir}"> 72 <include name="main/*" /> 73 <include name="test/*" /> 74 </dirset> 75 <fileset dir="${lib.dir}" includes="**/*.jar" /> 76 </classpath> 77 </javac> 78 <copy todir="${build.dir}/test"> 79 <fileset dir="${src.dir}/test" excludes="java/**"/> 80 </copy> 81 <junit printsummary="on"> 82 <classpath> 83 <dirset dir="${build.dir}"> 84 <include name="main/*" /> 85 <include name="test/*" /> 86 </dirset> 87 <fileset dir="${lib.dir}" includes="**/*.jar" /> 88 </classpath> 89 <batchtest> 90 <fileset dir="${src.dir}/test/java"> 91 <include name="**/*Tests.java" /> 92 </fileset> 93 </batchtest> 94 </junit> 95 </target> 96 97 <target name="package" depends="compile" description="Build distribution files"> 98 <mkdir dir="${dist.dir}" /> 99 <jar destfile="${dist.dir}/xtc.jar"> 100 <fileset dir="${build.dir}/main/java" /> 101 <fileset dir="${build.dir}/main/resources" /> 102 </jar> 103 <!-- Use ivy to copy the runtime dependencies to distribution directory --> 104 <path id="ivy.lib.path"> 105 <fileset file="${ivy.dest.file}" /> 106 </path> 107 <taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path" /> 108 <ivy:configure file="ivysettings.xml" /> 109 <ivy:resolve file="ivy.xml" /> 110 <ivy:retrieve pattern="${dist.dir}/[artifact]-[revision].[ext]" conf="default" /> 111 </target> 112 113 <target name="integration-test" depends="package" description="Test distribution files"> 114 </target> 115 116 <target name="clean" description="Clean the project built files (not dist)"> 117 <delete includeemptydirs="true" failonerror="false"> 118 <fileset dir="${build.dir}" /> 119 </delete> 120 </target> 121 122 <target name="clean-dist" depends="clean" description="Clean compiled, packaged and downloaded library files"> 123 <delete includeemptydirs="true" failonerror="false"> 124 <fileset dir="${dist.dir}" /> 125 </delete> 126 </target> 127 128 <target name="clean-all" depends="clean-dist" description="Clean all generated (or downloaded) files"> 129 <delete includeemptydirs="true" failonerror="false"> 130 <fileset dir="${ant.lib.dir}" /> 131 <fileset dir="${lib.dir}" /> 132 </delete> 133 </target> 134 135 <target name="help"> 136 <echo message="Run ant -p to see a list of targets." /> 137 <echo message="Most likely you want to test or package." /> 138 </target> 139 112 140 </project> trunk/ivy.xml
r2776 r2783 12 12 <dependency org="com.noelios.restlet" name="com.noelios.restlet.ext.simple" rev="1.0.1" conf="default"/> 13 13 <dependency org="de.odysseus.juel" name="juel" rev="2.1.0" conf="default,compile->default"/> 14 <dependency org="junit" name="junit" rev="3.8.2" conf="test->default"/> 14 <dependency org="junit" name="junit" rev="3.8.1" conf="test->default"/> 15 <dependency org="xmlunit" name="xmlunit" rev="1.0" conf="test->default"/> 15 16 </dependencies> 16 17 </ivy-module> trunk/src/main/java/org/sarugo/xtc/Template.java
r2746 r2783 16 16 17 17 import java.io.IOException; 18 import java.io.Writer;19 18 20 19 import javax.el.ELException; trunk/src/main/java/org/sarugo/xtc/TemplateClient.java
r2746 r2783 16 16 17 17 import java.io.IOException; 18 import java.io.Writer;19 18 20 19 import javax.el.ELException; trunk/src/main/java/org/sarugo/xtc/TemplateContext.java
r2746 r2783 26 26 27 27 /** 28 * Context representative of a single request from a Facelet28 * Represents the state for a (typically) single rendering of a Template. 29 29 * 30 30 * @author Jacob Hookom 31 * @version $Id: FaceletContext.java,v 1.6 2006/03/29 04:10:11 jhook Exp $32 31 */ 33 32 public abstract class TemplateContext extends ELContext { trunk/src/main/java/org/sarugo/xtc/TemplateFactory.java
r2746 r2783 1 /* *1 /* 2 2 * Licensed under the Common Development and Distribution License, 3 3 * you may not use this file except in compliance with the License. … … 19 19 import javax.el.ELException; 20 20 21 import org.sarugo.xtc.util.Classpath; 22 21 23 /** 22 * FaceletFactory for producing Facelets relative to the context of the23 * underlying implementation.24 * Compiles XML template definitions into Template instances and manages 25 * caching. 24 26 * 25 * @author Jacob Hookom 26 * @version $Id: FaceletFactory.java,v 1.3 2005/11/30 23:36:39 jhook Exp $ 27 * @author Michael Terrington 27 28 */ 28 29 public abstract class TemplateFactory { 29 30 30 private static ThreadLocal<TemplateFactory> Instance = new ThreadLocal<TemplateFactory>();31 private static ThreadLocal<TemplateFactory> instance = new ThreadLocal<TemplateFactory>(); 31 32 32 /** 33 * Return a Facelet instance as specified by the file at the passed URI. 34 * 35 * @param uri 36 * @return 37 * @throws IOException 38 * @throws TemplateException 39 * @throws FacesException 40 * @throws ELException 41 */ 42 public abstract Template getFacelet(String uri) throws IOException, 43 TemplateException, ELException; 33 private static final String PROVIDER_RESOURCE = "META-INF/services/org.sarugo.xtc.TemplateFactory"; 44 34 45 /** 46 * Set the static instance 47 * 48 * @param factory 49 */ 50 public static final void setInstance(TemplateFactory factory) { 51 Instance.set(factory); 52 } 35 /** 36 * Return a Template instance as specified by the file at the passed URI. 37 * 38 * @param uri 39 * URI to the template definition. 40 * @return a Template instance. 41 * @throws IOException 42 * if the template definition cannot be read. 43 * @throws TemplateException 44 * if an error occurs during compilation. 45 * @throws ELException 46 * if the an error occurs initialising the EL provider. 47 */ 48 public abstract Template getTemplate(String uri) throws IOException, 49 TemplateException, ELException; 53 50 54 /** 55 * Get the static instance 56 * 57 * @return 58 */ 59 public static final TemplateFactory getInstance() { 60 return Instance.get(); 61 } 51 public static TemplateFactory getInstance() { 52 TemplateFactory result = instance.get(); 53 if (result == null) { 54 try { 55 instance.set((TemplateFactory) Classpath 56 .instanceFromConfig(PROVIDER_RESOURCE)); 57 } catch (Exception e) { 58 throw new RuntimeException( 59 "Unable to register the TemplateFactory implementation", 60 e); 61 } 62 result = instance.get(); 63 } 64 if (result == null) { 65 throw new RuntimeException( 66 "Unable to register the TemplateFactory implementation"); 67 } 68 return result; 69 } 62 70 } trunk/src/main/java/org/sarugo/xtc/TemplateHandler.java
r2746 r2783 16 16 17 17 import java.io.IOException; 18 import java.io.Writer;19 18 20 19 import javax.el.ELException; 21 20 22 21 /** 23 * A participant in UIComponent tree building22 * A render participant, typically implemented by a tag library. 24 23 * 25 * @ author Jacob Hookom26 * @ version $Id: FaceletHandler.java,v 1.2 2005/08/24 04:38:59 jhook Exp $24 * @see org.sarugo.xtc.tag.TagHandler 25 * @author Michael Terrington 27 26 */ 28 27 public interface TemplateHandler { 29 28 30 29 /** 31 * Process changes on a particular UIComponent30 * Renders this component on the current TemplateContext. 32 31 * 33 * @param ctx the current FaceletContext instance for this execution 34 * @param parent the parent UIComponent to operate upon 35 * @throws IOException 36 * @throws FacesException 37 * @throws TemplateException 38 * @throws ELException 32 * @param ctx the current TemplateContext instance for this execution 39 33 */ 40 34 public void render(TemplateContext ctx) trunk/src/main/java/org/sarugo/xtc/compiler/Compiler.java
r2684 r2783 28 28 29 29 import org.sarugo.xtc.TemplateException; 30 import org.sarugo.xtc.TemplateFactory; 30 31 import org.sarugo.xtc.TemplateHandler; 31 32 import org.sarugo.xtc.tag.CompositeTagDecorator; … … 34 35 import org.sarugo.xtc.tag.TagLibrary; 35 36 import org.sarugo.xtc.tag.ui.UILibrary; 37 import org.sarugo.xtc.util.Classpath; 36 38 import org.sarugo.xtc.util.ParameterCheck; 37 38 39 39 40 /** … … 45 46 public abstract class Compiler { 46 47 47 protected final static Logger log = Logger.getLogger("facelets.compiler"); 48 49 public final static String EXPRESSION_FACTORY = "compiler.ExpressionFactory"; 50 51 private static final TagLibrary EMPTY_LIBRARY = new CompositeTagLibrary( 52 new TagLibrary[0]); 53 54 private static final TagDecorator EMPTY_DECORATOR = new CompositeTagDecorator( 55 new TagDecorator[0]); 56 57 private boolean validating = false; 58 59 private boolean trimmingWhitespace = false; 60 61 private boolean trimmingComments = false; 62 63 private final List libraries = new ArrayList(); 64 65 private final List decorators = new ArrayList(); 66 67 private final Map features = new HashMap(); 68 69 private boolean initialized = false; 70 71 /** 72 * 73 */ 74 public Compiler() { 75 76 } 77 78 private synchronized void initialize() { 79 if (this.initialized) 80 return; 81 log.fine("Initializing"); 82 try { 83 TagLibraryConfig cfg = new TagLibraryConfig(); 84 cfg.loadImplicit(this); 85 86 if (!this.createTagLibrary().containsNamespace(UILibrary.Namespace)) { 87 log.severe("Missing Built-in Tag Libraries! Make sure they are included within the META-INF directory of Facelets' Jar"); 88 } 89 90 } catch (IOException e) { 91 log.log(Level.SEVERE, "Compiler Initialization Error", e); 92 } finally { 93 this.initialized = true; 94 } 95 log.fine("Initialization Successful"); 96 } 97 98 public final TemplateHandler compile(URL src, String alias) 99 throws IOException, TemplateException, ELException { 100 if (!this.initialized) 101 this.initialize(); 102 return this.doCompile(src, alias); 103 } 104 105 protected abstract TemplateHandler doCompile(URL src, String alias) 106 throws IOException, TemplateException, ELException; 107 108 public final TagDecorator createTagDecorator() { 109 if (this.decorators.size() > 0) { 110 return new CompositeTagDecorator((TagDecorator[]) this.decorators 111 .toArray(new TagDecorator[this.decorators.size()])); 112 } 113 return EMPTY_DECORATOR; 114 } 115 116 public final void addTagDecorator(TagDecorator decorator) { 117 ParameterCheck.notNull("decorator", decorator); 118 if (!this.decorators.contains(decorator)) { 119 this.decorators.add(decorator); 120 } 121 } 122 123 public final ExpressionFactory createExpressionFactory() { 124 ExpressionFactory el = null; 125 el = (ExpressionFactory) this.featureInstance(EXPRESSION_FACTORY); 126 if (el == null) { 127 this.features.put(EXPRESSION_FACTORY, "de.odysseus.el.ExpressionFactoryImpl"); 128 el = (ExpressionFactory) this.featureInstance(EXPRESSION_FACTORY); 129 } 130 return el; 131 } 132 133 private final Object featureInstance(String name) { 134 String type = (String) this.features.get(name); 135 if (type != null) { 136 try { 137 return Class.forName(type, true, Thread.currentThread().getContextClassLoader()).newInstance(); 138 } catch (Throwable t) { 139 throw new TemplateException("Could not instantiate feature[" 140 + name + "]: " + type); 141 } 142 } 143 return null; 144 } 145 146 public final TagLibrary createTagLibrary() { 147 if (this.libraries.size() > 0) { 148 return new CompositeTagLibrary((TagLibrary[]) this.libraries 149 .toArray(new TagLibrary[this.libraries.size()])); 150 } 151 return EMPTY_LIBRARY; 152 } 153 154 public final void addTagLibrary(TagLibrary library) { 155 ParameterCheck.notNull("library", library); 156 if (!this.libraries.contains(library)) { 157 this.libraries.add(library); 158 } 159 } 160 161 public final void setFeature(String name, String value) { 162 this.features.put(name, value); 163 } 164 165 public final String getFeature(String name) { 166 return (String) this.features.get(name); 167 } 168 169 public final boolean isTrimmingComments() { 170 return this.trimmingComments; 171 } 172 173 public final void setTrimmingComments(boolean trimmingComments) { 174 this.trimmingComments = trimmingComments; 175 } 176 177 public final boolean isTrimmingWhitespace() { 178 return this.trimmingWhitespace; 179 } 180 181 public final void setTrimmingWhitespace(boolean trimmingWhitespace) { 182 this.trimmingWhitespace = trimmingWhitespace; 183 } 184 185 public final boolean isValidating() { 186 return this.validating; 187 } 188 189 public final void setValidating(boolean validating) { 190 this.validating = validating; 191 } 48 private static ThreadLocal<Compiler> instance = new ThreadLocal<Compiler>(); 49 50 private static final String PROVIDER_RESOURCE = "META-INF/services/org.sarugo.xtc.compiler.Compiler"; 51 52 protected final static Logger log = Logger.getLogger("facelets.compiler"); 53 54 public final static String EXPRESSION_FACTORY = "compiler.ExpressionFactory"; 55 56 private static final TagLibrary EMPTY_LIBRARY = new CompositeTagLibrary( 57 new TagLibrary[0]); 58 59 private static final TagDecorator EMPTY_DECORATOR = new CompositeTagDecorator( 60 new TagDecorator[0]); 61 62 private boolean validating = false; 63 64 private boolean trimmingWhitespace = false; 65 66 private boolean trimmingComments = false; 67 68 private final List libraries = new ArrayList(); 69 70 private final List decorators = new ArrayList(); 71 72 private final Map features = new HashMap(); 73 74 private boolean initialized = false; 75 76 /** 77 * 78 */ 79 public Compiler() { 80 81 } 82 83 private synchronized void initialize() { 84 if (this.initialized) 85 return; 86 log.fine("Initializing"); 87 try { 88 TagLibraryConfig cfg = new TagLibraryConfig(); 89 cfg.loadImplicit(this); 90 91 if (!this.createTagLibrary().containsNamespace(UILibrary.Namespace)) { 92 log 93 .severe("Missing Built-in Tag Libraries! Make sure they are included within the META-INF directory of Facelets' Jar"); 94 } 95 96 } catch (IOException e) { 97 log.log(Level.SEVERE, "Compiler Initialization Error", e); 98 } finally { 99 this.initialized = true; 100 } 101 log.fine("Initialization Successful"); 102 } 103 104 public final TemplateHandler compile(URL src, String alias) 105 throws IOException, TemplateException, ELException { 106 if (!this.initialized) 107 this.initialize(); 108 return this.doCompile(src, alias); 109 } 110 111 protected abstract TemplateHandler doCompile(URL src, String alias) 112 throws IOException, TemplateException, ELException; 113 114 public final TagDecorator createTagDecorator() { 115 if (this.decorators.size() > 0) { 116 return new CompositeTagDecorator((TagDecorator[]) this.decorators 117 .toArray(new TagDecorator[this.decorators.size()])); 118 } 119 return EMPTY_DECORATOR; 120 } 121 122 public final void addTagDecorator(TagDecorator decorator) { 123 ParameterCheck.notNull("decorator", decorator); 124 if (!this.decorators.contains(decorator)) { 125 this.decorators.add(decorator); 126 } 127 } 128 129 public final ExpressionFactory createExpressionFactory() { 130 ExpressionFactory el = null; 131 el = (ExpressionFactory) this.featureInstance(EXPRESSION_FACTORY); 132 if (el == null) { 133 this.features.put(EXPRESSION_FACTORY, 134 "de.odysseus.el.ExpressionFactoryImpl"); 135 el = (ExpressionFactory) this.featureInstance(EXPRESSION_FACTORY); 136 } 137 return el; 138 } 139 140 private final Object featureInstance(String name) { 141 String type = (String) this.features.get(name); 142 if (type != null) { 143 try { 144 return Class.forName(type, true, 145 Thread.currentThread().getContextClassLoader()) 146 .newInstance(); 147 } catch (Throwable t) { 148 throw new TemplateException("Could not instantiate feature[" 149 + name + "]: " + type); 150 } 151 } 152 return null; 153 } 154 155 public final TagLibrary createTagLibrary() { 156 if (this.libraries.size() > 0) { 157 return new CompositeTagLibrary((TagLibrary[]) this.libraries 158 .toArray(new TagLibrary[this.libraries.size()])); 159 } 160 return EMPTY_LIBRARY; 161 } 162 163 public final void addTagLibrary(TagLibrary library) { 164 ParameterCheck.notNull("library", library); 165 if (!this.libraries.contains(library)) { 166 this.libraries.add(library); 167 } 168 } 169 170 public final void setFeature(String name, String value) { 171 this.features.put(name, value); 172 } 173 174 public final String getFeature(String name) { 175 return (String) this.features.get(name); 176 } 177 178 public final boolean isTrimmingComments() { 179 return this.trimmingComments; 180 } 181 182 public final void setTrimmingComments(boolean trimmingComments) { 183 this.trimmingComments = trimmingComments; 184 } 185 186 public final boolean isTrimmingWhitespace() { 187 return this.trimmingWhitespace; 188 } 189 190 public final void setTrimmingWhitespace(boolean trimmingWhitespace) { 191 this.trimmingWhitespace = trimmingWhitespace; 192 } 193 194 public final boolean isValidating() { 195 return this.validating; 196 } 197 198 public final void setValidating(boolean validating) { 199 this.validating = validating; 200 } 201 202 public static Compiler getInstance() { 203 204 Compiler result = instance.get(); 205 if (result == null) { 206 try { 207 instance.set((Compiler) Classpath 208 .instanceFromConfig(PROVIDER_RESOURCE)); 209 } catch (Exception e) { 210 throw new RuntimeException( 211 "Unable to register the Compiler implementation", e); 212 } 213 result = instance.get(); 214 } 215 if (result == null) { 216 throw new RuntimeException( 217 "Unable to register the Compiler implementation"); 218 } 219 return result; 220 } 192 221 } trunk/src/main/java/org/sarugo/xtc/impl/DefaultTemplateContext.java
r2684 r2783 34 34 import javax.el.VariableMapper; 35 35 36 import org.sarugo.xtc.TemplateClient; 36 37 import org.sarugo.xtc.TemplateContext; 37 38 import org.sarugo.xtc.TemplateException; 38 import org.sarugo.xtc.TemplateClient;39 39 import org.sarugo.xtc.XMLWriter; 40 41 import de.odysseus.el.util.SimpleContext; 40 42 41 43 /** … … 66 68 67 69 private String characterEncoding; 68 70 69 71 public DefaultTemplateContext(DefaultTemplateContext ctx, 70 72 DefaultTemplate facelet) { … … 79 81 80 82 public DefaultTemplateContext(DefaultTemplate facelet) { 81 this.ctx = new de.odysseus.el.util.SimpleContext();82 83 this.ids = new HashMap(); 83 84 this.clients = new ArrayList(5); 84 85 this.facelet = facelet; 86 SimpleContext simpleContext = new SimpleContext(); 87 // workaround to ensure variable mapper is created 88 simpleContext.setVariable(null, null); 89 this.ctx = simpleContext; 85 90 this.varMapper = this.ctx.getVariableMapper(); 86 91 this.fnMapper = this.ctx.getFunctionMapper(); trunk/src/main/java/org/sarugo/xtc/impl/DefaultTemplateFactory.java
r2684 r2783 54 54 55 55 private final long refreshPeriod; 56 57 public DefaultTemplateFactory() throws IOException { 58 this(Compiler.getInstance(), new ResourceResolver()); 59 } 56 60 57 61 public DefaultTemplateFactory(Compiler compiler, ResourceResolver resolver) throws IOException { … … 78 82 * @see com.sun.facelets.FaceletFactory#getFacelet(java.lang.String) 79 83 */ 80 public Template get Facelet(String uri) throws IOException, TemplateException,84 public Template getTemplate(String uri) throws IOException, TemplateException, 81 85 ELException { 82 86 URL url = (URL) this.relativeLocations.get(uri); trunk/src/main/java/org/sarugo/xtc/impl/ResourceResolver.java
r2684 r2783 3 3 import java.net.URL; 4 4 5 public interface ResourceResolver { 6 public URL resolveUrl(String path); 5 public class ResourceResolver { 6 public URL resolveUrl(String path) { 7 return getClass().getResource(path); 8 } 7 9 } trunk/src/main/java/org/sarugo/xtc/package.html
r2746 r2783 18 18 --> 19 19 </head> 20 <body bgcolor="white"> 21 Public Facelet API. Most developers should be able to utilizing the framework using 22 the public classes and interfaces. 23 <p/> 24 An application that wishes to use Facelets as a ViewHandler, they must specify the 25 following in their <code>faces-config.xml</code> (@see com.sun.facelets.FaceletViewHandler). 26 <pre><code> 27 <application> 28 <view-handler>com.sun.facelets.FaceletViewHandler</view-handler> 29 </application> 30 </code></pre> 31 <p/> 32 Below is sample code for using Facelets at the API level with JavaServer Faces. 33 <pre><code> 34 // get the view to render 35 FacesContext context = FacesContext.getCurrentInstance(); 36 UIViewRoot viewToRender = context.getViewRoot(); 37 38 // grab our FaceletFactory and create a Facelet 39 FaceletFactory factory = FaceletFactory.getInstance(); 40 Facelet f = factory.getFacelet(viewToRender.getViewId()); 41 42 // populate UIViewRoot 43 f.apply(context, viewToRender); 44 </code></pre> 20 <body> 21 <p> 22 XML Template Compiler based on the Facelets package by Jacob Hookom. Licensed 23 under the <a href="http://www.sun.com/cddl/">CDDL</a>. 24 </p> 25 <p> 26 Example usage: 27 <pre> 28 TemplateFactory factory = TemplateFactory.getInstance(); 29 Template f = factory.getFacelet("template.xhtml"); 30 TemplateContext context = f.createContext(); 31 context.setAttribute("variable", "value"); 32 context.setOutputWriter(new OutputStreamWriter(System.out)); 33 f.render(context); 34 </pre> 35 </p> 36 <p> 37 The typical render lifecyle is: 38 <ol> 39 <li>Template compilation</li> 40 <li>Context creation</li> 41 <li>Render</li> 42 </ol> 43 Compilation produces a tree of TemplateHandlers which is walked during the 44 render phase. The context contains EL instance and the output writer. 45 </p> 45 46 </body> 46 47 </html> trunk/src/main/java/org/sarugo/xtc/restlet/XtcResourceHandler.java
r2729 r2783 18 18 import org.sarugo.xtc.Template; 19 19 import org.sarugo.xtc.TemplateFactory; 20 import org.sarugo.xtc.compiler.SAXCompiler;21 import org.sarugo.xtc.impl.DefaultResourceResolver;22 import org.sarugo.xtc.impl.DefaultTemplateFactory;23 20 24 21 public class XtcResourceHandler extends Finder { 25 22 26 private static TemplateFactory TEMPLATE_FACTORY = null; 27 static { 28 try { 29 TEMPLATE_FACTORY = new DefaultTemplateFactory(new SAXCompiler(), 30 new DefaultResourceResolver()); 31 } catch (IOException e) { 32 // TODO do something about this 33 e.printStackTrace(); 34 } 35 } 23 private static TemplateFactory TEMPLATE_FACTORY = TemplateFactory.getInstance(); 36 24 37 25 private Class target; … … 47 35 private List<Field> outFields; 48 36 49 public XtcResourceHandler(Context context, Class target) {37 public XtcResourceHandler(Context context, Class<Object> target) { 50 38 super(context); 51 39 this.target = target; … … 59 47 contentType = representation.contentType(); 60 48 try { 61 template = TEMPLATE_FACTORY.get Facelet(representation.value());49 template = TEMPLATE_FACTORY.getTemplate(representation.value()); 62 50 } catch (IOException e) { 63 51 // TODO Auto-generated catch block trunk/src/main/java/org/sarugo/xtc/restlet/XtcRestApplication.java
r2729 r2783 114 114 115 115 @Override 116 @SuppressWarnings("unchecked") 116 117 public Restlet createRoot() { 117 118 Router router = new Router(getContext()); trunk/src/main/java/org/sarugo/xtc/util/Classpath.java
r2684 r2783 15 15 package org.sarugo.xtc.util; 16 16 17 import java.io.BufferedReader; 17 18 import java.io.File; 18 19 import java.io.IOException; 20 import java.io.InputStreamReader; 19 21 import java.net.JarURLConnection; 20 22 import java.net.URL; … … 26 28 import java.util.jar.JarFile; 27 29 30 import org.sarugo.xtc.TemplateFactory; 31 28 32 /** 29 33 * @author Jacob Hookom … … 33 37 public final class Classpath { 34 38 35 /** 36 * 37 */ 38 public Classpath() { 39 super(); 40 } 39 private Classpath() { 40 } 41 41 42 public static URL[] search(String prefix, String suffix) throws IOException { 43 return search(Thread.currentThread().getContextClassLoader(), prefix, 44 suffix); 45 } 42 public static Object instanceFromConfig(String providerResource) 43 throws Exception { 44 // Find the provider class name 45 String providerClassName = null; 46 46 47 public static URL[] search(ClassLoader cl, String prefix, String suffix) 48 throws IOException { 49 Enumeration e = cl.getResources(prefix); 50 Set all = new HashSet(); 51 URL url; 52 URLConnection conn; 53 JarFile jarFile; 54 while (e.hasMoreElements()) { 55 url = (URL) e.nextElement(); 56 conn = url.openConnection(); 57 conn.setUseCaches(false); 58 conn.setDefaultUseCaches(false); 59 if (conn instanceof JarURLConnection) { 60 jarFile = ((JarURLConnection) conn).getJarFile(); 61 } else { 62 jarFile = getAlternativeJarFile(url); 63 } 64 if (jarFile != null) { 65 searchJar(cl, all, jarFile, prefix, suffix); 66 } else { 67 searchDir(all, new File(url.getFile()), suffix); 68 } 69 } 70 URL[] urlArray = (URL[]) all.toArray(new URL[all.size()]); 71 return urlArray; 72 } 47 // Try the default classloader 48 ClassLoader cl = TemplateFactory.class.getClassLoader(); 49 URL configURL = cl.getResource(providerResource); 73 50 74 private static void searchDir(Set result, File file, String suffix) 75 throws IOException { 76 if (file.exists() && file.isDirectory()) { 77 File[] fc = file.listFiles(); 78 String path; 79 URL src; 80 for (int i = 0; i < fc.length; i++) { 81 path = fc[i].getAbsolutePath(); 82 if (fc[i].isDirectory()) { 83 searchDir(result, fc[i], suffix); 84 } else if (path.endsWith(suffix)) { 85 //result.add(new URL("file:/" + path)); 86 result.add(fc[i].toURL()); 87 } 88 } 89 } 90 } 51 if (configURL == null) { 52 // Try the current thread's classloader 53 cl = Thread.currentThread().getContextClassLoader(); 54 configURL = cl.getResource(providerResource); 55 } 91 56 92 /** For URLs to JARs that do not use JarURLConnection - allowed by 93 * the servlet spec - attempt to produce a JarFile object all the same. 94 * Known servlet engines that function like this include Weblogic 95 * and OC4J. 96 * This is not a full solution, since an unpacked WAR or EAR will not 97 * have JAR "files" as such. 98 */ 99 private static JarFile getAlternativeJarFile(URL url) throws IOException { 100 String urlFile = url.getFile(); 101 // Trim off any suffix - which is prefixed by "!/" on Weblogic 102 int separatorIndex = urlFile.indexOf("!/"); 57 if (configURL == null) { 58 // Try the system classloader 59 cl = ClassLoader.getSystemClassLoader(); 60 configURL = cl.getResource(providerResource); 61 } 103 62 104 // OK, didn't find that. Try the less safe "!", used on OC4J 105 if (separatorIndex == -1) { 106 separatorIndex = urlFile.indexOf('!'); 107 } 63 if (configURL != null) { 64 BufferedReader reader = null; 65 try { 66 reader = new BufferedReader(new InputStreamReader(configURL 67 .openStream(), "utf-8")); 68 String providerName = reader.readLine(); 108 69 109 if (separatorIndex != -1) { 110 String jarFileUrl = urlFile.substring(0, separatorIndex); 111 // And trim off any "file:" prefix. 112 if (jarFileUrl.startsWith("file:")) { 113 jarFileUrl = jarFileUrl.substring("file:".length()); 114 } 115 return new JarFile(jarFileUrl); 116 } 117 return null; 118 } 70 if (providerName != null && providerName.indexOf('#') > 0) { 71 providerClassName = providerName.substring(0, 72 providerName.indexOf('#')).trim(); 73 } else { 74 providerClassName = providerName.trim(); 75 } 76 } catch (IOException e) { 77 // TODO logging 78 } finally { 79 if (reader != null) { 80 try { 81 reader.close(); 82 } catch (IOException e) { 83 // TODO logging 84 } 85 } 119 86 120 private static void searchJar(ClassLoader cl, Set result, JarFile file, 121 String prefix, String suffix) throws IOException { 122 Enumeration e = file.entries(); 123 JarEntry entry; 124 String name; 125 while (e.hasMoreElements()) { 126 try { 127 entry = (JarEntry) e.nextElement(); 128 } catch (Throwable t) { 129 continue; 130 } 131 name = entry.getName(); 132 if (name.startsWith(prefix) && name.endsWith(suffix)) { 133 Enumeration e2 = cl.getResources(name); 134 while (e2.hasMoreElements()) { 135 result.add(e2.nextElement()); 136 } 137 } 138 } 139 } 87 } 88 89 } 90 // Instantiate the provider 91 if (providerClassName != null) { 92 return Class.forName(providerClassName).newInstance(); 93 } else { 94 return null; 95 } 96 } 97 98 public static URL[] search(String prefix, String suffix) throws IOException { 99 return search(Thread.currentThread().getContextClassLoader(), prefix, 100 suffix); 101 } 102 103 public static URL[] search(ClassLoader cl, String prefix, String suffix) 104 throws IOException { 105 Enumeration<URL> e = cl.getResources(prefix); 106 Set<URL> all = new HashSet<URL>(); 107 URL url; 108 URLConnection conn; 109 JarFile jarFile; 110 while (e.hasMoreElements()) { 111 url = (URL) e.nextElement(); 112 conn = url.openConnection(); 113 conn.setUseCaches(false); 114 conn.setDefaultUseCaches(false); 115 if (conn instanceof JarURLConnection) { 116 jarFile = ((JarURLConnection) conn).getJarFile(); 117 } else { 118 jarFile = getAlternativeJarFile(url); 119 } 120 if (jarFile != null) { 121 searchJar(cl, all, jarFile, prefix, suffix); 122 } else { 123 searchDir(all, new File(url.getFile()), suffix); 124 } 125 } 126 URL[] urlArray = (URL[]) all.toArray(new URL[all.size()]); 127 return urlArray; 128 } 129 130 private static void searchDir(Set<URL> result, File file, String suffix) 131 throws IOException { 132 if (file.exists() && file.isDirectory()) { 133 File[] fc = file.listFiles(); 134 String path; 135 for (int i = 0; i < fc.length; i++) { 136 path = fc[i].getAbsolutePath(); 137 if (fc[i].isDirectory()) { 138 searchDir(result, fc[i], suffix); 139 } else if (path.endsWith(suffix)) { 140 // result.add(new URL("file:/" + path)); 141 result.add(fc[i].toURL()); 142 } 143 } 144 } 145 } 146 147 /** 148 * For URLs to JARs that do not use JarURLConnection - allowed by the 149 * servlet spec - attempt to produce a JarFile object all the same. Known 150 * servlet engines that function like this include Weblogic and OC4J. This 151 * is not a full solution, since an unpacked WAR or EAR will not have JAR 152 * "files" as such. 153 */ 154 private static JarFile getAlternativeJarFile(URL url) throws IOException { 155 String urlFile = url.getFile(); 156 // Trim off any suffix - which is prefixed by "!/" on Weblogic 157 int separatorIndex = urlFile.indexOf("!/"); 158 159 // OK, didn't find that. Try the less safe "!", used on OC4J 160 if (separatorIndex == -1) { 161 separatorIndex = urlFile.indexOf('!'); 162 } 163 164 if (separatorIndex != -1) { 165 String jarFileUrl = urlFile.substring(0, separatorIndex); 166 // And trim off any "file:" prefix. 167 if (jarFileUrl.startsWith("file:")) { 168 jarFileUrl = jarFileUrl.substring("file:".length()); 169 } 170 return new JarFile(jarFileUrl); 171 } 172 return null; 173 } 174 175 private static void searchJar(ClassLoader cl, Set<URL> result, 176 JarFile file, String prefix, String suffix) throws IOException { 177 Enumeration e = file.entries(); 178 JarEntry entry; 179 String name; 180 while (e.hasMoreElements()) { 181 try { 182 entry = (JarEntry) e.nextElement(); 183 } catch (Throwable t) { 184 continue; 185 } 186 name = entry.getName(); 187 if (name.startsWith(prefix) && name.endsWith(suffix)) { 188 Enumeration<URL> e2 = cl.getResources(name); 189 while (e2.hasMoreElements()) { 190 result.add(e2.nextElement()); 191 } 192 } 193 } 194 } 140 195 141 196 } trunk/src/test/java/org/sarugo/xtc/BasicTests.java
r2746 r2783 1 1 package org.sarugo.xtc; 2 2 3 import java.io.OutputStreamWriter;4 3 5 import junit.framework.TestCase; 6 7 import org.sarugo.xtc.compiler.SAXCompiler; 8 import org.sarugo.xtc.impl.DefaultTemplateFactory; 9 import org.sarugo.xtc.impl.DefaultResourceResolver; 10 11 public class BasicTests extends TestCase { 12 13 private TemplateFactory factory; 14 15 @Override 16 protected void setUp() throws Exception { 17 super.setUp(); 18 factory = new DefaultTemplateFactory(new SAXCompiler(), new DefaultResourceResolver()); 19 } 20 21 private void getAndRender(String source) throws Exception { 22 Template f = factory.getFacelet(source); 23 TemplateContext context = f.createContext(); 24 context.setOutputWriter(new OutputStreamWriter(System.out)); 25 f.render(context); 26 context.getXMLWriter().flush(); 27 } 4 public class BasicTests extends XtcTestFixture { 28 5 29 6 public void testPlainHTMLRender() throws Exception { 30 7 getAndRender("/plain.xhtml"); 31 8 } 32 9 33 10 public void testJSTLCore() throws Exception { 34 11 getAndRender("/jstl-core.xhtml"); 35 12 } 36 13 37 14 public void testJSTLFunctions() throws Exception { 38 15 getAndRender("/jstl-fn.xhtml"); trunk/src/test/java/org/sarugo/xtc/UITests.java
r2746 r2783 1 1 package org.sarugo.xtc; 2 2 3 import java.io.OutputStreamWriter;4 3 5 import junit.framework.TestCase; 6 7 import org.sarugo.xtc.compiler.SAXCompiler; 8 import org.sarugo.xtc.impl.DefaultTemplateFactory; 9 import org.sarugo.xtc.impl.DefaultResourceResolver; 10 11 public class UITests extends TestCase { 12 13 private TemplateFactory factory; 14 15 @Override 16 protected void setUp() throws Exception { 17 super.setUp(); 18 factory = new DefaultTemplateFactory(new SAXCompiler(), new DefaultResourceResolver()); 19 } 20 21 private void getAndRender(String source) throws Exception { 22 Template f = factory.getFacelet(source); 23 TemplateContext context = f.createContext(); 24 context.setOutputWriter(new OutputStreamWriter(System.out)); 25 f.render(context); 26 context.getXMLWriter().flush(); 27 } 4 public class UITests extends XtcTestFixture { 28 5 29 6 public void testInclude() throws Exception { trunk/src/test/resources/decorate.xhtml
r2750 r2783 5 5 <body> 6 6 This text should be printed. 7 <ui:decorate template="/ template.xhtml">7 <ui:decorate template="/component.xhtml"> 8 8 <ui:define name="title">Decorate Test</ui:define> 9 9 <ui:define name="body">Decorate <b>body</b></ui:define>
