Пример #1
0
 /**
  * Uses the constructor represented by this Constructor object to create 
  * and initialize a new instance of the constructor's declaring class, 
  * with the specified initialization parameters.
  *
  * Example:
  * <code>
  *   $constructor= XPClass::forName('util.Binford')->getConstructor();
  *
  *   $instance= $constructor->newInstance();
  *   $instance= $constructor->newInstance([6100]);
  * </code>
  *
  * @param   var[] args
  * @return  lang.Generic
  * @throws  lang.IllegalAccessException in case the constructor is not public or if it is abstract
  * @throws  lang.reflect.TargetInvocationException in case the constructor throws an exception
  */
 public function newInstance(array $args = [])
 {
     $class = new \ReflectionClass($this->_class);
     if ($class->isAbstract()) {
         throw new IllegalAccessException('Cannot instantiate abstract class ' . XPClass::nameOf($this->_class));
     }
     // Check modifiers. If caller is an instance of this class, allow private and
     // protected constructor invocation (which the PHP reflection API does not).
     $m = $this->_reflect->getModifiers();
     $public = $m & MODIFIER_PUBLIC;
     if (!$public && !$this->accessible) {
         $t = debug_backtrace(0, 2);
         $decl = $this->_reflect->getDeclaringClass()->getName();
         if ($m & MODIFIER_PROTECTED) {
             $allow = $t[1]['class'] === $decl || is_subclass_of($t[1]['class'], $decl);
         } else {
             $allow = $t[1]['class'] === $decl;
         }
         if (!$allow) {
             throw new IllegalAccessException(sprintf('Cannot invoke %s constructor of class %s from scope %s', Modifiers::stringOf($this->getModifiers()), XPClass::nameOf($this->_class), $t[1]['class']));
         }
     }
     // For non-public constructors: Use setAccessible() / invokeArgs() combination
     try {
         if ($public) {
             return $class->newInstanceArgs($args);
         }
         $instance = unserialize('O:' . strlen($this->_class) . ':"' . $this->_class . '":0:{}');
         $this->_reflect->setAccessible(true);
         $this->_reflect->invokeArgs($instance, $args);
         return $instance;
     } catch (\lang\SystemExit $e) {
         throw $e;
     } catch (\lang\Throwable $e) {
         throw new TargetInvocationException(XPClass::nameOf($this->_class) . '::<init>', $e);
     } catch (\Exception $e) {
         throw new TargetInvocationException(XPClass::nameOf($this->_class) . '::<init>', new \lang\XPException($e->getMessage()));
     } catch (\BaseException $e) {
         throw new TargetInvocationException(XPClass::nameOf($this->_class) . '::' . $this->_reflect->getName(), new \lang\Error($e->getMessage()));
     }
 }
Пример #2
0
 /**
  * Invokes the underlying method represented by this Method object, 
  * on the specified object with the specified parameters.
  *
  * Example:
  * ```php
  * $method= XPClass::forName('lang.Object')->getMethod('toString');
  * $str= $method->invoke(new Object());
  * ```
  *
  * Example (passing arguments)
  * ```php
  * $method= XPClass::forName('lang.types.String')->getMethod('concat');
  * $str= $method->invoke(new String('Hello'), ['World']);
  * ```
  *
  * Example (static invokation):
  * ```php
  * $method= XPClass::forName('util.log.Logger')->getMethod('getInstance');
  * $log= $method->invoke(null);
  * ```
  *
  * @param   lang.Object $obj
  * @param   var[] $args default []
  * @return  var
  * @throws  lang.IllegalArgumentException in case the passed object is not an instance of the declaring class
  * @throws  lang.IllegalAccessException in case the method is not public or if it is abstract
  * @throws  lang.reflect.TargetInvocationException for any exception raised from the invoked method
  */
 public function invoke($obj, $args = [])
 {
     if (null !== $obj && !$obj instanceof $this->_class) {
         throw new IllegalArgumentException(sprintf('Passed argument is not a %s class (%s)', XPClass::nameOf($this->_class), \xp::typeOf($obj)));
     }
     // Check modifiers. If caller is an instance of this class, allow
     // protected method invocation (which the PHP reflection API does
     // not).
     $m = $this->_reflect->getModifiers();
     if ($m & MODIFIER_ABSTRACT) {
         throw new IllegalAccessException(sprintf('Cannot invoke abstract %s::%s', XPClass::nameOf($this->_class), $this->_reflect->getName()));
     }
     $public = $m & MODIFIER_PUBLIC;
     if (!$public && !$this->accessible) {
         $t = debug_backtrace(0, 2);
         $decl = $this->_reflect->getDeclaringClass()->getName();
         if ($m & MODIFIER_PROTECTED) {
             $allow = $t[1]['class'] === $decl || is_subclass_of($t[1]['class'], $decl);
         } else {
             $allow = $t[1]['class'] === $decl;
         }
         if (!$allow) {
             throw new IllegalAccessException(sprintf('Cannot invoke %s %s::%s from scope %s', Modifiers::stringOf($this->getModifiers()), XPClass::nameOf($this->_class), $this->_reflect->getName(), $t[1]['class']));
         }
     }
     try {
         if (!$public) {
             $this->_reflect->setAccessible(true);
         }
         return $this->_reflect->invokeArgs($obj, (array) $args);
     } catch (\lang\SystemExit $e) {
         throw $e;
     } catch (\lang\Throwable $e) {
         throw new TargetInvocationException(XPClass::nameOf($this->_class) . '::' . $this->_reflect->getName(), $e);
     } catch (\Exception $e) {
         throw new TargetInvocationException(XPClass::nameOf($this->_class) . '::' . $this->_reflect->getName(), new \lang\XPException($e->getMessage()));
     } catch (\Throwable $e) {
         throw new TargetInvocationException(XPClass::nameOf($this->_class) . '::' . $this->_reflect->getName(), new \lang\Error($e->getMessage()));
     }
 }
 public function staticModifierString()
 {
     $this->assertEquals('public static', \lang\reflect\Modifiers::stringOf(MODIFIER_STATIC));
 }
Пример #4
0
 /**
  * Retrieve string representation. Examples:
  *
  * <pre>
  *   public lang.XPClass getClass()
  *   public static util.Date now()
  *   public open(string $mode) throws io.FileNotFoundException, io.IOException
  * </pre>
  *
  * @return  string
  */
 public function toString()
 {
     $signature = '';
     foreach ($this->getParameters() as $param) {
         if ($param->isOptional()) {
             $signature .= ', [' . $param->getTypeName() . ' $' . $param->getName() . '= ' . str_replace("\n", ' ', \xp::stringOf($param->getDefaultValue())) . ']';
         } else {
             $signature .= ', ' . $param->getTypeName() . ' $' . $param->getName();
         }
     }
     if ($exceptions = $this->getExceptionNames()) {
         $throws = ' throws ' . implode(', ', $exceptions);
     } else {
         $throws = '';
     }
     return sprintf('%s %s %s(%s)%s', Modifiers::stringOf($this->getModifiers()), $this->getReturnTypeName(), $this->getName(), substr($signature, 2), $throws);
 }
Пример #5
0
 /**
  * Creates a string representation of this field
  *
  * @return  string
  */
 public function toString()
 {
     return sprintf('%s %s %s::$%s', Modifiers::stringOf($this->getModifiers()), $this->getTypeName(), $this->getDeclaringClass()->getName(), $this->getName());
 }