001    /**
002     * Copyright (c) 2000-2013 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.servlet;
016    
017    import com.liferay.portal.NoSuchLayoutException;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.servlet.PortalMessages;
021    import com.liferay.portal.kernel.servlet.SessionMessages;
022    import com.liferay.portal.kernel.struts.LastPath;
023    import com.liferay.portal.kernel.util.CharPool;
024    import com.liferay.portal.kernel.util.GetterUtil;
025    import com.liferay.portal.kernel.util.LocaleUtil;
026    import com.liferay.portal.kernel.util.Validator;
027    import com.liferay.portal.model.Group;
028    import com.liferay.portal.model.Layout;
029    import com.liferay.portal.model.LayoutFriendlyURL;
030    import com.liferay.portal.model.LayoutFriendlyURLComposite;
031    import com.liferay.portal.model.User;
032    import com.liferay.portal.service.GroupLocalServiceUtil;
033    import com.liferay.portal.service.LayoutFriendlyURLLocalServiceUtil;
034    import com.liferay.portal.service.ServiceContext;
035    import com.liferay.portal.service.ServiceContextFactory;
036    import com.liferay.portal.service.ServiceContextThreadLocal;
037    import com.liferay.portal.service.UserLocalServiceUtil;
038    import com.liferay.portal.util.Portal;
039    import com.liferay.portal.util.PortalInstances;
040    import com.liferay.portal.util.PortalUtil;
041    import com.liferay.portal.util.WebKeys;
042    
043    import java.io.IOException;
044    
045    import java.util.HashMap;
046    import java.util.List;
047    import java.util.Locale;
048    import java.util.Map;
049    
050    import javax.servlet.RequestDispatcher;
051    import javax.servlet.ServletConfig;
052    import javax.servlet.ServletContext;
053    import javax.servlet.ServletException;
054    import javax.servlet.http.HttpServlet;
055    import javax.servlet.http.HttpServletRequest;
056    import javax.servlet.http.HttpServletResponse;
057    
058    /**
059     * @author Brian Wing Shun Chan
060     * @author Jorge Ferrer
061     * @author Shuyang Zhou
062     */
063    public class FriendlyURLServlet extends HttpServlet {
064    
065            @Override
066            public void init(ServletConfig servletConfig) throws ServletException {
067                    super.init(servletConfig);
068    
069                    _private = GetterUtil.getBoolean(
070                            servletConfig.getInitParameter("private"));
071                    _user = GetterUtil.getBoolean(servletConfig.getInitParameter("user"));
072    
073                    if (_private) {
074                            if (_user) {
075                                    _friendlyURLPathPrefix =
076                                            PortalUtil.getPathFriendlyURLPrivateUser();
077                            }
078                            else {
079                                    _friendlyURLPathPrefix =
080                                            PortalUtil.getPathFriendlyURLPrivateGroup();
081                            }
082                    }
083                    else {
084                            _friendlyURLPathPrefix = PortalUtil.getPathFriendlyURLPublic();
085                    }
086            }
087    
088            @Override
089            public void service(
090                            HttpServletRequest request, HttpServletResponse response)
091                    throws IOException, ServletException {
092    
093                    // Do not set the entire full main path. See LEP-456.
094    
095                    //String mainPath = (String)ctx.getAttribute(WebKeys.MAIN_PATH);
096                    String mainPath = Portal.PATH_MAIN;
097    
098                    String redirect = mainPath;
099    
100                    String pathInfo = request.getPathInfo();
101    
102                    String friendlyURL = _friendlyURLPathPrefix;
103    
104                    if (Validator.isNotNull(pathInfo)) {
105                            friendlyURL = friendlyURL.concat(pathInfo);
106                    }
107    
108                    request.setAttribute(WebKeys.FRIENDLY_URL, friendlyURL);
109    
110                    Object[] redirectArray = null;
111    
112                    boolean forcePermanentRedirect = false;
113    
114                    try {
115                            redirectArray = getRedirect(
116                                    request, pathInfo, mainPath, request.getParameterMap());
117    
118                            redirect = (String)redirectArray[0];
119                            forcePermanentRedirect = (Boolean)redirectArray[1];
120    
121                            if (request.getAttribute(WebKeys.LAST_PATH) == null) {
122                                    LastPath lastPath = new LastPath(
123                                            _friendlyURLPathPrefix, pathInfo,
124                                            request.getParameterMap());
125    
126                                    request.setAttribute(WebKeys.LAST_PATH, lastPath);
127                            }
128                    }
129                    catch (NoSuchLayoutException nsle) {
130                            _log.warn(nsle);
131    
132                            PortalUtil.sendError(
133                                    HttpServletResponse.SC_NOT_FOUND, nsle, request, response);
134    
135                            return;
136                    }
137                    catch (Exception e) {
138                            if (_log.isWarnEnabled()) {
139                                    _log.warn(e);
140                            }
141                    }
142    
143                    if (Validator.isNull(redirect)) {
144                            redirect = mainPath;
145                    }
146    
147                    if (_log.isDebugEnabled()) {
148                            _log.debug("Redirect " + redirect);
149                    }
150    
151                    if ((redirect.charAt(0) == CharPool.SLASH) && !forcePermanentRedirect) {
152                            ServletContext servletContext = getServletContext();
153    
154                            RequestDispatcher requestDispatcher =
155                                    servletContext.getRequestDispatcher(redirect);
156    
157                            if (requestDispatcher != null) {
158                                    requestDispatcher.forward(request, response);
159                            }
160                    }
161                    else {
162                            if (forcePermanentRedirect) {
163                                    response.setHeader("Location", redirect);
164                                    response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
165                            }
166                            else {
167                                    response.sendRedirect(redirect);
168                            }
169                    }
170            }
171    
172            protected Object[] getRedirect(
173                            HttpServletRequest request, String path, String mainPath,
174                            Map<String, String[]> params)
175                    throws Exception {
176    
177                    if (Validator.isNull(path) || (path.charAt(0) != CharPool.SLASH)) {
178                            return new Object[] {mainPath, false};
179                    }
180    
181                    // Group friendly URL
182    
183                    String friendlyURL = null;
184    
185                    int pos = path.indexOf(CharPool.SLASH, 1);
186    
187                    if (pos != -1) {
188                            friendlyURL = path.substring(0, pos);
189                    }
190                    else if (path.length() > 1) {
191                            friendlyURL = path;
192                    }
193    
194                    if (Validator.isNull(friendlyURL)) {
195                            return new Object[] {mainPath, Boolean.FALSE};
196                    }
197    
198                    long companyId = PortalInstances.getCompanyId(request);
199    
200                    Group group = GroupLocalServiceUtil.fetchFriendlyURLGroup(
201                            companyId, friendlyURL);
202    
203                    if (group == null) {
204                            String screenName = friendlyURL.substring(1);
205    
206                            if (_user || !Validator.isNumber(screenName)) {
207                                    User user = UserLocalServiceUtil.fetchUserByScreenName(
208                                            companyId, screenName);
209    
210                                    if (user != null) {
211                                            group = user.getGroup();
212                                    }
213                                    else if (_log.isWarnEnabled()) {
214                                            _log.warn("No user exists with friendly URL " + screenName);
215                                    }
216                            }
217                            else {
218                                    long groupId = GetterUtil.getLong(screenName);
219    
220                                    group = GroupLocalServiceUtil.fetchGroup(groupId);
221    
222                                    if (group == null) {
223                                            if (_log.isDebugEnabled()) {
224                                                    _log.debug(
225                                                            "No group exists with friendly URL " + groupId +
226                                                                    ". Try fetching by screen name instead.");
227                                            }
228    
229                                            User user = UserLocalServiceUtil.fetchUserByScreenName(
230                                                    companyId, screenName);
231    
232                                            if (user != null) {
233                                                    group = user.getGroup();
234                                            }
235                                            else if (_log.isWarnEnabled()) {
236                                                    _log.warn(
237                                                            "No user or group exists with friendly URL " +
238                                                                    groupId);
239                                            }
240                                    }
241                            }
242                    }
243    
244                    if (group == null) {
245                            return new Object[] {mainPath, Boolean.FALSE};
246                    }
247    
248                    // Layout friendly URL
249    
250                    friendlyURL = null;
251    
252                    if ((pos != -1) && ((pos + 1) != path.length())) {
253                            friendlyURL = path.substring(pos);
254                    }
255    
256                    if (Validator.isNull(friendlyURL)) {
257                            request.setAttribute(
258                                    WebKeys.REDIRECT_TO_DEFAULT_LAYOUT, Boolean.TRUE);
259                    }
260    
261                    Map<String, Object> requestContext = new HashMap<String, Object>();
262    
263                    requestContext.put("request", request);
264    
265                    ServiceContext serviceContext =
266                            ServiceContextThreadLocal.getServiceContext();
267    
268                    if (serviceContext == null) {
269                            serviceContext = ServiceContextFactory.getInstance(request);
270    
271                            ServiceContextThreadLocal.pushServiceContext(serviceContext);
272                    }
273    
274                    String actualURL = PortalUtil.getActualURL(
275                            group.getGroupId(), _private, mainPath, friendlyURL, params,
276                            requestContext);
277    
278                    if (Validator.isNotNull(friendlyURL)) {
279                            Locale locale = PortalUtil.getLocale(request);
280    
281                            LayoutFriendlyURLComposite layoutFriendlyURLComposite =
282                                    PortalUtil.getLayoutFriendlyURLComposite(
283                                            group.getGroupId(), _private, friendlyURL, params,
284                                            requestContext);
285    
286                            Layout layout = layoutFriendlyURLComposite.getLayout();
287    
288                            friendlyURL = layoutFriendlyURLComposite.getFriendlyURL();
289    
290                            pos = friendlyURL.indexOf(Portal.FRIENDLY_URL_SEPARATOR);
291    
292                            if (pos != 0) {
293                                    if (pos != -1) {
294                                            friendlyURL = friendlyURL.substring(0, pos);
295                                    }
296    
297                                    if (!friendlyURL.equals(layout.getFriendlyURL(locale))) {
298                                            setAlternativeLayoutFriendlyURL(
299                                                    request, layout, friendlyURL);
300    
301                                            String redirect = PortalUtil.getLocalizedFriendlyURL(
302                                                    request, layout, locale);
303    
304                                            return new Object[] {redirect, Boolean.TRUE};
305                                    }
306                            }
307                    }
308    
309                    return new Object[] {actualURL, Boolean.FALSE};
310            }
311    
312            protected void setAlternativeLayoutFriendlyURL(
313                            HttpServletRequest request, Layout layout, String friendlyURL)
314                    throws Exception {
315    
316                    List<LayoutFriendlyURL> layoutFriendlyURLs =
317                            LayoutFriendlyURLLocalServiceUtil.getLayoutFriendlyURLs(
318                                    layout.getPlid(), friendlyURL, 0, 1);
319    
320                    if (layoutFriendlyURLs.isEmpty()) {
321                            return;
322                    }
323    
324                    LayoutFriendlyURL layoutFriendlyURL = layoutFriendlyURLs.get(0);
325    
326                    Locale locale = LocaleUtil.fromLanguageId(
327                            layoutFriendlyURL.getLanguageId());
328    
329                    String alternativeLayoutFriendlyURL =
330                            PortalUtil.getLocalizedFriendlyURL(request, layout, locale);
331    
332                    SessionMessages.add(
333                            request, "alternativeLayoutFriendlyURL",
334                            alternativeLayoutFriendlyURL);
335    
336                    PortalMessages.add(
337                            request, PortalMessages.KEY_JSP_PATH,
338                            "/html/common/themes/layout_friendly_url_redirect.jsp");
339            }
340    
341            private static Log _log = LogFactoryUtil.getLog(FriendlyURLServlet.class);
342    
343            private String _friendlyURLPathPrefix;
344            private boolean _private;
345            private boolean _user;
346    
347    }