0001: /*
0002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
0003: *
0004: * This file is part of Resin(R) Open Source
0005: *
0006: * Each copy or derived work must preserve the copyright notice and this
0007: * notice unmodified.
0008: *
0009: * Resin Open Source is free software; you can redistribute it and/or modify
0010: * it under the terms of the GNU General Public License as published by
0011: * the Free Software Foundation; either version 2 of the License, or
0012: * (at your option) any later version.
0013: *
0014: * Resin Open Source is distributed in the hope that it will be useful,
0015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
0017: * of NON-INFRINGEMENT. See the GNU General Public License for more
0018: * details.
0019: *
0020: * You should have received a copy of the GNU General Public License
0021: * along with Resin Open Source; if not, write to the
0022: *
0023: * Free Software Foundation, Inc.
0024: * 59 Temple Place, Suite 330
0025: * Boston, MA 02111-1307 USA
0026: *
0027: * @author Scott Ferguson
0028: */
0029:
0030: package com.caucho.quercus.env;
0031:
0032: import com.caucho.quercus.QuercusRuntimeException;
0033: import com.caucho.quercus.expr.ClassConstExpr;
0034: import com.caucho.quercus.expr.Expr;
0035: import com.caucho.quercus.expr.StringLiteralExpr;
0036: import com.caucho.quercus.module.ModuleContext;
0037: import com.caucho.quercus.program.AbstractFunction;
0038: import com.caucho.quercus.program.ClassDef;
0039: import com.caucho.quercus.program.JavaClassDef;
0040: import com.caucho.quercus.program.InstanceInitializer;
0041: import com.caucho.util.IdentityIntMap;
0042: import com.caucho.util.IntMap;
0043: import com.caucho.util.L10N;
0044:
0045: import java.util.*;
0046: import java.util.logging.Level;
0047: import java.util.logging.Logger;
0048:
0049: /**
0050: * Represents a Quercus runtime class.
0051: */
0052: public class QuercusClass {
0053: private final L10N L = new L10N(QuercusClass.class);
0054: private final Logger log = Logger.getLogger(QuercusClass.class
0055: .getName());
0056:
0057: private final JavaClassDef _javaClassDef;
0058: private final ClassDef _classDef;
0059:
0060: private boolean _isJavaWrapper;
0061:
0062: private ClassDef[] _classDefList;
0063:
0064: private QuercusClass _parent;
0065:
0066: private AbstractFunction _constructor;
0067:
0068: private AbstractFunction _fieldGet;
0069: private AbstractFunction _fieldSet;
0070:
0071: private AbstractFunction _call;
0072:
0073: private ArrayDelegate _arrayDelegate;
0074: private TraversableDelegate _traversableDelegate;
0075: private CountDelegate _countDelegate;
0076:
0077: private final ArrayList<InstanceInitializer> _initializers = new ArrayList<InstanceInitializer>();
0078:
0079: private final ArrayList<StringValue> _fieldNames = new ArrayList<StringValue>();
0080:
0081: private final IntMap _fieldMap = new IntMap();
0082:
0083: private final HashMap<StringValue, Expr> _fieldInitMap = new HashMap<StringValue, Expr>();
0084:
0085: /*
0086: private final IdentityHashMap<String,AbstractFunction> _methodMap
0087: = new IdentityHashMap<String,AbstractFunction>();
0088:
0089: private final HashMap<String,AbstractFunction> _lowerMethodMap
0090: = new HashMap<String,AbstractFunction>();
0091: */
0092:
0093: private final MethodMap<AbstractFunction> _methodMap = new MethodMap<AbstractFunction>();
0094:
0095: private final HashMap<String, Expr> _constMap = new HashMap<String, Expr>();
0096:
0097: private final HashMap<String, ArrayList<StaticField>> _staticFieldExprMap = new LinkedHashMap<String, ArrayList<StaticField>>();
0098:
0099: private final HashMap<String, Value> _staticFieldMap = new LinkedHashMap<String, Value>();
0100:
0101: public QuercusClass(ClassDef classDef, QuercusClass parent) {
0102: this (ModuleContext.getLocalContext(Thread.currentThread()
0103: .getContextClassLoader()), classDef, parent);
0104: }
0105:
0106: public QuercusClass(ModuleContext moduleContext, ClassDef classDef,
0107: QuercusClass parent) {
0108: _classDef = classDef;
0109: _parent = parent;
0110:
0111: JavaClassDef javaClassDef = null;
0112:
0113: if (classDef instanceof JavaClassDef) {
0114: javaClassDef = (JavaClassDef) classDef;
0115: _isJavaWrapper = !javaClassDef.isDelegate();
0116: }
0117:
0118: for (QuercusClass cls = parent; cls != null; cls = cls
0119: .getParent()) {
0120: AbstractFunction cons = cls.getConstructor();
0121:
0122: if (cons != null) {
0123: addMethod(cls.getName(), cons);
0124: }
0125: }
0126:
0127: ClassDef[] classDefList;
0128:
0129: if (_parent != null) {
0130: classDefList = new ClassDef[parent._classDefList.length + 1];
0131:
0132: System.arraycopy(parent._classDefList, 0, classDefList, 1,
0133: parent._classDefList.length);
0134:
0135: classDefList[0] = classDef;
0136: } else {
0137: classDefList = new ClassDef[] { classDef };
0138: }
0139:
0140: _classDefList = classDefList;
0141:
0142: for (int i = 0; i < classDefList.length; i++) {
0143: if (classDefList[i] instanceof JavaClassDef)
0144: javaClassDef = (JavaClassDef) classDefList[i];
0145: }
0146:
0147: _javaClassDef = javaClassDef;
0148:
0149: HashSet<String> ifaces = new HashSet<String>();
0150:
0151: for (int i = classDefList.length - 1; i >= 0; i--) {
0152: classDef = classDefList[i];
0153:
0154: if (classDef == null) {
0155: throw new NullPointerException("classDef:" + _classDef
0156: + " i:" + i + " parent:" + parent);
0157: }
0158:
0159: classDef.init();
0160:
0161: for (String iface : classDef.getInterfaces()) {
0162:
0163: // XXX: php/0cn2, but this is wrong:
0164: QuercusClass cl = Env.getInstance().findClass(iface);
0165:
0166: if (cl == null)
0167: throw new QuercusRuntimeException(L.l(
0168: "cannot find interface {0}", iface));
0169:
0170: ClassDef ifaceDef = cl.getClassDef();
0171: // ClassDef ifaceDef = moduleContext.findClass(iface);
0172:
0173: if (ifaceDef != null) {
0174: if (ifaces.add(iface))
0175: ifaceDef.initClass(this );
0176: }
0177: }
0178:
0179: classDef.initClass(this );
0180: }
0181:
0182: if (_constructor == null && parent != null)
0183: _constructor = parent.getConstructor();
0184: }
0185:
0186: public ClassDef getClassDef() {
0187: return _classDef;
0188: }
0189:
0190: public MethodMap<AbstractFunction> getMethodMap() {
0191: return _methodMap;
0192: }
0193:
0194: /**
0195: * Returns the name.
0196: */
0197: public String getName() {
0198: return _classDef.getName();
0199: }
0200:
0201: /**
0202: * Returns the parent class.
0203: */
0204: public QuercusClass getParent() {
0205: return _parent;
0206: }
0207:
0208: /*
0209: * Returns the class definitions for this class.
0210: */
0211: public ClassDef[] getClassDefList() {
0212: return _classDefList;
0213: }
0214:
0215: /*
0216: * Returns the name of the extension that this class is part of.
0217: */
0218: public String getExtension() {
0219: return _classDef.getExtension();
0220: }
0221:
0222: public boolean isInterface() {
0223: return _classDef.isInterface();
0224: }
0225:
0226: public boolean isAbstract() {
0227: return _classDef.isAbstract();
0228: }
0229:
0230: public boolean isFinal() {
0231: return _classDef.isFinal();
0232: }
0233:
0234: /**
0235: * Sets the constructor.
0236: */
0237: public void setConstructor(AbstractFunction fun) {
0238: _constructor = fun;
0239: }
0240:
0241: /**
0242: * Gets the constructor.
0243: */
0244: public AbstractFunction getConstructor() {
0245: return _constructor;
0246: }
0247:
0248: /**
0249: * Sets the array delegate (see ArrayAccess)
0250: */
0251: public void setArrayDelegate(ArrayDelegate delegate) {
0252: if (log.isLoggable(Level.FINEST))
0253: log.log(Level.FINEST, L.l("{0} adding array delegate {1}",
0254: this , delegate));
0255:
0256: _arrayDelegate = delegate;
0257: }
0258:
0259: /**
0260: * Gets the array delegate (see ArrayAccess)
0261: */
0262: public final ArrayDelegate getArrayDelegate() {
0263: return _arrayDelegate;
0264: }
0265:
0266: /**
0267: * Sets the traversable delegate
0268: */
0269: public void setTraversableDelegate(TraversableDelegate delegate) {
0270: if (log.isLoggable(Level.FINEST))
0271: log.log(Level.FINEST, L.l(
0272: "{0} setting traversable delegate {1}", this ,
0273: delegate));
0274:
0275: _traversableDelegate = delegate;
0276: }
0277:
0278: /**
0279: * Gets the traversable delegate
0280: */
0281: public final TraversableDelegate getTraversableDelegate() {
0282: return _traversableDelegate;
0283: }
0284:
0285: /**
0286: * Sets the count delegate
0287: */
0288: public void setCountDelegate(CountDelegate delegate) {
0289: if (log.isLoggable(Level.FINEST))
0290: log.log(Level.FINEST, L.l("{0} setting count delegate {1}",
0291: this , delegate));
0292:
0293: _countDelegate = delegate;
0294: }
0295:
0296: /**
0297: * Gets the count delegate
0298: */
0299: public final CountDelegate getCountDelegate() {
0300: return _countDelegate;
0301: }
0302:
0303: /**
0304: * Sets the __fieldGet
0305: */
0306: public void setFieldGet(AbstractFunction fun) {
0307: _fieldGet = fun;
0308: }
0309:
0310: /**
0311: * Returns the __fieldGet
0312: */
0313: public AbstractFunction getFieldGet() {
0314: return _fieldGet;
0315: }
0316:
0317: /**
0318: * Sets the __fieldSet
0319: */
0320: public void setFieldSet(AbstractFunction fun) {
0321: _fieldSet = fun;
0322: }
0323:
0324: /**
0325: * Returns the __fieldSet
0326: */
0327: public AbstractFunction getFieldSet() {
0328: return _fieldSet;
0329: }
0330:
0331: /**
0332: * Sets the __call
0333: */
0334: public void setCall(AbstractFunction fun) {
0335: _call = fun;
0336: }
0337:
0338: /**
0339: * Gets the __call
0340: */
0341: public AbstractFunction getCall() {
0342: return _call;
0343: }
0344:
0345: /**
0346: * Adds an initializer
0347: */
0348: public void addInitializer(InstanceInitializer init) {
0349: _initializers.add(init);
0350: }
0351:
0352: /**
0353: * Adds a field.
0354: */
0355: public void addField(StringValue name, int index, Expr initExpr) {
0356: _fieldNames.add(name);
0357: _fieldMap.put(name, index);
0358: _fieldInitMap.put(name, initExpr);
0359: }
0360:
0361: /**
0362: * Adds a field.
0363: */
0364: public int addFieldIndex(StringValue name) {
0365: int index = _fieldMap.get(name);
0366:
0367: if (index >= 0)
0368: return index;
0369: else {
0370: index = _fieldNames.size();
0371:
0372: _fieldMap.put(name, index);
0373: _fieldNames.add(name);
0374:
0375: return index;
0376: }
0377: }
0378:
0379: /**
0380: * Returns a set of the fields and their initial values
0381: */
0382: public HashMap<StringValue, Expr> getClassVars() {
0383: return _fieldInitMap;
0384: }
0385:
0386: /**
0387: * Returns the declared functions.
0388: */
0389: public Iterable<AbstractFunction> getClassMethods() {
0390: return _methodMap.values();
0391: }
0392:
0393: /**
0394: * Adds a method.
0395: */
0396: public void addMethod(String name, AbstractFunction fun) {
0397: //php/09j9
0398: // XXX: this is a hack to get Zend Framework running, the better fix is
0399: // to initialize all interface classes before any concrete classes
0400: AbstractFunction existingFun = _methodMap.get(name);
0401:
0402: if (existingFun == null || !fun.isAbstract())
0403: _methodMap.put(name, fun);
0404: }
0405:
0406: /**
0407: * Adds a static class field.
0408: */
0409: public void addStaticFieldExpr(String className, String name,
0410: Expr value) {
0411: ArrayList<StaticField> fieldList = _staticFieldExprMap
0412: .get(className);
0413:
0414: if (fieldList == null) {
0415: fieldList = new ArrayList<StaticField>();
0416:
0417: _staticFieldExprMap.put(className, fieldList);
0418: }
0419:
0420: fieldList.add(new StaticField(name, value));
0421: }
0422:
0423: /**
0424: * Adds a constant definition
0425: */
0426: public void addConstant(String name, Expr expr) {
0427: _constMap.put(name, expr);
0428: }
0429:
0430: /**
0431: * Returns the number of fields.
0432: */
0433: public int getFieldSize() {
0434: return _fieldNames.size();
0435: }
0436:
0437: /**
0438: * Returns the field index.
0439: */
0440: public int findFieldIndex(StringValue name) {
0441: return _fieldMap.get(name);
0442: }
0443:
0444: /**
0445: * Returns the key set.
0446: */
0447: public ArrayList<StringValue> getFieldNames() {
0448: return _fieldNames;
0449: }
0450:
0451: public void validate(Env env) {
0452: if (!_classDef.isAbstract() && !_classDef.isInterface()) {
0453: for (AbstractFunction fun : _methodMap.values()) {
0454: /* XXX: abstract methods need to be validated
0455: php/393g, php/393i, php/39j2
0456: if (! (absFun instanceof Function))
0457: continue;
0458:
0459: Function fun = (Function) absFun;
0460: */
0461:
0462: boolean isAbstract;
0463:
0464: // php/093g constructor
0465: if (_constructor != null
0466: && fun.getName().equals(_constructor.getName()))
0467: isAbstract = _constructor.isAbstract();
0468: else
0469: isAbstract = fun.isAbstract();
0470:
0471: if (isAbstract) {
0472: throw env
0473: .createErrorException(
0474: _classDef.getLocation(),
0475: L
0476: .l(
0477: "Abstract function '{0}' must be implemented in concrete class {1}.",
0478: fun.getName(),
0479: getName()));
0480: }
0481: }
0482: }
0483: }
0484:
0485: public void init(Env env) {
0486: for (Map.Entry<String, ArrayList<StaticField>> map : _staticFieldExprMap
0487: .entrySet()) {
0488: if (env.isInitializedClass(map.getKey()))
0489: continue;
0490:
0491: for (StaticField field : map.getValue()) {
0492: Value val;
0493: Expr expr = field._expr;
0494:
0495: //php/096f
0496: if (expr instanceof ClassConstExpr)
0497: val = ((ClassConstExpr) expr).eval(env);
0498: else
0499: val = expr.eval(env);
0500:
0501: _staticFieldMap.put(field._name, val);
0502: }
0503:
0504: env.addInitializedClass(map.getKey());
0505: }
0506: }
0507:
0508: /*
0509: public void setStaticField(String name, Value val)
0510: {
0511: Var var = new Var();
0512: var.set(val);
0513:
0514: _staticFieldMap.put(name, var);
0515: }
0516: */
0517:
0518: public Var getStaticField(Env env, String name) {
0519: Value value = _staticFieldMap.get(name);
0520:
0521: if (value != null) {
0522: String fullName = _classDef.getName() + "::" + name;
0523:
0524: Var var = env.getGlobalRaw(fullName);
0525:
0526: if (var == null) {
0527: var = env.getGlobalVar(fullName);
0528: var.set(value);
0529: }
0530:
0531: return var;
0532: }
0533:
0534: QuercusClass parent = getParent();
0535:
0536: if (parent != null)
0537: return parent.getStaticField(env, name);
0538: else
0539: return null;
0540: }
0541:
0542: /*
0543: * Returns the static fields.
0544: */
0545: public HashMap<String, Value> getStaticFieldMap() {
0546: return _staticFieldMap;
0547: }
0548:
0549: //
0550: // Constructors
0551: //
0552:
0553: /**
0554: * Creates a new instance.
0555: */
0556: /*
0557: public Value callNew(Env env, Expr []args)
0558: {
0559: Value object = _classDef.callNew(env, args);
0560:
0561: if (object != null)
0562: return object;
0563:
0564: object = newInstance(env);
0565:
0566: AbstractFunction fun = findConstructor();
0567:
0568: if (fun != null) {
0569: fun.callMethod(env, object, args);
0570: }
0571:
0572: return object;
0573: }
0574: */
0575:
0576: /**
0577: * Creates a new instance.
0578: */
0579: public Value callNew(Env env, Value[] args) {
0580: if (_classDef.isAbstract()) {
0581: throw env.createErrorException(L.l(
0582: "abstract class '{0}' cannot be instantiated.",
0583: _classDef.getName()));
0584: } else if (_classDef.isInterface()) {
0585: throw env.createErrorException(L.l(
0586: "interface '{0}' cannot be instantiated.",
0587: _classDef.getName()));
0588: }
0589:
0590: ObjectValue objectValue = null;
0591:
0592: if (_isJavaWrapper) {
0593: return _javaClassDef.callNew(env, args);
0594: } else if (_javaClassDef != null && _javaClassDef.isDelegate()) {
0595: objectValue = new ObjectExtValue(this );
0596: } else if (_javaClassDef != null && !_javaClassDef.isDelegate()) {
0597: Value javaWrapper = _javaClassDef
0598: .callNew(env, new Value[0]);
0599: Object object = javaWrapper.toJavaObject();
0600:
0601: objectValue = new ObjectExtJavaValue(this , object,
0602: _javaClassDef);
0603: } else {
0604: objectValue = _classDef.newInstance(env, this );
0605: }
0606:
0607: for (int i = 0; i < _initializers.size(); i++) {
0608: _initializers.get(i).initInstance(env, objectValue);
0609: }
0610:
0611: AbstractFunction fun = findConstructor();
0612:
0613: if (fun != null)
0614: fun.callMethod(env, objectValue, args);
0615: else {
0616: // if expr
0617: }
0618:
0619: return objectValue;
0620: }
0621:
0622: /**
0623: * Returns the parent class.
0624: */
0625: public String getParentName() {
0626: return _classDefList[0].getParentName();
0627: }
0628:
0629: /**
0630: * Returns true for an implementation of a class
0631: */
0632: public boolean isA(String name) {
0633: for (int i = _classDefList.length - 1; i >= 0; i--) {
0634: if (_classDefList[i].isA(name)) {
0635: return true;
0636: }
0637: }
0638:
0639: return false;
0640: }
0641:
0642: /*
0643: * Returns true if implements interface.
0644: */
0645: public boolean implements Interface(Env env, String name) {
0646: if (isInterface())
0647: return false;
0648:
0649: ClassDef[] defList = _classDefList;
0650:
0651: for (int i = 0; i < defList.length; i++) {
0652: ClassDef def = defList[i];
0653:
0654: if (def.isInterface()) {
0655: if (def.getName().equals(name))
0656: return true;
0657: } else {
0658: String[] defNames = def.getInterfaces();
0659:
0660: for (int j = 0; j < defNames.length; j++) {
0661: QuercusClass cls = env.findClass(defNames[j]);
0662:
0663: if (cls.getName().equals(name))
0664: return true;
0665: }
0666: }
0667: }
0668:
0669: return false;
0670: }
0671:
0672: /**
0673: * Finds the matching constructor.
0674: */
0675: public AbstractFunction findConstructor() {
0676: return _constructor;
0677: }
0678:
0679: //
0680: // Fields
0681: //
0682:
0683: /**
0684: * Implements the __get method call.
0685: */
0686: public Value getField(Env env, Value qThis, StringValue name) {
0687: if (_fieldGet != null)
0688: return _fieldGet.callMethod(env, qThis, name);
0689: else
0690: return UnsetValue.UNSET;
0691: }
0692:
0693: /**
0694: * Implements the __set method call.
0695: */
0696: public void setField(Env env, Value qThis, StringValue name,
0697: Value value) {
0698: if (_fieldSet != null)
0699: _fieldSet.callMethod(env, qThis, name, value);
0700: }
0701:
0702: /**
0703: * Finds the matching function.
0704: */
0705: public AbstractFunction findFunction(String name) {
0706: char[] key = name.toCharArray();
0707: int hash = MethodMap.hash(key, key.length);
0708:
0709: AbstractFunction fun = _methodMap.get(hash, key, key.length);
0710:
0711: return fun;
0712: }
0713:
0714: /**
0715: * Finds the matching function.
0716: */
0717: public AbstractFunction findFunctionExact(String name) {
0718: throw new UnsupportedOperationException();
0719:
0720: // return _methodMap.get(name);
0721: }
0722:
0723: /**
0724: * Finds the matching function.
0725: */
0726: public AbstractFunction findFunctionLowerCase(String name) {
0727: throw new UnsupportedOperationException();
0728:
0729: //return _lowerMethodMap.get(name.toLowerCase());
0730: }
0731:
0732: /**
0733: * Finds the matching function.
0734: */
0735: public AbstractFunction findStaticFunction(String name) {
0736: return findFunction(name);
0737: }
0738:
0739: /**
0740: * Finds the matching function.
0741: */
0742: public final AbstractFunction getFunction(String name) {
0743: char[] key = name.toCharArray();
0744: int hash = MethodMap.hash(key, key.length);
0745:
0746: return getFunction(hash, key, key.length);
0747: }
0748:
0749: /**
0750: * Finds the matching function.
0751: */
0752: public final AbstractFunction getFunction(int hash, char[] name,
0753: int nameLen) {
0754: AbstractFunction fun = _methodMap.get(hash, name, nameLen);
0755:
0756: if (fun != null)
0757: return fun;
0758: else {
0759: throw new QuercusRuntimeException(L.l(
0760: "{0}::{1} is an unknown method", getName(),
0761: toMethod(name, nameLen)));
0762: }
0763: }
0764:
0765: /**
0766: * calls the function.
0767: */
0768: public Value callMethod(Env env, Value this Value, int hash,
0769: char[] name, int nameLength, Expr[] args) {
0770: AbstractFunction fun = _methodMap.get(hash, name, nameLength);
0771:
0772: if (fun != null)
0773: return fun.callMethod(env, this Value, args);
0774: else if (getCall() != null) {
0775: Expr[] newArgs = new Expr[args.length + 1];
0776: newArgs[0] = new StringLiteralExpr(toMethod(name,
0777: nameLength));
0778: System.arraycopy(args, 0, newArgs, 1, args.length);
0779:
0780: return getCall().callMethod(env, this Value, newArgs);
0781: } else
0782: return env.error(L.l("Call to undefined method {0}::{1}",
0783: getName(), toMethod(name, nameLength)));
0784: }
0785:
0786: /**
0787: * calls the function.
0788: */
0789: public Value callMethod(Env env, Value this Value,
0790: StringValue methodName, Expr[] args) {
0791: AbstractFunction fun = _methodMap.get(methodName.toString());
0792:
0793: if (fun != null)
0794: return fun.callMethod(env, this Value, args);
0795: else if (getCall() != null) {
0796: Expr[] newArgs = new Expr[args.length + 1];
0797: newArgs[0] = new StringLiteralExpr(methodName.toString());
0798: System.arraycopy(args, 0, newArgs, 1, args.length);
0799:
0800: return getCall().callMethod(env, this Value, newArgs);
0801: } else
0802: return env.error(L.l("Call to undefined method {0}::{1}",
0803: getName(), methodName));
0804: }
0805:
0806: /**
0807: * calls the function.
0808: */
0809: public Value callMethod(Env env, Value this Value, int hash,
0810: char[] name, int nameLen, Value[] args) {
0811: AbstractFunction fun = _methodMap.get(hash, name, nameLen);
0812:
0813: if (fun != null)
0814: return fun.callMethod(env, this Value, args);
0815: else if (getCall() != null) {
0816: return getCall().callMethod(env, this Value,
0817: env.createString(name, nameLen),
0818: new ArrayValueImpl(args));
0819: } else
0820: return env.error(L.l("Call to undefined method {0}::{1}()",
0821: getName(), toMethod(name, nameLen)));
0822: }
0823:
0824: /**
0825: * calls the function.
0826: */
0827: public Value callMethod(Env env, Value this Value, StringValue name,
0828:
0829: Value[] args) {
0830: AbstractFunction fun = _methodMap.get(name.toString());
0831:
0832: if (fun != null)
0833: return fun.callMethod(env, this Value, args);
0834: else if (getCall() != null) {
0835: return getCall().callMethod(env, this Value, name,
0836: new ArrayValueImpl(args));
0837: } else
0838: return env.error(L.l("Call to undefined method {0}::{1}()",
0839: getName(), name));
0840: }
0841:
0842: /**
0843: * calls the function.
0844: */
0845: public Value callMethod(Env env, Value this Value, int hash,
0846: char[] name, int nameLen) {
0847: AbstractFunction fun = _methodMap.get(hash, name, nameLen);
0848:
0849: if (fun != null)
0850: return fun.callMethod(env, this Value);
0851: else if (getCall() != null) {
0852: return getCall().callMethod(env, this Value,
0853: env.createString(name, nameLen),
0854: new ArrayValueImpl());
0855: } else
0856: return env.error(L.l("Call to undefined method {0}::{1}()",
0857: getName(), toMethod(name, nameLen)));
0858: }
0859:
0860: /**
0861: * calls the function.
0862: */
0863: public Value callMethod(Env env, Value this Value, int hash,
0864: char[] name, int nameLen, Value a1) {
0865: AbstractFunction fun = _methodMap.get(hash, name, nameLen);
0866:
0867: if (fun != null)
0868: return fun.callMethod(env, this Value, a1);
0869: else if (getCall() != null) {
0870: return getCall().callMethod(env, this Value,
0871: env.createString(name, nameLen),
0872: new ArrayValueImpl().append(a1));
0873: } else
0874: return env.error(L.l("Call to undefined method {0}::{1}()",
0875: getName(), toMethod(name, nameLen)));
0876: }
0877:
0878: /**
0879: * calls the function.
0880: */
0881: public Value callMethod(Env env, Value this Value, int hash,
0882: char[] name, int nameLen, Value a1, Value a2) {
0883: AbstractFunction fun = _methodMap.get(hash, name, nameLen);
0884:
0885: if (fun != null)
0886: return fun.callMethod(env, this Value, a1, a2);
0887: else if (getCall() != null) {
0888: return getCall().callMethod(env, this Value,
0889: env.createString(name, nameLen),
0890: new ArrayValueImpl().append(a1).append(a2));
0891: } else
0892: return env.error(L.l("Call to undefined method {0}::{1}()",
0893: getName(), toMethod(name, nameLen)));
0894: }
0895:
0896: /**
0897: * calls the function.
0898: */
0899: public Value callMethod(Env env, Value this Value, int hash,
0900: char[] name, int nameLen, Value a1, Value a2, Value a3) {
0901: AbstractFunction fun = _methodMap.get(hash, name, nameLen);
0902:
0903: if (fun != null)
0904: return fun.callMethod(env, this Value, a1, a2, a3);
0905: else if (getCall() != null) {
0906: return getCall().callMethod(
0907: env,
0908: this Value,
0909: env.createString(name, nameLen),
0910: new ArrayValueImpl().append(a1).append(a2).append(
0911: a3));
0912: } else
0913: return env.error(L.l("Call to undefined method {0}::{1}()",
0914: getName(), toMethod(name, nameLen)));
0915: }
0916:
0917: /**
0918: * calls the function.
0919: */
0920: public Value callMethod(Env env, Value this Value, int hash,
0921: char[] name, int nameLen, Value a1, Value a2, Value a3,
0922: Value a4) {
0923: AbstractFunction fun = _methodMap.get(hash, name, nameLen);
0924:
0925: if (fun != null)
0926: return fun.callMethod(env, this Value, a1, a2, a3, a4);
0927: else if (getCall() != null) {
0928: return getCall().callMethod(
0929: env,
0930: this Value,
0931: env.createString(name, nameLen),
0932: new ArrayValueImpl().append(a1).append(a2).append(
0933: a3).append(a4));
0934: } else
0935: return env.error(L.l("Call to undefined method {0}::{1}()",
0936: getName(), toMethod(name, nameLen)));
0937: }
0938:
0939: /**
0940: * calls the function.
0941: */
0942: public Value callMethod(Env env, Value this Value, int hash,
0943: char[] name, int nameLen, Value a1, Value a2, Value a3,
0944: Value a4, Value a5) {
0945: AbstractFunction fun = _methodMap.get(hash, name, nameLen);
0946:
0947: if (fun != null)
0948: return fun.callMethod(env, this Value, a1, a2, a3, a4, a5);
0949: else if (getCall() != null) {
0950: return getCall().callMethod(
0951: env,
0952: this Value,
0953: env.createString(name, nameLen),
0954: new ArrayValueImpl().append(a1).append(a2).append(
0955: a3).append(a4).append(a5));
0956: } else
0957: return env.error(L.l("Call to undefined method {0}::{1}()",
0958: getName(), toMethod(name, nameLen)));
0959: }
0960:
0961: /**
0962: * calls the function.
0963: */
0964: public Value callMethodRef(Env env, Value this Value, int hash,
0965: char[] name, int nameLen, Expr[] args) {
0966: AbstractFunction fun = getFunction(hash, name, nameLen);
0967:
0968: return fun.callMethodRef(env, this Value, args);
0969: }
0970:
0971: /**
0972: * calls the function.
0973: */
0974: public Value callMethodRef(Env env, Value this Value,
0975: StringValue methodName, Expr[] args) {
0976: AbstractFunction fun = _methodMap.get(methodName.toString());
0977:
0978: if (fun != null)
0979: return fun.callMethodRef(env, this Value, args);
0980: else if (getCall() != null) {
0981: Expr[] newArgs = new Expr[args.length + 1];
0982: newArgs[0] = new StringLiteralExpr(methodName.toString());
0983: System.arraycopy(args, 0, newArgs, 1, args.length);
0984:
0985: return getCall().callMethodRef(env, this Value, newArgs);
0986: } else
0987: return env.error(L.l("Call to undefined method {0}::{1}",
0988: getName(), methodName));
0989: }
0990:
0991: /**
0992: * calls the function.
0993: */
0994: public Value callMethodRef(Env env, Value this Value, int hash,
0995: char[] name, int nameLen, Value[] args) {
0996: AbstractFunction fun = _methodMap.get(hash, name, nameLen);
0997:
0998: if (fun != null)
0999: return fun.callMethodRef(env, this Value, args);
1000: else if (getCall() != null) {
1001: return getCall().callMethodRef(env, this Value,
1002: env.createString(name, nameLen),
1003: new ArrayValueImpl(args));
1004: } else
1005: return env.error(L.l("Call to undefined method {0}::{1}()",
1006: getName(), toMethod(name, nameLen)));
1007: }
1008:
1009: /**
1010: * calls the function.
1011: */
1012: public Value callMethodRef(Env env, Value this Value,
1013: StringValue name, Value[] args) {
1014: AbstractFunction fun = _methodMap.get(name.toString());
1015:
1016: if (fun != null)
1017: return fun.callMethodRef(env, this Value, args);
1018: else if (getCall() != null) {
1019: return getCall().callMethodRef(env, this Value, name,
1020: new ArrayValueImpl(args));
1021: } else
1022: return env.error(L.l("Call to undefined method {0}::{1}()",
1023: getName(), name));
1024: }
1025:
1026: /**
1027: * calls the function.
1028: */
1029: public Value callMethodRef(Env env, Value this Value, int hash,
1030: char[] name, int nameLen) {
1031: AbstractFunction fun = _methodMap.get(hash, name, nameLen);
1032:
1033: if (fun != null)
1034: return fun.callMethodRef(env, this Value);
1035: else if (getCall() != null) {
1036: return getCall().callMethodRef(env, this Value,
1037: env.createString(name, nameLen),
1038: new ArrayValueImpl());
1039: } else
1040: return env.error(L.l("Call to undefined method {0}::{1}()",
1041: getName(), toMethod(name, nameLen)));
1042: }
1043:
1044: /**
1045: * calls the function.
1046: */
1047: public Value callMethodRef(Env env, Value this Value, int hash,
1048: char[] name, int nameLen, Value a1) {
1049: AbstractFunction fun = _methodMap.get(hash, name, nameLen);
1050:
1051: if (fun != null)
1052: return fun.callMethodRef(env, this Value, a1);
1053: else if (getCall() != null) {
1054: return getCall().callMethodRef(env, this Value,
1055: env.createString(name, nameLen),
1056: new ArrayValueImpl().append(a1));
1057: } else
1058: return env.error(L.l("Call to undefined method {0}::{1}()",
1059: getName(), toMethod(name, nameLen)));
1060: }
1061:
1062: /**
1063: * calls the function.
1064: */
1065: public Value callMethodRef(Env env, Value this Value, int hash,
1066: char[] name, int nameLen, Value a1, Value a2) {
1067: AbstractFunction fun = _methodMap.get(hash, name, nameLen);
1068:
1069: if (fun != null)
1070: return fun.callMethodRef(env, this Value, a1, a2);
1071: else if (getCall() != null) {
1072: return getCall().callMethodRef(env, this Value,
1073: env.createString(name, nameLen),
1074: new ArrayValueImpl().append(a1).append(a2));
1075: } else
1076: return env.error(L.l("Call to undefined method {0}::{1}()",
1077: getName(), toMethod(name, nameLen)));
1078: }
1079:
1080: /**
1081: * calls the function.
1082: */
1083: public Value callMethodRef(Env env, Value this Value, int hash,
1084: char[] name, int nameLen, Value a1, Value a2, Value a3) {
1085: AbstractFunction fun = _methodMap.get(hash, name, nameLen);
1086:
1087: if (fun != null)
1088: return fun.callMethodRef(env, this Value, a1, a2, a3);
1089: else if (getCall() != null) {
1090: return getCall().callMethodRef(
1091: env,
1092: this Value,
1093: env.createString(name, nameLen),
1094: new ArrayValueImpl().append(a1).append(a2).append(
1095: a3));
1096: } else
1097: return env.error(L.l("Call to undefined method {0}::{1}()",
1098: getName(), toMethod(name, nameLen)));
1099: }
1100:
1101: /**
1102: * calls the function.
1103: */
1104: public Value callMethodRef(Env env, Value this Value, int hash,
1105: char[] name, int nameLen, Value a1, Value a2, Value a3,
1106: Value a4) {
1107: AbstractFunction fun = _methodMap.get(hash, name, nameLen);
1108:
1109: if (fun != null)
1110: return fun.callMethodRef(env, this Value, a1, a2, a3, a4);
1111: else if (getCall() != null) {
1112: return getCall().callMethodRef(
1113: env,
1114: this Value,
1115: env.createString(name, nameLen),
1116: new ArrayValueImpl().append(a1).append(a2).append(
1117: a3).append(a4));
1118: } else
1119: return env.error(L.l("Call to undefined method {0}::{1}()",
1120: getName(), toMethod(name, nameLen)));
1121: }
1122:
1123: /**
1124: * calls the function.
1125: */
1126: public Value callMethodRef(Env env, Value this Value, int hash,
1127: char[] name, int nameLen, Value a1, Value a2, Value a3,
1128: Value a4, Value a5) {
1129: AbstractFunction fun = _methodMap.get(hash, name, nameLen);
1130:
1131: if (fun != null)
1132: return fun
1133: .callMethodRef(env, this Value, a1, a2, a3, a4, a5);
1134: else if (getCall() != null) {
1135: return getCall().callMethodRef(
1136: env,
1137: this Value,
1138: env.createString(name, nameLen),
1139: new ArrayValueImpl().append(a1).append(a2).append(
1140: a3).append(a4).append(a5));
1141: } else
1142: return env.error(L.l("Call to undefined method {0}::{1}()",
1143: getName(), toMethod(name, nameLen)));
1144: }
1145:
1146: private String toMethod(char[] key, int keyLength) {
1147: return new String(key, 0, keyLength);
1148: }
1149:
1150: /**
1151: * Finds a function.
1152: */
1153: public AbstractFunction findStaticFunctionLowerCase(String name) {
1154: return null;
1155: }
1156:
1157: /**
1158: * Finds the matching function.
1159: */
1160: public final AbstractFunction getStaticFunction(String name) {
1161: AbstractFunction fun = findStaticFunction(name);
1162: /*
1163: if (fun != null)
1164: return fun;
1165:
1166: fun = findStaticFunctionLowerCase(name.toLowerCase());
1167: */
1168:
1169: if (fun != null)
1170: return fun;
1171: else {
1172: throw new QuercusRuntimeException(L.l(
1173: "{0}::{1} is an unknown method", getName(), name));
1174: }
1175: }
1176:
1177: /**
1178: * Finds the matching constant
1179: */
1180: public final Value getConstant(Env env, String name) {
1181: Expr expr = _constMap.get(name);
1182:
1183: if (expr != null)
1184: return expr.eval(env);
1185:
1186: throw new QuercusRuntimeException(L.l(
1187: "{0}::{1} is an unknown constant", getName(), name));
1188: }
1189:
1190: /**
1191: * Returns true if the constant exists.
1192: */
1193: public final boolean hasConstant(String name) {
1194: return _constMap.get(String.valueOf(name)) != null;
1195: }
1196:
1197: /*
1198: * Returns the constants defined in this class.
1199: */
1200: public final HashMap<String, Expr> getConstantMap() {
1201: return _constMap;
1202: }
1203:
1204: public String toString() {
1205: return getClass().getSimpleName() + "[" + getName() + "]";
1206: }
1207:
1208: static class StaticField {
1209: String _name;
1210: Expr _expr;
1211:
1212: StaticField(String name, Expr expr) {
1213: _name = name;
1214: _expr = expr;
1215: }
1216: }
1217: }
|