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