/* * Copyright (C) 2000 - 2013 TagServlet Ltd * * This file is part of Open BlueDragon (OpenBD) CFML Server Engine. * * OpenBD is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * Free Software Foundation,version 3. * * OpenBD is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenBD. If not, see http://www.gnu.org/licenses/ * * Additional permission under GNU GPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or combining * it with any of the JARS listed in the README.txt (or a modified version of * (that library), containing parts covered by the terms of that JAR, the * licensors of this Program grant you additional permission to convey the * resulting work. * README.txt @ http://www.openbluedragon.org/license/README.txt * * http://openbd.org/ * $Id: cfCustomTag.java 2334 2013-03-03 16:41:52Z alan $ */ package com.naryx.tagfusion.cfm.tag; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import com.naryx.tagfusion.cfm.engine.catchDataFactory; import com.naryx.tagfusion.cfm.engine.cfSession; import com.naryx.tagfusion.cfm.engine.cfStructData; import com.naryx.tagfusion.cfm.engine.cfmBadFileException; import com.naryx.tagfusion.cfm.engine.cfmRunTimeException; import com.naryx.tagfusion.cfm.file.cfFile; import com.naryx.tagfusion.cfm.file.cfmlFileCache; import com.naryx.tagfusion.cfm.file.cfmlURI; public class cfCustomTag extends cfMODULE implements cfOptionalBodyTag, Serializable { static final long serialVersionUID = 1; private transient cfmlURI[] directoryMapping; private String[] directories = null; // used for CFIMPORTed tags private boolean imported = false; protected void defaultParameters(String _tag) throws cfmBadFileException { tagName = getTagName(_tag).trim(); customTagName = tagName.toUpperCase(); parseTagHeader(_tag); // Need to get the file mapping setDirectoryMappings(); setCustomTagKey(tagName); } private void setDirectoryMappings() throws cfmBadFileException { List<String> directory = cfmlFileCache.getCustomDirMapping(tagName.toUpperCase()); if (directory == null) { throw invalidAttributeException("cfmodule.missingMapping", new String[] { tagName }); } String filename = tagName.substring(tagName.indexOf("_") + 1) + ".cfm"; directoryMapping = new cfmlURI[directory.size()]; for (int i = 0; i < directory.size(); i++) { directoryMapping[i] = new cfmlURI(directory.get(i), filename); } } // used by cfimported custom tags protected void defaultParameters(String _tag, String _dir) throws cfmBadFileException { tagName = getTagName(_tag, false).trim(); // doesn't matter what the prefix of the cfimport tag is, the custom tag name begins with "CF_" customTagName = "CF_" + tagName.substring(tagName.indexOf(':') + 1).toUpperCase(); imported = true; parseTagHeader(_tag); directories = com.nary.util.string.convertToList(_dir, ','); setCustomTagKey(tagName); } private static String getTagName(String tag) { return getTagName(tag, true); } private static String getTagName(String tag, boolean _convert) { // find first whitespace character int c1 = -1; for (int i = 1; (i < tag.length()) && (c1 == -1); i++) { if (Character.isWhitespace(tag.charAt(i))) c1 = i; } String tagname; if (c1 == -1) { if (tag.endsWith("/>")) tagname = tag.substring(1, tag.length() - 2); else tagname = tag.substring(1, tag.length() - 1); } else tagname = tag.substring(1, c1); if (_convert) { return tagname.replace(':', '_'); } return tagname; } /** * Have to override the cfMODULE implementation as it excludes the possibility of NAME, TEMPLATE and ATTRIBUTECOLLECTION named attributes (e.g. in <cf_mycustomtag name="foo">, the name attribute would not get passed to the attributes scope of this tag. */ protected cfStructData packageUpAttributes(cfSession _Session) throws cfmRunTimeException { cfStructData attributeValues = super.packageUpAttributes(_Session); if (properties.containsKey("TEMPLATE")) { attributeValues.setData("template", getDynamic(_Session, "TEMPLATE")); } if (properties.containsKey("NAME")) { attributeValues.setData("name", getDynamic(_Session, "NAME")); } return attributeValues; } // ----------------------------------------------------------------- public cfTagReturnType render(cfSession _Session) throws cfmRunTimeException { cfFile svrFile = null; if (imported) { resolveImportedTagMappings(_Session); // shallow search of custom tag directories (does not search local directory) svrFile = getCustomTagFile(_Session, tagName.substring(tagName.indexOf(":") + 1), directoryMapping, false, false, false); } else { String tagFileName = tagName.substring(tagName.indexOf("_") + 1); if (directoryMapping == null) setDirectoryMappings(); // Do we have a custom tag situation? cfmlURI[] dirs = getCombinedCustomTagDirectories(_Session, tagFileName + ".cfm", directoryMapping); // deep search of custom tag directories (including local directory) svrFile = getCustomTagFile(_Session, tagFileName, dirs, true, true); } // Check to see we have an instance if (svrFile == null) throw newRunTimeException(catchDataFactory.missingCustomTagException(tagName)); // Render the custom file // return customRender(_Session, svrFile); return realCustomRender(_Session, svrFile); } // ---------------------------------------------------------- // if this tag was imported then it resolves the directoryMapping field private void resolveImportedTagMappings(cfSession _Session) { // if this custom tag was created as an imported tag // (i.e. the mapping was CFIMPORTed to enable this custom tag) if (directories != null) { String dir; List<cfmlURI> mappings = new ArrayList<cfmlURI>(); for (int i = 0; i < directories.length; i++) { dir = directories[i]; // resolve the dir to include the file name String filename = tagName.substring(tagName.indexOf(":") + 1) + ".cfm"; if (!dir.endsWith("/")) { dir = dir + '/'; } dir = dir + filename; // if the path given is relative to the current directory if (!dir.startsWith("/")) { String path = _Session.getPresentFilePath(); if (path == null) { path = _Session.getPresentURIPath(); } mappings.add(new cfmlURI(path, dir)); } else { // the path is relative to the web root so work out the // dir remains the same but cf mappings also need to be searched cfmlURI resolvedPath = getMappedCfmlURI(_Session, dir); if (resolvedPath != null) { mappings.add(new cfmlURI(_Session.REQ, dir)); mappings.add(resolvedPath); } else { mappings.add(new cfmlURI(_Session.REQ, dir)); } } } directoryMapping = new cfmlURI[mappings.size()]; for (int j = 0; j < mappings.size(); j++) { directoryMapping[j] = (cfmlURI) mappings.get(j); } } } }