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