001
014
015 package com.liferay.portal.servlet;
016
017 import com.liferay.portal.kernel.exception.NoSuchLayoutException;
018 import com.liferay.portal.kernel.language.LanguageUtil;
019 import com.liferay.portal.kernel.log.Log;
020 import com.liferay.portal.kernel.log.LogFactoryUtil;
021 import com.liferay.portal.kernel.util.CharPool;
022 import com.liferay.portal.kernel.util.GetterUtil;
023 import com.liferay.portal.kernel.util.HashUtil;
024 import com.liferay.portal.kernel.util.LocaleUtil;
025 import com.liferay.portal.kernel.util.PortalUtil;
026 import com.liferay.portal.kernel.util.StringPool;
027 import com.liferay.portal.kernel.util.Validator;
028 import com.liferay.portal.kernel.util.WebKeys;
029 import com.liferay.portal.kernel.xml.Element;
030 import com.liferay.portal.util.PropsValues;
031
032 import java.io.IOException;
033
034 import java.util.Collections;
035 import java.util.HashSet;
036 import java.util.List;
037 import java.util.Locale;
038 import java.util.Objects;
039 import java.util.Set;
040
041 import javax.servlet.RequestDispatcher;
042 import javax.servlet.ServletContext;
043 import javax.servlet.ServletException;
044 import javax.servlet.http.HttpServlet;
045 import javax.servlet.http.HttpServletRequest;
046 import javax.servlet.http.HttpServletResponse;
047 import javax.servlet.http.HttpSession;
048
049 import org.apache.struts.Globals;
050
051
054 public class I18nServlet extends HttpServlet {
055
056 public static Set<String> getLanguageIds() {
057 return _languageIds;
058 }
059
060 public static void setLanguageIds(Element root) {
061 _languageIds = new HashSet<>();
062
063 List<Element> rootElements = root.elements("servlet-mapping");
064
065 for (Element element : rootElements) {
066 String servletName = element.elementText("servlet-name");
067
068 if (servletName.equals("I18n Servlet")) {
069 String urlPattern = element.elementText("url-pattern");
070
071 String languageId = urlPattern.substring(
072 0, urlPattern.lastIndexOf(CharPool.SLASH));
073
074 _languageIds.add(languageId);
075 }
076 }
077
078 _languageIds = Collections.unmodifiableSet(_languageIds);
079 }
080
081 @Override
082 public void service(
083 HttpServletRequest request, HttpServletResponse response)
084 throws IOException, ServletException {
085
086 try {
087 I18nData i18nData = getI18nData(request);
088
089 if ((i18nData == null) ||
090 !PortalUtil.isValidResourceId(i18nData.getPath())) {
091
092 PortalUtil.sendError(
093 HttpServletResponse.SC_NOT_FOUND,
094 new NoSuchLayoutException(), request, response);
095 }
096 else {
097 request.setAttribute(
098 WebKeys.I18N_LANGUAGE_CODE, i18nData.getLanguageCode());
099 request.setAttribute(
100 WebKeys.I18N_LANGUAGE_ID, i18nData.getLanguageId());
101 request.setAttribute(WebKeys.I18N_PATH, i18nData.getI18nPath());
102
103 Locale locale = LocaleUtil.fromLanguageId(
104 i18nData.getLanguageId(), false, false);
105
106 HttpSession session = request.getSession();
107
108 session.setAttribute(Globals.LOCALE_KEY, locale);
109
110 LanguageUtil.updateCookie(request, response, locale);
111
112 ServletContext servletContext = getServletContext();
113
114 RequestDispatcher requestDispatcher =
115 servletContext.getRequestDispatcher(i18nData.getPath());
116
117 requestDispatcher.forward(request, response);
118 }
119 }
120 catch (Exception e) {
121 _log.error(e, e);
122
123 PortalUtil.sendError(
124 HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e, request,
125 response);
126 }
127 }
128
129 protected I18nData getI18nData(HttpServletRequest request) {
130 String path = GetterUtil.getString(request.getPathInfo());
131
132 if (Validator.isNull(path)) {
133 return null;
134 }
135
136 String i18nLanguageId = request.getServletPath();
137
138 int pos = i18nLanguageId.lastIndexOf(CharPool.SLASH);
139
140 i18nLanguageId = i18nLanguageId.substring(pos + 1);
141
142 if (_log.isDebugEnabled()) {
143 _log.debug("Language ID " + i18nLanguageId);
144 }
145
146 if (Validator.isNull(i18nLanguageId)) {
147 return null;
148 }
149
150 String i18nPath = StringPool.SLASH + i18nLanguageId;
151
152 Locale locale = LocaleUtil.fromLanguageId(i18nLanguageId, true, false);
153
154 String i18nLanguageCode = i18nLanguageId;
155
156 if ((locale == null) || Validator.isNull(locale.getCountry())) {
157
158
159
160 locale = LanguageUtil.getLocale(i18nLanguageCode);
161 }
162
163 if (locale != null) {
164 i18nLanguageId = LocaleUtil.toLanguageId(locale);
165
166 i18nLanguageCode = locale.getLanguage();
167 }
168
169 if (!PropsValues.LOCALE_USE_DEFAULT_IF_NOT_AVAILABLE &&
170 !LanguageUtil.isAvailableLocale(i18nLanguageId)) {
171
172 return null;
173 }
174
175 String redirect = path;
176
177 if (_log.isDebugEnabled()) {
178 _log.debug("Redirect " + redirect);
179 }
180
181 return new I18nData(
182 i18nPath, i18nLanguageCode, i18nLanguageId, redirect);
183 }
184
185 protected I18nData getI18nData(Locale locale) {
186 String languageId = LocaleUtil.toLanguageId(locale);
187
188 return new I18nData(
189 StringPool.SLASH + languageId, locale.getLanguage(), languageId,
190 StringPool.SLASH);
191 }
192
193 protected class I18nData {
194
195 public I18nData(
196 String i18nPath, String languageCode, String languageId,
197 String path) {
198
199 _i18nPath = i18nPath;
200 _languageCode = languageCode;
201 _languageId = languageId;
202 _path = path;
203 }
204
205 @Override
206 public boolean equals(Object obj) {
207 if (this == obj) {
208 return true;
209 }
210
211 if (!(obj instanceof I18nData)) {
212 return false;
213 }
214
215 I18nData i18nData = (I18nData)obj;
216
217 if (Objects.equals(getI18nPath(), i18nData.getI18nPath()) &&
218 Objects.equals(
219 getLanguageCode(), i18nData.getLanguageCode()) &&
220 Objects.equals(getLanguageId(), i18nData.getLanguageId()) &&
221 Objects.equals(getPath(), i18nData.getPath())) {
222
223 return true;
224 }
225
226 return false;
227 }
228
229 public String getI18nPath() {
230 return _i18nPath;
231 }
232
233 public String getLanguageCode() {
234 return _languageCode;
235 }
236
237 public String getLanguageId() {
238 return _languageId;
239 }
240
241 public String getPath() {
242 return _path;
243 }
244
245 @Override
246 public int hashCode() {
247 int hash = HashUtil.hash(0, getI18nPath());
248
249 hash = HashUtil.hash(hash, getLanguageCode());
250 hash = HashUtil.hash(hash, getLanguageId());
251
252 return HashUtil.hash(hash, getPath());
253 }
254
255 private final String _i18nPath;
256 private final String _languageCode;
257 private final String _languageId;
258 private final String _path;
259
260 }
261
262 private static final Log _log = LogFactoryUtil.getLog(I18nServlet.class);
263
264 private static Set<String> _languageIds;
265
266 }