001// Licensed under the Apache License, Version 2.0 (the "License"); 002// you may not use this file except in compliance with the License. 003// You may obtain a copy of the License at 004// 005// http://www.apache.org/licenses/LICENSE-2.0 006// 007// Unless required by applicable law or agreed to in writing, software 008// distributed under the License is distributed on an "AS IS" BASIS, 009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 010// See the License for the specific language governing permissions and 011// limitations under the License. 012 013package org.apache.tapestry5.internal.services.assets; 014 015import org.apache.tapestry5.http.ContentType; 016import org.apache.tapestry5.http.services.Response; 017import org.apache.tapestry5.services.assets.AssetChecksumGenerator; 018import org.apache.tapestry5.services.assets.CompressionStatus; 019import org.apache.tapestry5.services.assets.ResponseCustomizer; 020import org.apache.tapestry5.services.assets.StreamableResource; 021 022import java.io.IOException; 023import java.io.InputStream; 024import java.io.OutputStream; 025 026public class StreamableResourceImpl implements StreamableResource 027{ 028 protected final String description; 029 030 private final ContentType contentType; 031 032 protected final CompressionStatus compression; 033 034 protected final long lastModified; 035 036 protected final BytestreamCache bytestreamCache; 037 038 protected final AssetChecksumGenerator assetChecksumGenerator; 039 040 protected final ResponseCustomizer responseCustomizer; 041 042 public StreamableResourceImpl(String description, ContentType contentType, CompressionStatus compression, long lastModified, BytestreamCache bytestreamCache, AssetChecksumGenerator assetChecksumGenerator, ResponseCustomizer responseCustomizer) 043 { 044 this.lastModified = lastModified; 045 this.description = description; 046 this.bytestreamCache = bytestreamCache; 047 this.contentType = contentType; 048 this.compression = compression; 049 this.assetChecksumGenerator = assetChecksumGenerator; 050 this.responseCustomizer = responseCustomizer; 051 } 052 053 public String getDescription() 054 { 055 return description; 056 } 057 058 public CompressionStatus getCompression() 059 { 060 return compression; 061 } 062 063 public ContentType getContentType() 064 { 065 return contentType; 066 } 067 068 public int getSize() 069 { 070 return bytestreamCache.size(); 071 } 072 073 public long getLastModified() 074 { 075 return lastModified; 076 } 077 078 public void streamTo(OutputStream os) throws IOException 079 { 080 bytestreamCache.writeTo(os); 081 } 082 083 public InputStream openStream() throws IOException 084 { 085 return bytestreamCache.openStream(); 086 } 087 088 @Override 089 public String toString() 090 { 091 return String.format("StreamableResource<%s %s %s lastModified: %tc size: %d>", contentType, description, compression.name(), 092 lastModified, getSize()); 093 } 094 095 public String getChecksum() throws IOException 096 { 097 // Currently, we rely on AssetChecksumGenerator to manage a cache, but that may be better done 098 // here (but must be threads-afe). 099 return assetChecksumGenerator.generateChecksum(this); 100 } 101 102 @Override 103 public StreamableResource addResponseCustomizer(final ResponseCustomizer customizer) 104 { 105 final ResponseCustomizer oldCustomizer = responseCustomizer; 106 107 if (oldCustomizer == null) 108 { 109 return withNewResourceCustomizer(customizer); 110 } 111 112 return withNewResourceCustomizer(new ResponseCustomizer() 113 { 114 @Override 115 public void customizeResponse(StreamableResource resource, Response response) throws IOException 116 { 117 oldCustomizer.customizeResponse(resource, response); 118 customizer.customizeResponse(resource, response); 119 } 120 }); 121 } 122 123 @Override 124 public ResponseCustomizer getResponseCustomizer() 125 { 126 return responseCustomizer; 127 } 128 129 @Override 130 public StreamableResource withContentType(ContentType newContentType) 131 { 132 return new StreamableResourceImpl(description, newContentType, compression, lastModified, bytestreamCache, assetChecksumGenerator, responseCustomizer); 133 } 134 135 private StreamableResourceImpl withNewResourceCustomizer(ResponseCustomizer customizer) 136 { 137 return new StreamableResourceImpl(description, contentType, compression, lastModified, bytestreamCache, assetChecksumGenerator, customizer); 138 } 139}