Package com.caucho.quercus.lib

Source Code of com.caucho.quercus.lib.VariableModule

/*
* Copyright (c) 1998-2008 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.QuercusModuleException;
import com.caucho.quercus.annotation.Optional;
import com.caucho.quercus.annotation.PassThru;
import com.caucho.quercus.annotation.ReadOnly;
import com.caucho.quercus.annotation.Reference;
import com.caucho.quercus.annotation.ReturnNullAsFalse;
import com.caucho.quercus.annotation.UsesSymbolTable;
import com.caucho.quercus.env.*;
import com.caucho.quercus.module.AbstractQuercusModule;
import com.caucho.util.L10N;
import com.caucho.util.LruCache;
import com.caucho.vfs.StringWriter;
import com.caucho.vfs.WriteStream;

import java.io.IOException;
import java.lang.ref.*;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Information about PHP variables.
*/
public class VariableModule extends AbstractQuercusModule {
  private static final Logger log
    = Logger.getLogger(VariableModule.class.getName());
  private static final L10N L = new L10N(VariableModule.class);

  private static final
    LruCache<UnserializeKey,UnserializeCacheEntry> _unserializeCache
    = new LruCache<UnserializeKey,UnserializeCacheEntry>(256);

  /**
   * Returns a constant
   *
   * @param env the quercus calling environment
   * @param name the constant name
   */
  public static Value constant(Env env, String name)
  {
    if (name == null) {
      env.warning(L.l("null passed as constant name"));
      return NullValue.NULL;
    }
   
    int i = name.indexOf("::");
   
    if (i > 0) {
      String cls = name.substring(0, i);
     
      name = name.substring(i + 2);
     
      return env.getClass(cls).getConstant(env, name);
    }
    else
      return env.getConstant(name);
  }

  /**
   * Prints a debug version of the variable
   *
   * @param env the quercus calling environment
   * @param v the variable to print
   * @return the escaped stringPhp
   */
  public static Value debug_zval_dump(Env env, @ReadOnly Value v)
  {
    try {
      debug_impl(env, v, 0);

      return NullValue.NULL;
    } catch (IOException e) {
      throw new QuercusModuleException(e);
    }
  }

  /**
   * Defines a constant
   *
   * @param env the quercus calling environment
   * @param name the constant name
   * @param value the constant value
   */
  public static Value define(Env env,
                             StringValue name,
                             Value value,
                             @Optional boolean isCaseInsensitive)
  {
    return env.addConstant(name, value, isCaseInsensitive);
  }

  /**
   * Returns true if the constant is defined.
   *
   * @param env the quercus calling environment
   * @param name the constant name
   */
  public static boolean defined(Env env, String name)
  {
    if (name == null)
      return false;
   
    int i = name.indexOf("::");
   
    if (i > 0) {
      String clsName = name.substring(0, i);
      name = name.substring(i + 2);
     
      QuercusClass cls = env.getClass(clsName);
     
      return cls.hasConstant(name);
    }
    else
      return env.isDefined(name);
  }

  /**
   * Converts to a double
   *
   * @param v the variable to convert
   * @return the double value
   */
  public static Value doubleval(@ReadOnly Value v)
  {
    return floatval(v);
  }

  /**
   * Returns true for an empty variable.
   *
   * @param v the value to test
   *
   * @return true if the value is empty
   */
  public static boolean empty(@ReadOnly Value v)
  {
    return v.isEmpty();
  }

  /**
   * Converts to a double
   *
   * @param v the variable to convert
   * @return the double value
   */
  public static Value floatval(@ReadOnly Value v)
  {
    return new DoubleValue(v.toDouble());
  }

  /**
   * Returns the defined variables in the current scope.
   */
  @UsesSymbolTable
  public static Value get_defined_vars(Env env)
  {
    ArrayValue result = new ArrayValueImpl();

    Map<String,EnvVar> map = env.getEnv();

    for (Map.Entry<String,EnvVar> entry : map.entrySet()) {
      result.append(env.createStringOld(entry.getKey()),
                    entry.getValue().get());
    }

    Map<String,EnvVar> globalMap = env.getGlobalEnv();
    if (map != globalMap) {
      for (Map.Entry<String,EnvVar> entry : globalMap.entrySet()) {
        result.append(env.createStringOld(entry.getKey()),
                      entry.getValue().get());
      }
    }

    return result;
  }

  /*
   * Returns the type of this resource.
   */
  @ReturnNullAsFalse
  public static String get_resource_type(Env env, Value v)
  {
    return v.getResourceType();
  }

