001    /**
002     * Copyright (c) 2000-2013 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.servlet.filters.i18n;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.language.LanguageUtil;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.servlet.HttpMethods;
023    import com.liferay.portal.kernel.util.CookieKeys;
024    import com.liferay.portal.kernel.util.LocaleUtil;
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    import com.liferay.portal.model.Group;
029    import com.liferay.portal.model.LayoutSet;
030    import com.liferay.portal.model.User;
031    import com.liferay.portal.service.GroupLocalServiceUtil;
032    import com.liferay.portal.servlet.filters.BasePortalFilter;
033    import com.liferay.portal.util.PortalUtil;
034    import com.liferay.portal.util.PropsValues;
035    import com.liferay.portal.util.WebKeys;
036    
037    import java.util.Collections;
038    import java.util.HashSet;
039    import java.util.Locale;
040    import java.util.Set;
041    
042    import javax.servlet.FilterChain;
043    import javax.servlet.http.HttpServletRequest;
044    import javax.servlet.http.HttpServletResponse;
045    import javax.servlet.http.HttpSession;
046    
047    import org.apache.struts.Globals;
048    
049    /**
050     * @author Brian Wing Shun Chan
051     */
052    public class I18nFilter extends BasePortalFilter {
053    
054            public static final String SKIP_FILTER =
055                    I18nFilter.class.getName() + "SKIP_FILTER";
056    
057            public static Set<String> getLanguageIds() {
058                    return _languageIds;
059            }
060    
061            public static void setLanguageIds(Set<String> languageIds) {
062                    _languageIds = new HashSet<String>();
063    
064                    for (String languageId : languageIds) {
065                            languageId = languageId.substring(1);
066    
067                            _languageIds.add(languageId);
068                    }
069    
070                    _languageIds = Collections.unmodifiableSet(_languageIds);
071            }
072    
073            @Override
074            public boolean isFilterEnabled(
075                    HttpServletRequest request, HttpServletResponse response) {
076    
077                    if (!isAlreadyFiltered(request) && !isForwardedByI18nServlet(request) &&
078                            !isWidget(request)) {
079    
080                            return true;
081                    }
082                    else {
083                            return false;
084                    }
085            }
086    
087            protected String getDefaultLanguageId(HttpServletRequest request) {
088                    String defaultLanguageId = getSiteDefaultLanguageId(request);
089    
090                    if (Validator.isNull(defaultLanguageId)) {
091                            defaultLanguageId = LocaleUtil.toLanguageId(
092                                    LocaleUtil.getDefault());
093                    }
094    
095                    return defaultLanguageId;
096            }
097    
098            protected String getFriendlyURL(HttpServletRequest request) {
099                    String friendlyURL = StringPool.BLANK;
100    
101                    String pathInfo = request.getPathInfo();
102    
103                    if (Validator.isNotNull(pathInfo)) {
104                            String[] pathInfoElements = pathInfo.split("/");
105    
106                            if (Validator.isNotNull(pathInfoElements) &&
107                                    (pathInfoElements.length > 1)) {
108    
109                                    friendlyURL = StringPool.SLASH + pathInfoElements[1];
110                            }
111                    }
112    
113                    return friendlyURL;
114            }
115    
116            protected String getRedirect(HttpServletRequest request) throws Exception {
117                    if (PropsValues.LOCALE_PREPEND_FRIENDLY_URL_STYLE == 0) {
118                            return null;
119                    }
120    
121                    String method = request.getMethod();
122    
123                    if (method.equals(HttpMethods.POST)) {
124                            return null;
125                    }
126    
127                    String contextPath = PortalUtil.getPathContext();
128    
129                    String requestURI = request.getRequestURI();
130    
131                    if (Validator.isNotNull(contextPath) &&
132                            requestURI.contains(contextPath)) {
133    
134                            requestURI = requestURI.substring(contextPath.length());
135                    }
136    
137                    requestURI = StringUtil.replace(
138                            requestURI, StringPool.DOUBLE_SLASH, StringPool.SLASH);
139    
140                    String i18nLanguageId = prependI18nLanguageId(
141                            request, PropsValues.LOCALE_PREPEND_FRIENDLY_URL_STYLE);
142    
143                    if (i18nLanguageId == null) {
144                            return null;
145                    }
146    
147                    Locale locale = LocaleUtil.fromLanguageId(i18nLanguageId);
148    
149                    if (!LanguageUtil.isAvailableLocale(locale)) {
150                            return null;
151                    }
152    
153                    String i18nPathLanguageId = PortalUtil.getI18nPathLanguageId(
154                            locale, i18nLanguageId);
155    
156                    String i18nPath = StringPool.SLASH.concat(i18nPathLanguageId);
157    
158                    if (requestURI.contains(i18nPath.concat(StringPool.SLASH))) {
159                            return null;
160                    }
161    
162                    String redirect = contextPath + i18nPath + requestURI;
163    
164                    int[] groupFriendlyURLIndex = PortalUtil.getGroupFriendlyURLIndex(
165                            requestURI);
166    
167                    String groupFriendlyURL = StringPool.BLANK;
168    
169                    int friendlyURLStart = 0;
170                    int friendlyURLEnd = 0;
171    
172                    if (groupFriendlyURLIndex != null) {
173                            friendlyURLStart = groupFriendlyURLIndex[0];
174                            friendlyURLEnd = groupFriendlyURLIndex[1];
175    
176                            groupFriendlyURL = requestURI.substring(
177                                    friendlyURLStart, friendlyURLEnd);
178                    }
179    
180                    long companyId = PortalUtil.getCompanyId(request);
181    
182                    Group friendlyURLGroup = GroupLocalServiceUtil.fetchFriendlyURLGroup(
183                            companyId, groupFriendlyURL);
184    
185                    if ((friendlyURLGroup != null) &&
186                            !LanguageUtil.isAvailableLocale(
187                                    friendlyURLGroup.getGroupId(), i18nLanguageId)) {
188    
189                            return null;
190                    }
191    
192                    LayoutSet layoutSet = (LayoutSet)request.getAttribute(
193                            WebKeys.VIRTUAL_HOST_LAYOUT_SET);
194    
195                    if ((layoutSet != null) &&
196                            requestURI.startsWith(
197                                    PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING)) {
198    
199                            Group group = layoutSet.getGroup();
200    
201                            if (groupFriendlyURL.equals(group.getFriendlyURL())) {
202                                    redirect =
203                                            contextPath + i18nPath +
204                                                    requestURI.substring(friendlyURLEnd);
205                            }
206                    }
207    
208                    String queryString = request.getQueryString();
209    
210                    if (Validator.isNotNull(queryString)) {
211                            redirect += StringPool.QUESTION + request.getQueryString();
212                    }
213    
214                    return redirect;
215            }
216    
217            protected String getRequestedLanguageId(
218                    HttpServletRequest request, String userLanguageId) {
219    
220                    HttpSession session = request.getSession();
221    
222                    Locale locale = (Locale)session.getAttribute(Globals.LOCALE_KEY);
223    
224                    String requestedLanguageId = null;
225    
226                    if (Validator.isNotNull(locale)) {
227                            requestedLanguageId = LocaleUtil.toLanguageId(locale);
228                    }
229    
230                    if (Validator.isNull(requestedLanguageId)) {
231                            requestedLanguageId = userLanguageId;
232                    }
233    
234                    if (Validator.isNull(requestedLanguageId)) {
235                            requestedLanguageId = CookieKeys.getCookie(
236                                    request, CookieKeys.GUEST_LANGUAGE_ID, false);
237                    }
238    
239                    return requestedLanguageId;
240            }
241    
242            protected String getSiteDefaultLanguageId(HttpServletRequest request) {
243                    String friendlyURL = getFriendlyURL(request);
244    
245                    long companyId = PortalUtil.getCompanyId(request);
246    
247                    try {
248                            Group group = GroupLocalServiceUtil.getFriendlyURLGroup(
249                                    companyId, friendlyURL);
250    
251                            Locale siteDefaultLocale = PortalUtil.getSiteDefaultLocale(
252                                    group.getGroupId());
253    
254                            return LocaleUtil.toLanguageId(siteDefaultLocale);
255                    }
256                    catch (PortalException pe) {
257                            if (_log.isDebugEnabled()) {
258                                    pe.printStackTrace();
259                            }
260    
261                            return StringPool.BLANK;
262                    }
263                    catch (SystemException se) {
264                            if (_log.isDebugEnabled()) {
265                                    se.printStackTrace();
266                            }
267    
268                            return StringPool.BLANK;
269                    }
270            }
271    
272            protected boolean isAlreadyFiltered(HttpServletRequest request) {
273                    if (request.getAttribute(SKIP_FILTER) != null) {
274                            return true;
275                    }
276                    else {
277                            return false;
278                    }
279            }
280    
281            protected boolean isForwardedByI18nServlet(HttpServletRequest request) {
282                    if ((request.getAttribute(WebKeys.I18N_LANGUAGE_ID) != null) ||
283                            (request.getAttribute(WebKeys.I18N_PATH) != null)) {
284    
285                            return true;
286                    }
287                    else {
288                            return false;
289                    }
290            }
291    
292            protected boolean isWidget(HttpServletRequest request) {
293                    if (request.getAttribute(WebKeys.WIDGET) != null) {
294                            return true;
295                    }
296                    else {
297                            return false;
298                    }
299            }
300    
301            protected String prependI18nLanguageId(
302                    HttpServletRequest request, int prependFriendlyUrlStyle) {
303    
304                    User user = (User)request.getAttribute(WebKeys.USER);
305    
306                    String userLanguageId = null;
307    
308                    if (user != null) {
309                            userLanguageId = user.getLanguageId();
310                    }
311    
312                    String requestedLanguageId = getRequestedLanguageId(
313                            request, userLanguageId);
314    
315                    String defaultLanguageId = getDefaultLanguageId(request);
316    
317                    if (Validator.isNull(requestedLanguageId)) {
318                            requestedLanguageId = defaultLanguageId;
319                    }
320    
321                    if (prependFriendlyUrlStyle == 1) {
322                            return prependIfRequestedLocaleDiffersFromDefaultLocale(
323                                    defaultLanguageId, requestedLanguageId);
324                    }
325                    else if (prependFriendlyUrlStyle == 2) {
326                            return requestedLanguageId;
327                    }
328                    else if (prependFriendlyUrlStyle == 3) {
329                            if (user != null) {
330                                    if (userLanguageId.equals(requestedLanguageId)) {
331                                            return null;
332                                    }
333    
334                                    return requestedLanguageId;
335                            }
336                            else {
337                                    return prependIfRequestedLocaleDiffersFromDefaultLocale(
338                                            defaultLanguageId, requestedLanguageId);
339                            }
340                    }
341    
342                    return null;
343            }
344    
345            protected String prependIfRequestedLocaleDiffersFromDefaultLocale(
346                    String defaultLanguageId, String guestLanguageId) {
347    
348                    if (defaultLanguageId.equals(guestLanguageId)) {
349                            return null;
350                    }
351    
352                    return guestLanguageId;
353            }
354    
355            @Override
356            protected void processFilter(
357                            HttpServletRequest request, HttpServletResponse response,
358                            FilterChain filterChain)
359                    throws Exception {
360    
361                    request.setAttribute(SKIP_FILTER, Boolean.TRUE);
362    
363                    String redirect = getRedirect(request);
364    
365                    if (redirect == null) {
366                            processFilter(I18nFilter.class, request, response, filterChain);
367    
368                            return;
369                    }
370    
371                    if (_log.isDebugEnabled()) {
372                            _log.debug("Redirect " + redirect);
373                    }
374    
375                    response.sendRedirect(redirect);
376            }
377    
378            private static Log _log = LogFactoryUtil.getLog(I18nFilter.class);
379    
380            private static Set<String> _languageIds;
381    
382    }