Search in sources :

Example 1 with StreamableResource

use of org.apache.tapestry5.services.assets.StreamableResource in project tapestry-5 by apache.

the class ResourceStreamerImpl method streamResource.

public boolean streamResource(Resource resource, StreamableResource streamable, String providedChecksum, Set<Options> options) throws IOException {
    assert streamable != null;
    assert providedChecksum != null;
    assert options != null;
    String actualChecksum = streamable.getChecksum();
    if (providedChecksum.length() > 0 && !providedChecksum.equals(actualChecksum)) {
        // TAP5-2185: Trying to find the wrongly-checksummed resource in the classpath and context,
        // so we can create an Asset with the correct checksum and redirect to it.
        Asset asset = null;
        if (resource != null) {
            asset = findAssetInsideWebapp(resource);
        }
        if (asset != null) {
            response.sendRedirect(asset.toClientURL());
            return true;
        }
        return false;
    }
    // ETag should be surrounded with quotes.
    String token = QUOTE + actualChecksum + QUOTE;
    // Even when sending a 304, we want the ETag associated with the request.
    // In most cases (except JavaScript modules), the checksum is also embedded into the URL.
    // However, E-Tags are also useful for enabling caching inside intermediate servers, CDNs, etc.
    response.setHeader("ETag", token);
    // If the client can send the correct ETag token, then its cache already contains the correct
    // content.
    String providedToken = request.getHeader("If-None-Match");
    if (token.equals(providedToken)) {
        response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
        return true;
    }
    long lastModified = streamable.getLastModified();
    long ifModifiedSince;
    try {
        ifModifiedSince = request.getDateHeader(IF_MODIFIED_SINCE_HEADER);
    } catch (IllegalArgumentException ex) {
        // Simulate the header being missing if it is poorly formatted.
        ifModifiedSince = -1;
    }
    if (ifModifiedSince > 0 && ifModifiedSince >= lastModified) {
        response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
        return true;
    }
    // Prevent the upstream code from compressing when we don't want to.
    response.disableCompression();
    response.setDateHeader("Last-Modified", lastModified);
    if (productionMode && !options.contains(Options.OMIT_EXPIRATION)) {
        // Starting in 5.4, this is a lot less necessary; any change to a Resource will result
        // in a new asset URL with the changed checksum incorporated into the URL.
        response.setDateHeader("Expires", lastModified + InternalConstants.TEN_YEARS);
    }
    // mostly result in quick SC_NOT_MODIFIED responses.
    if (options.contains(Options.OMIT_EXPIRATION)) {
        response.setHeader("Cache-Control", omitExpirationCacheControlHeader);
    }
    if (streamable.getCompression() == CompressionStatus.COMPRESSED) {
        response.setHeader(TapestryHttpInternalConstants.CONTENT_ENCODING_HEADER, TapestryHttpInternalConstants.GZIP_CONTENT_ENCODING);
    }
    ResponseCustomizer responseCustomizer = streamable.getResponseCustomizer();
    if (responseCustomizer != null) {
        responseCustomizer.customizeResponse(streamable, response);
    }
    if (!request.getMethod().equals("HEAD")) {
        response.setContentLength(streamable.getSize());
        OutputStream os = response.getOutputStream(streamable.getContentType().toString());
        streamable.streamTo(os);
        os.close();
    }
    return true;
}
Also used : OutputStream(java.io.OutputStream) Asset(org.apache.tapestry5.Asset)

Example 2 with StreamableResource

use of org.apache.tapestry5.services.assets.StreamableResource in project tapestry-5 by apache.

the class AbstractAssetFactory method createAsset.

protected Asset createAsset(final Resource resource, final String folder, final String resourcePath) {
    assert resource != null;
    assert InternalUtils.isNonBlank(folder);
    assert InternalUtils.isNonBlank(resourcePath);
    return new AbstractAsset(false) {

        public String toClientURL() {
            try {
                // Get the uncompressed version, so that we can identify its content type (and remember, the extension is not enough,
                // as some types get translated to new content types by the SRS).
                StreamableResource uncompressed = streamableResourceSource.getStreamableResource(resource, StreamableResourceProcessing.COMPRESSION_DISABLED, resourceChangeTracker);
                StreamableResource forRequest = isCompressable(uncompressed) ? streamableResourceSource.getStreamableResource(resource, StreamableResourceProcessing.COMPRESSION_ENABLED, resourceChangeTracker) : uncompressed;
                return assetPathConstructor.constructAssetPath(folder, resourcePath, forRequest);
            } catch (IOException ex) {
                throw new RuntimeException(String.format("Unable to construct asset path for %s: %s", resource, ExceptionUtils.toMessage(ex)), ex);
            }
        }

        public Resource getResource() {
            return resource;
        }
    };
}
Also used : StreamableResource(org.apache.tapestry5.services.assets.StreamableResource) IOException(java.io.IOException)

Example 3 with StreamableResource

use of org.apache.tapestry5.services.assets.StreamableResource in project tapestry-5 by apache.

the class StreamableResourceSourceImpl method getStreamableResource.

