1   /**
2    * Copyright (c) 2000-2009 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.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   */
53  public class StrutsURLEncoder implements URLEncoder {
54  
55      public static void setParameters(
56          LiferayPortletURL portletURL, String queryString) {
57  
58          String[] params = StringUtil.split(queryString, "&");
59  
60          for (int i = 0; i < params.length; i++) {
61              int pos = params[i].indexOf("=");
62  
63              if (pos != -1) {
64                  String param = params[i].substring(0, pos);
65                  String value = params[i].substring(pos + 1, params[i].length());
66  
67                  if (param.equals("windowState")) {
68                      try {
69                          portletURL.setWindowState(
70                              WindowStateFactory.getWindowState(value));
71                      }
72                      catch (WindowStateException wse) {
73                          _log.error(wse.getMessage());
74                      }
75                  }
76                  else if (param.equals("portletMode")) {
77                      try {
78                          portletURL.setPortletMode(
79                              PortletModeFactory.getPortletMode(value));
80                      }
81                      catch (PortletModeException pme) {
82                          _log.error(pme.getMessage());
83                      }
84                  }
85                  else if (param.equals("actionURL")) {
86                      String lifecycle = PortletRequest.RENDER_PHASE;
87  
88                      if (GetterUtil.getBoolean(value)) {
89                          lifecycle = PortletRequest.ACTION_PHASE;
90                      }
91  
92                      portletURL.setLifecycle(lifecycle);
93                  }
94                  else {
95                      portletURL.setParameter(
96                          param, HttpUtil.decodeURL(value), true);
97                  }
98              }
99          }
100     }
101 
102     public StrutsURLEncoder(
103         String contextPath, String mainPath, String servletMapping,
104         LiferayPortletURL portletURL) {
105 
106         _contextPath = contextPath;
107         _mainPath = mainPath;
108         _setServletMapping(servletMapping);
109         _portletURL = portletURL;
110         _windowState = portletURL.getWindowState();
111         _portletMode = portletURL.getPortletMode();
112     }
113 
114     public String encodeURL(HttpServletResponse response, String path) {
115         if (_log.isDebugEnabled()) {
116             _log.debug("Path " + path);
117             _log.debug("Context path " + _contextPath);
118             _log.debug("Servlet mapping " + _servletMapping);
119         }
120 
121         String encodedURL = path;
122 
123         if (path.startsWith("//") ||
124             path.startsWith(_contextPath) ||
125             path.startsWith(_servletMapping)) {
126 
127             // Struts uses &amp; instead of & to delimit parameter key value
128             // pairs when you set the "name" attribute for html:link.
129 
130             path = StringUtil.replace(path, "&amp;", "&");
131 
132             // Reset portlet URL settings so it can be reused
133 
134             _portletURL.setLifecycle(PortletRequest.RENDER_PHASE);
135             _portletURL.setParameters(new HashMap<String, String[]>());
136 
137             try {
138                 _portletURL.setWindowState(_windowState);
139             }
140             catch (WindowStateException wse) {
141             }
142 
143             try {
144                 _portletURL.setPortletMode(_portletMode);
145             }
146             catch (PortletModeException pme) {
147             }
148 
149             // Separate the Struts action from the query string
150 
151             String strutsAction = path;
152             String queryString = StringPool.BLANK;
153 
154             int pos = strutsAction.indexOf(StringPool.QUESTION);
155 
156             if (pos != -1) {
157                 strutsAction = path.substring(0, pos);
158                 queryString = path.substring(pos + 1, path.length());
159             }
160 
161             // Set the Struts action
162 
163             if (strutsAction.startsWith("c/")) {
164                 strutsAction = strutsAction.substring(1);
165             }
166             else if (strutsAction.startsWith("/c/")) {
167                 strutsAction = strutsAction.substring(2);
168             }
169 
170             if (Validator.isNotNull(_contextPath)) {
171                 strutsAction = strutsAction.substring(
172                     _contextPath.length(), strutsAction.length());
173             }
174 
175             if (strutsAction.startsWith(_servletMapping)) {
176                 strutsAction = strutsAction.substring(
177                     _servletMapping.length(), strutsAction.length());
178             }
179 
180             if (!strutsAction.startsWith(StringPool.SLASH)) {
181                 strutsAction = StringPool.SLASH + strutsAction;
182             }
183 
184             if (_log.isDebugEnabled()) {
185                 _log.debug("Struts action " + strutsAction);
186             }
187 
188             _portletURL.setParameter("struts_action", strutsAction);
189 
190             // Set the query string
191 
192             setParameters(_portletURL, queryString);
193 
194             // Return the portlet URL
195 
196             encodedURL = _portletURL.toString();
197 
198             if (_log.isDebugEnabled()) {
199                 _log.debug("Encoded portlet URL " + encodedURL);
200             }
201         }
202 
203         return encodedURL;
204     }
205 
206     private void _setServletMapping(String servletMapping) {
207         if (servletMapping != null) {
208 
209             // See org.apache.struts.util.RequestUtils.getActionMappingURL
210 
211             if (servletMapping.endsWith("/*")) {
212                 int pos = 0;
213 
214                 if (servletMapping.startsWith(_mainPath)) {
215                     pos = _mainPath.length() - 2;
216                 }
217 
218                 _servletMapping = servletMapping.substring(
219                     pos, servletMapping.length() - 1);
220             }
221         }
222     }
223 
224     private static Log _log = LogFactoryUtil.getLog(StrutsURLEncoder.class);
225 
226     private String _contextPath;
227     private String _mainPath;
228     private String _servletMapping = StringPool.BLANK;
229     private LiferayPortletURL _portletURL;
230     private WindowState _windowState;
231     private PortletMode _portletMode;
232 
233 }