  /**
   * Returns the type string for the variable
   */
  public static String gettype(@ReadOnly Value v)
  {
    return v.getType();
  }

  /**
   * Imports request variables
   *
   * @param types the variables to import
   * @param prefix the prefix
   */
  public static boolean import_request_variables(Env env,
                                                 String types,
                                                 @Optional String prefix)
  {
    if ("".equals(prefix))
      env.notice(L.l("import_request_variables should use a prefix argument"));

    for (int i = 0; i < types.length(); i++) {
      char ch = types.charAt(i);

      Value value = null;

      if (ch == 'c' || ch == 'C')
        value = env.getGlobalValue("_COOKIE");
      else if (ch == 'g' || ch == 'G')
        value = env.getGlobalValue("_GET");
      else if (ch == 'p' || ch == 'P')
        value = env.getGlobalValue("_POST");

      if (! (value instanceof ArrayValue))
        continue;

      ArrayValue array = (ArrayValue) value;

      for (Map.Entry<Value,Value> entry : array.entrySet()) {
        String key = entry.getKey().toString();

        env.setGlobalValue(prefix + key,
                         array.getRef(entry.getKey()));
      }
    }

    return true;
  }

  /**
   * Converts to a long
   *
   * @param v the variable to convert
   * @return the double value
   */
  public static Value intval(@ReadOnly Value v)
  {
    return v.toLongValue();
  }

  /**
   * Converts to a long
   *
   * @param v the variable to convert
   * @return the double value
   */
  public static long intval(Env env, @ReadOnly Value v, int base)
  {
    if (! v.isString())
      return v.toLong();

    StringValue s = v.toStringValue(env);

    int len = s.length();
    long value = 0;

    for (int i = 0; i < len; i++) {
      char ch = s.charAt(i);

      int digit;

      if ('0' <= ch && ch <= '9')
        digit = ch - '0';
      else if ('a' <= ch && ch <= 'z')
        digit = ch - 'a' + 10;
      else if ('A' <= ch && ch <= 'Z')
        digit = ch - 'A' + 10;
      else
        digit = 0;

      value = value * base + digit;
    }

    return value;
  }

  /**
   * Returns true for an array.
   *
   * @param v the value to test
   *
   * @return true for an array
   */
  public static boolean is_array(@ReadOnly Value v)
  {
    return v.isArray();
  }

  // XXX: is_binary

  /**
   * Returns true for a boolean
   *
   * @param v the value to test
   *
   * @return true for a boolean
   */
  public static Value is_bool(@ReadOnly Value v)
  {
    return (v.toValue() instanceof BooleanValue
            ? BooleanValue.TRUE
            : BooleanValue.FALSE);
  }

  // XXX: is_buffer

  /**
   * Returns the type string for the variable
   */
  public static boolean is_callable(Env env,
                                    Value v,
                                    @Optional boolean isSyntaxOnly,
                                    @Optional @Reference Value nameRef)
  {
    if (v instanceof StringValue) {
      if (nameRef != null)
        nameRef.set(v);

      if (isSyntaxOnly)
        return true;
      else
        return env.findFunction(v.toString()) != null;
    }
    else if (v instanceof ArrayValue) {
      Value obj = v.get(LongValue.ZERO);
      Value name = v.get(LongValue.ONE);

      if (! (name instanceof StringValue))
        return false;

      if (nameRef != null)
        nameRef.set(name);

      if (obj instanceof StringValue) {
        if (isSyntaxOnly)
          return true;

        QuercusClass cl = env.findClass(obj.toString());
        if (cl == null)
          return false;

        return (cl.findFunction(name.toString()) != null);
      }
      else if (obj.isObject()) {
        if (isSyntaxOnly)
          return true;

        return obj.findFunction(name.toString()) != null;
      }
      else
        return false;
    }
    else
      return false;
  }

  /**
   * Returns true for a double
   *
   * @param v the value to test
   *
   * @return true for a double
   */
  public static boolean is_double(@ReadOnly Value v)
  {
    return is_float(v);
  }

  /**
   * Returns true for a double
   *
   * @param v the value to test
   *
   * @return true for a double
   */
  public static boolean is_float(@ReadOnly Value v)
  {
    return (v.toValue() instanceof DoubleValue);
  }

  /**
   * Returns true for an integer
   *
   * @param v the value to test
   *
   * @return true for a double
   */
  public static Value is_int(@ReadOnly Value v)
  {
    return (v.toValue() instanceof LongValue
            ? BooleanValue.TRUE
            : BooleanValue.FALSE);
  }

