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