public static void useSunInternalXPathSupport() throws Exception { Class.forName("com.sun.org.apache.xpath.internal.XPath"); Class c = Class.forName("freemarker.ext.dom.SunInternalXalanXPathSupport"); if (logger.isDebugEnabled()) { logger.debug("Using Sun's internal Xalan classes for XPath support"); } xpathSupportClass = c; }
/** * Convenience method. Tells the system to use Xalan for XPath queries. * * @throws Exception if the Xalan XPath classes are not present. */ public static void useXalanXPathSupport() throws Exception { Class.forName("org.apache.xpath.XPath"); Class c = Class.forName("freemarker.ext.dom.XalanXPathSupport"); if (logger.isDebugEnabled()) { logger.debug("Using Xalan classes for XPath support"); } xpathSupportClass = c; }
/** * Convenience method. Tells the system to use Jaxen for XPath queries. * * @throws Exception if the Jaxen classes are not present. */ public static void useJaxenXPathSupport() throws Exception { Class.forName("org.jaxen.dom.DOMXPath"); Class c = Class.forName("freemarker.ext.dom.JaxenXPathSupport"); jaxenXPathSupport = (XPathSupport) c.newInstance(); if (logger.isDebugEnabled()) { logger.debug("Using Jaxen classes for XPath support"); } xpathSupportClass = c; }
static { try { useDefaultXPathSupport(); } catch (Exception e) { // do nothing } if (xpathSupportClass == null && logger.isWarnEnabled()) { logger.warn("No XPath support is available."); } }
@Override public void render(Environment env, Map params, TemplateDirectiveBody body) throws IOException, TemplateException { if (getSubject() == null || !getSubject().isAuthenticated()) { log.debug("Subject does not exist or is not authenticated. Tag body will be evaluated."); renderBody(env, body); } else { log.debug("Subject exists and is authenticated. Tag body will not be evaluated."); } }
@Override public void render(Environment env, Map params, TemplateDirectiveBody body) throws IOException, TemplateException { if (getSubject() != null && getSubject().getPrincipal() != null) { log.debug("Subject has known identity (aka 'principal'). Tag body will be evaluated."); renderBody(env, body); } else { log.debug( "Subject does not exist or have a known identity (aka 'principal'). Tag body will not be evaluated."); } }
public Object findTemplateSource(String name) throws IOException { String fullPath = subdirPath + name; if (attemptFileAccess) { // First try to open as plain file (to bypass servlet container resource caches). try { String realPath = servletContext.getRealPath(fullPath); if (realPath != null) { File file = new File(realPath); if (file.canRead() && file.isFile()) { return file; } } } catch (SecurityException e) {; // ignore } } // If it fails, try to open it with servletContext.getResource. URL url = null; try { url = servletContext.getResource(fullPath); } catch (MalformedURLException e) { LOG.warn("Could not retrieve resource " + StringUtil.jQuoteNoXSS(fullPath), e); return null; } return url == null ? null : new URLTemplateSource(url, getURLConnectionUsesCaches()); }
XPathSupport getXPathSupport() { if (jaxenXPathSupport != null) { return jaxenXPathSupport; } XPathSupport xps = null; Document doc = node.getOwnerDocument(); if (doc == null) { doc = (Document) node; } synchronized (doc) { WeakReference ref = (WeakReference) xpathSupportMap.get(doc); if (ref != null) { xps = (XPathSupport) ref.get(); } if (xps == null) { try { xps = (XPathSupport) xpathSupportClass.newInstance(); xpathSupportMap.put(doc, new WeakReference(xps)); } catch (Exception e) { logger.error("Error instantiating xpathSupport class", e); } } } return xps; }
@SuppressWarnings("rawtypes") @Override public void render(Environment env, Map params, TemplateDirectiveBody body) throws IOException, TemplateException { if (getSubject() != null && getSubject().isAuthenticated()) { if (log.isDebugEnabled()) { log.debug("Subject exists and is authenticated. Tag body will be evaluated."); } renderBody(env, body); } else { if (log.isDebugEnabled()) { log.debug( "Subject does not exist or is not authenticated. Tag body will not be evaluated."); } } }
private static ExpressionFactory tryExpressionFactoryImplementation(String packagePrefix) { String className = packagePrefix + ".el.ExpressionFactoryImpl"; try { Class cl = ClassUtil.forName(className); if (ExpressionFactory.class.isAssignableFrom(cl)) { logger.info( "Using " + className + " as implementation of " + ExpressionFactory.class.getName()); return (ExpressionFactory) cl.newInstance(); } logger.warn( "Class " + className + " does not implement " + ExpressionFactory.class.getName()); } catch (ClassNotFoundException e) { } catch (Exception e) { logger.error("Failed to instantiate " + className, e); } return null; }
private static ExpressionFactory findExpressionFactoryImplementation() { ExpressionFactory ef = tryExpressionFactoryImplementation("com.sun"); if (ef == null) { ef = tryExpressionFactoryImplementation("org.apache"); if (ef == null) { logger.warn("Could not find any implementation for " + ExpressionFactory.class.getName()); } } return ef; }
/** * Freemarker tag that renders the tag body only if the current user has <em>not</em> executed a * successful authentication attempt <em>during their current session</em>. * * <p>The logically opposite tag of this one is the {@link * org.apache.shiro.web.tags.AuthenticatedTag}. * * <p>Equivalent to {@link org.apache.shiro.web.tags.NotAuthenticatedTag} */ public class NotAuthenticatedTag extends SecureTag { static final Logger log = Logger.getLogger("NotAuthenticatedTag"); @Override public void render(Environment env, Map params, TemplateDirectiveBody body) throws IOException, TemplateException { if (getSubject() == null || !getSubject().isAuthenticated()) { log.debug("Subject does not exist or is not authenticated. Tag body will be evaluated."); renderBody(env, body); } else { log.debug("Subject exists and is authenticated. Tag body will not be evaluated."); } } }
@SuppressWarnings("unchecked") Object getPrincipalFromClassName(Map params) { String type = this.getType(params); try { Class cls = Class.forName(type); return getSubject().getPrincipals().oneByType(cls); } catch (ClassNotFoundException ex) { log.error("Unable to find class for name [" + type + "]", ex); } return null; }
public static void main(String[] args) throws Exception { System.out.println(repeat("-", 80)); for (String line : readLines(getResource("banner.txt"), Charsets.UTF_8)) { System.out.println(line); } String version = ComputeCommandLine.class.getPackage().getImplementationVersion(); System.out.println("Version: " + (version != null ? version : "DEVELOPMENT")); System.out.println(repeat("-", 80)); // disable freemarker logging freemarker.log.Logger.selectLoggerLibrary(freemarker.log.Logger.LIBRARY_NONE); // parse options ComputeProperties computeProperties = new ComputeProperties(args); new ComputeCommandLine().execute(computeProperties); }
@SuppressWarnings("deprecation") private static synchronized void init() throws Exception { Version version = new Version(2, 3, 23); Logger.selectLoggerLibrary(0); cfg = new Configuration(version); // cfg.setLogTemplateExceptions(true); cfg.setCacheStorage(new MruCacheStorage(0, Integer.MAX_VALUE)); cfg.setObjectWrapper(new DefaultObjectWrapper(version)); // cfg.setDirectoryForTemplateLoading(new // File(FreemarkerUtil.class.getClassLoader().getResource("template").getFile() )); // cfg.setClassForTemplateLoading(FreemarkerUtil.class, "template"); StringTemplateLoader st = new StringTemplateLoader(); // st.putTemplate("autoMall", // "<AutoMall><docid>${autoMall.docid!}</docid><Id>${autoMall.id!}</Id><Name><![CDATA[${autoMall.name!}]]></Name><NameAlias><![CDATA[${autoMall.nameAlias!}]]></NameAlias><ImgUrl><![CDATA[${autoMall.imgUrl!}]]></ImgUrl><CarStyleId>${autoMall.carStyleId!}</CarStyleId><CategoryId>${autoMall.categoryId!}</CategoryId><CategoryLevel>${autoMall.categoryLevel!}</CategoryLevel><BrandId>${autoMall.brandId!}</BrandId><SpecificationsId>${autoMall.specificationsId!}</SpecificationsId><FactoryNumber>${autoMall.factoryNumber!}</FactoryNumber><ShelvesTime>${autoMall.shelvesTime!}</ShelvesTime><RegionId>${autoMall.regionId!}</RegionId><IsHstock>${autoMall.isHstock!}</IsHstock><IsCerGoods>${autoMall.isCerGoods!}</IsCerGoods><IsStarProducts>${autoMall.isStarProducts!}</IsStarProducts><SalesVolume>${autoMall.salesVolume!}</SalesVolume><Evaluation>${autoMall.evaluation!}</Evaluation><Price>${autoMall.price!}</Price><GoodsModel><![CDATA[${autoMall.goodsModel!}]]></GoodsModel><UserDefinedBrandName><![CDATA[${autoMall.userDefinedBrandName!}]]></UserDefinedBrandName><FactoryName><![CDATA[${autoMall.factoryName!}]]></FactoryName><CarStyleName><![CDATA[${autoMall.carStyleName!}]]></CarStyleName><ServiceStationName><![CDATA[${autoMall.serviceStationName!}]]></ServiceStationName><StoreId>${autoMall.storeId!}</StoreId><StoreName><![CDATA[${autoMall.storeName!}]]></StoreName><AttrValue><![CDATA[${autoMall.attrValue!}]]></AttrValue><CarName><![CDATA[${autoMall.carName!}]]></CarName><BrandName><![CDATA[${autoMall.brandName!}]]></BrandName></AutoMall>"); String[] templates = new String[] {"carParts", "stores", "storesrecomm"}; for (String template : templates) { st.putTemplate(template, CommonUtil.readFileInJar("/template/" + template)); } cfg.setTemplateLoader(st); }
/** * Tag used to print out the String value of a user's default principal, or a specific principal as * specified by the tag's attributes. * * <p>If no attributes are specified, the tag prints out the <tt>toString()</tt> value of the user's * default principal. If the <tt>type</tt> attribute is specified, the tag looks for a principal * with the given type. If the <tt>property</tt> attribute is specified, the tag prints the string * value of the specified property of the principal. If no principal is found or the user is not * authenticated, the tag displays nothing unless a <tt>defaultValue</tt> is specified. * * <p>Equivalent to {@link org.apache.shiro.web.tags.PrincipalTag} * * @since 0.2 */ public class PrincipalTag extends SecureTag { private final Logger log = Logger.getLogger("PrincipalTag"); /** The type of principal to be retrieved, or null if the default principal should be used. */ String getType(Map params) { return getParam(params, "type"); } /** * The property name to retrieve of the principal, or null if the <tt>toString()</tt> value should * be used. */ String getProperty(Map params) { return getParam(params, "property"); } @SuppressWarnings("unchecked") @Override public void render(Environment env, Map params, TemplateDirectiveBody body) throws IOException, TemplateException { String result = null; if (getSubject() != null) { // Get the principal to print out Object principal; if (this.getType(params) == null) { principal = getSubject().getPrincipal(); } else { principal = this.getPrincipalFromClassName(params); } // Get the string value of the principal if (principal != null) { String property = this.getProperty(params); if (property == null) { result = principal.toString(); } else { result = this.getPrincipalProperty(principal, property); } } } // Print out the principal value if not null if (result != null) { try { env.getOut().write(result); } catch (IOException ex) { throw new TemplateException("Error writing [" + result + "] to Freemarker.", ex, env); } } } @SuppressWarnings("unchecked") Object getPrincipalFromClassName(Map params) { String type = this.getType(params); try { Class cls = Class.forName(type); return getSubject().getPrincipals().oneByType(cls); } catch (ClassNotFoundException ex) { log.error("Unable to find class for name [" + type + "]", ex); } return null; } String getPrincipalProperty(Object principal, String property) throws TemplateModelException { try { BeanInfo beanInfo = Introspector.getBeanInfo(principal.getClass()); // Loop through the properties to get the string value of the specified property for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors()) { if (propertyDescriptor.getName().equals(property)) { Object value = propertyDescriptor.getReadMethod().invoke(principal, (Object[]) null); return String.valueOf(value); } } // property not found, throw throw new TemplateModelException( "Property [" + property + "] not found in principal of type [" + principal.getClass().getName() + "]"); } catch (Exception ex) { throw new TemplateModelException( "Error reading property [" + property + "] from principal of type [" + principal.getClass().getName() + "]", ex); } } }
/** * A base class for wrapping a W3C DOM Node as a FreeMarker template model. * * @author <a href="mailto:[email protected]">Jonathan Revusky</a> * @version $Id: NodeModel.java,v 1.80 2005/06/22 11:33:31 ddekany Exp $ */ public abstract class NodeModel implements TemplateNodeModel, TemplateHashModel, TemplateSequenceModel, AdapterTemplateModel, WrapperTemplateModel { static final Logger logger = Logger.getLogger("freemarker.dom"); private static DocumentBuilderFactory docBuilderFactory; private static Map xpathSupportMap = Collections.synchronizedMap(new WeakHashMap()); private static XPathSupport jaxenXPathSupport; private static ErrorHandler errorHandler; static Class xpathSupportClass; static { try { useDefaultXPathSupport(); } catch (Exception e) { // do nothing } if (xpathSupportClass == null && logger.isWarnEnabled()) { logger.warn("No XPath support is available."); } } /** The W3C DOM Node being wrapped. */ final Node node; private TemplateSequenceModel children; private NodeModel parent; /** * Sets the DOM Parser implementation to be used when building NodeModel objects from XML files. */ public static void setDocumentBuilderFactory(DocumentBuilderFactory docBuilderFactory) { NodeModel.docBuilderFactory = docBuilderFactory; } /** * @return the DOM Parser implementation that is used when building NodeModel objects from XML * files. */ public static DocumentBuilderFactory getDocumentBuilderFactory() { if (docBuilderFactory == null) { docBuilderFactory = DocumentBuilderFactory.newInstance(); docBuilderFactory.setNamespaceAware(true); docBuilderFactory.setIgnoringElementContentWhitespace(true); } return docBuilderFactory; } /** sets the error handler to use when parsing the document. */ public static void setErrorHandler(ErrorHandler errorHandler) { NodeModel.errorHandler = errorHandler; } /** * Create a NodeModel from a SAX input source. Adjacent text nodes will be merged (and CDATA * sections are considered as text nodes). * * @param removeComments whether to remove all comment nodes (recursively) from the tree before * processing * @param removePIs whether to remove all processing instruction nodes (recursively from the tree * before processing */ public static NodeModel parse(InputSource is, boolean removeComments, boolean removePIs) throws SAXException, IOException, ParserConfigurationException { DocumentBuilder builder = getDocumentBuilderFactory().newDocumentBuilder(); if (errorHandler != null) builder.setErrorHandler(errorHandler); Document doc = builder.parse(is); if (removeComments && removePIs) { simplify(doc); } else { if (removeComments) { removeComments(doc); } if (removePIs) { removePIs(doc); } mergeAdjacentText(doc); } return wrap(doc); } /** * Create a NodeModel from an XML input source. By default, all comments and processing * instruction nodes are stripped from the tree. */ public static NodeModel parse(InputSource is) throws SAXException, IOException, ParserConfigurationException { return parse(is, true, true); } /** * Create a NodeModel from an XML file. * * @param removeComments whether to remove all comment nodes (recursively) from the tree before * processing * @param removePIs whether to remove all processing instruction nodes (recursively from the tree * before processing */ public static NodeModel parse(File f, boolean removeComments, boolean removePIs) throws SAXException, IOException, ParserConfigurationException { DocumentBuilder builder = getDocumentBuilderFactory().newDocumentBuilder(); if (errorHandler != null) builder.setErrorHandler(errorHandler); Document doc = builder.parse(f); if (removeComments) { removeComments(doc); } if (removePIs) { removePIs(doc); } mergeAdjacentText(doc); return wrap(doc); } /** * Create a NodeModel from an XML file. By default, all comments and processing instruction nodes * are stripped from the tree. */ public static NodeModel parse(File f) throws SAXException, IOException, ParserConfigurationException { return parse(f, true, true); } protected NodeModel(Node node) { this.node = node; } /** @return the underling W3C DOM Node object that this TemplateNodeModel is wrapping. */ public Node getNode() { return node; } public TemplateModel get(String key) throws TemplateModelException { if (key.startsWith("@@")) { if (key.equals("@@text")) { return new SimpleScalar(getText(node)); } if (key.equals("@@namespace")) { String nsURI = node.getNamespaceURI(); return nsURI == null ? null : new SimpleScalar(nsURI); } if (key.equals("@@local_name")) { String localName = node.getLocalName(); if (localName == null) { localName = getNodeName(); } return new SimpleScalar(localName); } if (key.equals("@@markup")) { StringBuilder buf = new StringBuilder(); NodeOutputter nu = new NodeOutputter(node); nu.outputContent(node, buf); return new SimpleScalar(buf.toString()); } if (key.equals("@@nested_markup")) { StringBuilder buf = new StringBuilder(); NodeOutputter nu = new NodeOutputter(node); nu.outputContent(node.getChildNodes(), buf); return new SimpleScalar(buf.toString()); } if (key.equals("@@qname")) { String qname = getQualifiedName(); return qname == null ? null : new SimpleScalar(qname); } } XPathSupport xps = getXPathSupport(); if (xps != null) { return xps.executeQuery(node, key); } else { throw new TemplateModelException( "Can't try to resolve the XML query key, because no XPath support is available. " + "It's either malformed or an XPath expression: " + key); } } public TemplateNodeModel getParentNode() { if (parent == null) { Node parentNode = node.getParentNode(); if (parentNode == null) { if (node instanceof Attr) { parentNode = ((Attr) node).getOwnerElement(); } } parent = wrap(parentNode); } return parent; } public TemplateSequenceModel getChildNodes() { if (children == null) { children = new NodeListModel(node.getChildNodes(), this); } return children; } public final String getNodeType() throws TemplateModelException { short nodeType = node.getNodeType(); switch (nodeType) { case Node.ATTRIBUTE_NODE: return "attribute"; case Node.CDATA_SECTION_NODE: return "text"; case Node.COMMENT_NODE: return "comment"; case Node.DOCUMENT_FRAGMENT_NODE: return "document_fragment"; case Node.DOCUMENT_NODE: return "document"; case Node.DOCUMENT_TYPE_NODE: return "document_type"; case Node.ELEMENT_NODE: return "element"; case Node.ENTITY_NODE: return "entity"; case Node.ENTITY_REFERENCE_NODE: return "entity_reference"; case Node.NOTATION_NODE: return "notation"; case Node.PROCESSING_INSTRUCTION_NODE: return "pi"; case Node.TEXT_NODE: return "text"; } throw new TemplateModelException( "Unknown node type: " + nodeType + ". This should be impossible!"); } public TemplateModel exec(List args) throws TemplateModelException { if (args.size() != 1) { throw new TemplateModelException("Expecting exactly one arguments"); } String query = (String) args.get(0); // Now, we try to behave as if this is an XPath expression XPathSupport xps = getXPathSupport(); if (xps == null) { throw new TemplateModelException("No XPath support available"); } return xps.executeQuery(node, query); } public final int size() { return 1; } public final TemplateModel get(int i) { return i == 0 ? this : null; } public String getNodeNamespace() { int nodeType = node.getNodeType(); if (nodeType != Node.ATTRIBUTE_NODE && nodeType != Node.ELEMENT_NODE) { return null; } String result = node.getNamespaceURI(); if (result == null && nodeType == Node.ELEMENT_NODE) { result = ""; } else if ("".equals(result) && nodeType == Node.ATTRIBUTE_NODE) { result = null; } return result; } public final int hashCode() { return node.hashCode(); } public boolean equals(Object other) { if (other == null) return false; return other.getClass() == this.getClass() && ((NodeModel) other).node.equals(this.node); } public static NodeModel wrap(Node node) { if (node == null) { return null; } NodeModel result = null; switch (node.getNodeType()) { case Node.DOCUMENT_NODE: result = new DocumentModel((Document) node); break; case Node.ELEMENT_NODE: result = new ElementModel((Element) node); break; case Node.ATTRIBUTE_NODE: result = new AttributeNodeModel((Attr) node); break; case Node.CDATA_SECTION_NODE: case Node.COMMENT_NODE: case Node.TEXT_NODE: result = new CharacterDataNodeModel((org.w3c.dom.CharacterData) node); break; case Node.PROCESSING_INSTRUCTION_NODE: result = new PINodeModel((ProcessingInstruction) node); break; case Node.DOCUMENT_TYPE_NODE: result = new DocumentTypeModel((DocumentType) node); break; } return result; } /** * Recursively removes all comment nodes from the subtree. * * @see #simplify */ public static void removeComments(Node node) { NodeList children = node.getChildNodes(); int i = 0; int len = children.getLength(); while (i < len) { Node child = children.item(i); if (child.hasChildNodes()) { removeComments(child); i++; } else { if (child.getNodeType() == Node.COMMENT_NODE) { node.removeChild(child); len--; } else { i++; } } } } /** * Recursively removes all processing instruction nodes from the subtree. * * @see #simplify */ public static void removePIs(Node node) { NodeList children = node.getChildNodes(); int i = 0; int len = children.getLength(); while (i < len) { Node child = children.item(i); if (child.hasChildNodes()) { removePIs(child); i++; } else { if (child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) { node.removeChild(child); len--; } else { i++; } } } } /** * Merges adjacent text/cdata nodes, so that there are no adjacent text/cdata nodes. Operates * recursively on the entire subtree. You thus lose information about any CDATA sections occurring * in the doc. * * @see #simplify */ public static void mergeAdjacentText(Node node) { Node child = node.getFirstChild(); while (child != null) { if (child instanceof Text || child instanceof CDATASection) { Node next = child.getNextSibling(); if (next instanceof Text || next instanceof CDATASection) { String fullText = child.getNodeValue() + next.getNodeValue(); ((CharacterData) child).setData(fullText); node.removeChild(next); } } else { mergeAdjacentText(child); } child = child.getNextSibling(); } } /** * Removes comments and processing instruction, and then unites adjacent text nodes. Note that * CDATA sections count as text nodes. */ public static void simplify(Node node) { NodeList children = node.getChildNodes(); int i = 0; int len = children.getLength(); Node prevTextChild = null; while (i < len) { Node child = children.item(i); if (child.hasChildNodes()) { simplify(child); prevTextChild = null; i++; } else { int type = child.getNodeType(); if (type == Node.PROCESSING_INSTRUCTION_NODE) { node.removeChild(child); len--; } else if (type == Node.COMMENT_NODE) { node.removeChild(child); len--; } else if (type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE) { if (prevTextChild != null) { CharacterData ptc = (CharacterData) prevTextChild; ptc.setData(ptc.getNodeValue() + child.getNodeValue()); node.removeChild(child); len--; } else { prevTextChild = child; i++; } } else { prevTextChild = null; i++; } } } } NodeModel getDocumentNodeModel() { if (node instanceof Document) { return this; } else { return wrap(node.getOwnerDocument()); } } /** * Tells the system to use (restore) the default (initial) XPath system used by this FreeMarker * version on this system. */ public static void useDefaultXPathSupport() { xpathSupportClass = null; jaxenXPathSupport = null; try { useXalanXPathSupport(); } catch (Exception e) {; // ignore } if (xpathSupportClass == null) try { useSunInternalXPathSupport(); } catch (Exception e) {; // ignore } if (xpathSupportClass == null) try { useJaxenXPathSupport(); } catch (Exception e) {; // ignore } } /** * Convenience method. Tells the system to use Jaxen for XPath queries. * * @throws Exception if the Jaxen classes are not present. */ public static void useJaxenXPathSupport() throws Exception { Class.forName("org.jaxen.dom.DOMXPath"); Class c = Class.forName("freemarker.ext.dom.JaxenXPathSupport"); jaxenXPathSupport = (XPathSupport) c.newInstance(); if (logger.isDebugEnabled()) { logger.debug("Using Jaxen classes for XPath support"); } xpathSupportClass = c; } /** * Convenience method. Tells the system to use Xalan for XPath queries. * * @throws Exception if the Xalan XPath classes are not present. */ public static void useXalanXPathSupport() throws Exception { Class.forName("org.apache.xpath.XPath"); Class c = Class.forName("freemarker.ext.dom.XalanXPathSupport"); if (logger.isDebugEnabled()) { logger.debug("Using Xalan classes for XPath support"); } xpathSupportClass = c; } public static void useSunInternalXPathSupport() throws Exception { Class.forName("com.sun.org.apache.xpath.internal.XPath"); Class c = Class.forName("freemarker.ext.dom.SunInternalXalanXPathSupport"); if (logger.isDebugEnabled()) { logger.debug("Using Sun's internal Xalan classes for XPath support"); } xpathSupportClass = c; } /** * Set an alternative implementation of freemarker.ext.dom.XPathSupport to use as the XPath * engine. * * @param cl the class, or <code>null</code> to disable XPath support. */ public static void setXPathSupportClass(Class cl) { if (cl != null && !XPathSupport.class.isAssignableFrom(cl)) { throw new RuntimeException( "Class " + cl.getName() + " does not implement freemarker.ext.dom.XPathSupport"); } xpathSupportClass = cl; } /** * Get the currently used freemarker.ext.dom.XPathSupport used as the XPath engine. Returns <code> * null</code> if XPath support is disabled. */ public static Class getXPathSupportClass() { return xpathSupportClass; } private static String getText(Node node) { String result = ""; if (node instanceof Text || node instanceof CDATASection) { result = ((org.w3c.dom.CharacterData) node).getData(); } else if (node instanceof Element) { NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { result += getText(children.item(i)); } } else if (node instanceof Document) { result = getText(((Document) node).getDocumentElement()); } return result; } XPathSupport getXPathSupport() { if (jaxenXPathSupport != null) { return jaxenXPathSupport; } XPathSupport xps = null; Document doc = node.getOwnerDocument(); if (doc == null) { doc = (Document) node; } synchronized (doc) { WeakReference ref = (WeakReference) xpathSupportMap.get(doc); if (ref != null) { xps = (XPathSupport) ref.get(); } if (xps == null) { try { xps = (XPathSupport) xpathSupportClass.newInstance(); xpathSupportMap.put(doc, new WeakReference(xps)); } catch (Exception e) { logger.error("Error instantiating xpathSupport class", e); } } } return xps; } String getQualifiedName() throws TemplateModelException { return getNodeName(); } public Object getAdaptedObject(Class hint) { return node; } public Object getWrappedObject() { return node; } }
/** * A {@link TemplateLoader} that uses streams reachable through {@link * ServletContext#getResource(String)} as its source of templates. */ public class WebappTemplateLoader implements TemplateLoader { private static final Logger LOG = Logger.getLogger("freemarker.cache"); private final ServletContext servletContext; private final String subdirPath; private Boolean urlConnectionUsesCaches; private boolean attemptFileAccess = true; /** * Creates a resource template cache that will use the specified servlet context to load the * resources. It will use the base path of <code>"/"</code> meaning templates will be resolved * relative to the servlet context root location. * * @param servletContext the servlet context whose {@link ServletContext#getResource(String)} will * be used to load the templates. */ public WebappTemplateLoader(ServletContext servletContext) { this(servletContext, "/"); } /** * Creates a template loader that will use the specified servlet context to load the resources. It * will use the specified base path, which is interpreted relatively to the context root (does not * mater if you start it with "/" or not). Path components should be separated by forward slashes * independently of the separator character used by the underlying operating system. * * @param servletContext the servlet context whose {@link ServletContext#getResource(String)} will * be used to load the templates. * @param subdirPath the base path to template resources. */ public WebappTemplateLoader(ServletContext servletContext, String subdirPath) { if (servletContext == null) { throw new IllegalArgumentException("servletContext == null"); } if (subdirPath == null) { throw new IllegalArgumentException("path == null"); } subdirPath = subdirPath.replace('\\', '/'); if (!subdirPath.endsWith("/")) { subdirPath += "/"; } if (!subdirPath.startsWith("/")) { subdirPath = "/" + subdirPath; } this.subdirPath = subdirPath; this.servletContext = servletContext; } public Object findTemplateSource(String name) throws IOException { String fullPath = subdirPath + name; if (attemptFileAccess) { // First try to open as plain file (to bypass servlet container resource caches). try { String realPath = servletContext.getRealPath(fullPath); if (realPath != null) { File file = new File(realPath); if (file.canRead() && file.isFile()) { return file; } } } catch (SecurityException e) {; // ignore } } // If it fails, try to open it with servletContext.getResource. URL url = null; try { url = servletContext.getResource(fullPath); } catch (MalformedURLException e) { LOG.warn("Could not retrieve resource " + StringUtil.jQuoteNoXSS(fullPath), e); return null; } return url == null ? null : new URLTemplateSource(url, getURLConnectionUsesCaches()); } public long getLastModified(Object templateSource) { if (templateSource instanceof File) { return ((File) templateSource).lastModified(); } else { return ((URLTemplateSource) templateSource).lastModified(); } } public Reader getReader(Object templateSource, String encoding) throws IOException { if (templateSource instanceof File) { return new InputStreamReader(new FileInputStream((File) templateSource), encoding); } else { return new InputStreamReader(((URLTemplateSource) templateSource).getInputStream(), encoding); } } public void closeTemplateSource(Object templateSource) throws IOException { if (templateSource instanceof File) { // Do nothing. } else { ((URLTemplateSource) templateSource).close(); } } /** * Getter pair of {@link #setURLConnectionUsesCaches(Boolean)}. * * @since 2.3.21 */ public Boolean getURLConnectionUsesCaches() { return urlConnectionUsesCaches; } /** * It does the same as {@link URLTemplateLoader#setURLConnectionUsesCaches(Boolean)}; see there. * * @since 2.3.21 */ public void setURLConnectionUsesCaches(Boolean urlConnectionUsesCaches) { this.urlConnectionUsesCaches = urlConnectionUsesCaches; } /** * Show class name and some details that are useful in template-not-found errors. * * @since 2.3.21 */ @Override public String toString() { return TemplateLoaderUtils.getClassNameForToString(this) + "(subdirPath=" + StringUtil.jQuote(subdirPath) + ", servletContext={contextPath=" + StringUtil.jQuote(getContextPath()) + ", displayName=" + StringUtil.jQuote(servletContext.getServletContextName()) + "})"; } /** * Gets the context path if we are on Servlet 2.5+, or else returns failure description string. */ private String getContextPath() { try { Method m = servletContext.getClass().getMethod("getContextPath", CollectionUtils.EMPTY_CLASS_ARRAY); return (String) m.invoke(servletContext, CollectionUtils.EMPTY_OBJECT_ARRAY); } catch (Throwable e) { return "[can't query before Serlvet 2.5]"; } } /** * Getter pair of {@link #setAttemptFileAccess(boolean)}. * * @since 2.3.23 */ public boolean getAttemptFileAccess() { return attemptFileAccess; } /** * Specifies that before loading templates with {@link ServletContext#getResource(String)}, it * should try to load the template as {@link File}; default is {@code true}, though it's not * always recommended anymore. This is a workaround for the case when the servlet container * doesn't show template modifications after the template was already loaded earlier. But it's * certainly better to counter this problem by disabling the URL connection cache with {@link * #setURLConnectionUsesCaches(Boolean)}, which is also the default behavior with {@link * Configuration#setIncompatibleImprovements(freemarker.template.Version) * incompatible_improvements} 2.3.21 and later. * * @since 2.3.23 */ public void setAttemptFileAccess(boolean attemptLoadingFromFile) { this.attemptFileAccess = attemptLoadingFromFile; } }
/** @author Attila Szegedi */ class FreeMarkerJspApplicationContext implements JspApplicationContext { private static final Logger logger = Logger.getLogger("freemarker.jsp"); private static final ExpressionFactory expressionFactoryImpl = findExpressionFactoryImplementation(); private final LinkedList listeners = new LinkedList(); private final CompositeELResolver elResolver = new CompositeELResolver(); private final CompositeELResolver additionalResolvers = new CompositeELResolver(); { elResolver.add(new ImplicitObjectELResolver()); elResolver.add(additionalResolvers); elResolver.add(new MapELResolver()); elResolver.add(new ResourceBundleELResolver()); elResolver.add(new ListELResolver()); elResolver.add(new ArrayELResolver()); elResolver.add(new BeanELResolver()); elResolver.add(new ScopedAttributeELResolver()); } public void addELContextListener(ELContextListener listener) { synchronized (listeners) { listeners.addLast(listener); } } private static ExpressionFactory findExpressionFactoryImplementation() { ExpressionFactory ef = tryExpressionFactoryImplementation("com.sun"); if (ef == null) { ef = tryExpressionFactoryImplementation("org.apache"); if (ef == null) { logger.warn("Could not find any implementation for " + ExpressionFactory.class.getName()); } } return ef; } private static ExpressionFactory tryExpressionFactoryImplementation(String packagePrefix) { String className = packagePrefix + ".el.ExpressionFactoryImpl"; try { Class cl = ClassUtil.forName(className); if (ExpressionFactory.class.isAssignableFrom(cl)) { logger.info( "Using " + className + " as implementation of " + ExpressionFactory.class.getName()); return (ExpressionFactory) cl.newInstance(); } logger.warn( "Class " + className + " does not implement " + ExpressionFactory.class.getName()); } catch (ClassNotFoundException e) { } catch (Exception e) { logger.error("Failed to instantiate " + className, e); } return null; } public void addELResolver(ELResolver resolver) { additionalResolvers.add(resolver); } public ExpressionFactory getExpressionFactory() { return expressionFactoryImpl; } ELContext createNewELContext(final FreeMarkerPageContext pageCtx) { ELContext ctx = new FreeMarkerELContext(pageCtx); ELContextEvent event = new ELContextEvent(ctx); synchronized (listeners) { for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { ELContextListener l = (ELContextListener) iter.next(); l.contextCreated(event); } } return ctx; } private class FreeMarkerELContext extends ELContext { private final FreeMarkerPageContext pageCtx; FreeMarkerELContext(FreeMarkerPageContext pageCtx) { this.pageCtx = pageCtx; } public ELResolver getELResolver() { return elResolver; } public FunctionMapper getFunctionMapper() { return null; } public VariableMapper getVariableMapper() { return new VariableMapper() { public ValueExpression resolveVariable(String name) { Object obj = pageCtx.findAttribute(name); if (obj == null) { return null; } return expressionFactoryImpl.createValueExpression(obj, obj.getClass()); } public ValueExpression setVariable(String name, ValueExpression value) { ValueExpression prev = resolveVariable(name); pageCtx.setAttribute(name, value.getValue(FreeMarkerELContext.this)); return prev; } }; } } }