001/* 002 Licensed to the Apache Software Foundation (ASF) under one 003 or more contributor license agreements. See the NOTICE file 004 distributed with this work for additional information 005 regarding copyright ownership. The ASF licenses this file 006 to you under the Apache License, Version 2.0 (the 007 "License"); you may not use this file except in compliance 008 with the License. You may obtain a copy of the License at 009 010 http://www.apache.org/licenses/LICENSE-2.0 011 012 Unless required by applicable law or agreed to in writing, 013 software distributed under the License is distributed on an 014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 KIND, either express or implied. See the License for the 016 specific language governing permissions and limitations 017 under the License. 018 */ 019package org.apache.wiki.url; 020 021import org.apache.commons.lang3.StringUtils; 022import org.apache.wiki.WikiContext; 023import org.apache.wiki.WikiEngine; 024import org.apache.wiki.ui.Command; 025import org.apache.wiki.ui.CommandResolver; 026import org.apache.wiki.util.TextUtil; 027 028import javax.servlet.http.HttpServletRequest; 029import java.nio.charset.Charset; 030import java.util.Properties; 031 032/** 033 * Implements the default URL constructor using links directly to the 034 * JSP pages. This is what JSPWiki by default is using. For example, 035 * WikiContext.VIEW points at "Wiki.jsp", etc. 036 * 037 * @since 2.2 038 */ 039public class DefaultURLConstructor implements URLConstructor { 040 041 protected WikiEngine m_engine; 042 043 /** 044 * Contains the absolute path of the JSPWiki Web application without the 045 * actual servlet (which is the m_urlPrefix). 046 */ 047 protected String m_pathPrefix = ""; 048 049 /** 050 * 051 * {@inheritDoc} 052 */ 053 public void initialize( final WikiEngine engine, final Properties properties ) { 054 m_engine = engine; 055 m_pathPrefix = engine.getBaseURL() + "/"; 056 } 057 058 /** 059 * Does replacement of some particular variables. The variables are: 060 * 061 * <ul> 062 * <li> "%u" - inserts either the base URL (when absolute is required), or the base path 063 * (which is an absolute path without the host name). 064 * <li> "%U" - always inserts the base URL 065 * <li> "%p" - always inserts the base path 066 * <li> "%n" - inserts the page name 067 * </ul> 068 * 069 * @param baseptrn The pattern to use 070 * @param name The page name 071 * @param absolute If true, %u is always the entire base URL, otherwise it depends on 072 * the setting in jspwiki.properties. 073 * @return A replacement. 074 */ 075 protected final String doReplacement( String baseptrn, final String name, final boolean absolute ) { 076 String baseurl = m_pathPrefix; 077 078 if( absolute ) { 079 baseurl = m_engine.getBaseURL() + "/"; 080 } 081 082 baseptrn = TextUtil.replaceString( baseptrn, "%u", baseurl ); 083 baseptrn = TextUtil.replaceString( baseptrn, "%U", m_engine.getBaseURL() ); 084 baseptrn = TextUtil.replaceString( baseptrn, "%n", encodeURI(name) ); 085 baseptrn = TextUtil.replaceString( baseptrn, "%p", m_pathPrefix ); 086 087 return baseptrn; 088 } 089 090 /** 091 * URLEncoder returns pluses, when we want to have the percent 092 * encoding. See http://issues.apache.org/bugzilla/show_bug.cgi?id=39278 093 * for more info. 094 * 095 * We also convert any %2F's back to slashes to make nicer-looking URLs. 096 */ 097 private String encodeURI( String uri ) { 098 uri = m_engine.encodeName(uri); 099 uri = StringUtils.replace( uri, "+", "%20" ); 100 uri = StringUtils.replace( uri, "%2F", "/" ); 101 102 return uri; 103 } 104 105 /** 106 * Returns the URL pattern for a supplied wiki request context. 107 * @param context the wiki context 108 * @param name the wiki page 109 * @return A pattern for replacement. 110 * @throws IllegalArgumentException if the context cannot be found 111 */ 112 public static String getURLPattern( final String context, final String name ) throws IllegalArgumentException { 113 if( context.equals(WikiContext.VIEW) && name == null) { 114 // FIXME 115 return "%uWiki.jsp"; 116 } 117 118 // Find the action matching our pattern (could throw exception) 119 final Command command = CommandResolver.findCommand( context ); 120 121 return command.getURLPattern(); 122 } 123 124 /** 125 * Constructs the actual URL based on the context. 126 */ 127 private String makeURL( final String context, final String name, final boolean absolute ) { 128 return doReplacement( getURLPattern(context,name), name, absolute ); 129 } 130 131 /** 132 * Constructs the URL with a bunch of parameters. 133 * @param parameters If null or empty, no parameters are added. 134 * 135 * {@inheritDoc} 136 */ 137 public String makeURL( final String context, final String name, final boolean absolute, String parameters ) { 138 if( parameters != null && parameters.length() > 0 ) { 139 if( context.equals(WikiContext.ATTACH) ) { 140 parameters = "?"+parameters; 141 } else if( context.equals(WikiContext.NONE) ) { 142 parameters = (name.indexOf('?') != -1 ) ? "&" : "?" + parameters; 143 } else { 144 parameters = "&"+parameters; 145 } 146 } else { 147 parameters = ""; 148 } 149 return makeURL( context, name, absolute ) + parameters; 150 } 151 152 /** 153 * Should parse the "page" parameter from the actual 154 * request. 155 * 156 * {@inheritDoc} 157 */ 158 public String parsePage( final String context, final HttpServletRequest request, final Charset encoding ) { 159 String pagereq = request.getParameter( "page" ); 160 if( context.equals(WikiContext.ATTACH) ) { 161 pagereq = parsePageFromURL( request, encoding ); 162 } 163 164 return pagereq; 165 } 166 167 /** 168 * Takes the name of the page from the request URI. 169 * The initial slash is also removed. If there is no page, 170 * returns null. 171 * 172 * @param request The request to parse 173 * @param encoding The encoding to use 174 * 175 * @return a parsed page name, or null, if it cannot be found 176 */ 177 public static String parsePageFromURL( final HttpServletRequest request, final Charset encoding ) { 178 final String name = request.getPathInfo(); 179 if( name == null || name.length() <= 1 ) { 180 return null; 181 } else if( name.charAt(0) == '/' ) { 182 return name.substring(1); 183 } 184 185 // 186 // This is required, because by default all URLs are handled as Latin1, even if they are really UTF-8. 187 // 188 // name = TextUtil.urlDecode( name, encoding ); 189 190 return name; 191 } 192 193 194 /** 195 * This method is not needed for the DefaultURLConstructor. 196 * 197 * @param request The HTTP Request that was used to end up in this page. 198 * @return "Wiki.jsp", "PageInfo.jsp", etc. Just return the name, JSPWiki will figure out the page. 199 */ 200 public String getForwardPage( final HttpServletRequest request ) { 201 return "Wiki.jsp"; 202 } 203 204}