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