示例#1
0
 /**
  * Adds a source loader
  *
  * @param   lang.IClassLoader
  */
 public function addSourceLoader(IClassLoader $l)
 {
     $this->sourcepath[$l->hashCode()] = $l;
 }
示例#2
0
 /**
  * Returns the XPClass object for a proxy class given a class loader 
  * and an array of interfaces.  The proxy class will be defined by the 
  * specified class loader and will implement all of the supplied 
  * interfaces (also loaded by the classloader).
  *
  * @param   lang.IClassLoader classloader
  * @param   lang.XPClass[] interfaces names of the interfaces to implement
  * @return  lang.XPClass
  * @throws  lang.IllegalArgumentException
  */
 public static function getProxyClass(IClassLoader $classloader, array $interfaces)
 {
     static $num = 0;
     static $cache = array();
     $t = sizeof($interfaces);
     if (0 === $t) {
         throw new IllegalArgumentException('Interfaces may not be empty');
     }
     // Calculate cache key (composed of the names of all interfaces)
     $key = $classloader->hashCode() . ':' . implode(';', array_map(create_function('$i', 'return $i->getName();'), $interfaces));
     if (isset($cache[$key])) {
         return $cache[$key];
     }
     // Create proxy class' name, using a unique identifier and a prefix
     $name = self::PREFIX . $num++;
     $bytes = 'class ' . $name . ' extends ' . xp::reflect('lang.reflect.Proxy') . ' implements ';
     $added = array();
     for ($j = 0; $j < $t; $j++) {
         $bytes .= xp::reflect($interfaces[$j]->getName()) . ', ';
     }
     $bytes = substr($bytes, 0, -2) . " {\n";
     for ($j = 0; $j < $t; $j++) {
         $if = $interfaces[$j];
         // Verify that the Class object actually represents an interface
         if (!$if->isInterface()) {
             throw new IllegalArgumentException($if->getName() . ' is not an interface');
         }
         // Implement all the interface's methods
         foreach ($if->getMethods() as $m) {
             // Check for already declared methods, do not redeclare them
             if (isset($added[$m->getName()])) {
                 continue;
             }
             $added[$m->getName()] = TRUE;
             // Build signature and argument list
             if ($m->hasAnnotation('overloaded')) {
                 $signatures = $m->getAnnotation('overloaded', 'signatures');
                 $max = 0;
                 $cases = array();
                 foreach ($signatures as $signature) {
                     $args = sizeof($signature);
                     $max = max($max, $args - 1);
                     if (isset($cases[$args])) {
                         continue;
                     }
                     $cases[$args] = 'case ' . $args . ': ' . 'return $this->_h->invoke($this, \'' . $m->getName(TRUE) . '\', array(' . ($args ? '$_' . implode(', $_', range(0, $args - 1)) : '') . '));';
                 }
                 // Create method
                 $bytes .= 'function ' . $m->getName() . '($_' . implode('= NULL, $_', range(0, $max)) . '= NULL) { ' . 'switch (func_num_args()) {' . implode("\n", $cases) . ' default: throw new IllegalArgumentException(\'Illegal number of arguments\'); }' . '}' . "\n";
             } else {
                 $signature = $args = '';
                 foreach ($m->getParameters() as $param) {
                     $signature .= ', ';
                     $restriction = $param->getTypeRestriction();
                     if ($restriction instanceof XPClass) {
                         $signature .= '\\' . strtr($restriction->getName(), array('php.' => '', '.' => '\\'));
                     } else {
                         if (Primitive::$ARRAY->equals($restriction)) {
                             $signature .= 'array';
                         }
                     }
                     $signature .= ' $' . $param->getName();
                     $args .= ', $' . $param->getName();
                     $param->isOptional() && ($signature .= '= ' . var_export($param->getDefaultValue(), TRUE));
                 }
                 $signature = substr($signature, 2);
                 $args = substr($args, 2);
                 // Create method
                 $bytes .= 'function ' . $m->getName() . '(' . $signature . ') { ' . 'return $this->_h->invoke($this, \'' . $m->getName(TRUE) . '\', array(' . $args . ')); ' . '}' . "\n";
             }
         }
     }
     $bytes .= ' }';
     // Define the generated class
     try {
         $dyn = DynamicClassLoader::instanceFor(__METHOD__);
         $dyn->setClassBytes($name, $bytes);
         $class = $dyn->loadClass($name);
     } catch (FormatException $e) {
         throw new IllegalArgumentException($e->getMessage());
     }
     // Update cache and return XPClass object
     $cache[$key] = $class;
     return $class;
 }
 /**
  * Unregister a class loader as a delegate
  *
  * @param   lang.IClassLoader l
  * @return  bool TRUE if the delegate was unregistered
  */
 public static function removeLoader(IClassLoader $l)
 {
     $id = $l->instanceId();
     if (!isset(self::$delegates[$id])) {
         return FALSE;
     }
     unset(self::$delegates[$id]);
     return TRUE;
 }