001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
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.GetterUtil;
024    import com.liferay.portal.kernel.util.HttpUtil;
025    import com.liferay.portal.kernel.util.StringPool;
026    import com.liferay.portal.kernel.util.StringUtil;
027    import com.liferay.portal.kernel.util.Validator;
028    
029    import java.util.HashMap;
030    
031    import javax.portlet.PortletMode;
032    import javax.portlet.PortletModeException;
033    import javax.portlet.PortletRequest;
034    import javax.portlet.WindowState;
035    import javax.portlet.WindowStateException;
036    
037    import javax.servlet.http.HttpServletResponse;
038    
039    /**
040     * @author Brian Wing Shun Chan
041     */
042    public class StrutsURLEncoder implements URLEncoder {
043    
044            public static void setParameters(
045                    LiferayPortletURL liferayPortletURL, String queryString) {
046    
047                    String[] params = StringUtil.split(queryString, "&");
048    
049                    for (int i = 0; i < params.length; i++) {
050                            int pos = params[i].indexOf("=");
051    
052                            if (pos != -1) {
053                                    String param = params[i].substring(0, pos);
054                                    String value = params[i].substring(pos + 1, params[i].length());
055    
056                                    if (param.equals("windowState")) {
057                                            try {
058                                                    liferayPortletURL.setWindowState(
059                                                            WindowStateFactory.getWindowState(value));
060                                            }
061                                            catch (WindowStateException wse) {
062                                                    _log.error(wse.getMessage());
063                                            }
064                                    }
065                                    else if (param.equals("portletMode")) {
066                                            try {
067                                                    liferayPortletURL.setPortletMode(
068                                                            PortletModeFactory.getPortletMode(value));
069                                            }
070                                            catch (PortletModeException pme) {
071                                                    _log.error(pme.getMessage());
072                                            }
073                                    }
074                                    else if (param.equals("actionURL")) {
075                                            String lifecycle = PortletRequest.RENDER_PHASE;
076    
077                                            if (GetterUtil.getBoolean(value)) {
078                                                    lifecycle = PortletRequest.ACTION_PHASE;
079                                            }
080    
081                                            liferayPortletURL.setLifecycle(lifecycle);
082                                    }
083                                    else {
084                                            liferayPortletURL.setParameter(
085                                                    param, HttpUtil.decodeURL(value), true);
086                                    }
087                            }
088                    }
089            }
090    
091            public StrutsURLEncoder(
092                    String contextPath, String mainPath, String servletMapping,
093                    LiferayPortletURL liferayPortletURL) {
094    
095                    _contextPath = contextPath;
096                    _mainPath = mainPath;
097                    _setServletMapping(servletMapping);
098                    _liferayPortletURL = liferayPortletURL;
099                    _windowState = liferayPortletURL.getWindowState();
100                    _portletMode = liferayPortletURL.getPortletMode();
101            }
102    
103            public String encodeURL(HttpServletResponse response, String path) {
104                    if (_log.isDebugEnabled()) {
105                            _log.debug("Path " + path);
106                            _log.debug("Context path " + _contextPath);
107                            _log.debug("Servlet mapping " + _servletMapping);
108                    }
109    
110                    String encodedURL = path;
111    
112                    if (path.startsWith("//") ||
113                            path.startsWith(_contextPath) ||
114                            path.startsWith(_servletMapping)) {
115    
116                            // Struts uses &amp; instead of & to delimit parameter key value
117                            // pairs when you set the "name" attribute for html:link.
118    
119                            path = StringUtil.replace(path, "&amp;", "&");
120    
121                            // Reset portlet URL settings so it can be reused
122    
123                            _liferayPortletURL.setLifecycle(PortletRequest.RENDER_PHASE);
124                            _liferayPortletURL.setParameters(new HashMap<String, String[]>());
125    
126                            try {
127                                    _liferayPortletURL.setWindowState(_windowState);
128                            }
129                            catch (WindowStateException wse) {
130                            }
131    
132                            try {
133                                    _liferayPortletURL.setPortletMode(_portletMode);
134                            }
135                            catch (PortletModeException pme) {
136                            }
137    
138                            // Separate the Struts action from the query string
139    
140                            String strutsAction = path;
141                            String queryString = StringPool.BLANK;
142    
143                            int pos = strutsAction.indexOf(StringPool.QUESTION);
144    
145                            if (pos != -1) {
146                                    strutsAction = path.substring(0, pos);
147                                    queryString = path.substring(pos + 1, path.length());
148                            }
149    
150                            // Set the Struts action
151    
152                            if (strutsAction.startsWith("c/")) {
153                                    strutsAction = strutsAction.substring(1);
154                            }
155                            else if (strutsAction.startsWith("/c/")) {
156                                    strutsAction = strutsAction.substring(2);
157                            }
158    
159                            if (Validator.isNotNull(_contextPath)) {
160                                    strutsAction = strutsAction.substring(
161                                            _contextPath.length(), strutsAction.length());
162                            }
163    
164                            if (strutsAction.startsWith(_servletMapping)) {
165                                    strutsAction = strutsAction.substring(
166                                            _servletMapping.length(), strutsAction.length());
167                            }
168    
169                            if (!strutsAction.startsWith(StringPool.SLASH)) {
170                                    strutsAction = StringPool.SLASH + strutsAction;
171                            }
172    
173                            if (_log.isDebugEnabled()) {
174                                    _log.debug("Struts action " + strutsAction);
175                            }
176    
177                            _liferayPortletURL.setParameter("struts_action", strutsAction);
178    
179                            // Set the query string
180    
181                            setParameters(_liferayPortletURL, queryString);
182    
183                            // Return the portlet URL
184    
185                            encodedURL = _liferayPortletURL.toString();
186    
187                            if (_log.isDebugEnabled()) {
188                                    _log.debug("Encoded portlet URL " + encodedURL);
189                            }
190                    }
191    
192                    return encodedURL;
193            }
194    
195            private void _setServletMapping(String servletMapping) {
196                    if (servletMapping != null) {
197    
198                            // See org.apache.struts.util.RequestUtils.getActionMappingURL
199    
200                            if (servletMapping.endsWith("/*")) {
201                                    int pos = 0;
202    
203                                    if (servletMapping.startsWith(_mainPath)) {
204                                            pos = _mainPath.length() - 2;
205                                    }
206    
207                                    _servletMapping = servletMapping.substring(
208                                            pos, servletMapping.length() - 1);
209                            }
210                    }
211            }
212    
213            private static Log _log = LogFactoryUtil.getLog(StrutsURLEncoder.class);
214    
215            private String _contextPath;
216            private LiferayPortletURL _liferayPortletURL;
217            private String _mainPath;
218            private PortletMode _portletMode;
219            private String _servletMapping = StringPool.BLANK;
220            private WindowState _windowState;
221    
222    }