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.services.assets;
014
015import org.apache.tapestry5.commons.Resource;
016import org.apache.tapestry5.http.ContentType;
017import org.apache.tapestry5.ioc.annotations.IncompatibleChange;
018
019import java.io.IOException;
020import java.io.InputStream;
021import java.io.OutputStream;
022
023/**
024 * An object, derived from a {@link Resource}, that can be streamed (ultimately, to a client web browser). In addition,
025 * a StreamableResource may be transformed (by the stack of interceptors around {@link StreamableResourceSource}: this
026 * includes transforming a Resource (example: CoffeeScript to JavaScript compilation), as well as aggregation
027 * and compression.
028 *
029 * @since 5.3
030 */
031public interface StreamableResource
032{
033    /**
034     * Describes the underlying {@link Resource} (or resources} for this streamable resource; expressly used
035     * as part of the object's {@code toString()}.
036     */
037    String getDescription();
038
039    /**
040     * Indicates if the content is compressed, or compressable.
041     */
042    CompressionStatus getCompression();
043
044    /**
045     * Returns the resource's content type.
046     */
047    @IncompatibleChange(release = "5.4", details = "Changed from type String to ContentType")
048    ContentType getContentType();
049
050    /**
051     * The size, in bytes, of the underlying bytestream.
052     */
053    int getSize();
054
055    /**
056     * Streams the resource's content to the provided stream. The caller is responsible for flushing or closing
057     * the output stream.
058     */
059    void streamTo(OutputStream os) throws IOException;
060
061    /**
062     * Opens the content of the resource as an input stream; the caller is responsible for closing the stream
063     * after reading it.
064     *
065     * @return stream of the contents of the resource
066     * @throws IOException
067     */
068    InputStream openStream() throws IOException;
069
070    /**
071     * Returns the time the resource was last modified, with accuracy to one second (so as to match
072     * the HTTP request/response date headers).
073     */
074    long getLastModified();
075
076    /**
077     * Compute and return the checksum of the content for this asset; the checksum should be computed
078     * based on the uncompressed content.
079     *
080     * @return checksum for uncompressed content
081     * @see AssetChecksumGenerator#generateChecksum(StreamableResource)
082     * @since 5.4
083     */
084    String getChecksum() throws IOException;
085
086
087    /**
088     * Returns a new StreamableResource that includes the provided customizer. Customizers are invoked
089     * in the order they are added.
090     *
091     * @since 5.4
092     */
093    StreamableResource addResponseCustomizer(ResponseCustomizer customizer);
094
095    /**
096     * Returns the customizer, if any, for this resource.  This may represent an aggregate customizer.
097     *
098     * @since 5.4
099     */
100    ResponseCustomizer getResponseCustomizer();
101
102    /**
103     * Returns a new StreamableResource instance with the new content type.
104     *
105     * @param newContentType
106     * @since 5.4
107     */
108    StreamableResource withContentType(ContentType newContentType);
109}