1 16 package org.apache.cocoon.components.pipeline.impl; 17 18 import org.apache.avalon.framework.parameters.ParameterException; 19 import org.apache.avalon.framework.parameters.Parameters; 20 21 import org.apache.cocoon.ProcessingException; 22 import org.apache.cocoon.caching.CacheValidity; 23 import org.apache.cocoon.caching.CacheValidityToSourceValidity; 24 import org.apache.cocoon.caching.Cacheable; 25 import org.apache.cocoon.caching.CacheableProcessingComponent; 26 import org.apache.cocoon.caching.CachedResponse; 27 import org.apache.cocoon.caching.CachingOutputStream; 28 import org.apache.cocoon.caching.ComponentCacheKey; 29 import org.apache.cocoon.caching.PipelineCacheKey; 30 import org.apache.cocoon.environment.Environment; 31 import org.apache.cocoon.transformation.Transformer; 32 import org.apache.cocoon.util.HashUtil; 33 34 import org.apache.excalibur.source.SourceValidity; 35 import org.apache.excalibur.source.impl.validity.AggregatedValidity; 36 import org.apache.excalibur.source.impl.validity.DeferredValidity; 37 import org.apache.excalibur.source.impl.validity.NOPValidity; 38 39 import java.io.ByteArrayOutputStream ; 40 import java.io.OutputStream ; 41 import java.io.Serializable ; 42 import java.util.ArrayList ; 43 import java.util.Date ; 44 45 54 public abstract class AbstractCachingProcessingPipeline extends BaseCachingProcessingPipeline { 55 56 57 protected String generatorRole; 58 59 60 protected ArrayList transformerRoles = new ArrayList (); 61 62 63 protected String serializerRole; 64 65 66 protected String readerRole; 67 68 69 protected CachedResponse cachedResponse; 70 71 72 protected int firstProcessedTransformerIndex; 73 74 75 protected boolean completeResponseIsCached; 76 77 78 79 protected PipelineCacheKey fromCacheKey; 80 81 82 protected PipelineCacheKey toCacheKey; 83 84 85 protected SourceValidity[] toCacheSourceValidities; 86 87 88 protected int firstNotCacheableTransformerIndex; 89 90 91 protected boolean cacheCompleteResponse; 92 93 protected boolean generatorIsCacheableProcessingComponent; 94 protected boolean serializerIsCacheableProcessingComponent; 95 protected boolean[] transformerIsCacheableProcessingComponent; 96 97 98 protected boolean doSmartCaching; 99 100 101 protected boolean configuredDoSmartCaching; 102 103 104 105 protected abstract void cacheResults(Environment environment, 106 OutputStream os) 107 throws Exception ; 108 109 110 protected abstract ComponentCacheKey newComponentCacheKey(int type, 111 String role, 112 Serializable key); 113 114 115 protected abstract void connectCachingPipeline(Environment environment) 116 throws ProcessingException; 117 118 119 122 public void parameterize(Parameters params) 123 throws ParameterException { 124 super.parameterize(params); 125 this.configuredDoSmartCaching = 126 params.getParameterAsBoolean("smart-caching", true); 127 } 128 129 132 public void setup(Parameters params) { 133 super.setup(params); 134 this.doSmartCaching = params.getParameterAsBoolean("smart-caching", 135 this.configuredDoSmartCaching); 136 } 137 138 141 public void setGenerator (String role, String source, Parameters param, 142 Parameters hintParam) 143 throws ProcessingException { 144 super.setGenerator(role, source, param, hintParam); 145 this.generatorRole = role; 146 } 147 148 151 public void addTransformer (String role, String source, Parameters param, 152 Parameters hintParam) throws ProcessingException { 153 super.addTransformer(role, source, param, hintParam); 154 this.transformerRoles.add(role); 155 } 156 157 158 161 public void setSerializer (String role, String source, Parameters param, 162 Parameters hintParam, String mimeType) throws ProcessingException { 163 super.setSerializer(role, source, param, hintParam, mimeType); 164 this.serializerRole = role; 165 } 166 167 170 public void setReader (String role, String source, Parameters param, 171 String mimeType) 172 throws ProcessingException { 173 super.setReader(role, source, param, mimeType); 174 this.readerRole = role; 175 } 176 177 180 protected boolean processXMLPipeline(Environment environment) 181 throws ProcessingException { 182 if (this.toCacheKey == null && this.cachedResponse == null) { 183 return super.processXMLPipeline(environment); 184 } 185 186 if (this.cachedResponse != null && this.completeResponseIsCached) { 187 188 if (checkIfModified(environment, this.cachedResponse.getLastModified())) { 190 return true; 191 } 192 193 if (this.cachedResponse.getContentType() != null) { 195 environment.setContentType(this.cachedResponse.getContentType()); 196 } else { 197 setMimeTypeForSerializer(environment); 198 } 199 200 try { 202 final OutputStream outputStream = environment.getOutputStream(0); 203 final byte[] content = this.cachedResponse.getResponse(); 204 if (content.length > 0) { 205 environment.setContentLength(content.length); 206 outputStream.write(content); 207 } 208 } catch (Exception e) { 209 handleException(e); 210 } 211 } else { 212 setMimeTypeForSerializer(environment); 213 if (getLogger().isDebugEnabled() && this.toCacheKey != null) { 214 getLogger().debug("processXMLPipeline: caching content for further" + 215 " requests of '" + environment.getURI() + 216 "' using key " + this.toCacheKey); 217 } 218 219 try { 220 OutputStream os = null; 221 222 if (this.cacheCompleteResponse && this.toCacheKey != null) { 223 os = new CachingOutputStream(environment.getOutputStream(this.outputBufferSize)); 224 } 225 226 if (super.serializer != super.lastConsumer) { 227 if (os == null) { 228 os = environment.getOutputStream(this.outputBufferSize); 229 } 230 231 if (this.xmlDeserializer != null) { 233 this.xmlDeserializer.deserialize(this.cachedResponse.getResponse()); 234 } else { 235 this.generator.generate(); 236 } 237 238 } else { 239 if (this.serializer.shouldSetContentLength()) { 240 if (os == null) { 241 os = environment.getOutputStream(0); 242 } 243 244 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 246 this.serializer.setOutputStream(baos); 247 248 if (this.xmlDeserializer != null) { 250 this.xmlDeserializer.deserialize(this.cachedResponse.getResponse()); 251 } else { 252 this.generator.generate(); 253 } 254 255 environment.setContentLength(baos.size()); 256 baos.writeTo(os); 257 } else { 258 if (os == null) { 259 os = environment.getOutputStream(this.outputBufferSize); 260 } 261 262 this.serializer.setOutputStream(os); 264 265 if (this.xmlDeserializer != null) { 267 this.xmlDeserializer.deserialize(this.cachedResponse.getResponse()); 268 } else { 269 this.generator.generate(); 270 } 271 } 272 } 273 274 cacheResults(environment,os); 279 280 } catch (Exception e) { 281 handleException(e); 282 } 283 284 return true; 285 } 286 287 return true; 288 } 289 290 293 protected void generateCachingKey(Environment environment) 294 throws ProcessingException { 295 296 this.toCacheKey = null; 297 298 this.generatorIsCacheableProcessingComponent = false; 299 this.serializerIsCacheableProcessingComponent = false; 300 this.transformerIsCacheableProcessingComponent = 301 new boolean[this.transformers.size()]; 302 303 this.firstNotCacheableTransformerIndex = 0; 304 this.cacheCompleteResponse = false; 305 306 312 Serializable key = getGeneratorKey(); 314 if (key != null) { 315 this.toCacheKey = new PipelineCacheKey(); 316 this.toCacheKey.addKey( 317 this.newComponentCacheKey( 318 ComponentCacheKey.ComponentType_Generator, 319 this.generatorRole, key)); 320 321 final int transformerSize = super.transformers.size(); 323 boolean continueTest = true; 324 325 while (this.firstNotCacheableTransformerIndex < transformerSize && continueTest) { 326 final Transformer trans = 327 (Transformer)super.transformers.get(this.firstNotCacheableTransformerIndex); 328 key = getTransformerKey(trans); 329 if (key != null) { 330 this.toCacheKey.addKey( 331 this.newComponentCacheKey( 332 ComponentCacheKey.ComponentType_Transformer, 333 (String )this.transformerRoles.get( 334 this.firstNotCacheableTransformerIndex), 335 key)); 336 337 this.firstNotCacheableTransformerIndex++; 338 } else { 339 continueTest = false; 340 } 341 } 342 if (this.firstNotCacheableTransformerIndex == transformerSize 345 && super.serializer == this.lastConsumer) { 346 347 key = getSerializerKey(); 348 if (key != null) { 349 this.toCacheKey.addKey( 350 this.newComponentCacheKey( 351 ComponentCacheKey.ComponentType_Serializer, 352 this.serializerRole, 353 key)); 354 this.cacheCompleteResponse = true; 355 } 356 } 357 } 358 } 359 360 363 protected void setupValidities() throws ProcessingException { 364 365 if (this.toCacheKey != null) { 366 if (this.fromCacheKey == null 370 || this.fromCacheKey.size() < this.toCacheKey.size()) { 371 372 this.toCacheSourceValidities = 373 new SourceValidity[this.toCacheKey.size()]; 374 375 int len = this.toCacheSourceValidities.length; 376 int i = 0; 377 while (i < len) { 378 final SourceValidity validity = getValidityForInternalPipeline(i); 379 380 if (validity == null) { 381 if (i > 0 382 && (this.fromCacheKey == null 383 || i > this.fromCacheKey.size())) { 384 for (int m=i; m < this.toCacheSourceValidities.length; m++) { 386 this.toCacheKey.removeLastKey(); 387 if (!this.cacheCompleteResponse) { 388 this.firstNotCacheableTransformerIndex--; 389 } 390 this.cacheCompleteResponse = false; 391 } 392 SourceValidity[] copy = new SourceValidity[i]; 393 System.arraycopy(this.toCacheSourceValidities, 0, copy, 0, copy.length); 394 this.toCacheSourceValidities = copy; 395 len = this.toCacheSourceValidities.length; 396 } else { 397 this.toCacheKey = null; 399 this.toCacheSourceValidities = null; 400 this.cacheCompleteResponse = false; 401 len = 0; 402 } 403 } else { 404 this.toCacheSourceValidities[i] = validity; 405 } 406 i++; 407 } 408 } else { 409 this.toCacheKey = null; 411 this.cacheCompleteResponse = false; 412 } 413 } 414 } 415 416 420 protected void validatePipeline(Environment environment) 421 throws ProcessingException { 422 this.completeResponseIsCached = this.cacheCompleteResponse; 423 this.fromCacheKey = this.toCacheKey.copy(); 424 this.firstProcessedTransformerIndex = this.firstNotCacheableTransformerIndex; 425 426 boolean finished = false; 427 while (this.fromCacheKey != null && !finished) { 428 finished = true; 429 430 final CachedResponse response = this.cache.get(this.fromCacheKey); 431 432 if (response != null) { 434 if (getLogger().isDebugEnabled()) { 435 getLogger().debug("Found cached response for '" + environment.getURI() + 436 "' using key: " + this.fromCacheKey); 437 } 438 439 boolean responseIsValid = true; 440 boolean responseIsUsable = true; 441 442 Long responseExpires = response.getExpires(); 445 446 if (responseExpires != null) { 447 if (getLogger().isDebugEnabled()) { 448 getLogger().debug("Expires time found for " + environment.getURI()); 449 } 450 451 if (responseExpires.longValue() > System.currentTimeMillis()) { 452 if (getLogger().isDebugEnabled()) { 453 getLogger().debug("Expires time still fresh for " + environment.getURI() + 454 ", ignoring all other cache settings. This entry expires on "+ 455 new Date (responseExpires.longValue())); 456 } 457 this.cachedResponse = response; 458 return; 459 } else { 460 if (getLogger().isDebugEnabled()) { 461 getLogger().debug("Expires time has expired for " + environment.getURI() + 462 ", regenerating content."); 463 } 464 465 if (expires != 0) { 469 if (this.getLogger().isDebugEnabled()) 470 this.getLogger().debug("Refreshing expires informations"); 471 response.setExpires(new Long (expires + System.currentTimeMillis())); 472 } else { 473 if (this.getLogger().isDebugEnabled()) 474 this.getLogger().debug("No expires defined anymore for this object, setting it to no expires"); 475 response.setExpires(null); 476 } 477 } 478 } else { 479 if (expires != 0) { 481 if (this.getLogger().isDebugEnabled()) 482 this.getLogger().debug("Setting a new expires object for this resource"); 483 response.setExpires(new Long (expires + System.currentTimeMillis())); 484 } 485 } 486 487 SourceValidity[] fromCacheValidityObjects = response.getValidityObjects(); 488 489 int i = 0; 490 while (responseIsValid && i < fromCacheValidityObjects.length) { 491 boolean isValid = false; 492 493 SourceValidity validity = fromCacheValidityObjects[i]; 496 int valid = validity == null ? SourceValidity.INVALID : validity.isValid(); 497 if (valid == SourceValidity.UNKNOWN) { 498 validity = getValidityForInternalPipeline(i); 500 if (validity != null) { 501 valid = fromCacheValidityObjects[i].isValid(validity); 502 if (valid == SourceValidity.UNKNOWN) { 503 validity = null; 504 } else { 505 isValid = (valid == SourceValidity.VALID); 506 } 507 } 508 } else { 509 isValid = (valid == SourceValidity.VALID); 510 } 511 512 if (!isValid) { 513 responseIsValid = false; 514 if (validity == null) { 516 responseIsUsable = false; 517 if (getLogger().isDebugEnabled()) { 518 getLogger().debug("validatePipeline: responseIsUsable is false, valid=" + 519 valid + " at index " + i); 520 } 521 } else { 522 if (getLogger().isDebugEnabled()) { 523 getLogger().debug("validatePipeline: responseIsValid is false due to " + 524 validity); 525 } 526 } 527 } else { 528 i++; 529 } 530 } 531 532 if (responseIsValid) { 533 if (getLogger().isDebugEnabled()) { 534 getLogger().debug("validatePipeline: using valid cached content for '" + 535 environment.getURI() + "'."); 536 } 537 538 this.cachedResponse = response; 540 this.toCacheSourceValidities = fromCacheValidityObjects; 541 } else { 542 if (getLogger().isDebugEnabled()) { 543 getLogger().debug("validatePipeline: cached content is invalid for '" + 544 environment.getURI() + "'."); 545 } 546 548 if (!responseIsUsable) { 549 if (i > 0) { 552 int deleteCount = fromCacheValidityObjects.length - i; 553 if (i > 0 && i <= firstNotCacheableTransformerIndex + 1) { 554 this.firstNotCacheableTransformerIndex = i-1; 555 } 556 for(int x=0; x < deleteCount; x++) { 557 this.toCacheKey.removeLastKey(); 558 } 559 finished = false; 560 } else { 561 this.toCacheKey = null; 562 } 563 this.cacheCompleteResponse = false; 564 } else { 565 this.cache.remove(this.fromCacheKey); 567 } 568 569 if (i > 0) { 571 this.fromCacheKey.removeLastKey(); 572 if (!this.completeResponseIsCached) { 573 this.firstProcessedTransformerIndex--; 574 } 575 } else { 576 this.fromCacheKey = null; 577 } 578 finished = false; 579 this.completeResponseIsCached = false; 580 } 581 } else { 582 583 if (this.getLogger().isDebugEnabled()) { 585 this.getLogger().debug( 586 "Cached response not found for '" + environment.getURI() + 587 "' using key: " + this.fromCacheKey 588 ); 589 } 590 591 if (!this.doSmartCaching) { 592 if (this.fromCacheKey.size() > 1) { 594 this.fromCacheKey.removeLastKey(); 595 if (!this.completeResponseIsCached) { 596 this.firstProcessedTransformerIndex--; 597 } 598 finished = false; 599 } else { 600 this.fromCacheKey = null; 601 } 602 } else { 603 this.fromCacheKey = null; 605 } 606 this.completeResponseIsCached = false; 607 } 608 } 609 610 } 611 612 617 protected void setupPipeline(Environment environment) 618 throws ProcessingException { 619 super.setupPipeline(environment); 620 621 generateCachingKey(environment); 623 624 if (this.toCacheKey != null) { 626 validatePipeline(environment); 627 } 628 629 setupValidities(); 630 } 631 632 635 protected void connectPipeline(Environment environment) 636 throws ProcessingException { 637 if (this.toCacheKey == null && this.cachedResponse == null) { 638 super.connectPipeline(environment); 639 return; 640 } else if (this.completeResponseIsCached) { 641 return; 643 } else { 644 this.connectCachingPipeline(environment); 645 } 646 } 647 648 651 protected boolean processReader(Environment environment) 652 throws ProcessingException { 653 try { 654 boolean usedCache = false; 655 OutputStream outputStream = null; 656 SourceValidity readerValidity = null; 657 PipelineCacheKey pcKey = null; 658 659 Serializable readerKey = null; 661 boolean isCacheableProcessingComponent = false; 662 if (super.reader instanceof CacheableProcessingComponent) { 663 readerKey = ((CacheableProcessingComponent)super.reader).getKey(); 664 isCacheableProcessingComponent = true; 665 } else if (super.reader instanceof Cacheable) { 666 readerKey = new Long (((Cacheable)super.reader).generateKey()); 667 } 668 669 if (readerKey != null) { 670 pcKey = new PipelineCacheKey(); 672 pcKey.addKey(new ComponentCacheKey(ComponentCacheKey.ComponentType_Reader, 673 this.readerRole, 674 readerKey) 675 ); 676 677 CachedResponse cachedObject = this.cache.get(pcKey); 679 if (cachedObject != null) { 680 if (getLogger().isDebugEnabled()) { 681 getLogger().debug("Found cached response for '" + 682 environment.getURI() + "' using key: " + pcKey); 683 } 684 685 SourceValidity[] validities = cachedObject.getValidityObjects(); 686 if (validities == null || validities.length != 1) { 687 this.cache.remove(pcKey); 689 if (getLogger().isDebugEnabled()) { 690 getLogger().debug("Cached response for '" + environment.getURI() + 691 "' using key: " + pcKey + " is invalid."); 692 } 693 this.cachedResponse = null; 694 } else { 695 SourceValidity cachedValidity = validities[0]; 696 boolean isValid = false; 697 int valid = cachedValidity.isValid(); 698 if (valid == SourceValidity.UNKNOWN) { 699 if (isCacheableProcessingComponent) { 701 readerValidity = ((CacheableProcessingComponent) super.reader).getValidity(); 702 } else { 703 CacheValidity cv = ((Cacheable) super.reader).generateValidity(); 704 if (cv != null) { 705 readerValidity = CacheValidityToSourceValidity.createValidity(cv); 706 } 707 } 708 if (readerValidity != null) { 709 valid = cachedValidity.isValid(readerValidity); 710 if (valid == SourceValidity.UNKNOWN) { 711 readerValidity = null; 712 } else { 713 isValid = (valid == SourceValidity.VALID); 714 } 715 } 716 } else { 717 isValid = (valid == SourceValidity.VALID); 718 } 719 720 if (isValid) { 721 if (getLogger().isDebugEnabled()) { 722 getLogger().debug("processReader: using valid cached content for '" + 723 environment.getURI() + "'."); 724 } 725 byte[] response = cachedObject.getResponse(); 726 if (response.length > 0) { 727 usedCache = true; 728 if (cachedObject.getContentType() != null) { 729 environment.setContentType(cachedObject.getContentType()); 730 } else { 731 setMimeTypeForReader(environment); 732 } 733 outputStream = environment.getOutputStream(0); 734 environment.setContentLength(response.length); 735 outputStream.write(response); 736 } 737 } else { 738 if (getLogger().isDebugEnabled()) { 739 getLogger().debug("processReader: cached content is invalid for '" + 740 environment.getURI() + "'."); 741 } 742 this.cache.remove(pcKey); 744 } 745 } 746 } 747 } 748 749 if (!usedCache) { 750 if (pcKey != null) { 751 if (getLogger().isDebugEnabled()) { 752 getLogger().debug("processReader: caching content for further requests of '" + 753 environment.getURI() + "'."); 754 } 755 756 if (readerValidity == null) { 757 if (isCacheableProcessingComponent) { 758 readerValidity = ((CacheableProcessingComponent)super.reader).getValidity(); 759 } else { 760 CacheValidity cv = ((Cacheable)super.reader).generateValidity(); 761 if ( cv != null ) { 762 readerValidity = CacheValidityToSourceValidity.createValidity( cv ); 763 } 764 } 765 } 766 767 if (readerValidity != null) { 768 outputStream = environment.getOutputStream(this.outputBufferSize); 769 outputStream = new CachingOutputStream(outputStream); 770 } else { 771 pcKey = null; 772 } 773 } 774 775 setMimeTypeForReader(environment); 776 if (this.reader.shouldSetContentLength()) { 777 ByteArrayOutputStream os = new ByteArrayOutputStream (); 778 this.reader.setOutputStream(os); 779 this.reader.generate(); 780 environment.setContentLength(os.size()); 781 if (outputStream == null) { 782 outputStream = environment.getOutputStream(0); 783 } 784 os.writeTo(outputStream); 785 } else { 786 if (outputStream == null) { 787 outputStream = environment.getOutputStream(this.outputBufferSize); 788 } 789 this.reader.setOutputStream(outputStream); 790 this.reader.generate(); 791 } 792 793 if (pcKey != null) { 795 final CachedResponse res = new CachedResponse(new SourceValidity[] {readerValidity}, 796 ((CachingOutputStream)outputStream).getContent()); 797 res.setContentType(environment.getContentType()); 798 this.cache.store(pcKey, res); 799 } 800 } 801 } catch (Exception e) { 802 handleException(e); 803 } 804 805 return true; 806 } 807 808 809 817 public SourceValidity getValidityForEventPipeline() { 818 if (isInternalError()) { 819 return null; 820 } 821 822 if (this.cachedResponse != null) { 823 if (!this.cacheCompleteResponse && 824 this.firstNotCacheableTransformerIndex < super.transformers.size()) { 825 return null; 827 } 828 829 if (this.toCacheSourceValidities != null) { 830 final AggregatedValidity validity = new AggregatedValidity(); 833 for (int i=0; i < this.toCacheSourceValidities.length; i++) { 834 validity.add(this.toCacheSourceValidities[i]); 835 } 836 837 return validity; 838 } 839 840 return NOPValidity.SHARED_INSTANCE; 842 } else { 843 int vals = 0; 844 845 if (null != this.toCacheKey 846 && !this.cacheCompleteResponse 847 && this.firstNotCacheableTransformerIndex == super.transformers.size()) { 848 vals = this.toCacheKey.size(); 849 } else if (null != this.fromCacheKey 850 && !this.completeResponseIsCached 851 && this.firstProcessedTransformerIndex == super.transformers.size()) { 852 vals = this.fromCacheKey.size(); 853 } 854 855 if (vals > 0) { 856 final AggregatedValidity validity = new AggregatedValidity(); 857 for (int i = 0; i < vals; i++) { 858 validity.add(getValidityForInternalPipeline(i)); 859 } 860 861 return validity; 862 } 863 864 return null; 865 } 866 } 867 868 871 private Serializable getGeneratorKey() { 872 Serializable key = null; 873 if (super.generator instanceof CacheableProcessingComponent) { 874 key = ((CacheableProcessingComponent)super.generator).getKey(); 875 this.generatorIsCacheableProcessingComponent = true; 876 } else if (super.generator instanceof Cacheable) { 877 key = new Long (((Cacheable)super.generator).generateKey()); 878 } 879 return key; 880 } 881 882 885 private Serializable getTransformerKey(final Transformer transformer) { 886 Serializable key = null; 887 if (transformer instanceof CacheableProcessingComponent) { 888 key = ((CacheableProcessingComponent)transformer).getKey(); 889 this.transformerIsCacheableProcessingComponent[this.firstNotCacheableTransformerIndex] = true; 890 } else if (transformer instanceof Cacheable) { 891 key = new Long (((Cacheable)transformer).generateKey()); 892 } 893 return key; 894 } 895 896 899 private Serializable getSerializerKey() { 900 Serializable key = null; 901 if (super.serializer instanceof CacheableProcessingComponent) { 902 key = ((CacheableProcessingComponent)this.serializer).getKey(); 903 this.serializerIsCacheableProcessingComponent = true; 904 } else if (this.serializer instanceof Cacheable) { 905 key = new Long (((Cacheable)this.serializer).generateKey()); 906 } 907 return key; 908 } 909 910 913 public String getKeyForEventPipeline() { 914 if (isInternalError()) { 915 return null; 916 } 917 918 if (null != this.toCacheKey 919 && !this.cacheCompleteResponse 920 && this.firstNotCacheableTransformerIndex == super.transformers.size()) { 921 return String.valueOf(HashUtil.hash(this.toCacheKey.toString())); 922 } 923 if (null != this.fromCacheKey 924 && !this.completeResponseIsCached 925 && this.firstProcessedTransformerIndex == super.transformers.size()) { 926 return String.valueOf(HashUtil.hash(this.fromCacheKey.toString())); 927 } 928 929 return null; 930 } 931 932 SourceValidity getValidityForInternalPipeline(int index) { 933 final SourceValidity validity; 934 935 final boolean debug = this.getLogger().isDebugEnabled(); 937 String msg = null; 938 if(debug) msg = "getValidityForInternalPipeline(" + index + "): "; 939 940 if (index == 0) { 941 if (this.generatorIsCacheableProcessingComponent) { 943 validity = ((CacheableProcessingComponent)super.generator).getValidity(); 944 if(debug) msg += "generator: using getValidity"; 945 } else { 946 validity = CacheValidityToSourceValidity.createValidity(((Cacheable)super.generator).generateValidity()); 947 if(debug) msg += "generator: using generateValidity"; 948 } 949 } else if (index <= firstNotCacheableTransformerIndex) { 950 final Transformer trans = (Transformer)super.transformers.get(index-1); 952 if (this.transformerIsCacheableProcessingComponent[index-1]) { 953 validity = ((CacheableProcessingComponent)trans).getValidity(); 954 if(debug) msg += "transformer: using getValidity"; 955 } else { 956 validity = CacheValidityToSourceValidity.createValidity(((Cacheable)trans).generateValidity()); 957 if(debug) msg += "transformer: using generateValidity"; 958 } 959 } else { 960 if (this.serializerIsCacheableProcessingComponent) { 962 validity = ((CacheableProcessingComponent)super.serializer).getValidity(); 963 if(debug) msg += "serializer: using getValidity"; 964 } else { 965 validity = CacheValidityToSourceValidity.createValidity(((Cacheable)super.serializer).generateValidity()); 966 if(debug) msg += "serializer: using generateValidity"; 967 } 968 } 969 970 if(debug) { 971 msg += ", validity==" + validity; 972 this.getLogger().debug(msg); 973 } 974 return validity; 975 } 976 977 980 public void recycle() { 981 this.generatorRole = null; 982 this.transformerRoles.clear(); 983 this.serializerRole = null; 984 this.readerRole = null; 985 986 this.fromCacheKey = null; 987 this.cachedResponse = null; 988 989 this.transformerIsCacheableProcessingComponent = null; 990 this.toCacheKey = null; 991 this.toCacheSourceValidities = null; 992 993 super.recycle(); 994 } 995 } 996 997 final class DeferredPipelineValidity implements DeferredValidity { 998 999 private final AbstractCachingProcessingPipeline pipeline; 1000 private final int index; 1001 1002 public DeferredPipelineValidity(AbstractCachingProcessingPipeline pipeline, int index) { 1003 this.pipeline = pipeline; 1004 this.index = index; 1005 } 1006 1007 1010 public SourceValidity getValidity() { 1011 return pipeline.getValidityForInternalPipeline(this.index); 1012 } 1013} 1014 | Popular Tags |