001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.request.mapper;
018
019import java.util.function.Supplier;
020
021import org.apache.wicket.request.IRequestHandler;
022import org.apache.wicket.request.IRequestMapper;
023import org.apache.wicket.request.Request;
024import org.apache.wicket.request.Url;
025import org.apache.wicket.util.NullProvider;
026import org.apache.wicket.util.lang.Args;
027
028/**
029 * Mapper that rewrites parent path segments ({@code ../}) with the specified string and viceversa.
030 * 
031 * @author igor.vaynberg
032 */
033public class ParentPathReferenceRewriter implements IRequestMapperDelegate
034{
035        private final Supplier<String> escapeSequence;
036        private final IRequestMapper chain;
037
038        /**
039         * Construct.
040         * 
041         * @param chain
042         *            chained request mapper
043         * 
044         * @param escapeSequence
045         */
046        public ParentPathReferenceRewriter(final IRequestMapper chain,
047                final Supplier<String> escapeSequence)
048        {
049                Args.notNull(chain, "chain");
050                Args.notNull(escapeSequence, "relativePathPartEscapeSequence");
051                this.escapeSequence = escapeSequence;
052                this.chain = chain;
053        }
054
055        /**
056         * Construct.
057         * 
058         * @param chain
059         *            chained request mapper
060         */
061        public ParentPathReferenceRewriter(final IRequestMapper chain)
062        {
063                this(chain, new NullProvider<String>());
064        }
065
066        /**
067         * @see org.apache.wicket.request.IRequestMapper#mapRequest(org.apache.wicket.request.Request)
068         */
069        @Override
070        public IRequestHandler mapRequest(final Request request)
071        {
072                Url url = request.getUrl();
073
074                if (escapeSequence.get() != null)
075                {
076                        for (int i = 0; i < url.getSegments().size(); i++)
077                        {
078                                if (url.getSegments().get(i).equals(escapeSequence.get()))
079                                {
080                                        url.getSegments().set(i, "..");
081                                }
082                        }
083                }
084
085                return chain.mapRequest(request.cloneWithUrl(url));
086        }
087
088        /** {@inheritDoc} */
089        @Override
090        public Url mapHandler(final IRequestHandler requestHandler)
091        {
092                Url url = chain.mapHandler(requestHandler);
093                if ((url != null) && (escapeSequence.get() != null))
094                {
095                        for (int i = 0; i < url.getSegments().size(); i++)
096                        {
097                                if ("..".equals(url.getSegments().get(i)))
098                                {
099                                        url.getSegments().set(i, escapeSequence.get());
100                                }
101                        }
102                }
103                return url;
104        }
105
106        /** {@inheritDoc} */
107        @Override
108        public int getCompatibilityScore(final Request request)
109        {
110                return chain.getCompatibilityScore(request);
111        }
112
113        /** {@inheritDoc} */
114        @Override
115        public IRequestMapper getDelegateMapper()
116        {
117                return chain;
118        }
119}