001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.type; 020 021import java.io.IOException; 022import java.io.ObjectInput; 023import java.io.ObjectOutput; 024 025import lucee.runtime.ComponentImpl; 026import lucee.runtime.PageContext; 027import lucee.runtime.dump.DumpData; 028import lucee.runtime.dump.DumpProperties; 029import lucee.runtime.engine.ThreadLocalPageContext; 030import lucee.runtime.exp.PageException; 031import lucee.runtime.type.scope.ClosureScope; 032import lucee.runtime.type.scope.Variables; 033import lucee.runtime.type.util.ComponentUtil; 034import lucee.runtime.type.util.KeyConstants; 035import lucee.runtime.type.util.UDFUtil; 036 037public class Closure extends UDFImpl { 038 039 040 041 private static final long serialVersionUID = -7200106903813254844L; // do not change 042 043 private Variables variables; 044 045 046 public Closure(){ 047 super(); 048 } 049 050 public Closure(UDFProperties properties) { 051 super(properties); 052 PageContext pc = ThreadLocalPageContext.get(); 053 if(pc.undefinedScope().getCheckArguments()) 054 this.variables=new ClosureScope(pc,pc.argumentsScope(),pc.localScope(),pc.variablesScope()); 055 else{ 056 this.variables=pc.variablesScope(); 057 variables.setBind(true); 058 } 059 } 060 061 public Closure(UDFProperties properties, Variables variables) { 062 super(properties); 063 this.variables=variables; 064 065 } 066 067 @Override 068 public UDF duplicate(ComponentImpl c) { 069 Closure clo = new Closure(properties,variables);// TODO duplicate variables as well? 070 clo.ownerComponent=c; 071 clo.setAccess(getAccess()); 072 return clo; 073 } 074 075 @Override 076 public Object callWithNamedValues(PageContext pc,Collection.Key calledName, Struct values, boolean doIncludePath) throws PageException { 077 Variables parent=pc.variablesScope(); 078 try{ 079 pc.setVariablesScope(variables); 080 return super.callWithNamedValues(pc, calledName,values, doIncludePath); 081 } 082 finally { 083 pc.setVariablesScope(parent); 084 } 085 } 086 087 @Override 088 public Object callWithNamedValues(PageContext pc, Struct values, boolean doIncludePath) throws PageException { 089 Variables parent=pc.variablesScope(); 090 try{ 091 pc.setVariablesScope(variables); 092 return super.callWithNamedValues(pc, values, doIncludePath); 093 } 094 finally { 095 pc.setVariablesScope(parent); 096 } 097 } 098 099 @Override 100 public Object call(PageContext pc,Collection.Key calledName, Object[] args, boolean doIncludePath) throws PageException { 101 Variables parent=pc.variablesScope(); 102 try{ 103 pc.setVariablesScope(variables); 104 return super.call(pc, calledName, args, doIncludePath); 105 } 106 finally { 107 pc.setVariablesScope(parent); 108 } 109 } 110 111 @Override 112 public Object call(PageContext pc, Object[] args, boolean doIncludePath) throws PageException { 113 Variables parent=pc.variablesScope(); 114 try{ 115 pc.setVariablesScope(variables); 116 return super.call(pc, args, doIncludePath); 117 } 118 finally { 119 pc.setVariablesScope(parent); 120 } 121 } 122 123 @Override 124 public DumpData toDumpData(PageContext pageContext, int maxlevel,DumpProperties dp) { 125 return UDFUtil.toDumpData(pageContext, maxlevel, dp,this,UDFUtil.TYPE_CLOSURE); 126 } 127 128 @Override 129 public Struct getMetaData(PageContext pc) throws PageException { 130 Struct meta = ComponentUtil.getMetaData(pc, properties); 131 meta.setEL(KeyConstants._closure, Boolean.TRUE);// MUST move this to class UDFProperties 132 meta.setEL("ANONYMOUSCLOSURE", Boolean.TRUE);// MUST move this to class UDFProperties 133 134 return meta; 135 } 136 137 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 138 // access 139 setAccess(in.readInt()); 140 141 // properties 142 properties=(UDFPropertiesImpl) in.readObject(); 143 } 144 145 146 public void writeExternal(ObjectOutput out) throws IOException { 147 // access 148 out.writeInt(getAccess()); 149 150 // properties 151 out.writeObject(properties); 152 } 153}