PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/com/didactilab/gwt/phprpc/phpjava/phprpc/classes.php

http://gwtphp-derpc.googlecode.com/
PHP | 1488 lines | 1123 code | 290 blank | 75 comment | 146 complexity | 0287116269974c96e0d901fefdee0df9 MD5 | raw file
  1. <?php
  2. /*
  3. * Copyright 2011 DidactiLab SAS
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  6. * use this file except in compliance with the License. You may obtain a copy of
  7. * the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  13. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  14. * License for the specific language governing permissions and limitations under
  15. * the License.
  16. *
  17. * Date: 30 avr. 2011
  18. * Author: Mathieu LIGOCKI
  19. */
  20. interface Magic {
  21. function getMagicClassName();
  22. function getMagicClassFullName();
  23. }
  24. abstract class Clazz {
  25. protected $name;
  26. public function __construct($name) {
  27. $this->name = $name;
  28. }
  29. public function getName() {
  30. return $this->name;
  31. }
  32. public abstract function getFields();
  33. public abstract function getDeclaredFields();
  34. public abstract function hasField($fieldName);
  35. public abstract function hasDeclaredField($fieldName);
  36. public abstract function getField($fieldName);
  37. public abstract function getDeclaredField($fieldName);
  38. public abstract function getSuperClass();
  39. public abstract function getMethods();
  40. public abstract function getMethod($methodName);
  41. public abstract function hasMethod($methodName);
  42. public abstract function getConstructor();
  43. public abstract function newInstance();
  44. public abstract function newInstanceArgs(array $args);
  45. public function getEnclosingClass() {
  46. return null;
  47. }
  48. public function getPackage() {
  49. return '';
  50. }
  51. public function getFullName() {
  52. return $this->name;
  53. }
  54. public function getComponentType() {
  55. return null;
  56. }
  57. public function isArray() {
  58. return false;
  59. }
  60. public function isEnum() {
  61. return false;
  62. }
  63. public function getConstantNameByValue($value) {
  64. return null;
  65. }
  66. public function getEnumValues() {
  67. return array();
  68. }
  69. public function isInterface() {
  70. return false;
  71. }
  72. public function getInterfaces() {
  73. return array();
  74. }
  75. public abstract function hasGWTName();
  76. public abstract function getGWTName();
  77. public function isPrimitive() {
  78. return false;
  79. }
  80. public function isAssignableFrom(Clazz $clazz) {
  81. return $clazz === $this;
  82. }
  83. public function implementsInterface(Clazz $interface) {
  84. return false;
  85. }
  86. public function subClassOf(Clazz $clazz) {
  87. return false;
  88. }
  89. public static function clazz() {
  90. return Classes::classOf(get_called_class());
  91. }
  92. }
  93. class JavaClazz extends Clazz {
  94. protected $fields = array();
  95. protected $super = null;
  96. protected $methods = array();
  97. protected $compatibleClasses = array();
  98. public function __construct($name, Clazz $super = null) {
  99. parent::__construct($name);
  100. $this->super = $super;
  101. }
  102. public function getFullName() {
  103. $classname = $this->name;
  104. return $classname::CLASSNAME;
  105. }
  106. public function getPackage() {
  107. $fullname = $this->getFullName();
  108. $pos = mb_strrpos($fullname, '.');
  109. if ($pos != false) {
  110. return mb_substr($fullname, 0, $pos);
  111. }
  112. else {
  113. return '';
  114. }
  115. }
  116. public function getFields() {
  117. return $this->fields;
  118. }
  119. public function getDeclaredFields() {
  120. return $this->fields;
  121. }
  122. public function getMethods() {
  123. return $this->methods;
  124. }
  125. public function getMethod($methodName) {
  126. return null;
  127. }
  128. public function hasMethod($methodName) {
  129. return false;
  130. }
  131. public function getConstructor() {
  132. return null;
  133. }
  134. public function hasField($fieldName) {
  135. return in_array($fieldName, $this->fields);
  136. }
  137. public function hasDeclaredField($fieldName) {
  138. return $this->hasField($fieldName);
  139. }
  140. public function getField($fieldName) {
  141. return null;
  142. }
  143. public function getDeclaredField($fieldName) {
  144. return null;
  145. }
  146. public function getSuperClass() {
  147. return $this->super;
  148. }
  149. public function newInstance() {
  150. return null;
  151. }
  152. public function newInstanceArgs(array $args) {
  153. return null;
  154. }
  155. public function hasGWTName() {
  156. return false;
  157. }
  158. public function getGWTName() {
  159. return '';
  160. }
  161. public function isAssignableFrom(Clazz $clazz) {
  162. return parent::isAssignableFrom($clazz) ||
  163. in_array($clazz, $this->compatibleClasses, true);
  164. }
  165. public function registerAssignableFrom(array $classes) {
  166. foreach ($classes as $cls) {
  167. if (!in_array($cls, $this->compatibleClasses, true)) {
  168. $this->compatibleClasses[] = $cls;
  169. }
  170. }
  171. }
  172. public function __toString() {
  173. return '{jclass ' . $this->name . '}';
  174. }
  175. }
  176. class JavaPrimitiveClazz extends JavaClazz {
  177. private $signature;
  178. public function __construct($name, $signature) {
  179. parent::__construct($name, null);
  180. $this->signature = $signature;
  181. }
  182. public function isPrimitive() {
  183. return true;
  184. }
  185. public function getFullName() {
  186. return $this->name;
  187. }
  188. public function getSignature() {
  189. return $this->signature;
  190. }
  191. public function __toString() {
  192. return '{jprimitive ' . $this->name . '}';
  193. }
  194. }
  195. class AliasClass extends Clazz {
  196. private $clazz;
  197. private $newName;
  198. public function __construct($clazz, $newName) {
  199. parent::__construct($newName);
  200. $this->clazz = $clazz;
  201. }
  202. public function getFields() {
  203. return $this->clazz->getFields();
  204. }
  205. public function hasField($fieldName) {
  206. return $this->clazz->hasField($fieldName);
  207. }
  208. public function getField($fieldName) {
  209. return $this->clazz->getField($fieldName);
  210. }
  211. public function getDeclaredFields() {
  212. return $this->clazz->getDeclaredFields();
  213. }
  214. public function hasDeclaredField($fieldName) {
  215. return $this->clazz->hasDeclaredField($fieldName);
  216. }
  217. public function getDeclaredField($fieldName) {
  218. return $this->clazz->getDeclaredField($fieldName);
  219. }
  220. public function getSuperClass() {
  221. return $this->clazz->getSuperClass();
  222. }
  223. public function getMethods() {
  224. return $this->clazz->getMethods();
  225. }
  226. public function getMethod($methodName) {
  227. return $this->clazz->getMethod($methodName);
  228. }
  229. public function hasMethod($methodName) {
  230. return $this->clazz->hasMethod($methodName);
  231. }
  232. public function getConstructor() {
  233. return $this->clazz->getConstructor();
  234. }
  235. public function newInstance() {
  236. return $this->clazz->newInstance();
  237. }
  238. public function newInstanceArgs(array $args) {
  239. return $this->clazz->newInstanceArgs($args);
  240. }
  241. public function getEnclosingClass() {
  242. return $this->clazz->getEnclosingClass();
  243. }
  244. public function getPackage() {
  245. return $this->clazz->getPackage();
  246. }
  247. public function getFullName() {
  248. return $this->clazz->getFullName();
  249. }
  250. public function getComponentType() {
  251. return $this->clazz->getComponentType();
  252. }
  253. public function isArray() {
  254. return $this->clazz->isArray();
  255. }
  256. public function isEnum() {
  257. return $this->clazz->isEnum();
  258. }
  259. public function getConstantNameByValue($value) {
  260. return $this->clazz->getConstantNameByValue($value);
  261. }
  262. public function getEnumValues() {
  263. return $this->clazz->getEnumValues();
  264. }
  265. public function isInterface() {
  266. return $this->clazz->isInterface();
  267. }
  268. public function hasGWTName() {
  269. return $this->clazz->hasGWTName();
  270. }
  271. public function getGWTName() {
  272. return $this->clazz->getGWTName();
  273. }
  274. public function isPrimitive() {
  275. return $this->clazz->isPrimitive();
  276. }
  277. public function isAssignableFrom(Clazz $clazz) {
  278. return $this->clazz->isAssignableFrom($clazz);
  279. }
  280. public function implementsInterface(Clazz $interface) {
  281. return $this->clazz->implementsInterface($interface);
  282. }
  283. public function subClassOf(Clazz $clazz) {
  284. return $this->clazz->subClassOf($clazz);
  285. }
  286. public function __toString() {
  287. return '{alias ' . $this->getName() . '}';
  288. }
  289. }
  290. class PhpClazz extends Clazz {
  291. protected $reflect;
  292. protected $fields = null;
  293. protected $declaredFields = null;
  294. private $methods = array();
  295. private $constructor = null;
  296. private $gwtname = '';
  297. private $enclosing = null;
  298. public function __construct($name) {
  299. if (!class_exists($name) && !interface_exists($name))
  300. throw new ClassException('php class "' . $name . '" does not exists');
  301. parent::__construct($name);
  302. $this->reflect = new ReflectionClass($name);
  303. if ($this->reflect->getName() !== $name)
  304. throw new ClassException('php class "' . $name . '" does not exists');
  305. $this->init();
  306. }
  307. protected function init() {
  308. // gwtname
  309. $doc = $this->reflect->getDocComment();
  310. $found = preg_match_all('/@gwtname[\s]([\w]+([.$_][\w]+)*)/', $doc, $matches, PREG_SET_ORDER);
  311. if ($found ==1) {
  312. $this->gwtname = $matches[0][1];
  313. }
  314. // Enclosing
  315. $found = preg_match_all('/@enclosing[\s]([\w]+([.$_][\w]+)*)/', $doc, $matches, PREG_SET_ORDER);
  316. if ($found ==1) {
  317. $this->enclosing = Classes::classOf($matches[0][1]);
  318. }
  319. }
  320. protected function createFields() {
  321. $fields = array();
  322. $decl = array();
  323. foreach ($this->reflect->getProperties() as $prop) {
  324. if ($prop->getDeclaringClass()->getShortName() !== $this->reflect->getShortName()) {
  325. $field = $this->getSuperClass()->getField($prop->getName());
  326. }
  327. else {
  328. $field = new PhpField($this, $prop);
  329. $decl[$prop->getName()] = $field;
  330. }
  331. $fields[$prop->getName()] = $field;
  332. }
  333. return array($fields, $decl);
  334. }
  335. private function checkFields() {
  336. if (is_null($this->fields)) {
  337. list($this->fields, $this->declaredFields) = $this->createFields();
  338. }
  339. }
  340. public function getFullName() {
  341. if (empty($this->gwtname))
  342. return parent::getFullName();
  343. else
  344. return $this->gwtname;
  345. }
  346. public function getPackage() {
  347. if (empty($this->gwtname)) {
  348. return self::getPackage();
  349. }
  350. else {
  351. $gwtname = $this->gwtname;
  352. $pos = mb_strpos($gwtname, '$');
  353. if ($pos != false) {
  354. $gwtname = mb_substr($gwtname, 0, $pos);
  355. }
  356. $pos = mb_strrpos($gwtname, '.');
  357. if ($pos != false) {
  358. return mb_substr($gwtname, 0, $pos);
  359. }
  360. else {
  361. return '';
  362. }
  363. }
  364. }
  365. public function getEnclosingClass() {
  366. return $this->enclosing;
  367. }
  368. public function getFields() {
  369. $this->checkFields();
  370. return $this->fields;
  371. }
  372. public function getDeclaredFields() {
  373. $this->checkFields();
  374. return $this->declaredFields;
  375. }
  376. public function hasField($fieldName) {
  377. return $this->reflect->hasProperty($fieldName);
  378. }
  379. public function hasDeclaredField($fieldName) {
  380. $this->checkFields();
  381. foreach ($this->declaredFields as $field) {
  382. if ($field->getName() === $fieldName) {
  383. return true;
  384. }
  385. }
  386. return false;
  387. }
  388. public function getField($fieldName) {
  389. $this->checkFields();
  390. if (!$this->hasField($fieldName)) {
  391. throw new ClassException('The field "' . $fieldName . '" does not exists in ' . $this);
  392. }
  393. return $this->fields[$fieldName];
  394. }
  395. public function getDeclaredField($fieldName) {
  396. $this->checkFields();
  397. if (!$this->hasDeclaredField($fieldName)) {
  398. throw new ClassException('The field "' . $fieldName . '" does not exists in ' . $this);
  399. }
  400. return $this->declaredFields[$fieldName];
  401. }
  402. public function getMethods() {
  403. $ms = get_class_methods($this->name);
  404. foreach ($ms as $m) {
  405. if (!isset($this->methods[$m])) {
  406. $this->methods[$m] = new PhpMethod($this, $m);
  407. }
  408. }
  409. return array_values($this->methods);
  410. }
  411. public function getMethod($methodName) {
  412. if (!method_exists($this->name, $methodName))
  413. return null;
  414. else {
  415. if (!isset($this->methods[$methodName]))
  416. $this->methods[$methodName] = new PhpMethod($this, $methodName);
  417. return $this->methods[$methodName];
  418. }
  419. }
  420. public function hasMethod($methodName) {
  421. return method_exists($this->name, $methodName);
  422. }
  423. public function getConstructor() {
  424. if (is_null($this->constructor)) {
  425. $method = $this->reflect->getConstructor();
  426. if (is_null($method)) {
  427. $this->constructor = new PhpEmptyConstructor($this);
  428. }
  429. else {
  430. $this->constructor = new PhpConstructor($this, $method);
  431. }
  432. }
  433. return $this->constructor;
  434. }
  435. public function getSuperClass() {
  436. $parentName = get_parent_class($this->name);
  437. if ($parentName !== false) {
  438. return Classes::classOf($parentName);
  439. }
  440. else {
  441. return Object::clazz();
  442. }
  443. }
  444. public function newInstance() {
  445. if (func_num_args() == 0) {
  446. return $this->reflect->newInstance();
  447. }
  448. else {
  449. return $this->newInstanceArgs(func_get_args());
  450. }
  451. }
  452. public function newInstanceArgs(array $args) {
  453. return $this->reflect->newInstanceArgs($args);
  454. }
  455. public function isInterface() {
  456. return $this->reflect->isInterface();
  457. }
  458. public function getInterfaces() {
  459. $interfaces = $this->reflect->getInterfaces();
  460. $result = array();
  461. foreach ($interfaces as $name => $reflect) {
  462. $result[] = Classes::classOf($name);
  463. }
  464. return $result;
  465. }
  466. public function isAssignableFrom(Clazz $clazz) {
  467. return parent::isAssignableFrom($clazz) ||
  468. ($this->isInterface() && $clazz->implementsInterface($this)) ||
  469. (!$this->isInterface() && $clazz->subClassOf($this));
  470. }
  471. public function __toString() {
  472. return '{class ' . $this->name . '}';
  473. }
  474. public function hasGWTName() {
  475. return !empty($this->gwtname);
  476. }
  477. public function getGWTName() {
  478. return $this->gwtname;
  479. }
  480. public function implementsInterface(Clazz $interface) {
  481. if (!interface_exists($interface->getName()))
  482. return false;
  483. return $this->reflect->implementsInterface($interface->getName());
  484. }
  485. public function subClassOf(Clazz $clazz) {
  486. return $this->reflect->isSubclassOf($clazz->getName());
  487. }
  488. }
  489. class PhpEnumClazz extends PhpClazz {
  490. protected function createFields() {
  491. list($fields, $decl) = parent::createFields();
  492. $temp = array();
  493. $constants = $this->getEnumValues();
  494. foreach ($constants as $value) {
  495. $temp[$value] = new VirtualField($this, $value, $this, 0, VirtualField::FLAG_STATIC);
  496. }
  497. $temp['ENUM$VALUES'] = new VirtualField($this, 'ENUM$VALUES', ArrayType::clazz($this), 0, VirtualField::FLAG_STATIC);
  498. return array(array_merge($fields, $temp), array_merge($decl, $temp));
  499. }
  500. public function isEnum() {
  501. return true;
  502. }
  503. public function getConstantNameByValue($value) {
  504. if (!$this->isEnum()) {
  505. return null;
  506. }
  507. $res = array_search($value, $this->reflect->getConstants());
  508. if ($res === false) {
  509. return null;
  510. }
  511. else {
  512. return $res;
  513. }
  514. }
  515. public function getEnumValues() {
  516. return array_values($this->reflect->getConstants());
  517. }
  518. }
  519. class MagicClazz extends PhpClazz {
  520. private $magicClassName;
  521. private $magicClassFullName;
  522. public function __construct($name, Magic $instance) {
  523. if (!($instance instanceof Magic)) {
  524. throw new ClassException('php class "' . $name . '" is not Magic implemented');
  525. }
  526. parent::__construct($name);
  527. $this->magicClassName = $instance->getMagicClassName();
  528. $this->magicClassFullName = $instance->getMagicClassFullName();
  529. }
  530. public function getName() {
  531. return $this->magicClassName;
  532. }
  533. public function getFullName() {
  534. return $this->magicClassFullName;
  535. }
  536. }
  537. abstract class Field {
  538. protected $clazz;
  539. public function __construct(Clazz $clazz) {
  540. $this->clazz = $clazz;
  541. }
  542. public function getDeclaringClass() {
  543. return $this->clazz;
  544. }
  545. public abstract function getName();
  546. public abstract function setValue($instance, $value);
  547. public abstract function getValue($instance);
  548. public abstract function hasGWTType();
  549. public abstract function getGWTType();
  550. public abstract function hasType();
  551. public abstract function getType();
  552. public abstract function isStatic();
  553. public abstract function isTransient();
  554. public abstract function isPrivate();
  555. public abstract function isProtected();
  556. public abstract function isPublic();
  557. public abstract function setAccessible($accessible);
  558. public abstract function isAccessible();
  559. }
  560. class PhpField extends Field {
  561. private $reflect;
  562. private $name;
  563. private $type;
  564. private $transient = false;
  565. public function __construct(Clazz $clazz, $reflect) {
  566. parent::__construct($clazz);
  567. $this->reflect = $reflect;
  568. $this->name = $reflect->getName();
  569. $this->init();
  570. }
  571. private function init() {
  572. $doc = $this->reflect->getDocComment();
  573. $found = preg_match_all('/@var[\s]([\w\[\]]+)/', $doc, $matches, PREG_SET_ORDER);
  574. if ($found ==1) {
  575. $this->type = $matches[0][1];
  576. }
  577. $found = preg_match_all('/@transient/', $doc, $matches, PREG_SET_ORDER);
  578. $this->transient = $found >= 1;
  579. }
  580. public function getName() {
  581. return $this->name;
  582. }
  583. public function setValue($instance, $value) {
  584. $field = $this->name;
  585. $instance->$field = $value;
  586. }
  587. public function getValue($instance) {
  588. $field = $this->name;
  589. return $instance->$field;
  590. }
  591. public function hasGWTType() {
  592. return !empty($this->type);
  593. }
  594. public function getGWTType() {
  595. return $this->type;
  596. }
  597. public function hasType() {
  598. return !empty($this->type);
  599. }
  600. public function getType() {
  601. if (!$this->hasGWTType()) {
  602. throw new ClassException('The field ' .
  603. $this->getDeclaringClass()->getName() . '.' . $this->getName() . ' have not type information');
  604. }
  605. return Classes::classOf($this->type);
  606. }
  607. public function isStatic() {
  608. return $this->reflect->isStatic();
  609. }
  610. public function isTransient() {
  611. return $this->transient;
  612. }
  613. public function isPrivate() {
  614. return $this->reflect->isPrivate();
  615. }
  616. public function isProtected() {
  617. return $this->reflect->isProtected();
  618. }
  619. public function isPublic() {
  620. return $this->reflect->isPublic();
  621. }
  622. public function setAccessible($accessible) {
  623. $this->reflect->setAccessible($accessible);
  624. }
  625. public function isAccessible() {
  626. return $this->reflect->isPrivate() || $this->reflect->isProtected();
  627. }
  628. }
  629. class VirtualField extends Field {
  630. const FLAG_TRANSIENT = 1;
  631. const FLAG_STATIC = 2;
  632. const VISIBILITY_PUBLIC = 0;
  633. const VISIBILITY_PROTECTED = 1;
  634. const VISIBILITY_PRIVATE = 2;
  635. private $name;
  636. private $type;
  637. private $visiblity;
  638. private $flags;
  639. public function __construct(Clazz $clazz, $name, Clazz $type, $visibility = self::VISIBILITY_PUBLIC, $flags = 0) {
  640. parent::__construct($clazz);
  641. $this->name = $name;
  642. $this->type = $type;
  643. $this->visibility = $visibility;
  644. $this->flags = $flags;
  645. }
  646. public function getName() {
  647. return $this->name;
  648. }
  649. public function setValue($instance, $value) {
  650. }
  651. public function getValue($instance) {
  652. return null;
  653. }
  654. public function hasGWTType() {
  655. return true;
  656. }
  657. public function getGWTType() {
  658. return $this->type->getName();
  659. }
  660. public function hasType() {
  661. return true;
  662. }
  663. public function getType() {
  664. return $this->type;
  665. }
  666. public function isStatic() {
  667. return ($this->flags & self::FLAG_STATIC) != 0;
  668. }
  669. public function isTransient() {
  670. return ($this->flags & self::FLAG_TRANSIENT) != 0;
  671. }
  672. public function isPrivate() {
  673. return $this->visibility == self::VISIBLITY_PRIVATE;
  674. }
  675. public function isProtected() {
  676. return $this->visibility == self::VISIBLITY_PROTECTED;
  677. }
  678. public function isPublic() {
  679. return $this->visibility == self::VISIBLITY_PUBLIC;
  680. }
  681. public function setAccessible($accessible) {
  682. }
  683. public function isAccessible() {
  684. return true;
  685. }
  686. }
  687. abstract class Method {
  688. protected $clazz;
  689. protected $name;
  690. public function __construct(Clazz $clazz, $name) {
  691. $this->clazz = $clazz;
  692. $this->name = $name;
  693. }
  694. public function getName() {
  695. return $this->name;
  696. }
  697. public function getDeclaringClass() {
  698. return $this->clazz;
  699. }
  700. public abstract function invoke();
  701. public abstract function invokeArgs();
  702. public abstract function isStatic();
  703. public abstract function hasReturnType();
  704. public abstract function getReturnType();
  705. public abstract function getExceptionTypes();
  706. public function __toString() {
  707. $result = '';
  708. if ($this->hasReturnType()) {
  709. $returnType = $this->getReturnType();
  710. if (!empty($returnType)) {
  711. $returnType = Classes::classOf($returnType)->getFullName();
  712. }
  713. $result .= $returnType . ' ';
  714. }
  715. return $result . $this->clazz->getFullName() . '.' . $this->name . '()';
  716. }
  717. }
  718. class PhpMethod extends Method {
  719. private $reflect;
  720. private $returnType = '';
  721. private $exceptionTypes = array();
  722. public function __construct(Clazz $clazz, $name) {
  723. parent::__construct($clazz, $name);
  724. $this->reflect = new ReflectionMethod($clazz->getName(), $name);
  725. $this->init();
  726. }
  727. private function init() {
  728. $doc = $this->reflect->getDocComment();
  729. $found = preg_match_all('/@return[\s]([\w\[\]]+)/', $doc, $matches, PREG_SET_ORDER);
  730. if ($found == 1) {
  731. $this->returnType = $matches[0][1];
  732. }
  733. $found = preg_match_all('/@throw[\s]([\w\[\]]+)/', $doc, $matches, PREG_SET_ORDER);
  734. if ($found >= 1) {
  735. foreach ($matches as $match) {
  736. $this->exceptionTypes[] = Classes::classOf($match[1]);
  737. }
  738. }
  739. }
  740. public function invoke() {
  741. if ($this->reflect->isStatic()) {
  742. return $this->reflect->invokeArgs(null, func_get_args());
  743. }
  744. else {
  745. $args = func_get_args();
  746. $instance = array_shift($args);
  747. return $this->reflect->invokeArgs($instance, $args);
  748. }
  749. }
  750. public function invokeArgs() {
  751. if ($this->reflect->isStatic()) {
  752. return $this->reflect->invokeArgs(null, func_get_arg(0));
  753. }
  754. else {
  755. return $this->reflect->invokeArgs(func_get_arg(0), func_get_arg(1));
  756. }
  757. }
  758. public function isStatic() {
  759. return $this->reflect->isStatic();
  760. }
  761. public function hasReturnType() {
  762. return !empty($this->returnType);
  763. }
  764. public function getReturnType() {
  765. return $this->returnType;
  766. }
  767. public function getExceptionTypes() {
  768. return $this->exceptionTypes;
  769. }
  770. public function __toString() {
  771. $result = '';
  772. if ($this->reflect->isPrivate()) {
  773. $result .= 'private ';
  774. }
  775. else if ($this->reflect->isProtected()) {
  776. $result .= 'protected ';
  777. }
  778. else if ($this->reflect->isPublic()) {
  779. $result .= 'public ';
  780. }
  781. if ($this->reflect->isStatic()) {
  782. $result .= 'static ';
  783. }
  784. if ($this->reflect->isAbstract()) {
  785. $result .= 'abstract ';
  786. }
  787. if ($this->reflect->isFinal()) {
  788. $result .= 'final ';
  789. }
  790. return $result . parent::__toString();
  791. }
  792. }
  793. abstract class Constructor {
  794. protected $clazz;
  795. public function __construct(Clazz $clazz) {
  796. $this->clazz = $clazz;
  797. }
  798. public function getDeclaringClass() {
  799. return $this->clazz;
  800. }
  801. public function newInstance() {
  802. if (func_num_args() == 0) {
  803. return $this->clazz->newInstance();
  804. }
  805. else {
  806. return $this->newInstanceArgs(func_get_args());
  807. }
  808. }
  809. public function newInstanceArgs(array $args) {
  810. return $this->clazz->newInstance($args);
  811. }
  812. public abstract function isPrivate();
  813. public abstract function isProtected();
  814. public abstract function isPublic();
  815. public abstract function isAccessible();
  816. public abstract function setAccessible($accessible);
  817. public function __toString() {
  818. return $this->clazz->getName() . '__construct()';
  819. }
  820. }
  821. class PhpConstructor extends Constructor {
  822. private $reflect;
  823. public function __construct(Clazz $clazz, ReflectionMethod $constructor) {
  824. parent::__construct($clazz);
  825. $this->reflect = $constructor;
  826. }
  827. public function isAccessible() {
  828. return $this->reflect->isPrivate() || $this->reflect->isProtected();
  829. }
  830. public function setAccessible($accessible) {
  831. //$this->reflect->setAccessible($accessible);
  832. }
  833. public function isPrivate() {
  834. return $this->reflect->isPrivate();
  835. }
  836. public function isProtected() {
  837. return $this->reflect->isProtected();
  838. }
  839. public function isPublic() {
  840. return $this->reflect->isPublic();
  841. }
  842. }
  843. class PhpEmptyConstructor extends Constructor {
  844. public function __construct(Clazz $clazz) {
  845. parent::__construct($clazz);
  846. }
  847. public function isAccessible() {
  848. return true;
  849. }
  850. public function setAccessible($accessible) {
  851. }
  852. public function isPrivate() {
  853. return false;
  854. }
  855. public function isProtected() {
  856. return false;
  857. }
  858. public function isPublic() {
  859. return true;
  860. }
  861. }
  862. class ArrayClazz extends JavaClazz {
  863. private $dim;
  864. private $componentType;
  865. private $fullname;
  866. public function __construct(Clazz $super, $componentType, $dim) {
  867. parent::__construct($componentType->getName() . '[]');
  868. $this->dim = $dim;
  869. $this->componentType = $componentType;
  870. $this->createFullName();
  871. }
  872. private function createFullName() {
  873. if ($this->componentType->isArray()) {
  874. $this->fullname = '[' . $this->componentType->getFullName();
  875. }
  876. else {
  877. if (!$this->componentType->isPrimitive()) {
  878. $this->fullname = '[L' . $this->componentType->getFullName() . ';';
  879. }
  880. else {
  881. $this->fullname = '[' . $this->componentType->getSignature();
  882. }
  883. }
  884. }
  885. public function getDimension() {
  886. return $this->dim;
  887. }
  888. public function getComponentType() {
  889. return $this->componentType;
  890. }
  891. public function isArray() {
  892. return true;
  893. }
  894. public function getFullName() {
  895. return $this->fullname;
  896. }
  897. public function __toString() {
  898. return '{jarray ' . $this->getName() . '}';
  899. }
  900. }
  901. class ArrayType {
  902. const TYPE = 'Array';
  903. const SIGNATURE = '[';
  904. private function __construct() {
  905. }
  906. /**
  907. * param1 : value to fill
  908. * param2..n : dim sizes
  909. * Enter description here ...
  910. */
  911. public static function newInstance() {
  912. $fill_value = func_get_arg(0);
  913. for ($arg_index = func_num_args() - 1; $arg_index >= 1; $arg_index--) {
  914. $dim_size = func_get_arg($arg_index);
  915. if ($dim_size == 0) {
  916. $fill_value = array();
  917. } else {
  918. $fill_value = array_fill(0, $dim_size, $fill_value);
  919. }
  920. }
  921. return $fill_value;
  922. }
  923. public static function clazz($componentType, $dim = 1) {
  924. $className = $componentType->getName() . str_repeat('[]', $dim);
  925. return Classes::classOf($className);
  926. }
  927. public static function autoClass(array &$value) {
  928. $type = null;
  929. for ($i=0; $i<count($value); $i++) {
  930. $itype = Classes::classOfValue($value[$i]);
  931. if (is_null($type)) {
  932. $type = $itype;
  933. }
  934. else {
  935. if ($type != $itype) {
  936. return self::clazz(Object::clazz(), 1);
  937. }
  938. }
  939. }
  940. return self::clazz($type, 1);
  941. }
  942. public static function getLength(array &$value) {
  943. return count($value);
  944. }
  945. public static function &get(array &$value, $index) {
  946. return $value[$index];
  947. }
  948. }
  949. /** @gwtname java.lang.Enum */
  950. class Enum {
  951. /** @var string */
  952. private $name;
  953. /** @var int */
  954. private $ordinal;
  955. private function __construct() {
  956. }
  957. }
  958. class Classes {
  959. private static $CLASSES = array();
  960. private static $SIGNATURES = array();
  961. private static function exists($className) {
  962. return isset(self::$CLASSES[$className]);
  963. }
  964. private static function getClass($className) {
  965. return self::$CLASSES[$className];
  966. }
  967. private static function registerClass($className, $class) {
  968. self::$CLASSES[$className] = $class;
  969. }
  970. public static function register($className, $class) {
  971. self::$CLASSES[$className] = $class;
  972. }
  973. public static function registerSignature($signature, $class) {
  974. self::$SIGNATURES[$signature] = $class;
  975. }
  976. public static function classOfValue($value) {
  977. $className = '';
  978. $type = gettype($value);
  979. if ($type == 'boolean') {
  980. $className = 'boolean';
  981. }
  982. else if ($type == 'integer') {
  983. $className = 'int';
  984. }
  985. else if ($type == 'double') {
  986. $className = 'double';
  987. }
  988. else if ($type == 'string') {
  989. $className = 'String';
  990. }
  991. else if ($type == 'array') {
  992. return ArrayType::autoClass($value);
  993. }
  994. else if ($type == 'object') {
  995. if ($value instanceof Magic) {
  996. return new MagicClazz(get_class($value), $value);
  997. }
  998. else {
  999. $className = get_class($value);
  1000. }
  1001. }
  1002. else if ($type == 'resource') {
  1003. throw new ClassNotFoundException('Resource have no class');
  1004. }
  1005. else if ($type == 'NULL') {
  1006. $className = 'Void';
  1007. }
  1008. else {
  1009. throw new ClassNotFoundException('Type of value is unknown');
  1010. }
  1011. return self::classOf($className);
  1012. }
  1013. public static function classOf($classNameOrObject) {
  1014. $className = '';
  1015. if (is_object($classNameOrObject)) {
  1016. if ($classNameOrObject instanceof Magic) {
  1017. return new MagicClazz(get_class($classNameOrObject), $classNameOrObject);
  1018. }
  1019. else {
  1020. $className = get_class($classNameOrObject);
  1021. }
  1022. }
  1023. else if (is_string($classNameOrObject)) {
  1024. $className = $classNameOrObject;
  1025. }
  1026. else {
  1027. debug_print_backtrace();
  1028. throw new ClassNotFoundException('The argument of method ClassOf is not string or object');
  1029. }
  1030. /*$type = gettype($classNameOrObject);
  1031. if ($type == 'boolean') {
  1032. $className = 'boolean';
  1033. }
  1034. else if ($type == 'integer') {
  1035. $className = 'int';
  1036. }
  1037. else if ($type == 'double') {
  1038. $className = 'double';
  1039. }
  1040. else if ($type == 'string') {
  1041. $className = $classNameOrObject;
  1042. }
  1043. else if ($type == 'array') {
  1044. return ArrayType::autoClass($classNameOrObject);
  1045. }
  1046. else if ($type == 'object') {
  1047. if ($classNameOrObject instanceof Magic) {
  1048. return new MagicClazz(get_class($classNameOrObject), $classNameOrObject);
  1049. }
  1050. else {
  1051. $className = get_class($classNameOrObject);
  1052. }
  1053. }
  1054. else if ($type == 'resource') {
  1055. return null;
  1056. }
  1057. else if ($type == 'NULL') {
  1058. $className = Void;
  1059. }
  1060. else {
  1061. return null;
  1062. }*/
  1063. if (self::isArrayClassName($className)) {
  1064. return self::classOfArray($className);
  1065. }
  1066. $className = self::cleanClassName($className);
  1067. /*if (strpos($className, '$') !== false) {
  1068. $className = substr(strrchr($className, '$'), 1);
  1069. }
  1070. if (strpos($className, '.') !== false) {
  1071. $className = substr(strrchr($className, '.'), 1);
  1072. }*/
  1073. if (!self::exists($className)) {
  1074. $clazz = null;
  1075. try {
  1076. if (self::isEnumClass($className)) {
  1077. $clazz = new PhpEnumClazz($className);
  1078. }
  1079. else {
  1080. $clazz = new PhpClazz($className);
  1081. }
  1082. }
  1083. catch (Exception $e) {
  1084. throw new ClassNotFoundException('Class not found [' . $className . ']');
  1085. }
  1086. self::registerClass($className, $clazz);
  1087. }
  1088. return self::getClass($className);
  1089. }
  1090. private static function cleanClassName($className) {
  1091. $pos = strpos($className, '<');
  1092. if ($pos !== false) {
  1093. $className = substr($className, 0, $pos);
  1094. }
  1095. if (strpos($className, '$') !== false) {
  1096. $className = str_replace('$', '_', $className);
  1097. //$className = substr(strrchr($className, '$'), 1);
  1098. }
  1099. if (strpos($className, '.') !== false) {
  1100. $className = substr(strrchr($className, '.'), 1);
  1101. }
  1102. return $className;
  1103. }
  1104. private static function isEnumClass($className) {
  1105. if (class_exists($className)) {
  1106. return is_subclass_of($className, 'Enum');
  1107. }
  1108. else {
  1109. return false;
  1110. }
  1111. }
  1112. private static function isArrayClassName($className) {
  1113. return strpos($className, '[') !== false;
  1114. }
  1115. private static function classOfArray($className) {
  1116. // Java array style
  1117. if ($className[0] == ArrayType::SIGNATURE) {
  1118. if (self::exists($className)) {
  1119. return self::getClass($className);
  1120. }
  1121. else {
  1122. $count = substr_count($className, '[');
  1123. $type = mb_substr($className, $count);
  1124. if ($type[0] == Object::SIGNATURE) {
  1125. $clazz = Classes::classOf(mb_substr($type, 1, mb_strlen($type) - 2));
  1126. }
  1127. else {
  1128. $clazz = self::$SIGNATURES[$type[0]];
  1129. }
  1130. $reformed = $clazz->getName() . str_repeat('[]', $count);
  1131. $wanted = self::classOfArray($reformed);
  1132. self::registerClass($className, $wanted);
  1133. return $wanted;
  1134. }
  1135. }
  1136. else {
  1137. $count = substr_count($className, '[');
  1138. $pos = strpos($className, '[');
  1139. $type = substr($className, 0, $pos);
  1140. $className = $type . str_repeat('[]', $count);
  1141. if (self::exists($className)) {
  1142. return self::getClass($className);
  1143. }
  1144. else {
  1145. $compType = $type . str_repeat('[]', $count - 1);
  1146. $class = new ArrayClazz(Object::clazz(), Classes::classOf($compType), $count);
  1147. self::registerClass($class->getName(), $class);
  1148. return $class;
  1149. }
  1150. }
  1151. }
  1152. public static function printClasses() {
  1153. foreach (self::$CLASSES as $className => $clazz) {
  1154. echo $className . ' => ' . $clazz . '<br />';
  1155. }
  1156. }
  1157. public static function registerAlias($className, Clazz $existingClass) {
  1158. if (self::exists($className)) {
  1159. return false;
  1160. }
  1161. else {
  1162. //self::registerClass($className, new AliasClass($existingClass, $className));
  1163. self::registerClass($className, $existingClass);
  1164. return true;
  1165. }
  1166. }
  1167. public static function toObject($value) {
  1168. $type = gettype($value);
  1169. if ($type == 'boolean') {
  1170. return new Boolean($value);
  1171. }
  1172. else if ($type == 'integer') {
  1173. return new Integer($value);
  1174. }
  1175. else if ($type == 'double') {
  1176. return new Double($value);
  1177. }
  1178. else {
  1179. return $value;
  1180. }
  1181. }
  1182. }
  1183. /** @gwtname java.lang.ClassNotFoundException */
  1184. class ClassNotFoundException extends Exception {
  1185. }
  1186. class ClassException extends Exception {
  1187. }
  1188. /** @gwtname java.lang.NoSuchMethodException */
  1189. class NoSuchMethodException extends Exception {
  1190. }
  1191. /** @gwtname java.lang.NoSuchFieldException */
  1192. class NoSuchFieldException extends ClassException {
  1193. }
  1194. class NotImplemented extends Exception {
  1195. }
  1196. class NumberFormatException extends Exception {
  1197. }