1 16 package org.apache.cocoon.components.treeprocessor; 17 18 import java.util.Map ; 19 20 import org.apache.avalon.excalibur.component.RoleManageable; 21 import org.apache.avalon.excalibur.component.RoleManager; 22 import org.apache.avalon.framework.activity.Disposable; 23 import org.apache.avalon.framework.component.ComponentException; 24 import org.apache.avalon.framework.component.ComponentManager; 25 import org.apache.avalon.framework.component.Composable; 26 import org.apache.avalon.framework.component.Recomposable; 27 import org.apache.avalon.framework.configuration.Configurable; 28 import org.apache.avalon.framework.configuration.Configuration; 29 import org.apache.avalon.framework.configuration.ConfigurationException; 30 import org.apache.avalon.framework.configuration.SAXConfigurationHandler; 31 import org.apache.avalon.framework.container.ContainerUtil; 32 import org.apache.avalon.framework.context.Context; 33 import org.apache.avalon.framework.context.ContextException; 34 import org.apache.avalon.framework.context.Contextualizable; 35 import org.apache.avalon.framework.logger.AbstractLogEnabled; 36 import org.apache.avalon.framework.thread.ThreadSafe; 37 import org.apache.cocoon.Processor; 38 import org.apache.cocoon.components.CocoonComponentManager; 39 import org.apache.cocoon.components.ExtendedComponentSelector; 40 import org.apache.cocoon.components.LifecycleHelper; 41 import org.apache.cocoon.components.pipeline.ProcessingPipeline; 42 import org.apache.cocoon.components.source.SourceUtil; 43 import org.apache.cocoon.components.source.impl.DelayedRefreshSourceWrapper; 44 import org.apache.cocoon.environment.Environment; 45 import org.apache.excalibur.source.Source; 46 import org.apache.excalibur.source.SourceResolver; 47 48 54 55 public class TreeProcessor 56 extends AbstractLogEnabled 57 implements ThreadSafe, 58 Processor, 59 Composable, 60 Configurable, 61 RoleManageable, 62 Contextualizable, 63 Disposable { 64 65 public static final String COCOON_REDIRECT_ATTR = "sitemap:cocoon-redirect"; 66 67 private static final String XCONF_URL = 68 "resource://org/apache/cocoon/components/treeprocessor/treeprocessor-builtins.xml"; 69 70 71 protected TreeProcessor parent; 72 73 74 protected Context context; 75 76 77 protected ComponentManager manager; 78 79 80 protected RoleManager roleManager; 81 82 83 protected ExtendedComponentSelector builderSelector; 84 85 86 protected long lastModified = 0; 87 88 89 protected DelayedRefreshSourceWrapper source; 90 91 92 protected long lastModifiedDelay; 93 94 95 protected Configuration currentLanguage; 96 97 98 protected boolean checkReload; 99 100 101 protected SourceResolver resolver; 102 103 104 ConcreteTreeProcessor concreteProcessor; 105 106 109 public TreeProcessor() { 110 this.checkReload = true; 111 this.lastModifiedDelay = 1000; 112 } 113 114 117 protected TreeProcessor(TreeProcessor parent, ComponentManager manager) { 118 this.parent = parent; 119 120 this.enableLogging(parent.getLogger()); 122 this.context = parent.context; 123 this.roleManager = parent.roleManager; 124 this.builderSelector = parent.builderSelector; 125 this.checkReload = parent.checkReload; 126 this.lastModifiedDelay = parent.lastModifiedDelay; 127 128 this.manager = manager; 130 } 131 132 138 public TreeProcessor createChildProcessor(ComponentManager manager, 139 String actualSource, 140 boolean checkReload) 141 throws Exception { 142 143 TreeProcessor child = new TreeProcessor(this, manager); 146 child.checkReload = checkReload; 147 child.resolver = (SourceResolver)manager.lookup(SourceResolver.ROLE); 148 child.source = new DelayedRefreshSourceWrapper(child.resolver.resolveURI(actualSource), lastModifiedDelay); 149 150 return child; 151 } 152 153 156 public void contextualize(Context context) throws ContextException { 157 this.context = context; 158 } 159 160 163 public void compose(ComponentManager manager) throws ComponentException { 164 this.manager = manager; 165 this.resolver = (SourceResolver)this.manager.lookup(SourceResolver.ROLE); 166 } 167 168 171 public void setRoleManager(RoleManager rm) { 172 this.roleManager = rm; 173 } 174 175 176 182 public void configure(Configuration config) 183 throws ConfigurationException { 184 185 this.checkReload = config.getAttributeAsBoolean("check-reload", true); 186 187 String xconfURL = config.getAttribute("config", XCONF_URL); 190 191 this.lastModifiedDelay = config.getChild("reload").getAttributeAsLong("delay", 1000L); 193 194 String fileName = config.getAttribute("file", "sitemap.xmap"); 195 196 try { 197 this.source = new DelayedRefreshSourceWrapper(this.resolver.resolveURI(fileName), lastModifiedDelay); 198 } catch (Exception e) { 199 throw new ConfigurationException("Cannot resolve " + fileName, e); 200 } 201 202 Configuration builtin; 204 try { 205 Source source = this.resolver.resolveURI(xconfURL); 206 try { 207 SAXConfigurationHandler handler = new SAXConfigurationHandler(); 208 SourceUtil.toSAX( this.manager, source, null, handler); 209 builtin = handler.getConfiguration(); 210 } finally { 211 this.resolver.release(source); 212 } 213 } catch(Exception e) { 214 String msg = "Error while reading " + xconfURL + ": " + e.getMessage(); 215 throw new ConfigurationException(msg, e); 216 } 217 218 this.builderSelector = new ExtendedComponentSelector(Thread.currentThread().getContextClassLoader()); 220 try { 221 LifecycleHelper.setupComponent(this.builderSelector, 222 getLogger(), 223 this.context, 224 this.manager, 225 this.roleManager, 226 builtin); 227 } catch (ConfigurationException e) { 228 throw e; 229 } catch (Exception e) { 230 throw new ConfigurationException("Could not setup builder selector", e); 231 } 232 } 233 234 244 public boolean process(Environment environment) throws Exception { 245 246 this.setupConcreteProcessor(environment); 247 248 return this.concreteProcessor.process(environment); 249 } 250 251 256 public ProcessingPipeline buildPipeline(Environment environment) 257 throws Exception { 258 259 setupConcreteProcessor(environment); 260 261 return this.concreteProcessor.buildPipeline(environment); 262 } 263 264 267 public Processor getRootProcessor() { 268 TreeProcessor result = this; 269 while(result.parent != null) { 270 result = result.parent; 271 } 272 273 return result; 274 } 275 276 279 public void setComponentConfigurations(Configuration componentConfigurations) { 280 this.concreteProcessor.setComponentConfigurations(componentConfigurations); 281 } 282 283 286 public Map getComponentConfigurations() { 287 return this.concreteProcessor.getComponentConfigurations(); 288 } 289 290 private void setupConcreteProcessor(Environment env) throws Exception { 291 292 if (this.parent == null) { 293 env.changeContext("", this.source.getURI()); 295 } 296 297 if (this.concreteProcessor == null || 299 (this.checkReload && this.source.getLastModified() != this.lastModified)) { 300 buildConcreteProcessor(env); 301 } 302 } 303 304 private synchronized void buildConcreteProcessor(Environment env) throws Exception { 305 306 if (this.concreteProcessor != null && source.getLastModified() == this.lastModified) { 309 return; 311 } 312 313 long startTime = System.currentTimeMillis(); 314 315 if (this.concreteProcessor != null) { 317 this.concreteProcessor.markForDisposal(); 318 } 319 320 TreeBuilder builder = (TreeBuilder)this.builderSelector.select("sitemap"); 322 ConcreteTreeProcessor newProcessor = new ConcreteTreeProcessor(this); 323 long newLastModified; 324 this.setupLogger(newProcessor); 325 CocoonComponentManager.enterEnvironment(env, this.manager, this); 327 try { 328 if (builder instanceof Recomposable) { 329 ((Recomposable)builder).recompose(this.manager); 330 } 331 builder.setProcessor(newProcessor); 332 333 newLastModified = this.source.getLastModified(); 334 335 ProcessingNode root = builder.build(this.source); 336 337 newProcessor.setProcessorData(builder.getSitemapComponentManager(), root, builder.getDisposableNodes()); 338 } finally { 339 CocoonComponentManager.leaveEnvironment(); 340 this.builderSelector.release(builder); 341 } 342 343 if (getLogger().isDebugEnabled()) { 344 double time = (this.lastModified - startTime) / 1000.0; 345 getLogger().debug("TreeProcessor built in " + time + " secs from " + source.getURI()); 346 } 347 348 this.concreteProcessor = newProcessor; 350 this.lastModified = newLastModified; 351 } 352 353 356 public void dispose() { 357 ContainerUtil.dispose(this.concreteProcessor); 360 this.concreteProcessor = null; 361 362 if (this.manager != null) { 363 if (this.source != null) { 364 this.resolver.release(this.source.getSource()); 365 this.source = null; 366 } 367 368 if (this.parent == null) { 369 this.builderSelector.dispose(); 371 this.builderSelector = null; 372 } 373 374 this.manager.release(this.resolver); 376 this.resolver = null; 377 378 this.manager = null; 379 } 380 } 381 382 public String toString() { 383 return "TreeProcessor - " + (source == null ? "[unknown location]" : source.getURI()); 384 } 385 } 386 | Popular Tags |