1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.struts;
16  
17  import com.liferay.portal.kernel.log.Log;
18  import com.liferay.portal.kernel.log.LogFactoryUtil;
19  import com.liferay.portal.kernel.portlet.LiferayPortletURL;
20  import com.liferay.portal.kernel.portlet.PortletModeFactory;
21  import com.liferay.portal.kernel.portlet.WindowStateFactory;
22  import com.liferay.portal.kernel.servlet.URLEncoder;
23  import com.liferay.portal.kernel.util.GetterUtil;
24  import com.liferay.portal.kernel.util.HttpUtil;
25  import com.liferay.portal.kernel.util.StringPool;
26  import com.liferay.portal.kernel.util.StringUtil;
27  import com.liferay.portal.kernel.util.Validator;
28  
29  import java.util.HashMap;
30  
31  import javax.portlet.PortletMode;
32  import javax.portlet.PortletModeException;
33  import javax.portlet.PortletRequest;
34  import javax.portlet.WindowState;
35  import javax.portlet.WindowStateException;
36  
37  import javax.servlet.http.HttpServletResponse;
38  
39  /**
40   * <a href="StrutsURLEncoder.java.html"><b><i>View Source</i></b></a>
41   *
42   * @author Brian Wing Shun Chan
43   */
44  public class StrutsURLEncoder implements URLEncoder {
45  
46      public static void setParameters(
47          LiferayPortletURL portletURL, String queryString) {
48  
49          String[] params = StringUtil.split(queryString, "&");
50  
51          for (int i = 0; i < params.length; i++) {
52              int pos = params[i].indexOf("=");
53  
54              if (pos != -1) {
55                  String param = params[i].substring(0, pos);
56                  String value = params[i].substring(pos + 1, params[i].length());
57  
58                  if (param.equals("windowState")) {
59                      try {
60                          portletURL.setWindowState(
61                              WindowStateFactory.getWindowState(value));
62                      }
63                      catch (WindowStateException wse) {
64                          _log.error(wse.getMessage());
65                      }
66                  }
67                  else if (param.equals("portletMode")) {
68                      try {
69                          portletURL.setPortletMode(
70                              PortletModeFactory.getPortletMode(value));
71                      }
72                      catch (PortletModeException pme) {
73                          _log.error(pme.getMessage());
74                      }
75                  }
76                  else if (param.equals("actionURL")) {
77                      String lifecycle = PortletRequest.RENDER_PHASE;
78  
79                      if (GetterUtil.getBoolean(value)) {
80                          lifecycle = PortletRequest.ACTION_PHASE;
81                      }
82  
83                      portletURL.setLifecycle(lifecycle);
84                  }
85                  else {
86                      portletURL.setParameter(
87                          param, HttpUtil.decodeURL(value), true);
88                  }
89              }
90          }
91      }
92  
93      public StrutsURLEncoder(
94          String contextPath, String mainPath, String servletMapping,
95          LiferayPortletURL portletURL) {
96  
97          _contextPath = contextPath;
98          _mainPath = mainPath;
99          _setServletMapping(servletMapping);
100         _portletURL = portletURL;
101         _windowState = portletURL.getWindowState();
102         _portletMode = portletURL.getPortletMode();
103     }
104 
105     public String encodeURL(HttpServletResponse response, String path) {
106         if (_log.isDebugEnabled()) {
107             _log.debug("Path " + path);
108             _log.debug("Context path " + _contextPath);
109             _log.debug("Servlet mapping " + _servletMapping);
110         }
111 
112         String encodedURL = path;
113 
114         if (path.startsWith("//") ||
115             path.startsWith(_contextPath) ||
116             path.startsWith(_servletMapping)) {
117 
118             // Struts uses &amp; instead of & to delimit parameter key value
119             // pairs when you set the "name" attribute for html:link.
120 
121             path = StringUtil.replace(path, "&amp;", "&");
122 
123             // Reset portlet URL settings so it can be reused
124 
125             _portletURL.setLifecycle(PortletRequest.RENDER_PHASE);
126             _portletURL.setParameters(new HashMap<String, String[]>());
127 
128             try {
129                 _portletURL.setWindowState(_windowState);
130             }
131             catch (WindowStateException wse) {
132             }
133 
134             try {
135                 _portletURL.setPortletMode(_portletMode);
136             }
137             catch (PortletModeException pme) {
138             }
139 
140             // Separate the Struts action from the query string
141 
142             String strutsAction = path;
143             String queryString = StringPool.BLANK;
144 
145             int pos = strutsAction.indexOf(StringPool.QUESTION);
146 
147             if (pos != -1) {
148                 strutsAction = path.substring(0, pos);
149                 queryString = path.substring(pos + 1, path.length());
150             }
151 
152             // Set the Struts action
153 
154             if (strutsAction.startsWith("c/")) {
155                 strutsAction = strutsAction.substring(1);
156             }
157             else if (strutsAction.startsWith("/c/")) {
158                 strutsAction = strutsAction.substring(2);
159             }
160 
161             if (Validator.isNotNull(_contextPath)) {
162                 strutsAction = strutsAction.substring(
163                     _contextPath.length(), strutsAction.length());
164             }
165 
166             if (strutsAction.startsWith(_servletMapping)) {
167                 strutsAction = strutsAction.substring(
168                     _servletMapping.length(), strutsAction.length());
169             }
170 
171             if (!strutsAction.startsWith(StringPool.SLASH)) {
172                 strutsAction = StringPool.SLASH + strutsAction;
173             }
174 
175             if (_log.isDebugEnabled()) {
176                 _log.debug("Struts action " + strutsAction);
177             }
178 
179             _portletURL.setParameter("struts_action", strutsAction);
180 
181             // Set the query string
182 
183             setParameters(_portletURL, queryString);
184 
185             // Return the portlet URL
186 
187             encodedURL = _portletURL.toString();
188 
189             if (_log.isDebugEnabled()) {
190                 _log.debug("Encoded portlet URL " + encodedURL);
191             }
192         }
193 
194         return encodedURL;
195     }
196 
197     private void _setServletMapping(String servletMapping) {
198         if (servletMapping != null) {
199 
200             // See org.apache.struts.util.RequestUtils.getActionMappingURL
201 
202             if (servletMapping.endsWith("/*")) {
203                 int pos = 0;
204 
205                 if (servletMapping.startsWith(_mainPath)) {
206                     pos = _mainPath.length() - 2;
207                 }
208 
209                 _servletMapping = servletMapping.substring(
210                     pos, servletMapping.length() - 1);
211             }
212         }
213     }
214 
215     private static Log _log = LogFactoryUtil.getLog(StrutsURLEncoder.class);
216 
217     private String _contextPath;
218     private String _mainPath;
219     private String _servletMapping = StringPool.BLANK;
220     private LiferayPortletURL _portletURL;
221     private WindowState _windowState;
222     private PortletMode _portletMode;
223 
224 }