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 */
019 package org.apache.wiki.ui;
020
021 import 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 */
029 public 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 StringBuffer newjsp = new StringBuffer( 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 }