Patches are best provided on JIRA; there's a checkbox that shows you
have granted the rights to the patch & code to the Apache Software
Foundation.  Thanks!

On Tue, Feb 21, 2012 at 12:28 PM, Paul Stanton <p...@mapshed.com.au> wrote:
> Here's my implementation:
>
> // Copyright 2006, 2008, 2009, 2010, 2011 The Apache Software Foundation
> //
> // Licensed under the Apache License, Version 2.0 (the "License");
> // you may not use this file except in compliance with the License.
> // You may obtain a copy of the License at
> //
> // http://www.apache.org/licenses/LICENSE-2.0
> //
> // Unless required by applicable law or agreed to in writing, software
> // distributed under the License is distributed on an "AS IS" BASIS,
> // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> // See the License for the specific language governing permissions and
> // limitations under the License.
>
> package org.apache.tapestry5.internal.services;
>
> import java.io.IOException;
> import java.util.Collections;
> import java.util.Comparator;
> import java.util.List;
> import java.util.Map;
>
> import javax.servlet.http.HttpServletResponse;
>
> import org.apache.tapestry5.SymbolConstants;
> import org.apache.tapestry5.ioc.annotations.Symbol;
> import org.apache.tapestry5.ioc.annotations.UsesMappedConfiguration;
> import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
> import org.apache.tapestry5.services.ClasspathAssetAliasManager;
> import org.apache.tapestry5.services.Dispatcher;
> import org.apache.tapestry5.services.Request;
> import org.apache.tapestry5.services.Response;
> import org.apache.tapestry5.services.assets.AssetRequestHandler;
>
> /**
>  * Recognizes requests where the path begins with "/asset/" and delivers the
> content therein as a bytestream. Also
>  * handles requests that are simply polling for a change to the file.
>  *
>  * @see ResourceStreamer
>  * @see ClasspathAssetAliasManager
>  * @see AssetRequestHandler
>  */
> // PATCHED incorrect APPLICATION_VERSION 302 temporary redirect to current
> APPLICATION_VERSION
>
> // PATCH +
> @SuppressWarnings("all")
> @UsesMappedConfiguration(AssetRequestHandler.class)
> public class AssetDispatcher implements Dispatcher
> {
>    /**
>     * Keyed on extended path name, which includes the pathPrefix first and a
> trailing slash.
>     */
>    private final Map<String, AssetRequestHandler> pathToHandler =
> CollectionFactory.newMap();
>
>    /**
>     * List of path prefixes in the pathToHandler, sorted be descending
> length.
>     */
>    private final List<String> assetPaths = CollectionFactory.newList();
>
>    private final String pathPrefix;
>
>    // PATCH +
>    private final String pathPrefixPattern;
>
>    public AssetDispatcher(Map<String, AssetRequestHandler> configuration,
>
>    @Symbol(SymbolConstants.APPLICATION_VERSION) String applicationVersion,
>
>    @Symbol(SymbolConstants.APPLICATION_FOLDER) String applicationFolder,
>
>    @Symbol(SymbolConstants.ASSET_PATH_PREFIX) String assetPathPrefix)
>    {
>        String folder = applicationFolder.equals("") ? "" : "/" +
> applicationFolder;
>
>        this.pathPrefix = folder + assetPathPrefix + applicationVersion +
> "/";
>
>        // PATCH +
>        this.pathPrefixPattern = "^" + folder + assetPathPrefix +
> "[^/]{1,}/(.*)$";
>
>        for (String path : configuration.keySet())
>        {
>            String extendedPath = this.pathPrefix + path + "/";
>
>            pathToHandler.put(extendedPath, configuration.get(path));
>
>            assetPaths.add(extendedPath);
>        }
>
>        // Sort by descending length
>
>        Collections.sort(assetPaths, new Comparator<String>()
>        {
>            public int compare(String o1, String o2)
>            {
>                return o2.length() - o1.length();
>            }
>        });
>    }
>
>    public boolean dispatch(Request request, Response response) throws
> IOException
>    {
>        String path = request.getPath();
>
>        // Remember that the request path does not include the context path,
> so we can simply start
>        // looking for the asset path prefix right off the bat.
>
>        if (!path.startsWith(pathPrefix))
>        {
>            // PATCH +
>            if (path.matches(pathPrefixPattern))
>            {
>                // send 302 temporary redirect to the version this server is
> using
>                String newPath = request.getContextPath() +
> path.replaceAll(pathPrefixPattern, pathPrefix + "$1");
>                response.setHeader("Location", newPath);
>                response.sendError(HttpServletResponse.SC_MOVED_TEMPORARILY,
> newPath);
>                return true;
>            }
>            return false;
>        }
>
>        for (String extendedPath : assetPaths)
>        {
>
>            if (path.startsWith(extendedPath))
>            {
>                AssetRequestHandler handler =
> pathToHandler.get(extendedPath);
>
>                String extraPath = path.substring(extendedPath.length());
>
>                boolean handled = handler.handleAssetRequest(request,
> response, extraPath);
>
>                if (handled)
>                {
>                    return true;
>                }
>            }
>        }
>
>        response.sendError(HttpServletResponse.SC_NOT_FOUND, path);
>
>        return true;
>
>    }
> }
>
>
> On 22/02/2012 6:05 AM, Howard Lewis Ship wrote:
>>
>> I suspect the 302 redirect may be the correct solution, and Tapestry
>> could support this pretty reasonably.
>>
>> The perfect solution would involve the following:
>> - The version number if replaced with the SHA1 hash of the resource's
>> (uncompressed) content
>> - All CSS is dynamically rewritten to convert relative references into
>> full paths including the correct SHA1 hash
>>
>> I wonder if the 302 redirect could act as a way to avoid rewriting the
>> CSS?
>>
>> On Sun, Feb 19, 2012 at 7:57 PM, Paul Stanton<p...@mapshed.com.au>  wrote:
>>>
>>> Hi Cezary,
>>>
>>> I think I have the same need as you.
>>>
>>> We use load balanced servers, and when upgrading we upgrade one at a time
>>> so
>>> that there is always a server running.
>>>
>>> But the side effect is that the upgraded server can receive requests for
>>> the
>>> old assets, and we don't want to fail in this case.
>>>
>>> In the past (5.1) I monkey-patched AssetResourceLocatorImpl to allow<=
>>> version number requests.
>>>
>>> However in migrating to 5.3 I would like a better solution, and the
>>> implementation is different now anyway.
>>>
>>> I like the idea of the 302 redirect.
>>>
>>> How did you end up solving this? Is it possible to just contribute your
>>> own
>>> AssetDispatcher instead of just replacing the class?
>>>
>>> Thanks, Paul.
>>>
>>>
>>> On 24/03/2011 10:09 AM, Cezary Biernacki wrote:
>>>>>
>>>>>
>>>>> Perhaps the AssetDispatcher could check the requested version number
>>>>> and
>>>>> if
>>>>> it doesn't match the app version, send a 302 redirect to the "correct"
>>>>> URL?
>>>>> /assets/1.3/ctx/script.js -->    /assets/1.2/ctx/script.js
>>>>>
>>>>> Or perhaps it should only deliver the asset if the requested version os
>>>>> older than or equal to the app version?
>>>>> Determining "older" and "newer" would however assume people name their
>>>>> application versions in a certain way.
>>>>
>>>>
>>>> It is exactly what I did in my application. I have overridden
>>>> AssetsDispatcher service with my copy based on original one, that
>>>> differs
>>>> only in handling missing resources: if resource actually exists but just
>>>> version numbers differ, my dispatcher just sends redirect response with
>>>> a
>>>> correct path.
>>>>
>>>> As a side note, I observed in that - at least in my case - typically a
>>>> favicon was a typical asset requested with wrong  version number,
>>>> probably
>>>> from bookmarks.
>>>>
>>>> Regards,
>>>> Cezary
>>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
>>> For additional commands, e-mail: users-h...@tapestry.apache.org
>>>
>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
> For additional commands, e-mail: users-h...@tapestry.apache.org
>



-- 
Howard M. Lewis Ship

Creator of Apache Tapestry

The source for Tapestry training, mentoring and support. Contact me to
learn how I can get you up and productive in Tapestry fast!

(971) 678-5210
http://howardlewisship.com

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
For additional commands, e-mail: users-h...@tapestry.apache.org

Reply via email to