1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.struts;
24  
25  import com.liferay.portal.kernel.portlet.LiferayPortletURL;
26  import com.liferay.portal.kernel.portlet.PortletModeFactory;
27  import com.liferay.portal.kernel.portlet.WindowStateFactory;
28  import com.liferay.portal.kernel.servlet.URLEncoder;
29  import com.liferay.portal.kernel.util.GetterUtil;
30  import com.liferay.portal.kernel.util.HttpUtil;
31  import com.liferay.portal.kernel.util.StringPool;
32  import com.liferay.portal.kernel.util.StringUtil;
33  import com.liferay.portal.kernel.util.Validator;
34  
35  import java.util.HashMap;
36  
37  import javax.portlet.PortletMode;
38  import javax.portlet.PortletModeException;
39  import javax.portlet.PortletRequest;
40  import javax.portlet.WindowState;
41  import javax.portlet.WindowStateException;
42  
43  import javax.servlet.http.HttpServletResponse;
44  
45  import org.apache.commons.logging.Log;
46  import org.apache.commons.logging.LogFactory;
47  
48  /**
49   * <a href="StrutsURLEncoder.java.html"><b><i>View Source</i></b></a>
50   *
51   * @author Brian Wing Shun Chan
52   *
53   */
54  public class StrutsURLEncoder implements URLEncoder {
55  
56      public static void setParameters(
57          LiferayPortletURL portletURL, String queryString) {
58  
59          String[] params = StringUtil.split(queryString, "&");
60  
61          for (int i = 0; i < params.length; i++) {
62              int pos = params[i].indexOf("=");
63  
64              if (pos != -1) {
65                  String param = params[i].substring(0, pos);
66                  String value = params[i].substring(pos + 1, params[i].length());
67  
68                  if (param.equals("windowState")) {
69                      try {
70                          portletURL.setWindowState(
71                              WindowStateFactory.getWindowState(value));
72                      }
73                      catch (WindowStateException wse) {
74                          _log.error(wse.getMessage());
75                      }
76                  }
77                  else if (param.equals("portletMode")) {
78                      try {
79                          portletURL.setPortletMode(
80                              PortletModeFactory.getPortletMode(value));
81                      }
82                      catch (PortletModeException pme) {
83                          _log.error(pme.getMessage());
84                      }
85                  }
86                  else if (param.equals("actionURL")) {
87                      String lifecycle = PortletRequest.RENDER_PHASE;
88  
89                      if (GetterUtil.getBoolean(value)) {
90                          lifecycle = PortletRequest.ACTION_PHASE;
91                      }
92  
93                      portletURL.setLifecycle(lifecycle);
94                  }
95                  else {
96                      portletURL.setParameter(
97                          param, HttpUtil.decodeURL(value), true);
98                  }
99              }
100         }
101     }
102 
103     public StrutsURLEncoder(
104         String contextPath, String mainPath, String servletMapping,
105         LiferayPortletURL portletURL) {
106 
107         _contextPath = contextPath;
108         _mainPath = mainPath;
109         _setServletMapping(servletMapping);
110         _portletURL = portletURL;
111         _windowState = portletURL.getWindowState();
112         _portletMode = portletURL.getPortletMode();
113     }
114 
115     public String encodeURL(HttpServletResponse response, String path) {
116         if (_log.isDebugEnabled()) {
117             _log.debug("Path " + path);
118             _log.debug("Context path " + _contextPath);
119             _log.debug("Servlet mapping " + _servletMapping);
120         }
121 
122         String encodedURL = path;
123 
124         if (path.startsWith("//") ||
125             path.startsWith(_contextPath) ||
126             path.startsWith(_servletMapping)) {
127 
128             // Struts uses &amp; instead of & to delimit parameter key value
129             // pairs when you set the "name" attribute for html:link.
130 
131             path = StringUtil.replace(path, "&amp;", "&");
132 
133             // Reset portlet URL settings so it can be reused
134 
135             _portletURL.setLifecycle(PortletRequest.RENDER_PHASE);
136             _portletURL.setParameters(new HashMap<String, String[]>());
137 
138             try {
139                 _portletURL.setWindowState(_windowState);
140             }
141             catch (WindowStateException wse) {
142             }
143 
144             try {
145                 _portletURL.setPortletMode(_portletMode);
146             }
147             catch (PortletModeException pme) {
148             }
149 
150             // Separate the Struts action from the query string
151 
152             String strutsAction = path;
153             String queryString = StringPool.BLANK;
154 
155             int pos = strutsAction.indexOf(StringPool.QUESTION);
156 
157             if (pos != -1) {
158                 strutsAction = path.substring(0, pos);
159                 queryString = path.substring(pos + 1, path.length());
160             }
161 
162             // Set the Struts action
163 
164             if (strutsAction.startsWith("c/")) {
165                 strutsAction = strutsAction.substring(1);
166             }
167             else if (strutsAction.startsWith("/c/")) {
168                 strutsAction = strutsAction.substring(2);
169             }
170 
171             if (Validator.isNotNull(_contextPath)) {
172                 strutsAction = strutsAction.substring(
173                     _contextPath.length(), strutsAction.length());
174             }
175 
176             if (strutsAction.startsWith(_servletMapping)) {
177                 strutsAction = strutsAction.substring(
178                     _servletMapping.length(), strutsAction.length());
179             }
180 
181             if (!strutsAction.startsWith(StringPool.SLASH)) {
182                 strutsAction = StringPool.SLASH + strutsAction;
183             }
184 
185             if (_log.isDebugEnabled()) {
186                 _log.debug("Struts action " + strutsAction);
187             }
188 
189             _portletURL.setParameter("struts_action", strutsAction);
190 
191             // Set the query string
192 
193             setParameters(_portletURL, queryString);
194 
195             // Return the portlet URL
196 
197             encodedURL = _portletURL.toString();
198 
199             if (_log.isDebugEnabled()) {
200                 _log.debug("Encoded portlet URL " + encodedURL);
201             }
202         }
203 
204         return encodedURL;
205     }
206 
207     private void _setServletMapping(String servletMapping) {
208         if (servletMapping != null) {
209 
210             // See org.apache.struts.util.RequestUtils.getActionMappingURL
211 
212             if (servletMapping.endsWith("/*")) {
213                 int pos = 0;
214 
215                 if (servletMapping.startsWith(_mainPath)) {
216                     pos = _mainPath.length() - 2;
217                 }
218 
219                 _servletMapping = servletMapping.substring(
220                     pos, servletMapping.length() - 1);
221             }
222         }
223     }
224 
225     private static Log _log = LogFactory.getLog(StrutsURLEncoder.class);
226 
227     private String _contextPath;
228     private String _mainPath;
229     private String _servletMapping = StringPool.BLANK;
230     private LiferayPortletURL _portletURL;
231     private WindowState _windowState;
232     private PortletMode _portletMode;
233 
234 }