001
014
015 package com.liferay.portal.servlet.filters.i18n;
016
017 import com.liferay.portal.kernel.language.LanguageUtil;
018 import com.liferay.portal.kernel.log.Log;
019 import com.liferay.portal.kernel.log.LogFactoryUtil;
020 import com.liferay.portal.kernel.util.CharPool;
021 import com.liferay.portal.kernel.util.LocaleUtil;
022 import com.liferay.portal.kernel.util.StringPool;
023 import com.liferay.portal.kernel.util.StringUtil;
024 import com.liferay.portal.kernel.util.Validator;
025 import com.liferay.portal.model.Group;
026 import com.liferay.portal.model.LayoutSet;
027 import com.liferay.portal.servlet.filters.BasePortalFilter;
028 import com.liferay.portal.util.CookieKeys;
029 import com.liferay.portal.util.PortalUtil;
030 import com.liferay.portal.util.PropsValues;
031 import com.liferay.portal.util.WebKeys;
032
033 import java.util.Collections;
034 import java.util.HashSet;
035 import java.util.Locale;
036 import java.util.Set;
037
038 import javax.servlet.FilterChain;
039 import javax.servlet.http.HttpServletRequest;
040 import javax.servlet.http.HttpServletResponse;
041
042
045 public class I18nFilter extends BasePortalFilter {
046
047 public static final String SKIP_FILTER =
048 I18nFilter.class.getName() + "SKIP_FILTER";
049
050 public static Set<String> getLanguageIds() {
051 return _languageIds;
052 }
053
054 public static void setLanguageIds(Set<String> languageIds) {
055 for (String languageId : languageIds) {
056 languageId = languageId.substring(1);
057
058 _languageIds.add(languageId);
059 }
060
061 _languageIds = Collections.unmodifiableSet(_languageIds);
062 }
063
064 protected String getRedirect(HttpServletRequest request) throws Exception {
065 if (PropsValues.LOCALE_PREPEND_FRIENDLY_URL_STYLE == 0) {
066 return null;
067 }
068
069 String contextPath = PortalUtil.getPathContext();
070
071 String requestURI = request.getRequestURI();
072
073 if ((Validator.isNotNull(contextPath)) &&
074 (requestURI.indexOf(contextPath) != -1)) {
075
076 requestURI = requestURI.substring(contextPath.length());
077 }
078
079 requestURI = StringUtil.replace(
080 requestURI, StringPool.DOUBLE_SLASH, StringPool.SLASH);
081
082 String i18nLanguageId = requestURI.substring(1);
083
084 int pos = requestURI.indexOf(CharPool.SLASH, 1);
085
086 if (pos != -1) {
087 i18nLanguageId = i18nLanguageId.substring(0, pos - 1);
088 }
089
090 if (_languageIds.contains(i18nLanguageId)) {
091 return null;
092 }
093
094 String defaultLanguageId = LocaleUtil.toLanguageId(
095 LocaleUtil.getDefault());
096
097 String guestLanguageId = CookieKeys.getCookie(
098 request, CookieKeys.GUEST_LANGUAGE_ID);
099
100 if (Validator.isNull(guestLanguageId)) {
101 guestLanguageId = defaultLanguageId;
102 }
103
104 if (PropsValues.LOCALE_PREPEND_FRIENDLY_URL_STYLE == 1) {
105 if (!defaultLanguageId.equals(guestLanguageId)) {
106 i18nLanguageId = guestLanguageId;
107 }
108 else {
109 return null;
110 }
111 }
112 else if (PropsValues.LOCALE_PREPEND_FRIENDLY_URL_STYLE == 2) {
113 i18nLanguageId = guestLanguageId;
114 }
115
116 if (i18nLanguageId == null) {
117 return null;
118 }
119
120 String i18nPath = StringPool.SLASH + i18nLanguageId;
121
122 Locale locale = LocaleUtil.fromLanguageId(i18nLanguageId);
123
124 if (!LanguageUtil.isDuplicateLanguageCode(locale.getLanguage())) {
125 i18nPath = StringPool.SLASH + locale.getLanguage();
126 }
127 else {
128 Locale priorityLocale = LanguageUtil.getLocale(
129 locale.getLanguage());
130
131 if (locale.equals(priorityLocale)) {
132 i18nPath = StringPool.SLASH + locale.getLanguage();
133 }
134 }
135
136 String redirect = contextPath + i18nPath + requestURI;
137
138 LayoutSet layoutSet = (LayoutSet)request.getAttribute(
139 WebKeys.VIRTUAL_HOST_LAYOUT_SET);
140
141 if ((layoutSet != null) &&
142 (requestURI.startsWith(_PRIVATE_GROUP_SERVLET_MAPPING) ||
143 requestURI.startsWith(_PRIVATE_USER_SERVLET_MAPPING) ||
144 requestURI.startsWith(_PUBLIC_GROUP_SERVLET_MAPPING))) {
145
146 int x = requestURI.indexOf(StringPool.SLASH, 1);
147
148 if (x == -1) {
149
150
151
152 requestURI += StringPool.SLASH;
153
154 x = requestURI.indexOf(CharPool.SLASH, 1);
155 }
156
157 int y = requestURI.indexOf(CharPool.SLASH, x + 1);
158
159 if (y == -1) {
160
161
162
163 requestURI += StringPool.SLASH;
164
165 y = requestURI.indexOf(CharPool.SLASH, x + 1);
166 }
167
168 String groupFriendlyURL = requestURI.substring(x, y);
169
170 Group group = layoutSet.getGroup();
171
172 if (group.getFriendlyURL().equals(groupFriendlyURL)) {
173 redirect = contextPath + i18nPath + requestURI.substring(y);
174 }
175 }
176
177 String queryString = request.getQueryString();
178
179 if (Validator.isNotNull(queryString)) {
180 redirect += StringPool.QUESTION + request.getQueryString();
181 }
182
183 return redirect;
184 }
185
186 protected boolean isAlreadyFiltered(HttpServletRequest request) {
187 if (request.getAttribute(SKIP_FILTER) != null) {
188 return true;
189 }
190 else {
191 return false;
192 }
193 }
194
195 protected boolean isForwardedByI18nServlet(HttpServletRequest request) {
196 if ((request.getAttribute(WebKeys.I18N_LANGUAGE_ID) != null) ||
197 (request.getAttribute(WebKeys.I18N_PATH) != null)) {
198
199 return true;
200 }
201 else {
202 return false;
203 }
204 }
205
206 protected void processFilter(
207 HttpServletRequest request, HttpServletResponse response,
208 FilterChain filterChain)
209 throws Exception {
210
211 if (isAlreadyFiltered(request) || isForwardedByI18nServlet(request)) {
212 processFilter(I18nFilter.class, request, response, filterChain);
213
214 return;
215 }
216
217 request.setAttribute(SKIP_FILTER, Boolean.TRUE);
218
219 String redirect = getRedirect(request);
220
221 if (redirect == null) {
222 processFilter(I18nFilter.class, request, response, filterChain);
223
224 return;
225 }
226
227 if (_log.isDebugEnabled()) {
228 _log.debug("Redirect " + redirect);
229 }
230
231 response.sendRedirect(redirect);
232 }
233
234 private static Log _log = LogFactoryUtil.getLog(I18nFilter.class);
235
236 private static final String _PRIVATE_GROUP_SERVLET_MAPPING =
237 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
238
239 private static final String _PRIVATE_USER_SERVLET_MAPPING =
240 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
241
242 private static final String _PUBLIC_GROUP_SERVLET_MAPPING =
243 PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
244
245 private static Set<String> _languageIds = new HashSet<String>();
246
247 }