public StreamableResource getStreamableResource(Resource baseResource, StreamableResourceProcessing processing, ResourceDependencies dependencies) throws IOException {
    assert baseResource != null;
    if (!baseResource.exists()) {
        throw new IOException(String.format("Resource %s does not exist.", baseResource));
    }
    String fileSuffix = TapestryInternalUtils.toFileSuffix(baseResource.getFile());
    // Optionally, transform the resource. The main driver for this is to allow
    // for libraries like LessJS (http://lesscss.org/) or
    // http://jashkenas.github.com/coffee-script/
    ResourceTransformer rt = configuration.get(fileSuffix);
    InputStream transformed = rt == null ? baseResource.openStream() : rt.transform(baseResource, dependencies);
    assert transformed != null;
    BytestreamCache bytestreamCache = readStream(transformed);
    transformed.close();
    ContentType contentType = rt == null ? new ContentType(contentTypeAnalyzer.getContentType(baseResource)) : rt.getTransformedContentType();
    boolean compressable = compressionAnalyzer.isCompressable(contentType.getMimeType());
    long lastModified = resourceChangeTracker.trackResource(baseResource);
    return new StreamableResourceImpl(baseResource.toString(), contentType, compressable ? CompressionStatus.COMPRESSABLE : CompressionStatus.NOT_COMPRESSABLE, lastModified, bytestreamCache, checksumGenerator, null);
}
Also used : ContentType(org.apache.tapestry5.http.ContentType) InputStream(java.io.InputStream) IOException(java.io.IOException)

Example 4 with StreamableResource

use of org.apache.tapestry5.services.assets.StreamableResource in project tapestry-5 by apache.

the class AbstractMinimizer method minimize.

@Override
public StreamableResource minimize(final StreamableResource input) throws IOException {
    if (!isEnabled(input)) {
        return input;
    }
    long startNanos = System.nanoTime();
    final ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
    tracker.perform("Minimizing " + input, new IOOperation<Void>() {

        @Override
        public Void perform() throws IOException {
            InputStream in = doMinimize(input);
            TapestryInternalUtils.copy(in, bos);
            in.close();
            return null;
        }
    });
    // The content is minimized, but can still be (GZip) compressed.
    StreamableResource output = new StreamableResourceImpl("minimized " + input.getDescription(), input.getContentType(), CompressionStatus.COMPRESSABLE, input.getLastModified(), new BytestreamCache(bos), checksumGenerator, input.getResponseCustomizer());
    if (logger.isInfoEnabled()) {
        long elapsedNanos = System.nanoTime() - startNanos;
        int inputSize = input.getSize();
        int outputSize = output.getSize();
        double elapsedMillis = ((double) elapsedNanos) * NANOS_TO_MILLIS;
        // e.g., reducing 100 bytes to 25 would be a (100-25)/100 reduction, or 75%
        double reduction = 100d * ((double) (inputSize - outputSize)) / ((double) inputSize);
        logger.info(String.format("Minimized %s (%,d input bytes of %s to %,d output bytes in %.2f ms, %.2f%% reduction)", input.getDescription(), inputSize, resourceType, outputSize, elapsedMillis, reduction));
    }
    return output;
}
Also used : StreamableResource(org.apache.tapestry5.services.assets.StreamableResource) BytestreamCache(org.apache.tapestry5.internal.services.assets.BytestreamCache) InputStream(java.io.InputStream) StreamableResourceImpl(org.apache.tapestry5.internal.services.assets.StreamableResourceImpl) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException)

Example 5 with StreamableResource

use of org.apache.tapestry5.services.assets.StreamableResource in project tapestry-5 by apache.

the class JavaScriptStackPathConstructorImpl method combinedStackURL.

private List<String> combinedStackURL(String stackName, JavaScriptStack stack) {
    try {
        StreamableResource assembled = assembler.assembleJavaScriptResourceForStack(stackName, compressionAnalyzer.isGZipSupported(), stack.getJavaScriptAggregationStrategy());
        String path = threadLocale.getLocale().toString() + '/' + stackName + ".js";
        String stackURL = assetPathConstructor.constructAssetPath(RequestConstants.STACK_FOLDER, path, assembled);
        return CollectionFactory.newList(stackURL);
    } catch (IOException ex) {
        throw new RuntimeException(String.format("Unable to construct path for '%s' JavaScript stack: %s", stackName, ExceptionUtils.toMessage(ex)), ex);
    }
}
Also used : StreamableResource(org.apache.tapestry5.services.assets.StreamableResource) IOException(java.io.IOException)

Aggregations

StreamableResource (org.apache.tapestry5.services.assets.StreamableResource)6 IOException (java.io.IOException)5 InputStream (java.io.InputStream)2 Asset (org.apache.tapestry5.Asset)2 ContentType (org.apache.tapestry5.http.ContentType)2 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 OutputStream (java.io.OutputStream)1 Matcher (java.util.regex.Matcher)1 Resource (org.apache.tapestry5.commons.Resource)1 BytestreamCache (org.apache.tapestry5.internal.services.assets.BytestreamCache)1 StreamableResourceImpl (org.apache.tapestry5.internal.services.assets.StreamableResourceImpl)1 JavaScriptStack (org.apache.tapestry5.services.javascript.JavaScriptStack)1