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