Changeset 844
- Timestamp:
- 08/19/07 15:43:22 (1 year ago)
- Files:
-
- trunk/experiments/people/schst/ioc/simple.php (modified) (3 diffs)
- trunk/src/main/php/net/stubbles/examples/service/RememberNameService.php (modified) (2 diffs)
- trunk/src/main/php/net/stubbles/ioc/injection/annotations/stubImplementedByAnnotation.php (modified) (4 diffs)
- trunk/src/main/php/net/stubbles/ioc/injection/annotations/stubInjectAnnotation.php (modified) (2 diffs)
- trunk/src/main/php/net/stubbles/ioc/injection/annotations/stubNamedAnnotation.php (modified) (1 diff)
- trunk/src/main/php/net/stubbles/ioc/injection/exceptions (added)
- trunk/src/main/php/net/stubbles/ioc/injection/exceptions/stubBindingException.php (added)
- trunk/src/main/php/net/stubbles/ioc/injection/exceptions/stubInjectionException.php (moved) (moved from trunk/src/main/php/net/stubbles/ioc/injection/stubInjectionException.php)
- trunk/src/main/php/net/stubbles/ioc/injection/stubBinder.php (modified) (2 diffs)
- trunk/src/main/php/net/stubbles/ioc/injection/stubBinding.php (modified) (2 diffs)
- trunk/src/main/php/net/stubbles/ioc/injection/stubInjectionMap.php (deleted)
- trunk/src/main/php/net/stubbles/ioc/injection/stubInjector.php (modified) (3 diffs)
- trunk/src/main/php/net/stubbles/service/jsonrpc/stubJsonRpcProcessor.php (modified) (8 diffs)
- trunk/src/test/php/net/stubbles/ioc/IOCTestSuite.php (modified) (2 diffs)
- trunk/src/test/php/net/stubbles/ioc/injection/annotations (added)
- trunk/src/test/php/net/stubbles/ioc/injection/annotations/stubImplementedByAnnotationTestCase.php (added)
- trunk/src/test/php/net/stubbles/ioc/injection/annotations/stubNamedAnnotationTestCase.php (added)
- trunk/src/test/php/net/stubbles/ioc/injection/annotations/stubSingletonAnnotationTestCase.php (added)
- trunk/src/test/php/net/stubbles/ioc/injection/stubBinderTestCase.php (added)
- trunk/src/test/php/net/stubbles/ioc/injection/stubInjectAnnotationTestCase.php (modified) (2 diffs)
- trunk/src/test/php/net/stubbles/ioc/injection/stubInjectionMapTestCase.php (deleted)
- trunk/src/test/php/net/stubbles/ioc/injection/stubInjectorBasicTestCase.php (added)
- trunk/src/test/php/net/stubbles/ioc/injection/stubInjectorImplementedByTestCase.php (added)
- trunk/src/test/php/net/stubbles/ioc/injection/stubInjectorNamedTestCase.php (added)
- trunk/src/test/php/net/stubbles/ioc/injection/stubInjectorSingletonTestCase.php (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/experiments/people/schst/ioc/simple.php
r810 r844 80 80 * 81 81 * @param Window $concrete 82 * @Inject 82 * @Inject(optional=true) 83 83 */ 84 84 public function setWindow(Window $window) { … … 102 102 stubClassLoader::load('net.stubbles.ioc.injection.stubBinder'); 103 103 104 $injector = new stubInjector(); 105 $binder = new stubBinder($injector); 104 $binder = new stubBinder(); 106 105 107 106 $binder->bind('Tire')->to('Goodyear'); … … 113 112 $binder->bind('Window'); 114 113 114 $injector = $binder->getInjector(); 115 115 116 $vehicle = $injector->getInstance('Vehicle'); 116 117 $vehicle->getDriver()->sayHello(); trunk/src/main/php/net/stubbles/examples/service/RememberNameService.php
r770 r844 11 11 * Simple service to demonstrate stateful services. 12 12 * 13 * @Inject(Session)14 13 * @author Stephan Schmidt <schst@stubbles.net> 15 14 * @package stubbles_examples … … 31 30 * 32 31 * @param stubSession $session 32 * @Inject 33 33 */ 34 34 public function setSession(stubSession $session) { trunk/src/main/php/net/stubbles/ioc/injection/annotations/stubImplementedByAnnotation.php
r820 r844 9 9 */ 10 10 11 stubClassLoader::load('net.stubbles.reflection.annotations.stubAbstractAnnotation'); 11 stubClassLoader::load('net.stubbles.reflection.annotations.stubAbstractAnnotation', 12 'net.stubbles.reflection.stubReflectionClass'); 12 13 13 14 /** … … 23 24 * default implementation 24 25 * 25 * @var array26 * @var stubReflectionClass 26 27 */ 27 28 protected $defaultImplementation; … … 30 31 * sets the list of class names to inject 31 32 * 32 * @param st ring$value33 * @param stubReflectionClass $value 33 34 */ 34 public function setValue( $value)35 public function setValue(stubReflectionClass $value) 35 36 { 36 37 $this->defaultImplementation = $value; … … 50 51 * Get the default implementation 51 52 * 52 * @return array53 * @return stubReflectionClass 53 54 */ 54 55 public function getDefaultImplementation() trunk/src/main/php/net/stubbles/ioc/injection/annotations/stubInjectAnnotation.php
r809 r844 1 1 <?php 2 2 /** 3 * Annotation to handle dependency injections. 3 * Annotation to mark a method that is used for 4 * dependency injection 4 5 * 5 * @author Frank Kleine <mikey@stubbles.net>6 * @author Stephan Schmidt <schst@stubbles.net> 6 7 * @package stubbles 7 8 * @subpackage ioc_injection 8 9 */ 9 stubClassLoader::load('net.stubbles.reflection.reflection', 10 'net.stubbles.ioc.injection.stubInjectionException', 11 'net.stubbles.ioc.injection.stubInjectionMap' 12 ); 10 stubClassLoader::load('net.stubbles.reflection.annotations.stubAbstractAnnotation'); 11 13 12 /** 14 * Annotation to handle dependency injections. 13 * Annotation to mark a method that is used for 14 * dependency injection 15 15 * 16 16 * @package stubbles 17 17 * @subpackage ioc_injection 18 * @todo think about a public static addPrefix() method that will19 * discard prefixes from injections for method and property names20 18 */ 21 19 class stubInjectAnnotation extends stubAbstractAnnotation 22 20 { 23 21 /** 24 * list of class names to inject22 * whether the injection is optional 25 23 * 26 * @var array24 * @var boolean 27 25 */ 28 protected $ injections = array();26 protected $optional = false; 29 27 30 28 /** 31 * sets the list of class names to inject29 * sets, whether the injection is optional 32 30 * 33 * @param string $value31 * @param boolean $optional 34 32 */ 35 public function set Value($value)33 public function setOptional($optional) 36 34 { 37 $this-> injections = explode(':', $value);35 $this->optional = $optional; 38 36 } 39 37 … … 45 43 public function getAnnotationTarget() 46 44 { 47 return stubAnnotation::TARGET_ ALL;45 return stubAnnotation::TARGET_METHOD; 48 46 } 49 47 50 48 /** 51 * returns the list of injections49 * Checks, whether the injection is optional 52 50 * 53 * @return array51 * @return boolean 54 52 */ 55 public function getInjections() 56 { 57 return $this->injections; 58 } 59 60 /** 61 * processes all injections 62 * 63 * @param stubReflectionClass $refClass the reflection class for $injectible 64 * @param stubInjectionProvider $injectionProvider map of values to inject 65 * @param object $injectible the class to inject into 66 * @throws stubInjectionException 67 */ 68 protected function handleInjections(stubReflectionClass $refClass, stubInjectionProvider $injectionProvider, $injectible) 69 { 70 foreach ($this->injections as $injection) { 71 if ($injectionProvider->hasInjection($injection) == false) { 72 $className = ($injectible instanceof stubObject) ? ($injectible->getClassName()) : (get_class($injectible)); 73 throw new stubInjectionException('Injectible ' . $className . ' needs ' . $injection . ' but it was not given in list of injected classes.'); 74 } 75 76 if (substr($injection, 0, 4) == 'stub') { 77 $injectionShort = substr($injection, 4); 78 } else { 79 $injectionShort = $injection; 80 } 81 82 $methodName = 'set' . ucfirst($injectionShort); 83 if ($refClass->hasMethod($methodName) == true && $refClass->getMethod($methodName)->isPublic() == true) { 84 try { 85 $refClass->getMethod($methodName)->invoke($injectible, $injectionProvider->getInjection($injection)); 86 } catch (ReflectionException $re) { 87 throw new stubInjectionException('Could not inject ' . $injection . ': ' . $re->getMessage()); 88 } 89 } elseif ($refClass->hasProperty($injectionShort) == true && $refClass->getProperty($injectionShort)->isPublic() == true) { 90 $refClass->getProperty($injectionShort)->setValue($injectible, $injectionProvider->getInjection($injection)); 91 } elseif ($refClass->hasMethod('__set') == true && $refClass->getMethod('__set')->isPublic() == true) { 92 $refClass->getMethod('__set')->invoke($injectible, $injection, $injectionProvider->getInjection($injection)); 93 } else { 94 $className = ($injectible instanceof stubObject) ? ($injectible->getClassName()) : (get_class($injectible)); 95 throw new stubInjectionException('Injectible ' . $className . ' has no method or property that accepts injection ' . $injection); 96 } 97 } 98 } 99 100 /** 101 * static call to hide all injection details 102 * 103 * @param stubInjectionProvider $injectionProvider map of values to inject 104 * @param object $injectible the class to inject into 105 * @throws stubInjectionException 106 */ 107 public static function factory(stubInjectionProvider $injectionProvider, $injectible) 108 { 109 if (is_object($injectible) == false) { 110 throw new stubInjectionException('Given injectible is not an object. Can only inject into objects.'); 111 } 112 113 $refClass = new stubReflectionClass(get_class($injectible)); 114 if ($refClass->hasAnnotation('Inject') == true) { 115 $inject = $refClass->getAnnotation('Inject'); 116 $inject->handleInjections($refClass, $injectionProvider, $injectible); 117 } 53 public function isOptional() { 54 return $this->optional; 118 55 } 119 56 } trunk/src/main/php/net/stubbles/ioc/injection/annotations/stubNamedAnnotation.php
r825 r844 21 21 * Name 22 22 * 23 * @var array23 * @var string 24 24 */ 25 25 protected $name; trunk/src/main/php/net/stubbles/ioc/injection/stubBinder.php
r825 r844 45 45 * @param stubInjector $injector 46 46 */ 47 public function __construct(stubInjector $injector) { 48 $this->injector = $injector; 47 public function __construct(stubInjector $injector = null) { 48 if ($injector === null) { 49 $this->injector = new stubInjector(); 50 } else { 51 $this->injector = $injector; 52 } 49 53 } 50 54 … … 60 64 return $binding; 61 65 } 66 67 /** 68 * Get an injector for this binder 69 * 70 * @return stubInjector 71 */ 72 public function getInjector() { 73 return $this->injector; 74 } 62 75 } 63 76 ?> trunk/src/main/php/net/stubbles/ioc/injection/stubBinding.php
r835 r844 10 10 * @subpackage ioc_injection 11 11 */ 12 12 stubClassLoader::load('net.stubbles.ioc.injection.exceptions.stubBindingException'); 13 13 /** 14 14 * Binding to bind an interface to an implementation … … 190 190 foreach ($method->getParameters() as $param) { 191 191 $class = $param->getClass(); 192 $type = $class->getName(); 192 193 $name = null; 193 194 if ($method->hasAnnotation('Named')) { 194 195 $name = $method->getAnnotation('Named')->getName(); 195 196 } 196 $paramValues[] = $this->injector->getInstance($class->getName(), $name); 197 if (!$this->injector->hasBinding($type, $name)) { 198 if ($method->getAnnotation('Inject')->isOptional()) { 199 continue 2; 200 } 201 throw new stubBindingException("Could not create instance of {$this->type}. No binding for type {$type} specified."); 202 } 203 $paramValues[] = $this->injector->getInstance($type, $name); 197 204 } 198 205 $method->invokeArgs($instance, $paramValues); trunk/src/main/php/net/stubbles/ioc/injection/stubInjector.php
r835 r844 20 20 * @package stubbles 21 21 * @subpackage ioc_injection 22 * @todo Improve the check for the index update 22 23 */ 23 class stubInjector extends stubBaseObject {24 class stubInjector extends stubBaseObject implements stubClonable { 24 25 25 26 /** … … 96 97 } 97 98 99 /** 100 * Get the binding for a name and type 101 * 102 * @param string $type 103 * @param string $name 104 * @return stubBinding 105 * @todo This method should also take care of implicit bindings 106 */ 98 107 protected function getBinding($type, $name = null) { 99 108 if ($name !== null) { … … 107 116 return null; 108 117 } 118 119 /** 120 * Check, whether a binding for a type is available 121 * 122 * @param string $type 123 * @param string $name 124 * @return boolean 125 */ 126 public function hasBinding($type, $name = null) { 127 if (!empty($this->bindings)) { 128 $this->updateIndex(); 129 } 130 131 return ($this->getBinding($type, $name) != null); 132 } 109 133 } 110 134 ?> trunk/src/main/php/net/stubbles/service/jsonrpc/stubJsonRpcProcessor.php
r793 r844 15 15 'net.stubbles.service.annotations.stubWebMethodAnnotation', 16 16 'net.stubbles.service.jsonrpc.stubJsonRpcResponse', 17 'net.stubbles.ioc.injection. injection'17 'net.stubbles.ioc.injection.stubBinder' 18 18 ); 19 19 /** … … 106 106 throw new stubFileNotFoundException($configFile); 107 107 } 108 108 109 109 return $configFile; 110 110 } … … 161 161 continue; 162 162 } 163 163 164 164 try { 165 165 $this->response->write($generator->generateJavascriptProxy($serviceConfig['className'], $jsClass)); … … 188 188 $result .= "console.{$level}('" . addslashes($line) . "');\n"; 189 189 } 190 190 191 191 return $result; 192 192 } … … 205 205 return; 206 206 } 207 207 208 208 if (!isset($phpJsonObj->id)) { 209 209 $this->response->writeFault(null, 'Invalid request: No id given.'); 210 210 return; 211 211 } 212 212 213 213 if (!isset($phpJsonObj->method)) { 214 214 $this->response->writeFault($phpJsonObj->id, 'Invalid request: No method given.'); 215 215 return; 216 216 } 217 217 218 218 if (!isset($phpJsonObj->params)) { 219 219 $this->response->writeFault($phpJsonObj->id, 'Invalid request: No params given.'); … … 268 268 throw new stubException('Invalid request: method-Pattern has to be <className>.<methodName>.'); 269 269 } 270 270 271 271 list($className, $methodName) = explode('.', $methodName); 272 272 if (!isset($this->classMap[$className])) { 273 273 throw new stubException('Unknown class ' . $className . '.'); 274 274 } 275 275 276 276 $clazz = new stubReflectionClass($this->classMap[$className]['className']); 277 277 if ($clazz->hasMethod($methodName) == false) { 278 278 throw new stubException('Unknown method ' . $className . '.' . $methodName . '.'); 279 279 } 280 280 281 281 $method = $clazz->getMethod($methodName); 282 282 if (!$method->hasAnnotation('WebMethod')) { 283 283 throw new stubException('Method ' . $className . '.' . $methodName . ' is no WebMethod.'); 284 284 } 285 285 286 286 return array('class' => $clazz, 'method' => $method); 287 287 } … … 301 301 throw new stubException('Invalid amount of parameters passed.'); 302 302 } 303 304 $instance = $class->newInstance(); 305 $injectionMap = new stubInjectionMap(); 306 $injectionMap->addInjection('Session', $this->session); 307 308 stubInjectAnnotation::factory($injectionMap, $instance); 303 $binder = new stubBinder(); 304 $binder->bind('stubSession')->toInstance($this->session); 305 $instance = $binder->getInjector()->getInstance($class->getName()); 309 306 return $method->invokeArgs($instance, $params); 310 307 } … … 327 324 throw new stubException('Param '. $paramName . ' is missing.'); 328 325 } 329 326 330 327 array_push($paramValues, $paramValue); 331 328 } 332 329 333 330 return $paramValues; 334 331 } trunk/src/test/php/net/stubbles/ioc/IOCTestSuite.php
r308 r844 4 4 * 5 5 * @author Frank Kleine <mikey@stubbles.net> 6 * @author Stephan Schmidt <schst@stubbles.net> 6 7 * @package stubbles 7 8 * @subpackage test … … 21 22 { 22 23 $this->TestSuite('All ioc tests'); 24 $this->addTestFile(dirname(__FILE__) . '/injection/annotations/stubImplementedByAnnotationTestCase.php'); 23 25 $this->addTestFile(dirname(__FILE__) . '/injection/stubInjectAnnotationTestCase.php'); 24 $this->addTestFile(dirname(__FILE__) . '/injection/stubInjectionMapTestCase.php'); 26 $this->addTestFile(dirname(__FILE__) . '/injection/annotations/stubNamedAnnotationTestCase.php'); 27 $this->addTestFile(dirname(__FILE__) . '/injection/annotations/stubSingletonAnnotationTestCase.php'); 28 29 $this->addTestFile(dirname(__FILE__) . '/injection/stubBinderTestCase.php'); 30 31 $this->addTestFile(dirname(__FILE__) . '/injection/stubInjectorBasicTestCase.php'); 32 $this->addTestFile(dirname(__FILE__) . '/injection/stubInjectorImplementedByTestCase.php'); 33 $this->addTestFile(dirname(__FILE__) . '/injection/stubInjectorNamedTestCase.php'); 34 $this->addTestFile(dirname(__FILE__) . '/injection/stubInjectorSingletonTestCase.php'); 25 35 } 26 36 } trunk/src/test/php/net/stubbles/ioc/injection/stubInjectAnnotationTestCase.php
r808 r844 3 3 * Test for net.stubbles.ioc.injection.annotations.stubInjectAnnotation 4 4 * 5 * @author Frank Kleine <mikey@stubbles.net>5 * @author Stephan Schmidt <schst@stubbles.net> 6 6 * @package stubbles 7 7 * @subpackage ioc_injection_test 8 8 */ 9 9 stubClassLoader::load('net.stubbles.ioc.injection.annotations.stubInjectAnnotation'); 10 class TestInjection1 extends stubBaseObject {}11 class TestInjection2 extends stubBaseObject {}12 class TestInjection3 extends stubBaseObject {}13 class stubTestInjection4 extends stubBaseObject {}14 /**15 * class for testing injections16 *17 * @Inject(TestInjection1:TestInjection2:TestInjection3)18 */19 class TestInjectible120 {21 protected $TestInjection1;22 public $TestInjection2;23 10 24 public function setTestInjection1($i)25 {26 $this->TestInjection1 = $i;27 }28 29 public function getTestInjection1()30 {31 return $this->TestInjection1;32 }33 34 public function __set($name, $value)35 {36 $this->$name = $value;37 }38 }39 /**40 * class for testing injections41 *42 * @Inject(TestInjection1:TestInjection2:TestInjection3)43 */44 class TestInjectible245 {46 }47 /**48 * class for testing injections49 *50 * @Inject(stubTestInjection4:stubTestInjection5)51 */52 class TestInjectible353 {54 protected $TestInjection4;55 public $TestInjection5;56 57 public function setTestInjection4($i)58 {59 $this->TestInjection4 = $i;60 }61 62 public function getTestInjection4()63 {64 return $this->TestInjection4;65 }66 }67 11 /** 68 12 * Test for net.stubbles.ioc.injection.annotations.stubInjectAnnotation … … 74 18 { 75 19 /** 76 * injection map to use for tests77 *78 * @var stubInjectionMap79 */80 protected $injectionMap;81 82 /**83 20 * set up test environment 84 21 */ 85 22 public function setUp() 86 23 { 87 $this->injectionMap = new stubInjectionMap();88 $this->injectionMap->addInjection('TestInjection1', new TestInjection1());89 $this->injectionMap->addInjection('TestInjection2', new TestInjection2());90 $this->injectionMap->addInjection('TestInjection3', new TestInjection3());91 $this->injectionMap->addInjection('stubTestInjection4', new stubTestInjection4());92 $this->injectionMap->addInjection('stubTestInjection5', new stubTestInjection4());93 24 } 25 94 26 /** 95 27 * test that the injection names are handles properly 96 28 */ 97 public function test Injections()29 public function testAnnotation() 98 30 { 99 31 $inject = new stubInjectAnnotation(); 100 $inject->setValue('TestInjection1:TestInjection2:TestInjection3');101 $this->assertEqual($inject->getInjections(), array('TestInjection1', 'TestInjection2', 'TestInjection3'));102 }103 32 104 /** 105 * check that the handling works as expected 106 */ 107 public function testHandlingOk() 108 { 109 $testInjectible = new TestInjectible1(); 110 stubInjectAnnotation::factory($this->injectionMap, $testInjectible); 111 $test1a = $this->injectionMap->getInjection('TestInjection1'); 112 $test1b = $testInjectible->getTestInjection1(); 113 $this->assertReference($test1a, $test1b); 114 } 33 $this->assertEqual(stubAnnotation::TARGET_METHOD, $inject->getAnnotationTarget()); 34 $this->assertFalse($inject->isOptional()); 115 35 116 /** 117 * check that the handling works as expected 118 */ 119 public function testHandlingMissingInjectedClass() 120 { 121 $testInjectible = new TestInjectible1(); 122 $this->expectException('stubInjectionException'); 123 stubInjectAnnotation::factory(new stubInjectionMap(), $testInjectible); 124 } 125 126 /** 127 * check that the handling works as expected 128 */ 129 public function testHandlingMissingMethodAndProperty() 130 { 131 $testInjectible = new TestInjectible2(); 132 $this->expectException('stubInjectionException'); 133 stubInjectAnnotation::factory($this->injectionMap, $testInjectible); 134 } 135 136 /** 137 * check that the handling works as expected 138 */ 139 public function testHandlingWithoutAnnotation() 140 { 141 Mock::generate('TestInjectible1'); 142 $testInjectible = new MockTestInjectible1(); 143 $testInjectible->expectNever('setTestInjection1'); 144 $testInjectible->expectNever('__set'); 145 stubInjectAnnotation::factory($this->injectionMap, $testInjectible); 146 } 147 148 /** 149 * check that the handling works as expected 150 */ 151 public function testHandlingWrongInjectible() 152 { 153 $this->expectException('stubInjectionException'); 154 stubInjectAnnotation::factory($this->injectionMap, 'foo'); 155 } 156 157 public function testStubPrefix() 158 { 159 $testInjectible = new TestInjectible3(); 160 stubInjectAnnotation::factory($this->injectionMap, $testInjectible); 161 $test4a = $this->injectionMap->getInjection('stubTestInjection4'); 162 $test4b = $testInjectible->getTestInjection4(); 163 $this->assertReference($test4a, $test4b); 164 $test5a = $this->injectionMap->getInjection('stubTestInjection5'); 165 $test5b = $testInjectible->TestInjection5; 166 $this->assertReference($test5a, $test5b); 36 $inject->setOptional(true); 37 $this->assertTrue($inject->isOptional()); 167 38 } 168 39 }
