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