/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source 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, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */ package com.caucho.quercus.lib; import com.caucho.quercus.annotation.Optional; import com.caucho.quercus.annotation.ReadOnly; import com.caucho.quercus.annotation.ReturnNullAsFalse; import com.caucho.quercus.env.*; import com.caucho.quercus.expr.Expr; import com.caucho.quercus.module.AbstractQuercusModule; import com.caucho.quercus.function.AbstractFunction; import com.caucho.util.L10N; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.logging.Logger; /** * Quercus class information */ public class ClassesModule extends AbstractQuercusModule { private static final L10N L = new L10N(ClassesModule.class); private static final Logger log = Logger.getLogger(ClassesModule.class.getName()); /** * Calls an object method. */ public static Value call_user_method(Env env, StringValue name, Value obj, Value []args) { if (obj.isObject()) { return obj.callMethod(env, name, args); } else { QuercusClass cls = env.findClass(obj.toString()); return cls.callMethod( env, env.getThis(), name, name.hashCode(), args).copyReturn(); } } /* * Calls a object method with arguments in an array. */ public static Value call_user_method_array(Env env, StringValue methodName, Value obj, ArrayValue params) { Value []args = params.valuesToArray(); return call_user_method(env, methodName, obj, args); } /** * returns true if the class exists. */ public boolean class_exists(Env env, String className, @Optional("true") boolean useAutoload) { if (className == null) return false; QuercusClass cl = env.findClass(className, useAutoload, true); // php/[03]9m1 return cl != null && ! cl.isInterface(); } /** * Returns the object's class name */ public Value get_class(Env env, Value value) { if (value instanceof ObjectValue) { ObjectValue obj = (ObjectValue) value; return env.createString(obj.getName()); } else if (value instanceof JavaValue) { JavaValue obj = (JavaValue) value; return env.createString(obj.getClassName()); } else return BooleanValue.FALSE; } /* * Returns the calling class name. */ @ReturnNullAsFalse public String get_called_class(Env env) { Value qThis = env.getThis(); if (qThis == null || qThis.getQuercusClass() == null) { env.warning("get_called_class was not called from a class method"); return null; } return qThis.getQuercusClass().getName(); } /** * Returns an array of method names * * @param clss the name of the class, or an instance of a class * * @return an array of method names */ public static Value get_class_methods(Env env, Value cls) { // php/1j11 QuercusClass cl; if (cls.isObject()) cl = ((ObjectValue) cls).getQuercusClass(); else cl = env.findClass(cls.toString()); if (cl == null) return NullValue.NULL; ArrayValue array = new ArrayValueImpl(); HashSet<String> set = new HashSet<String>(); // to combine __construct and class name constructors for (AbstractFunction fun : cl.getClassMethods()) { if (fun.isPublic()) set.add(fun.getName()); } for (String name : set) { array.put(name); } return array; } /** * Returns an array of member names and values * * @param clss the name of the class, or an instance of a class * * @return an array of member names and values */ public static Value get_class_vars(Env env, Value obj) { // php/1j10 QuercusClass cl; if (obj instanceof ObjectValue) cl = ((ObjectValue) obj).getQuercusClass(); else cl = env.findClass(obj.toString()); if (cl == null) return BooleanValue.FALSE; ArrayValue varArray = new ArrayValueImpl(); for (ClassField field : cl.getClassFields().values()) { if (field.isPublic()) { StringValue name = field.getName(); Expr initValue = field.getInitValue(); Value value = initValue.eval(env); varArray.append(name, value); } } ArrayModule.ksort(env, varArray, ArrayModule.SORT_STRING); return varArray; } /** * Returns the declared classes */ public static Value get_declared_classes(Env env) { return env.getDeclaredClasses(); } // XXX: get_declared_interfaces /** * Returns the object's variables */ public static Value get_object_vars(Env env, Value obj) { ArrayValue result = new ArrayValueImpl(); // #3253, php/4as7 - XXX: needs cleanup if (obj instanceof ObjectValue) { for (Map.Entry<Value,Value> entry : ((ObjectValue) obj).entrySet()) { result.put(entry.getKey(), entry.getValue()); } } else { Iterator<Map.Entry<Value,Value>> iter = obj.getIterator(env); while (iter.hasNext()) { Map.Entry<Value,Value> entry = iter.next(); result.put(entry.getKey(), entry.getValue()); } } return result; } /** * Returns the object's class name */ public Value get_parent_class(Env env, @ReadOnly Value value) { if (value instanceof ObjectValue) { ObjectValue obj = (ObjectValue) value; String parent = obj.getParentClassName(); if (parent != null) return env.createString(parent); } else if (value.isString()) { String className = value.toString(); QuercusClass cl = env.findClass(className); if (cl != null) { String parent = cl.getParentName(); if (parent != null) return env.createString(parent); } } return BooleanValue.FALSE; } /** * Returns true if the class exists. */ public boolean interface_exists(Env env, String interfaceName, @Optional("true") boolean useAutoload) { QuercusClass cl = env.findClass(interfaceName, useAutoload, true); // php/[03]9m0 return cl != null && cl.isInterface(); } /** * Returns true if the object implements the given class. */ public static boolean is_a(@ReadOnly Value value, String name) { return value.isA(name); } /** * Returns true if the argument is an object. */ public static boolean is_object(@ReadOnly Value value) { return value.isObject(); } /** * Returns true if the object implements the given class. */ public static boolean is_subclass_of(Env env, @ReadOnly Value value, String name) { if (value instanceof StringValue) { QuercusClass cl = env.findClass(value.toString()); return cl.isA(name) && !cl.getName().equalsIgnoreCase(name); } else return value.isA(name) && !value.getClassName().equalsIgnoreCase(name); } /** * Returns true if the named method exists on the object. * * @param obj the object to test * @param methodName the name of the method */ public static boolean method_exists(Env env, Value obj, StringValue methodName) { QuercusClass qClass = obj.getQuercusClass(); if (qClass == null) qClass = env.findClass(obj.toString()); if (qClass != null) return qClass.findFunction(methodName) != null; else return false; } /** * Returns true if the named property exists on the object. */ public static Value property_exists(Env env, Value obj, StringValue name) { QuercusClass cls; if (obj.isString()) cls = env.findClass(obj.toString()); else if (obj.isObject()) cls = ((ObjectValue) obj.toValue()).getQuercusClass(); else { env.warning("must pass in object or name of class"); return NullValue.NULL; } if (cls != null && cls.getClassField(name) != null) return BooleanValue.TRUE; else return BooleanValue.FALSE; } }