/* * Copyright (C) 2000 - 2012 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: cfSCRIPT.java 2197 2012-07-21 16:55:40Z alan $ */ package com.naryx.tagfusion.cfm.tag; import java.io.BufferedReader; import java.io.CharArrayReader; import java.io.IOException; import java.io.Serializable; import java.util.HashMap; import java.util.Iterator; import org.antlr.runtime.CommonTokenStream; import org.antlr.runtime.ParserRuleReturnScope; import org.antlr.runtime.RecognitionException; import org.antlr.runtime.tree.CommonTree; import org.antlr.runtime.tree.CommonTreeNodeStream; import com.naryx.tagfusion.cfm.engine.catchDataFactory; import com.naryx.tagfusion.cfm.engine.cfEngine; import com.naryx.tagfusion.cfm.engine.cfSession; 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.sourceReader; import com.naryx.tagfusion.cfm.parser.ANTLRNoCaseReaderStream; import com.naryx.tagfusion.cfm.parser.CFMLLexer; import com.naryx.tagfusion.cfm.parser.CFMLParser; import com.naryx.tagfusion.cfm.parser.CFMLTree; import com.naryx.tagfusion.cfm.parser.poundSignFilterStream; import com.naryx.tagfusion.cfm.parser.poundSignFilterStreamException; import com.naryx.tagfusion.cfm.parser.runTime; import com.naryx.tagfusion.cfm.parser.script.CFCompoundStatement; import com.naryx.tagfusion.cfm.parser.script.CFEmptyStatement; import com.naryx.tagfusion.cfm.parser.script.CFFuncDeclStatement; import com.naryx.tagfusion.cfm.parser.script.CFScriptStatement; import com.naryx.tagfusion.cfm.parser.script.CFStatementResult; import com.naryx.tagfusion.cfm.parser.script.userDefinedFunction; import com.naryx.tagfusion.xmlConfig.xmlCFML; public class cfSCRIPT extends cfTag implements ContentTypeStaticInterface, Serializable { static final long serialVersionUID = 1; private transient CFScriptStatement scriptStatement; private static HashMap<String,String> registeredLanguages = null; public static void init( xmlCFML configFile ) { cfEngine.thisPlatform.registerScriptExtensions(); } /** * Allows external engines to be able to register for lang="" support * * @param lang * @param impl */ public static void registerLanguage( String lang, String impl ){ if ( registeredLanguages == null ) registeredLanguages = new HashMap<String,String>(); registeredLanguages.put(lang.toLowerCase(), impl); cfEngine.log("cfSCRIPT Registered: language=" + lang.toLowerCase() + "; class=" + impl ); } public static cfSCRIPT getLanguage( String lang ) { String cp = registeredLanguages.get(lang.toLowerCase()); if ( cp == null ) return null; try { return (cfSCRIPT)Class.forName(cp).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } protected void defaultParameters( String _tag ) throws cfmBadFileException { parseTagHeader( _tag ); } @SuppressWarnings("unchecked") public java.util.Map getInfo(){ return createInfo("system", "Contains block of CFSCRIPT statements to be evaluated."); } public java.util.Map[] getAttInfo(){ return new java.util.Map[] { createAttInfo("LANGUAGE", "Specifies the type of language contained within the cfscript block. Additional languages are added through the plugin interface. Built-in support for 'java' and 'javascript'", "", false ), createAttInfo("JARLIST", "For language='java' only. Specifies the comma-separated list of JAR files that are in the /WEB-INF/lib/ folder that should be added to the dynamic compilation", "", false ), createAttInfo("IMPORT", "For language='java' only. Specifies the comma-separated list of packages that will be used to resolve inner class references. By default these are included: java.io.*, java.net.*, java.math.*, java.util.*", "", false ) }; } public String getEndMarker(){ return "</CFSCRIPT>"; } protected void tagLoadingComplete() throws cfmBadFileException { initScriptStatement(); if ( scriptStatement instanceof CFCompoundStatement ) { cfFile parentFile = this.getFile(); Iterator<CFScriptStatement> stmtIter = ((CFCompoundStatement)scriptStatement).getStatements().iterator(); while ( stmtIter.hasNext() ) { CFScriptStatement stmt = stmtIter.next(); if ( stmt instanceof CFFuncDeclStatement ) { userDefinedFunction udf = ((CFFuncDeclStatement)stmt).getUDF(); parentFile.addUDF( this, udf ); if ( this.isSubordinate( "CFCOMPONENT" ) ) { ((cfCOMPONENT)parentTag).addFunctionMetaData( udf.getMetaData() ); } } } } // Attach a reference to this tag to each of the statements this defines scriptStatement.setHostTag( this ); // Clean up wrapUnsedVars(); } public cfTagReturnType render( cfSession _Session ) throws cfmRunTimeException { CFStatementResult result = runTime.run( _Session, scriptStatement ); // allow return values to propagate up for CFFUNCTION if ( ( result != null ) && result.isReturn() ) return cfTagReturnType.newReturn( result.getReturnValue() ); else return cfTagReturnType.NORMAL; } public void setStatement( CFScriptStatement _statement ){ scriptStatement = _statement; } private void initScriptStatement() throws cfmBadFileException { if ( scriptStatement != null ) return; // Need to parse and compile the script char [] scriptWithEndTag = getStaticBody(); if ( scriptWithEndTag.length == 0 ){ scriptStatement = new CFEmptyStatement(); return; } try{ ANTLRNoCaseReaderStream input = new ANTLRNoCaseReaderStream( new poundSignFilterStream( new CharArrayReader( scriptWithEndTag ) ) ); CFMLLexer lexer = new CFMLLexer( input ); CommonTokenStream tokens = new CommonTokenStream( lexer ); CFMLParser parser = new CFMLParser( tokens ); ParserRuleReturnScope r = parser.scriptBlock(); CommonTree tree = (CommonTree) r.getTree(); CommonTreeNodeStream nodes = new CommonTreeNodeStream( tree ); nodes.setTokenStream( tokens ); CFMLTree p2 = new CFMLTree( nodes ); scriptStatement = p2.scriptBlock(); // find special cases of "#varName#"="value"; sourceReader sr = new sourceReader( new BufferedReader( new CharArrayReader( scriptWithEndTag ) ) ); scriptStatement.checkIndirectAssignments( sr.getLines() ); }catch( RecognitionException e ){ int startLine = e.line - 1; throw new cfmBadFileException( catchDataFactory.extendedScriptException( "errorCode.expressionError", "expression.Parse", new String[] { e.getMessage() }, startLine, 1 ) ); } catch ( IOException e ) { throw new cfmBadFileException(catchDataFactory.extendedException( "errorCode.expressionError", "expression.Parse", new String[] { new String( scriptWithEndTag ) }, e.getMessage() ) ); } catch ( poundSignFilterStreamException e ) { throw new cfmBadFileException(catchDataFactory.extendedException( "errorCode.expressionError", "expression.Parse", new String[] { new String( scriptWithEndTag ) }, e.getMessage() ) ); } } }