  /**
   * Returns true for an integer
   *
   * @param v the value to test
   *
   * @return true for a double
   */
  public static Value is_integer(@ReadOnly Value v)
  {
    return is_int(v);
  }

  /**
   * Returns true for an integer
   *
   * @param v the value to test
   *
   * @return true for a double
   */
  public static Value is_long(@ReadOnly Value v)
  {
    return is_int(v);
  }

  /**
   * Returns true for null
   *
   * @param v the value to test
   *
   * @return true for null
   */
  public static boolean is_null(@ReadOnly Value v)
  {
    return v.isNull();
  }

  /**
   * Returns true for numeric
   *
   * @param env the calling environment
   * @param v the value to test
   *
   * @return true for numeric
   */
  public static boolean is_numeric(Env env, @ReadOnly Value v)
  {
    return v.isNumeric();
  }

  /**
   * Returns true for an object
   *
   * @param env the calling environment
   * @param v the value to test
   *
   * @return true for object
   */
  public static boolean is_object(Env env, @ReadOnly Value v)
  {
    return v.isObject();
  }

  /**
   * Returns true for a real
   *
   * @param v the value to test
   *
   * @return true for a real
   */
  public static boolean is_real(@ReadOnly Value v)
  {
    return is_float(v);
  }

  /**
   * Returns true if the value is a resource
   */
  public boolean is_resource(@ReadOnly Value value)
  {
    return value.isResource();
  }

  /**
   * Returns true for a scalar
   *
   * @param v the value to test
   *
   * @return true for a scalar
   */
  public static boolean is_scalar(@ReadOnly Value v)
  {
    if (v == null)
      return false;

    Value value = v.toValue();
   
    return (value instanceof DoubleValue
            || value instanceof StringValue
            || value instanceof LongValue
            || value instanceof BooleanValue);
  }

  /**
   * Returns true if the value is a string
   */
  public boolean is_string(@ReadOnly Value value)
  {
    return value.isString();
  }

  // XXX: is_unicode

  /**
   * Returns the type string for the variable
   */
  public static boolean isset(@ReadOnly Value v)
  {
    return v.isset();
  }

  /**
   * Prints a value.  If isReturn is true, then returns what was supposed
   * to be printed as a string instead.
   *
   * @param env the quercus calling environment
   * @param v the variable to print
   * @param isReturn set to true if returning instead of printing value
   * @return the string that was supposed to be printed, or true
   */
  public static Value print_r(Env env,
                              @ReadOnly Value v,
                              @Optional boolean isReturn)
  {
    try {
      WriteStream out;
     
      if (isReturn) {
        StringWriter writer = new StringWriter();
        out = writer.openWrite();
       
        out.setNewlineString("\n");
       
        v.printR(env, out, 0, new IdentityHashMap<Value, String>());
       
        return env.createStringOld(writer.getString());
      }
      else {
        out = env.getOut();
       
        v.printR(env, out, 0, new IdentityHashMap<Value, String>());
       
        return BooleanValue.TRUE;
      }
    } catch (IOException e) {
      throw new QuercusModuleException(e);
    }
  }

  private static void printDepth(WriteStream out, int depth)
    throws IOException
  {
    for (int i = 0; i < depth; i++)
      out.print(' ');
  }

  /**
   * Serializes the value to a string.
   */
  public static String serialize(Env env,
                                 @PassThru @ReadOnly Value v)
  {
    StringBuilder sb = new StringBuilder();

    v.serialize(env, sb, new SerializeMap());

    return sb.toString();
  }

  /**
   * Converts the variable to a specified tyep.
   */
  public static boolean settype(Env env,
                                @Reference Value var,
                                String type)
  {
    Value value = var.toValue();

    if ("null".equals(type)) {
      var.set(NullValue.NULL);
      return true;
    }
    else if ("boolean".equals(type) || "bool".equals(type)) {
      var.set(value.toBoolean() ? BooleanValue.TRUE : BooleanValue.FALSE);
      return true;
    }
    else if ("string".equals(type)) {
      var.set(value.toStringValue(env));
      return true;
    }
    else if ("int".equals(type) || "integer".equals(type)) {
      var.set(LongValue.create(value.toLong()));
      return true;
    }
    else if ("float".equals(type) || "double".equals(type)) {
      var.set(new DoubleValue(value.toDouble()));
      return true;
    }
    else if ("object".equals(type)) {
      var.set(value.toObject(env));
      return true;
    }
    else if ("array".equals(type)) {
      if (value.isArray())
        var.set(value);
      else {
        ArrayValueImpl array = new ArrayValueImpl();
        var.set(array);
       
        if (! value.isNull())
          array.append(value);
      }

      return true;
    }
    else
      return false;
  }

