Package org.apache.wicket.request.mapper

Source Code of org.apache.wicket.request.mapper.BasicResourceReferenceMapper

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.wicket.request.mapper;

import org.apache.wicket.request.IRequestHandler;
import org.apache.wicket.request.Request;
import org.apache.wicket.request.Url;
import org.apache.wicket.request.handler.resource.ResourceReferenceRequestHandler;
import org.apache.wicket.request.mapper.parameter.IPageParametersEncoder;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.request.resource.ResourceReference;
import org.apache.wicket.util.IProvider;
import org.apache.wicket.util.lang.WicketObjects;
import org.apache.wicket.util.time.Time;

import java.util.List;
import java.util.StringTokenizer;

/**
* Generic {@link ResourceReference} encoder that encodes and decodes non-mounted
* {@link ResourceReference}s.
* <p>
* Decodes and encodes the following URLs:
*
* <pre>
*    /wicket/resource/org.apache.wicket.ResourceScope/name
*    /wicket/resource/org.apache.wicket.ResourceScope/name?en
*    /wicket/resource/org.apache.wicket.ResourceScope/name?-style
*    /wicket/resource/org.apache.wicket.ResourceScope/resource/name.xyz?en_EN-style
* </pre>
*
* @author Matej Knopp
* @author igor.vaynberg
*/
class BasicResourceReferenceMapper extends AbstractResourceReferenceMapper
{
  private static final String TIMESTAMP_PREFIX = "-ts";
  private final IPageParametersEncoder pageParametersEncoder;

  // if true, timestamps should be added to resource names
  private final IProvider<Boolean> timestamps;

  /**
   * Construct.
   *
   * @param pageParametersEncoder
   * @param relativePathPartEscapeSequence
   */
  public BasicResourceReferenceMapper(IPageParametersEncoder pageParametersEncoder, IProvider<Boolean> timestamps)
  {
    this.pageParametersEncoder = pageParametersEncoder;
    this.timestamps = timestamps;
  }

  /**
   * @see org.apache.wicket.request.IRequestMapper#mapRequest(org.apache.wicket.request.Request)
   */
  public IRequestHandler mapRequest(Request request)
  {
    Url url = request.getUrl();

    if (url.getSegments().size() >= 4 &&
        urlStartsWith(url, getContext().getNamespace(), getContext().getResourceIdentifier()))
    {
      String className = url.getSegments().get(2);
      StringBuilder name = new StringBuilder();
      int segmentsSize = url.getSegments().size();
      for (int i = 3; i < segmentsSize; ++i)
      {
        String segment = url.getSegments().get(i);

        // if timestamps are enabled the last segment (=resource name)
        // should be stripped of timestamps
        if (isTimestampsEnabled() && i + 1 == segmentsSize)
        {
          // The last segment eventually contains a timestamp which we have to remove
          // resource lookup will not care about timestamp but always deliver the
          // most current version of the resource. After all this whole timestamp
          // thing is about caching on proxies and browsers but does not affect wicket.
          segment = stripTimestampFromResourceName(segment);
        }
        if (name.length() > 0)
        {
          name.append("/");
        }
        name.append(segment);
      }

      ResourceReference.UrlAttributes attributes = getResourceReferenceAttributes(url);

      // extract the PageParameters from URL if there are any
      PageParameters pageParameters = extractPageParameters(request,
        url.getSegments().size(), pageParametersEncoder);

      Class<?> scope = resolveClass(className);
      if (scope != null)
      {
        ResourceReference res = getContext().getResourceReferenceRegistry()
          .getResourceReference(scope, name.toString(), attributes.getLocale(),
            attributes.getStyle(), attributes.getVariation(), true, true);

        if (res != null)
        {
          return new ResourceReferenceRequestHandler(res, pageParameters);
        }
      }
    }
    return null;
  }

  private boolean isTimestampsEnabled()
  {
    return timestamps.get();
  }

  /**
   * strip timestamp information from resource name
   *
   * @param resourceName
   * @return
   */

  private String stripTimestampFromResourceName(final String resourceName)
  {
    int pos = resourceName.lastIndexOf('.');

    final String fullname = pos == -1 ? resourceName : resourceName.substring(0, pos);
    final String extension = pos == -1 ? null : resourceName.substring(pos);

    pos = fullname.lastIndexOf(TIMESTAMP_PREFIX);

    if (pos != -1)
    {
      final String timestamp = fullname.substring(pos + TIMESTAMP_PREFIX.length());
      final String basename = fullname.substring(0, pos);

      try
      {
        Long.parseLong(timestamp); // just check the timestamp is numeric

        // create filename without timestamp for resource lookup
        return extension == null ? basename : basename + extension;
      }
      catch (NumberFormatException e)
      {
        // some strange case of coincidence where the filename contains the timestamp prefix
        // but the timestamp itself is non-numeric - we interpret this situation as
        // "file has no timestamp"

      }
    }
    return resourceName;
  }

  protected Class<?> resolveClass(String name)
  {
    return WicketObjects.resolveClass(name);
  }

  protected String getClassName(Class<?> scope)
  {
    return scope.getName();
  }

  /**
   * @see org.apache.wicket.request.IRequestMapper#mapHandler(org.apache.org.apache.wicket.request.IRequestHandler)
   */
  public Url mapHandler(IRequestHandler requestHandler)
  {
    if (requestHandler instanceof ResourceReferenceRequestHandler)
    {
      ResourceReferenceRequestHandler referenceRequestHandler = (ResourceReferenceRequestHandler)requestHandler;
      ResourceReference reference = referenceRequestHandler.getResourceReference();

      Url url = new Url();

      List<String> segments = url.getSegments();
      segments.add(getContext().getNamespace());
      segments.add(getContext().getResourceIdentifier());
      segments.add(getClassName(reference.getScope()));

      StringTokenizer tokens = new StringTokenizer(reference.getName(), "/");

      while (tokens.hasMoreTokens())
      {
        String token = tokens.nextToken();

        // on the last component of the resource path add the timestamp
        if (isTimestampsEnabled() && tokens.hasMoreTokens() == false)
        {
          // get last modification of resource
          Time lastModified = reference.getLastModified();

          // if resource provides a timestamp we include it in resource name
          if (lastModified != null)
          {
            // check if resource name has extension
            int extensionAt = token.lastIndexOf('.');

            // create timestamped version of filename:
            //
            //   filename := [basename][timestamp-prefix][last-modified-milliseconds](.extension)
            //
            StringBuilder filename = new StringBuilder();
            filename.append(extensionAt == -1 ? token : token.substring(0, extensionAt));
            filename.append(TIMESTAMP_PREFIX);
            filename.append(lastModified.getMilliseconds());

            if (extensionAt != -1)
              filename.append(token.substring(extensionAt));

            token = filename.toString();
          }
        }
        segments.add(token);
      }

      encodeResourceReferenceAttributes(url, reference);
      PageParameters parameters = referenceRequestHandler.getPageParameters();
      if (parameters != null)
      {
        parameters = new PageParameters(parameters);
        // need to remove indexed parameters otherwise the URL won't be able to decode
        parameters.clearIndexed();
        url = encodePageParameters(url, parameters, pageParametersEncoder);
      }

      return url;
    }
    return null;
  }

  /**
   * @see org.apache.wicket.request.IRequestMapper#getCompatibilityScore(org.apache.wicket.request.Request)
   */
  public int getCompatibilityScore(Request request)
  {
    // always return 0 here so that the mounts have higher priority
    return 0;
  }
}
TOP

Related Classes of org.apache.wicket.request.mapper.BasicResourceReferenceMapper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.