001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.struts;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.portlet.LiferayPortletURL;
020    import com.liferay.portal.kernel.portlet.PortletModeFactory;
021    import com.liferay.portal.kernel.portlet.WindowStateFactory;
022    import com.liferay.portal.kernel.servlet.URLEncoder;
023    import com.liferay.portal.kernel.util.CharPool;
024    import com.liferay.portal.kernel.util.GetterUtil;
025    import com.liferay.portal.kernel.util.HttpUtil;
026    import com.liferay.portal.kernel.util.StringPool;
027    import com.liferay.portal.kernel.util.StringUtil;
028    import com.liferay.portal.kernel.util.Validator;
029    
030    import java.util.HashMap;
031    
032    import javax.portlet.PortletMode;
033    import javax.portlet.PortletModeException;
034    import javax.portlet.PortletRequest;
035    import javax.portlet.WindowState;
036    import javax.portlet.WindowStateException;
037    
038    import javax.servlet.http.HttpServletResponse;
039    
040    /**
041     * @author Brian Wing Shun Chan
042     */
043    public class StrutsURLEncoder implements URLEncoder {
044    
045            public static void setParameters(
046                    LiferayPortletURL liferayPortletURL, String queryString) {
047    
048                    String[] params = StringUtil.split(queryString, "&");
049    
050                    for (int i = 0; i < params.length; i++) {
051                            int pos = params[i].indexOf("=");
052    
053                            if (pos != -1) {
054                                    String param = params[i].substring(0, pos);
055                                    String value = params[i].substring(pos + 1, params[i].length());
056    
057                                    if (param.equals("windowState")) {
058                                            try {
059                                                    liferayPortletURL.setWindowState(
060                                                            WindowStateFactory.getWindowState(value));
061                                            }
062                                            catch (WindowStateException wse) {
063                                                    _log.error(wse.getMessage());
064                                            }
065                                    }
066                                    else if (param.equals("portletMode")) {
067                                            try {
068                                                    liferayPortletURL.setPortletMode(
069                                                            PortletModeFactory.getPortletMode(value));
070                                            }
071                                            catch (PortletModeException pme) {
072                                                    _log.error(pme.getMessage());
073                                            }
074                                    }
075                                    else if (param.equals("actionURL")) {
076                                            String lifecycle = PortletRequest.RENDER_PHASE;
077    
078                                            if (GetterUtil.getBoolean(value)) {
079                                                    lifecycle = PortletRequest.ACTION_PHASE;
080                                            }
081    
082                                            liferayPortletURL.setLifecycle(lifecycle);
083                                    }
084                                    else {
085                                            liferayPortletURL.setParameter(
086                                                    param, HttpUtil.decodeURL(value), true);
087                                    }
088                            }
089                    }
090            }
091    
092            public StrutsURLEncoder(
093                    String contextPath, String mainPath, String servletMapping,
094                    LiferayPortletURL liferayPortletURL) {
095    
096                    _contextPath = contextPath;
097                    _mainPath = mainPath;
098                    _setServletMapping(servletMapping);
099                    _liferayPortletURL = liferayPortletURL;
100                    _windowState = liferayPortletURL.getWindowState();
101                    _portletMode = liferayPortletURL.getPortletMode();
102            }
103    
104            public String encodeURL(HttpServletResponse response, 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                            _liferayPortletURL.setLifecycle(PortletRequest.RENDER_PHASE);
125                            _liferayPortletURL.setParameters(new HashMap<String, String[]>());
126    
127                            try {
128                                    _liferayPortletURL.setWindowState(_windowState);
129                            }
130                            catch (WindowStateException wse) {
131                            }
132    
133                            try {
134                                    _liferayPortletURL.setPortletMode(_portletMode);
135                            }
136                            catch (PortletModeException pme) {
137                            }
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(CharPool.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                            _liferayPortletURL.setParameter("struts_action", strutsAction);
179    
180                            // Set the query string
181    
182                            setParameters(_liferayPortletURL, queryString);
183    
184                            // Return the portlet URL
185    
186                            encodedURL = _liferayPortletURL.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 = LogFactoryUtil.getLog(StrutsURLEncoder.class);
215    
216            private String _contextPath;
217            private LiferayPortletURL _liferayPortletURL;
218            private String _mainPath;
219            private PortletMode _portletMode;
220            private String _servletMapping = StringPool.BLANK;
221            private WindowState _windowState;
222    
223    }