  /**
   * Converts to a string
   *
   * @param env the quercus calling environment
   * @param v the variable to convert
   * @return the double value
   */
  public static Value strval(Env env, @ReadOnly Value v)
  {
    if (v instanceof StringValue)
      return (StringValue) v;
    else
      return v.toReprString(env);
  }

  /**
   * Unserializes the value from a string.
   */
  public static Value unserialize(Env env, StringValue s)
  {
    Value v = null;

    UnserializeKey key = new UnserializeKey(s);
   
    UnserializeCacheEntry entry = _unserializeCache.get(key);

    if (entry != null) {
      v = entry.getValue(env);

      if (v != null)
        return v;
    }

    UnserializeReader is = null;

    try {
      is = new UnserializeReader(s);
     
      v = is.unserialize(env);
    } catch (IOException e) {
      log.log(Level.FINE, e.toString(), e);

      env.notice(e.toString());

      v = BooleanValue.FALSE;
    }

    if (is != null && ! is.useReference()) {
      entry = new UnserializeCacheEntry(v);
     
      _unserializeCache.put(key, entry);

      return entry.getValue(env);
    }

    return v;
  }

  // XXX: unset

  /**
   * Prints a debug version of the variable
   *
   * @param env the quercus calling environment
   * @param v the variable to print
   * @return the escaped stringPhp
   */
  public static Value var_dump(Env env,
                               @PassThru @ReadOnly Value v,
                               Value []args)
  {
    try {
      if (v == null)
        env.getOut().print("NULL#java");
      else {
        v.varDump(env, env.getOut(), 0new IdentityHashMap<Value,String>());
         
        env.getOut().println();
      }
     
      if (args != null) {
        for (Value value : args) {
          if (value == null)
            env.getOut().print("NULL#java");
          else {
            value.varDump(env, env.getOut(), 0,
                          new IdentityHashMap<Value,String>());
           
            env.getOut().println();
          }
        }
      }

      return NullValue.NULL;
    } catch (IOException e) {
      throw new QuercusModuleException(e);
    }
  }

  /**
   * Serializes the value to a string.
   */
  public static Value var_export(Env env,
                                 @ReadOnly Value v,
                                 @Optional boolean isReturn)
  {
    StringBuilder sb = new StringBuilder();

    v.varExport(sb);

    if (isReturn)
      return env.createStringOld(sb.toString());
    else {
      env.print(sb);

      return NullValue.NULL;
    }
  }

  private static void debug_impl(Env env, Value v, int depth)
    throws IOException
  {
    WriteStream out = env.getOut();

    if (v instanceof Var)
      out.print("&");

    v = v.toValue();

    if (v instanceof ArrayValue) {
      ArrayValue array = (ArrayValue) v;

      out.println("Array");
      printDepth(out, 2 * depth);
      out.println("(");

      for (Map.Entry<Value,Value> entry : array.entrySet()) {
        printDepth(out, 2 * depth);
        out.print("    [");
        out.print(entry.getKey());
        out.print("] => ");
        debug_impl(env, entry.getValue(), depth + 1); // XXX: recursion
      }
      printDepth(out, 2 * depth);
      out.println(")");
    }
    else if (v instanceof BooleanValue) {
      if (v.toBoolean())
        out.print("bool(true)");
      else
        out.print("bool(false)");
    }
    else if (v instanceof LongValue) {
      out.print("int(" + v.toLong() + ")");
    }
    else if (v instanceof DoubleValue) {
      out.print("float(" + v.toDouble() + ")");
    }
    else if (v instanceof StringValue) {
      out.print("string(" + v.toString() + ")");
    }
    else if (v instanceof NullValue) {
      out.print("NULL");
    }
    else {
      v.print(env);
    }
  }

  static class UnserializeKey {
    private final SoftReference<StringValue> _stringRef;
    private int _hash;

    UnserializeKey(StringValue string)
    {
      _hash = string.hashCode();

      _stringRef = new SoftReference<StringValue>(string);
    }

    public int hashCode()
    {
      return _hash;
    }

    public boolean equals(Object o)
    {
      if (this == o)
        return true;
      else if (! (o instanceof UnserializeKey))
        return false;

      UnserializeKey key = (UnserializeKey) o;

      StringValue a = _stringRef.get();
      StringValue b = key._stringRef.get();

      if (a == null || b == null)
        return false;

      return a.equals(b);
    }
  }
}
TOP

Related Classes of com.caucho.quercus.lib.VariableModule

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.