Changeset 676
- Timestamp:
- 2008-10-07 09:58:24 (5 years ago)
- Location:
- trunk/modules/kauri-routing/kauri-routing-impl/src/main/java/org/kauriproject/routing/impl
- Files:
-
- 4 edited
-
components/DirectoryRouter.java (modified) (1 diff)
-
components/KauriJaxRsRestlet.java (modified) (8 diffs)
-
components/ReloadableResource.java (modified) (3 diffs)
-
routing/KauriRouter.java (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/modules/kauri-routing/kauri-routing-impl/src/main/java/org/kauriproject/routing/impl/components/DirectoryRouter.java
r674 r676 210 210 211 211 private class DirectoryRouterBuilder implements ReloadableResource.ResourceBuilder { 212 public Object build() { 213 return DirectoryRouter.this.build(); 212 public ReloadableResource.Result build() { 213 return new ReloadableResource.Result(DirectoryRouter.this.build()); 214 } 215 216 public void dispose(Object object) { 217 // we don't need disposing 214 218 } 215 219 } -
trunk/modules/kauri-routing/kauri-routing-impl/src/main/java/org/kauriproject/routing/impl/components/KauriJaxRsRestlet.java
r637 r676 14 14 import org.kauriproject.util.ArgumentValidator; 15 15 import org.kauriproject.routing.impl.routing.DisposableRoutingComponent; 16 import org.apache.commons.jci.monitor.FilesystemAlterationListener;17 import org.apache.commons.jci.monitor.FilesystemAlterationObserver;18 16 import org.apache.commons.logging.Log; 19 17 import org.apache.commons.logging.LogFactory; … … 58 56 private Set<String> providerClassNames = new HashSet<String>(); 59 57 60 private boolean initialized;58 private ReloadableResource reloadableResource; 61 59 private Context context; 62 60 private KauriModule module; 63 61 private ModuleSource moduleSource; 64 62 private AutowireCapableBeanFactory beanFactory; 63 private final Log log = LogFactory.getLog(getClass().getName()); 64 65 65 private static final String GROOVY_EXT = ".groovy"; 66 66 private static final String CLASS_EXT = ".class"; 67 private Restlet router;68 private boolean needsBuilding = true;69 private final Object needsBuildingLock = new Object();70 private FAMListener famListener;71 private final Log log = LogFactory.getLog(getClass().getName());72 67 73 68 public KauriJaxRsRestlet(Context context, KauriModule module) { … … 76 71 this.beanFactory = ((Module)module.getImplementation()).getApplicationContext().getAutowireCapableBeanFactory(); 77 72 moduleSource = module.getSource(); 73 reloadableResource = new ReloadableResource(moduleSource, groovyPath, new JaxRsRestletBuilder(), new FAMListener(), "JAX-RS routing"); 78 74 79 75 // Make sure RuntimeDelegate is searched for now, while the context classloader is appropriately set … … 81 77 } 82 78 83 /** 84 * Some initialization which should be done only once but can't be done in 85 * the constructor. 86 */ 87 private void init() { 88 if (initialized) 89 return; 90 initialized = true; 91 92 if (moduleSource.getFAM() != null && groovyPath != null) { 93 famListener = new FAMListener(); 94 moduleSource.addResourceListener(groovyPath, famListener); 95 } 79 public void dispose() { 80 reloadableResource.disposeReloading(); 96 81 } 97 82 … … 99 84 * Builds or rebuilds the JAX-RS router, rescanning classes etc. 100 85 */ 101 private synchronized void build() { 102 synchronized(needsBuildingLock) { 103 if (!needsBuilding) 104 return; 105 needsBuilding = false; 106 } 107 86 private ReloadableResource.Result build() { 108 87 log.debug("Rebuilding routing setup."); 109 init();110 88 try { 111 89 final Set<Class<?>> resourceClasses = new HashSet<Class<?>>(); … … 132 110 } 133 111 134 r outer = jrr;112 return new ReloadableResource.Result(jrr); 135 113 } catch (Throwable t) { 136 router= new Restlet() {114 Restlet restlet = new Restlet() { 137 115 public void handle(Request request, Response response) { 138 116 throw new RuntimeException("The JAX-RS request routing was not succesfully initialized."); 139 117 } 140 118 }; 141 throw new RuntimeException("Could not initialize JAX-RS router.", t);119 return new ReloadableResource.Result(restlet, t); 142 120 } 143 121 } … … 145 123 @Override 146 124 public void handle(Request request, Response response) { 147 build(); 148 router.handle(request, response); 125 ((Restlet)reloadableResource.build()).handle(request, response); 149 126 } 150 127 … … 423 400 } 424 401 425 private class FAMListener implements FilesystemAlterationListener { 426 private boolean changes; 427 428 public void onStart(FilesystemAlterationObserver filesystemAlterationObserver) { 429 changes = false; 430 } 431 432 public void onFileCreate(File file) { 433 if (file.getName().endsWith(GROOVY_EXT) || file.getName().endsWith(CLASS_EXT)) 434 changes = true; 435 } 436 437 public void onFileChange(File file) { 438 if (file.getName().endsWith(GROOVY_EXT) || file.getName().endsWith(CLASS_EXT)) 439 changes = true; 440 } 441 442 public void onFileDelete(File file) { 443 if (file.getName().endsWith(GROOVY_EXT) || file.getName().endsWith(CLASS_EXT)) 444 changes = true; 445 } 446 447 public void onDirectoryCreate(File file) { 448 } 449 450 public void onDirectoryChange(File file) { 451 } 452 453 public void onDirectoryDelete(File file) { 454 changes = true; 455 } 456 457 public void onStop(FilesystemAlterationObserver filesystemAlterationObserver) { 458 if (changes) { 459 synchronized (needsBuildingLock) { 460 needsBuilding = true; 461 } 462 } 463 } 464 } 465 466 public void dispose() { 467 if (famListener != null) 468 moduleSource.getFAM().removeListener(famListener); 469 } 402 private class FAMListener implements ReloadableResource.FAMListener { 403 public boolean onFileCreate(File file) { 404 return file.getName().endsWith(GROOVY_EXT) || file.getName().endsWith(CLASS_EXT); 405 } 406 407 public boolean onFileChange(File file) { 408 return file.getName().endsWith(GROOVY_EXT) || file.getName().endsWith(CLASS_EXT); 409 } 410 411 public boolean onFileDelete(File file) { 412 return file.getName().endsWith(GROOVY_EXT) || file.getName().endsWith(CLASS_EXT); 413 } 414 415 public boolean onDirectoryCreate(File file) { 416 return false; 417 } 418 419 public boolean onDirectoryChange(File file) { 420 return false; 421 } 422 423 public boolean onDirectoryDelete(File file) { 424 return true; 425 } 426 } 427 428 private class JaxRsRestletBuilder implements ReloadableResource.ResourceBuilder { 429 public ReloadableResource.Result build() { 430 return KauriJaxRsRestlet.this.build(); 431 } 432 433 public void dispose(Object object) { 434 // we don't need disposing 435 } 436 } 437 470 438 471 439 public void addResourceClass(String className) { -
trunk/modules/kauri-routing/kauri-routing-impl/src/main/java/org/kauriproject/routing/impl/components/ReloadableResource.java
r674 r676 9 9 import java.io.File; 10 10 11 /** 12 * This class encapsulates the rebuild-when-files-change pattern employed 13 * by multiple routing components. 14 * 15 * <p>Besides the normal rebuild-on-change, it also supports disposing 16 * the previously built object (if any) and putting in action a stub 17 * object in case an exception occurs. 18 */ 11 19 public class ReloadableResource { 12 20 private boolean needsBuilding = true; 13 21 private final Object needsBuildingLock = new Object(); 22 private FAMListener famListenerDelegate; 14 23 private FAMListenerWrapper famListener; 15 24 private ModuleSource moduleSource; … … 25 34 this.resourceBuilder = resourceBuilder; 26 35 this.path = path; 36 this.famListenerDelegate = famListener; 27 37 this.name = name; 38 } 39 40 private void init() { 28 41 if (moduleSource.getFAM() != null && path != null) { 29 this.famListener = new FAMListenerWrapper(famListener );42 this.famListener = new FAMListenerWrapper(famListenerDelegate); 30 43 moduleSource.addResourceListener(path, this.famListener); 31 44 } 32 45 } 33 46 34 public Object build() {47 public synchronized Object build() { 35 48 synchronized(needsBuildingLock) { 36 49 if (!needsBuilding) … … 39 52 } 40 53 54 init(); 55 41 56 if (log.isDebugEnabled()) { 42 57 log.debug("Will rebuild " + name + " due to changes on path " + path); 43 58 } 44 59 45 buildObject = resourceBuilder.build(); 46 return buildObject; 60 Object oldBuildObject = buildObject; 61 62 try { 63 Result result; 64 try { 65 result = resourceBuilder.build(); 66 } catch (Throwable t) { 67 throw new RuntimeException("Could not initialize " + name, t); 68 } 69 70 this.buildObject = result.object; 71 72 if (result.throwable != null) 73 throw new RuntimeException("Could not initialize " + name, result.throwable); 74 75 return buildObject; 76 } finally { 77 if (oldBuildObject != null) 78 resourceBuilder.dispose(oldBuildObject); 79 } 47 80 } 48 81 49 82 public void disposeReloading() { 50 83 if (famListener != null) 51 moduleSource.getFAM().removeListener(famListener); 84 moduleSource.getFAM().removeListener(famListener); 52 85 } 53 86 54 87 public static interface ResourceBuilder { 55 Object build(); 88 Result build(); 89 90 void dispose(Object object); 91 } 92 93 public static class Result { 94 private Object object; 95 private Throwable throwable; 96 97 public Result(Object object) { 98 this.object = object; 99 } 100 101 /** 102 * For the current call, the throwable will be thrown, but for next calls 103 * (until a new rebuild happens), the supplied object will be used. 104 */ 105 public Result(Object object, Throwable throwable) { 106 this.object = object; 107 this.throwable = throwable; 108 } 56 109 } 57 110 -
trunk/modules/kauri-routing/kauri-routing-impl/src/main/java/org/kauriproject/routing/impl/routing/KauriRouter.java
r651 r676 9 9 import org.kauriproject.runtime.module.Module; 10 10 import org.kauriproject.routing.impl.groovybuild.GroovyKauriRouterBuilder; 11 import org.kauriproject.routing.impl.components.ReloadableResource; 11 12 import org.kauriproject.routing.RoutingConfig; 12 13 import org.apache.commons.logging.Log; 13 14 import org.apache.commons.logging.LogFactory; 14 import org.apache.commons.jci.monitor.FilesystemAlterationListener;15 import org.apache.commons.jci.monitor.FilesystemAlterationObserver;16 15 import org.springframework.context.ApplicationContext; 17 16 … … 21 20 22 21 public class KauriRouter extends Restlet { 23 private final Log log = LogFactory.getLog(getClass().getName()); 24 private RouterData routerData; 22 private final Log log = LogFactory.getLog(getClass()); 25 23 private Context context; 26 24 private RoutingConfig routingConfig; … … 28 26 private ModuleSource moduleSource; 29 27 private ApplicationContext applicationContext; 30 private FAMListener famListener; 31 private boolean needsBuilding = true; 32 private final Object needsBuildingLock = new Object(); 28 private ReloadableResource reloadableResource; 33 29 34 30 public KauriRouter(Context context, KauriModule module, RoutingConfig routingConfig) { … … 43 39 moduleSource = module.getSource(); 44 40 45 if (moduleSource.getFAM() != null) { 46 famListener = new FAMListener(); 47 // TODO only listen to needed things 48 // TODO think about removing listeners 49 moduleSource.addResourceListener(routingConfig.getConfigPath(), famListener); 50 } 41 this.reloadableResource = new ReloadableResource(moduleSource, routingConfig.getConfigPath(), new RouterBuilder(), new FAMListener(), "router"); 51 42 } 52 43 53 44 public void handle(Request request, Response response) { 54 build(); 55 routerData.router.handle(request, response); 45 ((RouterData)reloadableResource.build()).router.handle(request, response); 56 46 } 57 47 58 private synchronized void build() { 59 synchronized(needsBuildingLock) { 60 if (!needsBuilding) 61 return; 62 needsBuilding = false; 63 } 64 65 RouterData currentRouterData = routerData; 48 private ReloadableResource.Result build() { 66 49 try { 67 50 log.debug("Rebuilding routing setup."); … … 81 64 buildContext, module, applicationContext, log); 82 65 83 r outerData = new RouterData(routingRestlet, disposables);66 return new ReloadableResource.Result(new RouterData(routingRestlet, disposables)); 84 67 } catch (Throwable t) { 85 68 // Set the router to a fixed config, so that we don't try 86 69 // to consistantly rebuild it 87 routerData = new RouterData(new Restlet() {70 RouterData routerData = new RouterData(new Restlet() { 88 71 public void handle(Request request, Response response) { 89 72 throw new RuntimeException("The request routing was not succesfully initialized."); 90 73 } 91 74 }, Collections.<DisposableRoutingComponent>emptyList()); 92 throw new RuntimeException("Could not initialize router.", t); 93 } finally { 94 if (currentRouterData != null) 95 currentRouterData.dispose(); 75 return new ReloadableResource.Result(routerData, t); 96 76 } 97 77 } 98 78 99 private class FAMListener implements FilesystemAlterationListener { 100 private boolean changes; 101 102 public void onStart(FilesystemAlterationObserver filesystemAlterationObserver) { 103 changes = false; 79 private class RouterBuilder implements ReloadableResource.ResourceBuilder { 80 public ReloadableResource.Result build() { 81 return KauriRouter.this.build(); 104 82 } 105 83 106 public void onFileCreate(File file) { 107 changes = true; 84 public void dispose(Object object) { 85 ((RouterData)object).dispose(); 86 } 87 } 88 89 private class FAMListener implements ReloadableResource.FAMListener { 90 public boolean onFileCreate(File file) { 91 return true; 108 92 } 109 93 110 public voidonFileChange(File file) {111 changes =true;94 public boolean onFileChange(File file) { 95 return true; 112 96 } 113 97 114 public voidonFileDelete(File file) {115 changes =true;98 public boolean onFileDelete(File file) { 99 return true; 116 100 } 117 101 118 public void onDirectoryCreate(File file) { 102 public boolean onDirectoryCreate(File file) { 103 return false; 119 104 } 120 105 121 public void onDirectoryChange(File file) { 106 public boolean onDirectoryChange(File file) { 107 return false; 122 108 } 123 109 124 public void onDirectoryDelete(File file) { 125 changes = true; 126 } 127 128 public void onStop(FilesystemAlterationObserver filesystemAlterationObserver) { 129 if (changes) { 130 synchronized (needsBuildingLock) { 131 needsBuilding = true; 132 } 133 } 110 public boolean onDirectoryDelete(File file) { 111 return true; 134 112 } 135 113 } … … 157 135 @PreDestroy 158 136 public void destroy() { 159 if (famListener != null) 160 moduleSource.getFAM().removeListener(famListener); 137 reloadableResource.disposeReloading(); 161 138 } 162 139 }
Note: See TracChangeset
for help on using the changeset viewer.