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: */
017:
018: package org.apache.cocoon.portal.pluto;
019:
020: import java.util.HashMap;
021: import java.util.Iterator;
022: import java.util.Map;
023: import java.util.StringTokenizer;
024:
025: import javax.portlet.PortletMode;
026: import javax.portlet.WindowState;
027:
028: import org.apache.pluto.util.StringUtils;
029: import org.apache.cocoon.portal.coplet.CopletInstanceData;
030:
031: /**
032: * Create the URL for a portlet
033: *
034: * @author <a href="mailto:rgoers@apache.org">Ralph Goers</a>
035: * @version SVN $Id: $
036: */
037:
038: public class PortletURLConverter {
039:
040: public static final String ACTION = "ac";
041: public static final String MODE = "md";
042: public static final String PORTLET_ID = "pid";
043: public static final String PREFIX = "_";
044: public static final String PARAM = "pm";
045: public static final String STATE = "st";
046:
047: private final Map urlData = new HashMap();
048: private final Map parameters = new HashMap();
049: private String portletId;
050:
051: /**
052: * Constructor used when the URL will be marshalled.
053: * @param cid The coplet id.
054: */
055: public PortletURLConverter(CopletInstanceData cid) {
056: this .portletId = cid.getId();
057: }
058:
059: /**
060: * Constructor used when the URL will be unmarshalled.
061: * @param eventData The url data.
062: */
063: public PortletURLConverter(String eventData) {
064: StringTokenizer tokenizer = new StringTokenizer(eventData, "/");
065: while (tokenizer.hasMoreTokens()) {
066: String token = tokenizer.nextToken();
067: if (isParameter(token)) {
068: String name = decodeParameterName(token);
069: String key = encodeParameterName(name);
070: this .parameters.put(key, token.substring(key.length()));
071: } else {
072: StringTokenizer tokens = new StringTokenizer(token,
073: PREFIX);
074:
075: if (tokens.countTokens() > 1) {
076: String key = tokens.nextToken();
077: if (key.equals(PORTLET_ID)) {
078: this .portletId = tokens.nextToken();
079: } else {
080: String value = tokens.nextToken();
081: urlData.put(key, value);
082: }
083: }
084: }
085: }
086: }
087:
088: /**
089: * Return the PortletMode
090: * @return The PortletMode
091: */
092: public PortletMode getMode() {
093: String mode = (String) urlData.get(getModeKey());
094: if (mode != null) {
095: return new PortletMode(mode);
096: }
097: return PortletMode.VIEW;
098: }
099:
100: /**
101: * Return the WindowState
102: * @return The WindowState
103: */
104: public WindowState getState() {
105: String state = (String) urlData.get(getStateKey());
106: if (state != null) {
107: return new WindowState(state);
108: }
109: return WindowState.NORMAL;
110: }
111:
112: /**
113: * Return the indicator if this is an action.
114: * @return true if this is an action URL, false if a render URL.
115: */
116: public boolean isAction() {
117: return (urlData.get(getActionKey()) != null);
118: }
119:
120: /**
121: * Indicates that the URL is an action.
122: */
123: public void setAction() {
124: urlData.put(getActionKey(), ACTION.toUpperCase());
125: }
126:
127: /**
128: * Sets the PortletMode.
129: * @param mode The PortletMode
130: */
131: public void setMode(PortletMode mode) {
132: urlData.put(getModeKey(), mode.toString());
133: }
134:
135: /**
136: * Sets the WindowState
137: * @param state The WindowState
138: */
139: public void setState(WindowState state) {
140: urlData.put(getStateKey(), state.toString());
141: }
142:
143: /**
144: * Returns the portlet id.
145: * @return The portlet id.
146: */
147: public String getPortletId() {
148: return this .portletId;
149: }
150:
151: /**
152: * Returns the request parameters for this portlet URL.
153: * @return A Map containing the parameters for this URL.
154: */
155: public Map getParameters() {
156: Map map = new HashMap();
157: Iterator iter = this .parameters.entrySet().iterator();
158: while (iter.hasNext()) {
159: Map.Entry entry = (Map.Entry) iter.next();
160: String key = decodeParameterName((String) entry.getKey());
161: String[] values = decodeParameterValues((String) entry
162: .getValue());
163: map.put(key, values);
164: }
165: return map;
166: }
167:
168: /**
169: * Adds the parameter, replacing a parameter with the same name.
170: * @param name The parameter name
171: * @param values An array of Strings.
172: */
173: public void setParam(String name, String[] values) {
174: this .parameters.put(encodeParameterName(name),
175: encodeParameterValues(values));
176: }
177:
178: /**
179: * Returns the marshalled URL.
180: * @return A String containing the marshalled URL.
181: */
182: public String toString() {
183: StringBuffer buffer = new StringBuffer("");
184: buffer.append(PORTLET_ID).append(PREFIX).append(portletId);
185: Iterator iter = urlData.entrySet().iterator();
186: while (iter.hasNext()) {
187: buffer.append("/");
188: Map.Entry entry = (Map.Entry) iter.next();
189: buffer.append(entry.getKey()).append(PREFIX).append(
190: entry.getValue());
191: }
192: iter = this .parameters.entrySet().iterator();
193: while (iter.hasNext()) {
194: buffer.append("/");
195: Map.Entry entry = (Map.Entry) iter.next();
196: buffer.append(entry.getKey()).append(PREFIX).append(
197: entry.getValue());
198: }
199: return buffer.toString();
200: }
201:
202: private String getActionKey() {
203: return ACTION;
204: }
205:
206: private String getModeKey() {
207: return MODE;
208: }
209:
210: private String getStateKey() {
211: return STATE;
212: }
213:
214: private String getParamKey() {
215: return PARAM + PREFIX;
216: }
217:
218: private boolean isParameter(String key) {
219: return key.startsWith(getParamKey());
220: }
221:
222: private String decodeParameterName(String encodedParamName) {
223: StringTokenizer tokenizer = new StringTokenizer(
224: encodedParamName, PREFIX);
225: if (!tokenizer.hasMoreTokens()) {
226: return null;
227: }
228: // Skip the key
229: tokenizer.nextToken();
230: if (!tokenizer.hasMoreTokens()) {
231: return null;
232: }
233: String name = tokenizer.nextToken();
234: return decodeValue(name);
235: }
236:
237: private String[] decodeParameterValues(String encodedParamValues) {
238: StringTokenizer tokenizer = new StringTokenizer(
239: encodedParamValues, PREFIX);
240: if (!tokenizer.hasMoreTokens()) {
241: return null;
242: }
243: String _count = tokenizer.nextToken();
244: int count = Integer.valueOf(_count).intValue();
245: String[] values = new String[count];
246: for (int i = 0; i < count; i++) {
247: if (!tokenizer.hasMoreTokens()) {
248: return null;
249: }
250: values[i] = decodeValue(tokenizer.nextToken());
251: }
252: return values;
253: }
254:
255: private String decodeValue(String value) {
256: value = StringUtils.replace(value, "0x1", "_");
257: value = StringUtils.replace(value, "0x2", ".");
258: value = StringUtils.replace(value, "0x3", "/");
259: value = StringUtils.replace(value, "0x4", "\r");
260: value = StringUtils.replace(value, "0x5", "\n");
261: value = StringUtils.replace(value, "0x6", "<");
262: value = StringUtils.replace(value, "0x7", ">");
263: value = StringUtils.replace(value, "0x8", " ");
264: value = StringUtils.replace(value, "0x0", "0x");
265: return value;
266: }
267:
268: private String encodeParameterName(String paramName) {
269: StringBuffer returnvalue = new StringBuffer(50);
270: returnvalue.append(getParamKey())
271: .append(encodeValue(paramName));
272: return returnvalue.toString();
273: }
274:
275: private String encodeParameterValues(String[] paramValues) {
276: StringBuffer returnvalue = new StringBuffer(100);
277: if (paramValues == null) {
278: returnvalue.append("0");
279: } else {
280: returnvalue.append(paramValues.length);
281: for (int i = 0; i < paramValues.length; i++) {
282: returnvalue.append("_");
283: returnvalue.append(encodeValue(paramValues[i]));
284: }
285: }
286: return returnvalue.toString();
287: }
288:
289: private String encodeValue(String value) {
290: value = StringUtils.replace(value, "0x", "0x0");
291: value = StringUtils.replace(value, "_", "0x1");
292: value = StringUtils.replace(value, ".", "0x2");
293: value = StringUtils.replace(value, "/", "0x3");
294: value = StringUtils.replace(value, "\r", "0x4");
295: value = StringUtils.replace(value, "\n", "0x5");
296: value = StringUtils.replace(value, "<", "0x6");
297: value = StringUtils.replace(value, ">", "0x7");
298: value = StringUtils.replace(value, " ", "0x8");
299: return value;
300: }
301: }
|