001
014
015 package com.liferay.portal.servlet;
016
017 import com.liferay.portal.NoSuchGroupException;
018 import com.liferay.portal.NoSuchLayoutException;
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.PortalMessages;
023 import com.liferay.portal.kernel.servlet.SessionMessages;
024 import com.liferay.portal.kernel.struts.LastPath;
025 import com.liferay.portal.kernel.util.CharPool;
026 import com.liferay.portal.kernel.util.GetterUtil;
027 import com.liferay.portal.kernel.util.LocaleUtil;
028 import com.liferay.portal.kernel.util.ParamUtil;
029 import com.liferay.portal.kernel.util.StringBundler;
030 import com.liferay.portal.kernel.util.StringUtil;
031 import com.liferay.portal.kernel.util.Validator;
032 import com.liferay.portal.kernel.util.WebKeys;
033 import com.liferay.portal.model.Group;
034 import com.liferay.portal.model.Layout;
035 import com.liferay.portal.model.LayoutConstants;
036 import com.liferay.portal.model.LayoutFriendlyURL;
037 import com.liferay.portal.model.LayoutFriendlyURLComposite;
038 import com.liferay.portal.model.User;
039 import com.liferay.portal.service.GroupLocalServiceUtil;
040 import com.liferay.portal.service.LayoutFriendlyURLLocalServiceUtil;
041 import com.liferay.portal.service.LayoutLocalServiceUtil;
042 import com.liferay.portal.service.ServiceContext;
043 import com.liferay.portal.service.ServiceContextFactory;
044 import com.liferay.portal.service.ServiceContextThreadLocal;
045 import com.liferay.portal.service.UserLocalServiceUtil;
046 import com.liferay.portal.util.Portal;
047 import com.liferay.portal.util.PortalInstances;
048 import com.liferay.portal.util.PortalUtil;
049
050 import java.io.IOException;
051
052 import java.util.HashMap;
053 import java.util.List;
054 import java.util.Locale;
055 import java.util.Map;
056
057 import javax.servlet.RequestDispatcher;
058 import javax.servlet.ServletConfig;
059 import javax.servlet.ServletContext;
060 import javax.servlet.ServletException;
061 import javax.servlet.http.HttpServlet;
062 import javax.servlet.http.HttpServletRequest;
063 import javax.servlet.http.HttpServletResponse;
064
065
070 public class FriendlyURLServlet extends HttpServlet {
071
072 @Override
073 public void init(ServletConfig servletConfig) throws ServletException {
074 super.init(servletConfig);
075
076 _private = GetterUtil.getBoolean(
077 servletConfig.getInitParameter("private"));
078 _user = GetterUtil.getBoolean(servletConfig.getInitParameter("user"));
079
080 if (_private) {
081 if (_user) {
082 _friendlyURLPathPrefix =
083 PortalUtil.getPathFriendlyURLPrivateUser();
084 }
085 else {
086 _friendlyURLPathPrefix =
087 PortalUtil.getPathFriendlyURLPrivateGroup();
088 }
089 }
090 else {
091 _friendlyURLPathPrefix = PortalUtil.getPathFriendlyURLPublic();
092 }
093 }
094
095 @Override
096 public void service(
097 HttpServletRequest request, HttpServletResponse response)
098 throws IOException, ServletException {
099
100
101
102
103 String mainPath = Portal.PATH_MAIN;
104
105 String redirect = mainPath;
106
107 String pathInfo = getPathInfo(request);
108
109 request.setAttribute(WebKeys.FRIENDLY_URL, getFriendlyURL(pathInfo));
110
111 Object[] redirectArray = null;
112
113 boolean forcePermanentRedirect = false;
114
115 try {
116 redirectArray = getRedirect(
117 request, pathInfo, mainPath, request.getParameterMap());
118
119 redirect = (String)redirectArray[0];
120 forcePermanentRedirect = (Boolean)redirectArray[1];
121
122 if (request.getAttribute(WebKeys.LAST_PATH) == null) {
123 LastPath lastPath = null;
124
125 String lifecycle = ParamUtil.getString(
126 request, "p_p_lifecycle");
127
128 if (lifecycle.equals("1")) {
129 lastPath = new LastPath(_friendlyURLPathPrefix, pathInfo);
130 }
131 else {
132 lastPath = new LastPath(
133 _friendlyURLPathPrefix, pathInfo,
134 request.getParameterMap());
135 }
136
137 request.setAttribute(WebKeys.LAST_PATH, lastPath);
138 }
139 }
140 catch (Exception e) {
141 if (_log.isWarnEnabled()) {
142 _log.warn(e);
143 }
144
145 if ((e instanceof NoSuchGroupException) ||
146 (e instanceof NoSuchLayoutException)) {
147
148 PortalUtil.sendError(
149 HttpServletResponse.SC_NOT_FOUND, e, request, response);
150
151 return;
152 }
153 }
154
155 if (Validator.isNull(redirect)) {
156 redirect = mainPath;
157 }
158
159 if (_log.isDebugEnabled()) {
160 _log.debug("Redirect " + redirect);
161 }
162
163 if ((redirect.charAt(0) == CharPool.SLASH) && !forcePermanentRedirect) {
164 ServletContext servletContext = getServletContext();
165
166 RequestDispatcher requestDispatcher =
167 servletContext.getRequestDispatcher(redirect);
168
169 if (requestDispatcher != null) {
170 requestDispatcher.forward(request, response);
171 }
172 }
173 else {
174 if (forcePermanentRedirect) {
175 response.setHeader("Location", redirect);
176 response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
177 }
178 else {
179 response.sendRedirect(redirect);
180 }
181 }
182 }
183
184 protected String getFriendlyURL(String pathInfo) {
185 String friendlyURL = _friendlyURLPathPrefix;
186
187 if (Validator.isNotNull(pathInfo)) {
188 friendlyURL = friendlyURL.concat(pathInfo);
189 }
190
191 return friendlyURL;
192 }
193
194 protected String getPathInfo(HttpServletRequest request) {
195 String requestURI = request.getRequestURI();
196
197 int pos = requestURI.indexOf(Portal.JSESSIONID);
198
199 if (pos != -1) {
200 requestURI = requestURI.substring(0, pos);
201 }
202
203 String pathProxy = PortalUtil.getPathProxy();
204
205 pos = _friendlyURLPathPrefix.length() - pathProxy.length();
206
207 return requestURI.substring(pos);
208 }
209
210 protected Object[] getRedirect(
211 HttpServletRequest request, String path, String mainPath,
212 Map<String, String[]> params)
213 throws Exception {
214
215 if (Validator.isNull(path) || (path.charAt(0) != CharPool.SLASH)) {
216 return new Object[] {mainPath, false};
217 }
218
219
220
221 String friendlyURL = null;
222
223 int pos = path.indexOf(CharPool.SLASH, 1);
224
225 if (pos != -1) {
226 friendlyURL = path.substring(0, pos);
227 }
228 else if (path.length() > 1) {
229 friendlyURL = path;
230 }
231
232 if (Validator.isNull(friendlyURL)) {
233 return new Object[] {mainPath, Boolean.FALSE};
234 }
235
236 long companyId = PortalInstances.getCompanyId(request);
237
238 Group group = GroupLocalServiceUtil.fetchFriendlyURLGroup(
239 companyId, friendlyURL);
240
241 if (group == null) {
242 String screenName = friendlyURL.substring(1);
243
244 if (_user || !Validator.isNumber(screenName)) {
245 User user = UserLocalServiceUtil.fetchUserByScreenName(
246 companyId, screenName);
247
248 if (user != null) {
249 group = user.getGroup();
250 }
251 else if (_log.isWarnEnabled()) {
252 _log.warn("No user exists with friendly URL " + screenName);
253 }
254 }
255 else {
256 long groupId = GetterUtil.getLong(screenName);
257
258 group = GroupLocalServiceUtil.fetchGroup(groupId);
259
260 if (group == null) {
261 if (_log.isDebugEnabled()) {
262 _log.debug(
263 "No group exists with friendly URL " + groupId +
264 ". Try fetching by screen name instead.");
265 }
266
267 User user = UserLocalServiceUtil.fetchUserByScreenName(
268 companyId, screenName);
269
270 if (user != null) {
271 group = user.getGroup();
272 }
273 else if (_log.isWarnEnabled()) {
274 _log.warn(
275 "No user or group exists with friendly URL " +
276 groupId);
277 }
278 }
279 }
280 }
281
282 if (group == null) {
283 StringBundler sb = new StringBundler(5);
284
285 sb.append("{companyId=");
286 sb.append(companyId);
287 sb.append(", friendlyURL=");
288 sb.append(friendlyURL);
289 sb.append("}");
290
291 throw new NoSuchGroupException(sb.toString());
292 }
293
294
295
296 friendlyURL = null;
297
298 if ((pos != -1) && ((pos + 1) != path.length())) {
299 friendlyURL = path.substring(pos);
300 }
301
302 if (Validator.isNull(friendlyURL)) {
303 request.setAttribute(
304 WebKeys.REDIRECT_TO_DEFAULT_LAYOUT, Boolean.TRUE);
305 }
306
307 Map<String, Object> requestContext = new HashMap<>();
308
309 requestContext.put("request", request);
310
311 ServiceContext serviceContext =
312 ServiceContextThreadLocal.getServiceContext();
313
314 if (serviceContext == null) {
315 serviceContext = ServiceContextFactory.getInstance(request);
316
317 ServiceContextThreadLocal.pushServiceContext(serviceContext);
318 }
319
320 try {
321 LayoutFriendlyURLComposite layoutFriendlyURLComposite =
322 PortalUtil.getLayoutFriendlyURLComposite(
323 group.getGroupId(), _private, friendlyURL, params,
324 requestContext);
325
326 Layout layout = layoutFriendlyURLComposite.getLayout();
327
328 request.setAttribute(WebKeys.LAYOUT, layout);
329
330 Locale locale = PortalUtil.getLocale(request);
331
332 String layoutFriendlyURLCompositeFriendlyURL =
333 layoutFriendlyURLComposite.getFriendlyURL();
334
335 if (Validator.isNull(layoutFriendlyURLCompositeFriendlyURL)) {
336 layoutFriendlyURLCompositeFriendlyURL = layout.getFriendlyURL(
337 locale);
338 }
339
340 pos = layoutFriendlyURLCompositeFriendlyURL.indexOf(
341 Portal.FRIENDLY_URL_SEPARATOR);
342
343 if (pos != 0) {
344 if (pos != -1) {
345 layoutFriendlyURLCompositeFriendlyURL =
346 layoutFriendlyURLCompositeFriendlyURL.substring(0, pos);
347 }
348
349 boolean i18nRedirect = false;
350
351 String i18nLanguageId = (String)request.getAttribute(
352 WebKeys.I18N_LANGUAGE_ID);
353
354 if (Validator.isNotNull(i18nLanguageId)) {
355 Locale i18nLocale = LocaleUtil.fromLanguageId(
356 i18nLanguageId);
357
358 if (!LanguageUtil.isAvailableLocale(
359 group.getGroupId(), i18nLocale)) {
360
361 i18nRedirect = true;
362 }
363 }
364
365 if (i18nRedirect ||
366 !StringUtil.equalsIgnoreCase(
367 layoutFriendlyURLCompositeFriendlyURL,
368 layout.getFriendlyURL(locale))) {
369
370 Locale originalLocale = setAlternativeLayoutFriendlyURL(
371 request, layout, layoutFriendlyURLCompositeFriendlyURL);
372
373 String redirect = PortalUtil.getLocalizedFriendlyURL(
374 request, layout, locale, originalLocale);
375
376 return new Object[] {redirect, Boolean.TRUE};
377 }
378 }
379 }
380 catch (NoSuchLayoutException nsle) {
381 List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(
382 group.getGroupId(), _private,
383 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
384
385 for (Layout layout : layouts) {
386 if (layout.matches(request, friendlyURL)) {
387 String redirect = PortalUtil.getLayoutActualURL(
388 layout, mainPath);
389
390 return new Object[] {redirect, Boolean.FALSE};
391 }
392 }
393
394 throw nsle;
395 }
396
397 String actualURL = PortalUtil.getActualURL(
398 group.getGroupId(), _private, mainPath, friendlyURL, params,
399 requestContext);
400
401 return new Object[] {actualURL, Boolean.FALSE};
402 }
403
404 protected Locale setAlternativeLayoutFriendlyURL(
405 HttpServletRequest request, Layout layout, String friendlyURL)
406 throws Exception {
407
408 List<LayoutFriendlyURL> layoutFriendlyURLs =
409 LayoutFriendlyURLLocalServiceUtil.getLayoutFriendlyURLs(
410 layout.getPlid(), friendlyURL, 0, 1);
411
412 if (layoutFriendlyURLs.isEmpty()) {
413 return null;
414 }
415
416 LayoutFriendlyURL layoutFriendlyURL = layoutFriendlyURLs.get(0);
417
418 Locale locale = LocaleUtil.fromLanguageId(
419 layoutFriendlyURL.getLanguageId());
420
421 String alternativeLayoutFriendlyURL =
422 PortalUtil.getLocalizedFriendlyURL(request, layout, locale, locale);
423
424 SessionMessages.add(
425 request, "alternativeLayoutFriendlyURL",
426 alternativeLayoutFriendlyURL);
427
428 PortalMessages.add(
429 request, PortalMessages.KEY_JSP_PATH,
430 "/html/common/themes/layout_friendly_url_redirect.jsp");
431
432 return locale;
433 }
434
435 private static final Log _log = LogFactoryUtil.getLog(
436 FriendlyURLServlet.class);
437
438 private String _friendlyURLPathPrefix;
439 private boolean _private;
440 private boolean _user;
441
442 }