1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.pluto.portalImpl.core;
21
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.Map;
26 import java.util.StringTokenizer;
27
28 import javax.portlet.PortletMode;
29 import javax.portlet.WindowState;
30
31 import org.apache.pluto.om.window.PortletWindow;
32 import org.apache.pluto.portalImpl.aggregation.Fragment;
33 import org.apache.pluto.portalImpl.aggregation.PortletFragment;
34 import org.apache.pluto.util.StringUtils;
35
36 public class PortalControlParameter {
37
38 static public final String ACTION = "ac";
39 static public final String MODE = "md";
40 static public final String PORTLET_ID = "pid";
41 static public final String PREFIX = "_";
42 static public final String PREV_MODE = "pm";
43 static public final String PREV_STATE = "ps";
44 static public final String RENDER_PARAM = "rp";
45 static public final String STATE = "st";
46
47 private Map requestParameter = new HashMap();
48
49 /***
50 * The map containing the encoded statefull control parameters.
51 * They are encoded in the sense, that names and values of
52 * <i>render parameters</i> and render parameters only are encoded
53 * using {{@link #encodeRenderParamName(PortletWindow, String)}}
54 * and {{@link #encodeRenderParamValues(String[])}}.
55 */
56 private Map encodedStateFullControlParameter;
57
58 private Map stateLessControlParameter;
59 private PortalURL url;
60
61
62 public PortalControlParameter(PortalURL url) {
63 this.url = url;
64 encodedStateFullControlParameter = this.url.getClonedEncodedStateFullControlParameter();
65 stateLessControlParameter = this.url.getClonedStateLessControlParameter();
66 }
67
68
69 /***
70 * Encodes the given String. Encoding means that all characters that might
71 * interfere with the algorithm used to prefix parameters to associate them
72 * with the correct portal window will be encoded. The reverse method is
73 * {{@link #decodeString(String)}}.
74 * @param value The String to be encoded.
75 * @return The encoded String.
76 * @see #decodeParameterName(String)
77 */
78 private static String encodeString(String value) {
79 value = StringUtils.replace(value, "0x", "0xx");
80 value = StringUtils.replace(value, "_", "0x1" );
81 value = StringUtils.replace(value, ".", "0x2" );
82 value = StringUtils.replace(value, "/", "0x3" );
83 value = StringUtils.replace(value, "\r", "0x4" );
84 value = StringUtils.replace(value, "\n", "0x5" );
85 value = StringUtils.replace(value, "<", "0x6" );
86 value = StringUtils.replace(value, ">", "0x7" );
87 value = StringUtils.replace(value, " ", "0x8" );
88 return value;
89 }
90
91 /***
92 * Decodes the given String. This is the reverse method to
93 * {{@link #encodeString(String)}}.
94 * @param value The string to be decoded.
95 * @return The decoded String.
96 */
97 private static String decodeString(String value) {
98 value = StringUtils.replace(value, "0x1", "_" );
99 value = StringUtils.replace(value, "0x2", "." );
100 value = StringUtils.replace(value, "0x3", "/" );
101 value = StringUtils.replace(value, "0x4", "\r" );
102 value = StringUtils.replace(value, "0x5", "\n" );
103 value = StringUtils.replace(value, "0x6", "<" );
104 value = StringUtils.replace(value, "0x7", ">" );
105 value = StringUtils.replace(value, "0x8", " " );
106 value = StringUtils.replace(value, "0xx", "0x");
107 return value;
108 }
109
110 /***
111 * Each parameter is encoded by prefixing it with the String
112 * {@link #PREFIX}. The reverse method is {{@link #decodeParameterName(String)}}.
113 * Don't mistake this method for {{@link #encodeRenderParamName(PortletWindow, String)}}
114 * or {{@link #encodeRenderParamValues(String[])}}.
115 * @param param The parameter to be encoded / prefixed.
116 * @return The encoded parameter.
117 */
118 public static String encodeParameterName(String param) {
119 return PREFIX + param;
120 }
121
122 /***
123 * Decodes a parameter by deleting the prefix, if the parameter
124 * was prefixed. Reverse method to {{@link #encodeParameterName(String)}}.
125 * Don't mistake this method for {{@link #decodeRenderParameterName(String)}}
126 * or {{@link #decodeRenderParamValues(String)}}.
127 * @param param The parameter to be decoded.
128 * @return The decoded parameter.
129 */
130 public static String decodeParameterName(String param) {
131 if (param.startsWith(PREFIX)) {
132 return param.substring(PREFIX.length());
133 } else {
134 return param;
135 }
136 }
137
138 /***
139 * Dummy method. Does nothing!
140 */
141 public static String decodeParameterValue(String paramName, String paramValue) {
142 return paramValue;
143 }
144
145 /***
146 * Encodes the given render parameter name. The name will be encoded using the
147 * {{@link #encodeValue(String)}} method, meaning that characters that will
148 * interfere with plutos internal url encoding and decoding
149 * mechanisms, like "/" or "_" will be encoded. The parameter name will then
150 * be prefixed with a string that encodes the portlet window the parameter belongs to.
151 * This prefix contains the characters ("/", "_", ...) that had to be encoded in
152 * the parameter name to later allow for a safe parsing of the prefix.
153 * @return A string encoding the given render parameter name to be used in portal urls.
154 */
155 public static String encodeRenderParamName(PortletWindow window, String paramName) {
156 String encodedParamName = encodeString(paramName);
157 StringBuffer returnvalue = new StringBuffer(50);
158 returnvalue.append(getRenderParamKey(window));
159 returnvalue.append("_");
160 returnvalue.append(encodedParamName);
161 return returnvalue.toString();
162 }
163
164 /***
165 * Reverse method for method {{@link #encodeRenderParamName(PortletWindow, String)}}.
166 */
167 public static String decodeRenderParamName(PortletWindow window, String encodedRenderParamName) {
168 String prefix = getRenderParamKey(window);
169 String unprefixedRenderParamName = null;
170 if (encodedRenderParamName.startsWith(prefix)) {
171 unprefixedRenderParamName = encodedRenderParamName.substring(prefix.length());
172 } else {
173 unprefixedRenderParamName = encodedRenderParamName;
174 }
175 return decodeString(unprefixedRenderParamName);
176 }
177
178 /***
179 * Encodes the given render parameter values. The values are encoded
180 * in one single string that will be used in portal urls.
181 * @param paramValues The render parameter values to be encoded.
182 * @return A string containing the encoded render parameter values.
183 */
184 public static String encodeRenderParamValues(String[] paramValues)
185 {
186 StringBuffer returnvalue = new StringBuffer(100);
187 returnvalue.append(paramValues.length);
188 for (int i=0; i<paramValues.length; i++) {
189 returnvalue.append("_");
190 if(paramValues[i]!=null) {
191 returnvalue.append(encodeString(paramValues[i]));
192 }
193 }
194 return returnvalue.toString();
195 }
196
197 /***
198 * Reverse method for the method {{@link #encodeRenderParamValues(String[])}}.
199 */
200 private static String[] decodeRenderParamValues(String encodedParamValues) {
201 StringTokenizer tokenizer = new StringTokenizer(encodedParamValues, "_");
202 if (!tokenizer.hasMoreTokens()) {
203 return null;
204 }
205 String _count = tokenizer.nextToken();
206 int count = Integer.valueOf(_count).intValue();
207 String[] values = new String[count];
208 for (int i = 0; i < count; i++) {
209 if (!tokenizer.hasMoreTokens()) {
210 return null;
211 }
212 values[i] = decodeString(tokenizer.nextToken());
213 }
214 return values;
215 }
216
217 /***
218 * Retrieve the key to use to prefix render parameters of the given
219 * portlet window.
220 * @param window
221 * @return
222 */
223 public static String getRenderParamKey(PortletWindow window) {
224 return RENDER_PARAM + "_" + window.getId().toString();
225 }
226
227 /***
228 * Check whether the given string encodes a control parameter.
229 */
230 public static boolean isControlParameter(String param) {
231 return param.startsWith(PREFIX);
232 }
233
234 /***
235 * Check whether the given string encodes a stateful parameter,
236 * i.e. mode, previous mode, window state, previous window state or
237 * render parameter.
238 */
239 public static boolean isStateFullParameter(String param) {
240 if (isControlParameter(param)) {
241 if ((param.startsWith(PREFIX + MODE)) ||
242 (param.startsWith(PREFIX + PREV_MODE)) ||
243 (param.startsWith(PREFIX + STATE)) ||
244 (param.startsWith(PREFIX + PREV_STATE)) ||
245 (param.startsWith(PREFIX + RENDER_PARAM))) {
246 return true;
247 }
248 }
249 return false;
250 }
251
252 /***
253 * Deletes all render parameter that belong to the given window.
254 */
255 public void clearRenderParameters(PortletWindow portletWindow) {
256 String prefix = getRenderParamKey(portletWindow);
257 Iterator keyIterator = encodedStateFullControlParameter.keySet().iterator();
258 while (keyIterator.hasNext()) {
259 String encodedName = (String)keyIterator.next();
260 if (encodedName.startsWith(prefix)) {
261 keyIterator.remove();
262 }
263 }
264 }
265
266 private String getActionKey(PortletWindow window)
267 {
268 return ACTION+"_"+window.getId().toString();
269 }
270
271 public String[] getActionParameter(PortletWindow window, String paramName) {
272 String encodedValues = (String)encodedStateFullControlParameter.get(encodeRenderParamName(window, paramName));
273 String[] decodedValues = decodeRenderParamValues(encodedValues);
274 return decodedValues;
275 }
276
277 public PortletMode getMode(PortletWindow window) {
278 String mode = (String)encodedStateFullControlParameter.get(getModeKey(window));
279 if (mode != null) {
280 return new PortletMode(mode);
281 } else {
282 return PortletMode.VIEW;
283 }
284 }
285
286 private String getModeKey(PortletWindow window) {
287 return MODE + "_" + window.getId().toString();
288 }
289
290 public String getPIDValue() {
291 String value = (String)stateLessControlParameter.get(getPortletIdKey());
292 return value == null ? "" : value;
293 }
294
295 private String getPortletIdKey() {
296 return PORTLET_ID;
297 }
298
299 public PortletWindow getPortletWindowOfAction() {
300 Iterator iterator = getStateLessControlParameter().keySet().iterator();
301 while (iterator.hasNext()) {
302 String name = (String)iterator.next();
303 if (name.startsWith(ACTION)) {
304 String id = name.substring(ACTION.length()+1);
305 Fragment fragment = org.apache.pluto.portalImpl.services.pageregistry.PageRegistry.getFragment(id);
306 if (fragment instanceof PortletFragment) {
307 return((PortletFragment)fragment).getPortletWindow();
308 }
309 }
310 }
311 return null;
312 }
313
314 public PortletMode getPrevMode(PortletWindow window) {
315 String mode = (String)encodedStateFullControlParameter.get(getPrevModeKey(window));
316 if (mode != null) {
317 return new PortletMode(mode);
318 } else {
319 return null;
320 }
321 }
322
323 private String getPrevModeKey(PortletWindow window) {
324 return PREV_MODE + "_" + window.getId().toString();
325 }
326
327 public WindowState getPrevState(PortletWindow window) {
328 String state = (String)encodedStateFullControlParameter.get(getPrevStateKey(window));
329 if (state!=null)
330 return new WindowState(state);
331 else
332 return null;
333 }
334
335 private String getPrevStateKey(PortletWindow window) {
336 return PREV_STATE + "_" + window.getId().toString();
337 }
338
339 public Iterator getRenderParamNames(PortletWindow window) {
340 ArrayList returnvalue = new ArrayList();
341 String prefix = getRenderParamKey(window);
342 Iterator keyIterator = encodedStateFullControlParameter.keySet().iterator();
343 while (keyIterator.hasNext()) {
344 String encodedName = (String)keyIterator.next();
345 if (encodedName.startsWith(prefix)) {
346
347 String decodedName = decodeRenderParamName(window, encodedName);
348
349 String unprefixedName = decodeParameterName(decodedName);
350 returnvalue.add(unprefixedName);
351 }
352 }
353 return returnvalue.iterator();
354 }
355
356 public String[] getRenderParamValues(PortletWindow window, String paramName) {
357 String encodedValues = (String)encodedStateFullControlParameter.get(encodeRenderParamName(window, paramName));
358 String[] decodedValues = decodeRenderParamValues(encodedValues);
359 return decodedValues;
360 }
361
362 public Map getRequestParameter() {
363 return requestParameter;
364 }
365
366 public WindowState getState(PortletWindow window) {
367 String state = (String)encodedStateFullControlParameter.get(getStateKey(window));
368 if (state!=null)
369 return new WindowState(state);
370 else
371 return WindowState.NORMAL;
372 }
373
374 public Map getEncodedStateFullControlParameter() {
375 return encodedStateFullControlParameter;
376 }
377
378 private String getStateKey(PortletWindow window) {
379 return STATE+"_"+window.getId().toString();
380 }
381
382 public Map getStateLessControlParameter() {
383 return stateLessControlParameter;
384 }
385
386 public boolean isOnePortletWindowMaximized() {
387 Iterator iterator = encodedStateFullControlParameter.keySet().iterator();
388 while (iterator.hasNext()) {
389 String encodedName = (String)iterator.next();
390 if (encodedName.startsWith(STATE)) {
391 if (encodedStateFullControlParameter.get(encodedName).equals(WindowState.MAXIMIZED.toString())) {
392 return true;
393 }
394 }
395 }
396 return false;
397 }
398
399 public void setAction(PortletWindow window) {
400 getEncodedStateFullControlParameter().put(getActionKey(window),ACTION.toUpperCase());
401 }
402
403 public void setMode(PortletWindow window, PortletMode mode) {
404 Object prevMode = encodedStateFullControlParameter.get(getModeKey(window));
405 if (prevMode!=null)
406 encodedStateFullControlParameter.put(getPrevModeKey(window), prevMode);
407
408 encodedStateFullControlParameter.put(getModeKey(window), mode.toString());
409 }
410
411 public void setPortletId(PortletWindow window) {
412 getEncodedStateFullControlParameter().put(getPortletIdKey(),window.getId().toString());
413
414 }
415
416 /***
417 * Sets the given render parameter. Note that its name as well as its values will
418 * be encoded for storage using {{@link #encodeRenderParamName(PortletWindow, String)}}
419 * and {{@link #encodeRenderParamValues(String[])}.
420 */
421 public void setRenderParam(PortletWindow window, String name, String[] values) {
422 encodedStateFullControlParameter.put(encodeRenderParamName(window, name),
423 encodeRenderParamValues(values) );
424 }
425
426 public void setRequestParam(String name, String[] values ) {
427 requestParameter.put(name, values );
428 }
429
430
431 public void setState(PortletWindow window, WindowState state) {
432 Object prevState = encodedStateFullControlParameter.get(getStateKey(window));
433 if (prevState != null) {
434 encodedStateFullControlParameter.put(getPrevStateKey(window), prevState);
435 }
436 encodedStateFullControlParameter.put(getStateKey(window), state.toString());
437 }
438
439 }