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.ui; 020 021import org.apache.wiki.util.TextUtil; 022 023 024/** 025 * Abstract, immutable Command implementation class. All of the fields in this 026 * class are <code>final</code>. This class is thread-safe. 027 * @since 2.4.22 028 */ 029public abstract class AbstractCommand implements Command 030{ 031 private static final Command[] ALL_COMMANDS = new Command[] { 032 PageCommand.ATTACH, 033 PageCommand.COMMENT, 034 PageCommand.CONFLICT, 035 PageCommand.DELETE, 036 PageCommand.DIFF, 037 PageCommand.EDIT, 038 PageCommand.INFO, 039 PageCommand.NONE, 040 PageCommand.OTHER, 041 PageCommand.PREVIEW, 042 PageCommand.RENAME, 043 PageCommand.RSS, 044 PageCommand.UPLOAD, 045 PageCommand.VIEW, 046 GroupCommand.DELETE_GROUP, 047 GroupCommand.EDIT_GROUP, 048 GroupCommand.VIEW_GROUP, 049 WikiCommand.CREATE_GROUP, 050 WikiCommand.ERROR, 051 WikiCommand.FIND, 052 WikiCommand.INSTALL, 053 WikiCommand.LOGIN, 054 WikiCommand.LOGOUT, 055 WikiCommand.MESSAGE, 056 WikiCommand.PREFS, 057 WikiCommand.WORKFLOW, 058 WikiCommand.ADMIN, 059 RedirectCommand.REDIRECT 060 }; 061 062 private static final String HTTPS = "HTTPS://"; 063 064 private static final String HTTP = "HTTP://"; 065 066 private final String m_jsp; 067 068 private final String m_jspFriendlyName; 069 070 private final String m_urlPattern; 071 072 private final String m_requestContext; 073 074 private final String m_contentTemplate; 075 076 private final Object m_target; 077 078 /** 079 * Constructs a new Command with a specified wiki context, URL pattern, 080 * content template and target. The URL pattern is used to derive 081 * the JSP; if it is a "local" JSP (that is, it does not contain 082 * the <code>http://</code> or <code>https://</code> prefixes), 083 * then the JSP will be a cleansed version of the URL pattern; 084 * symbols (such as <code>%u</code>) will removed. If it the supplied 085 * URL pattern points to a non-local destination, the JSP will be set 086 * to the value supplied, unmodified. 087 * @param requestContext the request context 088 * @param urlPattern the URL pattern 089 * @param contentTemplate the content template; may be <code>null</code> 090 * @param target the target of the command, such as a WikiPage; may be 091 * <code>null</code> 092 * @throws IllegalArgumentException if the request content or URL pattern is 093 * <code>null</code> 094 */ 095 protected AbstractCommand( String requestContext, String urlPattern, String contentTemplate, Object target ) 096 { 097 if ( requestContext == null || urlPattern == null ) 098 { 099 throw new IllegalArgumentException( "Request context, URL pattern and type must not be null." ); 100 } 101 102 m_requestContext = requestContext; 103 104 if ( urlPattern.toUpperCase().startsWith( HTTP ) || 105 urlPattern.toUpperCase().endsWith( HTTPS ) ) 106 { 107 // For an HTTP/HTTPS url, pass it through without modification 108 m_jsp = urlPattern; 109 m_jspFriendlyName = "Special Page"; 110 } 111 else 112 { 113 // For local JSPs, take everything to the left of ?, then 114 // delete all variable substitutions 115 String jsp = urlPattern; 116 int qPosition = urlPattern.indexOf( '?' ); 117 if ( qPosition != -1 ) 118 { 119 jsp = jsp.substring( 0, qPosition ); 120 } 121 m_jsp = removeSubstitutions(jsp); 122 123 // Calculate the "friendly name" for the JSP 124 if ( m_jsp.toUpperCase().endsWith( ".JSP" ) ) 125 { 126 m_jspFriendlyName = TextUtil.beautifyString( m_jsp.substring( 0, m_jsp.length() - 4 ) ); 127 } 128 else 129 { 130 m_jspFriendlyName = m_jsp; 131 } 132 } 133 134 m_urlPattern = urlPattern; 135 136 m_contentTemplate = contentTemplate; 137 138 m_target = target; 139 } 140 141 // 142 // This is just *so* much faster than doing String.replaceAll(). It would, in fact, 143 // be worth to cache this value. 144 // 145 private String removeSubstitutions(String jsp) 146 { 147 //return jsp.replaceAll( "\u0025[a-z|A-Z]", "" ); 148 StringBuilder newjsp = new StringBuilder( jsp.length() ); 149 for( int i = 0; i < jsp.length(); i++ ) 150 { 151 char c = jsp.charAt(i); 152 if( c == '%' && i < jsp.length()-1 && Character.isLetterOrDigit( jsp.charAt(i+1) ) ) 153 { 154 i++; 155 continue; 156 } 157 newjsp.append( c ); 158 } 159 return newjsp.toString(); 160 } 161 162 /** 163 * Returns a defensively-created array of all 164 * static Commands. 165 * @return the array of commands 166 */ 167 public static final Command[] allCommands() 168 { 169 return ALL_COMMANDS.clone(); 170 } 171 172 /** 173 * @see org.apache.wiki.ui.Command#targetedCommand(Object) 174 */ 175 public abstract Command targetedCommand( Object target ); 176 177 /** 178 * @see org.apache.wiki.ui.Command#getContentTemplate() 179 */ 180 public final String getContentTemplate() 181 { 182 return m_contentTemplate; 183 } 184 185 /** 186 * @see org.apache.wiki.ui.Command#getJSP() 187 */ 188 public final String getJSP() 189 { 190 return m_jsp; 191 } 192 193 /** 194 * @see org.apache.wiki.ui.Command#getName() 195 */ 196 public abstract String getName(); 197 198 /** 199 * @see org.apache.wiki.ui.Command#getRequestContext() 200 */ 201 public final String getRequestContext() 202 { 203 return m_requestContext; 204 } 205 206 /** 207 * @see org.apache.wiki.ui.Command#getTarget() 208 */ 209 public final Object getTarget() 210 { 211 return m_target; 212 } 213 214 /** 215 * @see org.apache.wiki.ui.Command#getURLPattern() 216 */ 217 public final String getURLPattern() 218 { 219 return m_urlPattern; 220 } 221 222 /** 223 * Returns the "friendly name" for this command's JSP, namely 224 * a beatified version of the JSP's name without the .jsp suffix. 225 * @return the friendly name 226 */ 227 protected final String getJSPFriendlyName() 228 { 229 return m_jspFriendlyName; 230 } 231 232 /** 233 * Returns a String representation of the Command. 234 * @see java.lang.Object#toString() 235 */ 236 public final String toString() 237 { 238 return "Command" + 239 "[context=" + m_requestContext + "," + 240 "urlPattern=" + m_urlPattern + "," + 241 "jsp=" + m_jsp + 242 ( m_target == null ? "" : ",target=" + m_target + m_target.toString() ) + 243 "]"; 244 } 245 246}