/*
   * 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.sling.servlets.get.impl;
 
 
 
The RedirectServlet implements support for GET requests to resources of type sling:redirect. This servlet tries to get the redirect target by
  • first adapting the resource to a org.apache.sling.api.resource.ValueMap and trying to get the property sling:target.
  • The second attempt is to access the resource sling:target below the requested resource and attapt this to a string.
  • If there is no value found for sling:target a 404 (NOT FOUND) status is sent by this servlet. Otherwise a 302 (FOUND, temporary redirect) status is sent where the target is the relative URL from the current resource to the target resource. Selectors, extension, suffix and query string are also appended to the redirect URL.

    Scr.component:
    immediate="true" metatype="no"
    Scr.service:
    interface="javax.servlet.Servlet"
    Scr.property:
    name="service.description" value="Request Redirect Servlet"
    Scr.property:
    name="service.vendor" value="The Apache Software Foundation"
    Scr.property:
    name="sling.servlet.resourceTypes" value="sling:redirect"
    Scr.property:
    name="sling.servlet.methods" value="GET"
    Scr.property:
    name="sling.servlet.prefix" value="-1" type="Integer" private="true"
 
 public class RedirectServlet extends SlingSafeMethodsServlet {

    
The name of the target property
 
     public static final String TARGET_PROP = "sling:target";
 
     private Servlet jsonRendererServlet;
 
     @Override
     protected void doGet(SlingHttpServletRequest request,
             SlingHttpServletResponse responsethrows ServletException,
             IOException {
 
         // handle json export of the redirect node
         if (JsonRendererServlet.EXT_JSON.equals(request.getRequestPathInfo().getExtension())) {
             getJsonRendererServlet().service(requestresponse);
             return;
         }
 
         String targetPath = null;
 
         // convert resource to a value map
         final Resource rsrc = request.getResource();
         final ValueMap valueMap = rsrc.adaptTo(ValueMap.class);
         if ( valueMap != null ) {
             targetPath = valueMap.get(TARGET_PROPString.class);
         }
         if ( targetPath == null ) {
             // old behaviour
             final Resource targetResource = request.getResourceResolver().getResource(
                     rsrcTARGET_PROP);
             if (targetResource == null) {
                 response.sendError(HttpServletResponse.SC_NOT_FOUND,
                     "Missing target for redirection");
                 return;
             }
 
             // if the target resource is a path (string), redirect there
             targetPath = targetResource.adaptTo(String.class);
        }
        // if we got a target path, make it external and redirect to it
        if (targetPath != null) {
            // make path relative and append selectors, extension etc.
            targetPath = toRedirectPath(targetPathrequest);
            // and redirect there ...
            response.sendRedirect(targetPath);
            return;
        }
        // no way of finding the target, just fail
        response.sendError(HttpServletResponse.SC_NOT_FOUND,
            "Cannot redirect to target resource " + targetPath);
    }

    
Create a relative redirect URL for the targetPath relative to the given request. The URL is relative to the request's resource and will include the selectors, extension, suffix and query string of the request.
    protected static String toRedirectPath(String targetPath,
            SlingHttpServletRequest request) {
        // first check for an absolute path
        final int protocolIndex = targetPath.indexOf(":/");
        final int queryIndex = targetPath.indexOf('?');
        if (  protocolIndex > -1 && (queryIndex == -1 || queryIndex > protocolIndex) ) {
            return targetPath;
        }
        String postFix;
        RequestPathInfo rpi = request.getRequestPathInfo();
        if (rpi.getExtension() != null) {
            StringBuffer postfixBuf = new StringBuffer();
            if (rpi.getSelectorString() != null) {
                postfixBuf.append('.').append(rpi.getSelectorString());
            }
            postfixBuf.append('.').append(rpi.getExtension());
            if (rpi.getSuffix() != null) {
                postfixBuf.append(rpi.getSuffix());
            }
            postFix = postfixBuf.toString();
        } else {
            postFix = null;
        }
        String basePath = request.getResource().getPath();
        // make sure the target path is absolute
        if (!targetPath.startsWith("/")) {
            if (!basePath.endsWith("/")) {
                targetPath = "/".concat(targetPath);
            }
            targetPath = basePath.concat(targetPath);
        }
        // append optional selectors etc.to the base path
        if (postFix != null) {
            basePath = basePath.concat(postFix);
        }
        StringBuffer pathBuf = new StringBuffer();
        makeRelative(pathBufbasePathtargetPath);
        if (postFix != null) {
            pathBuf.append(postFix);
        }
        if (request.getQueryString() != null) {
            pathBuf.append('?').append(request.getQueryString());
        }
        return pathBuf.toString();
    }

    
Converts the absolute path target into a path relative to base and stores this relative path into pathBuffer.
    private static void makeRelative(StringBuffer pathBufferString base,
            String target) {
        // pseudo entry to correctly calculate the relative path
        if (base.endsWith("/")) {
            base = base.concat(String.valueOf(Character.MAX_VALUE));
        }
        String[] bParts = base.substring(1).split("/");
        String[] tParts = target.substring(1).split("/");
        // find first non-matching part
        int off;
        for (off = 0; off < (bParts.length - 1) && off < tParts.length
            && bParts[off].equals(tParts[off]); off++);
        for (int i = bParts.length - offi > 1; i--) {
            pathBuffer.append("../");
        }
        for (int i = offi < tParts.lengthi++) {
            if (i > off) {
                pathBuffer.append('/');
            }
            pathBuffer.append(tParts[i]);
        }
    }
    private Servlet getJsonRendererServlet() {
        if (jsonRendererServlet == null) {
            Servlet jrs = new JsonRendererServlet();
            try {
                jrs.init(getServletConfig());
            } catch (Exception e) {
                // don't care too much here
            }
            jsonRendererServlet = jrs;
        }
        return jsonRendererServlet;
    }
New to GrepCode? Check out our FAQ X