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.exception.SystemException;
020 import com.liferay.portal.kernel.language.LanguageUtil;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.servlet.PortalMessages;
024 import com.liferay.portal.kernel.servlet.SessionMessages;
025 import com.liferay.portal.kernel.struts.LastPath;
026 import com.liferay.portal.kernel.util.CharPool;
027 import com.liferay.portal.kernel.util.GetterUtil;
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.StringUtil;
032 import com.liferay.portal.kernel.util.Validator;
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 import com.liferay.portal.util.WebKeys;
050
051 import java.io.IOException;
052
053 import java.util.Collection;
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 request.getParameterMap());
137 }
138
139 request.setAttribute(WebKeys.LAST_PATH, lastPath);
140 }
141 }
142 catch (Exception e) {
143 if (_log.isWarnEnabled()) {
144 _log.warn(e);
145 }
146
147 if ((e instanceof NoSuchGroupException) ||
148 (e instanceof NoSuchLayoutException)) {
149
150 PortalUtil.sendError(
151 HttpServletResponse.SC_NOT_FOUND, e, request, response);
152
153 return;
154 }
155 }
156
157 if (Validator.isNull(redirect)) {
158 redirect = mainPath;
159 }
160
161 if (_log.isDebugEnabled()) {
162 _log.debug("Redirect " + redirect);
163 }
164
165 if ((redirect.charAt(0) == CharPool.SLASH) && !forcePermanentRedirect) {
166 ServletContext servletContext = getServletContext();
167
168 RequestDispatcher requestDispatcher =
169 servletContext.getRequestDispatcher(redirect);
170
171 if (requestDispatcher != null) {
172 requestDispatcher.forward(request, response);
173 }
174 }
175 else {
176 if (forcePermanentRedirect) {
177 response.setHeader("Location", redirect);
178 response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
179 }
180 else {
181 response.sendRedirect(redirect);
182 }
183 }
184 }
185
186 protected String getFriendlyURL(String pathInfo) {
187 String friendlyURL = _friendlyURLPathPrefix;
188
189 if (Validator.isNotNull(pathInfo)) {
190 friendlyURL = friendlyURL.concat(pathInfo);
191 }
192
193 return friendlyURL;
194 }
195
196 protected String getPathInfo(HttpServletRequest request) {
197 String requestURI = request.getRequestURI();
198
199 int pos = requestURI.indexOf(Portal.JSESSIONID);
200
201 if (pos != -1) {
202 requestURI = requestURI.substring(0, pos);
203 }
204
205 String pathProxy = PortalUtil.getPathProxy();
206
207 pos = _friendlyURLPathPrefix.length() - pathProxy.length();
208
209 return requestURI.substring(pos);
210 }
211
212 protected Object[] getRedirect(
213 HttpServletRequest request, String path, String mainPath,
214 Map<String, String[]> params)
215 throws Exception {
216
217 if (Validator.isNull(path) || (path.charAt(0) != CharPool.SLASH)) {
218 return new Object[] {mainPath, false};
219 }
220
221
222
223 String friendlyURL = null;
224
225 int pos = path.indexOf(CharPool.SLASH, 1);
226
227 if (pos != -1) {
228 friendlyURL = path.substring(0, pos);
229 }
230 else if (path.length() > 1) {
231 friendlyURL = path;
232 }
233
234 if (Validator.isNull(friendlyURL)) {
235 return new Object[] {mainPath, Boolean.FALSE};
236 }
237
238 long companyId = PortalInstances.getCompanyId(request);
239
240 Group group = GroupLocalServiceUtil.fetchFriendlyURLGroup(
241 companyId, friendlyURL);
242
243 if (group == null) {
244 String screenName = friendlyURL.substring(1);
245
246 if (_user || !Validator.isNumber(screenName)) {
247 User user = UserLocalServiceUtil.fetchUserByScreenName(
248 companyId, screenName);
249
250 if (user != null) {
251 group = user.getGroup();
252 }
253 else if (_log.isWarnEnabled()) {
254 _log.warn("No user exists with friendly URL " + screenName);
255 }
256 }
257 else {
258 long groupId = GetterUtil.getLong(screenName);
259
260 group = GroupLocalServiceUtil.fetchGroup(groupId);
261
262 if (group == null) {
263 if (_log.isDebugEnabled()) {
264 _log.debug(
265 "No group exists with friendly URL " + groupId +
266 ". Try fetching by screen name instead.");
267 }
268
269 User user = UserLocalServiceUtil.fetchUserByScreenName(
270 companyId, screenName);
271
272 if (user != null) {
273 group = user.getGroup();
274 }
275 else if (_log.isWarnEnabled()) {
276 _log.warn(
277 "No user or group exists with friendly URL " +
278 groupId);
279 }
280 }
281 }
282 }
283
284 if (group == null) {
285 StringBundler sb = new StringBundler(5);
286
287 sb.append("{companyId=");
288 sb.append(companyId);
289 sb.append(", friendlyURL=");
290 sb.append(friendlyURL);
291 sb.append("}");
292
293 throw new NoSuchGroupException(sb.toString());
294 }
295
296
297
298 friendlyURL = null;
299
300 if ((pos != -1) && ((pos + 1) != path.length())) {
301 friendlyURL = path.substring(pos);
302 }
303
304 if (Validator.isNull(friendlyURL)) {
305 request.setAttribute(
306 WebKeys.REDIRECT_TO_DEFAULT_LAYOUT, Boolean.TRUE);
307 }
308
309 Map<String, Object> requestContext = new HashMap<String, Object>();
310
311 requestContext.put("request", request);
312
313 ServiceContext serviceContext =
314 ServiceContextThreadLocal.getServiceContext();
315
316 if (serviceContext == null) {
317 serviceContext = ServiceContextFactory.getInstance(request);
318
319 ServiceContextThreadLocal.pushServiceContext(serviceContext);
320 }
321
322 try {
323 LayoutFriendlyURLComposite layoutFriendlyURLComposite =
324 PortalUtil.getLayoutFriendlyURLComposite(
325 group.getGroupId(), _private, friendlyURL, params,
326 requestContext);
327
328 Layout layout = layoutFriendlyURLComposite.getLayout();
329
330 request.setAttribute(WebKeys.LAYOUT, layout);
331
332 Locale locale = PortalUtil.getLocale(request);
333
334 String layoutFriendlyURLCompositeFriendlyURL =
335 layoutFriendlyURLComposite.getFriendlyURL();
336
337 if (Validator.isNull(layoutFriendlyURLCompositeFriendlyURL)) {
338 layoutFriendlyURLCompositeFriendlyURL = layout.getFriendlyURL(
339 locale);
340 }
341
342 pos = layoutFriendlyURLCompositeFriendlyURL.indexOf(
343 Portal.FRIENDLY_URL_SEPARATOR);
344
345 if (pos != 0) {
346 if (pos != -1) {
347 layoutFriendlyURLCompositeFriendlyURL =
348 layoutFriendlyURLCompositeFriendlyURL.substring(0, pos);
349 }
350
351 String i18nLanguageId = (String)request.getAttribute(
352 WebKeys.I18N_LANGUAGE_ID);
353
354 if ((Validator.isNotNull(i18nLanguageId) &&
355 !LanguageUtil.isAvailableLocale(
356 group.getGroupId(), i18nLanguageId)) ||
357 !StringUtil.equalsIgnoreCase(
358 layoutFriendlyURLCompositeFriendlyURL,
359 layout.getFriendlyURL(locale))) {
360
361 Locale originalLocale = setAlternativeLayoutFriendlyURL(
362 request, layout, layoutFriendlyURLCompositeFriendlyURL);
363
364 String redirect = PortalUtil.getLocalizedFriendlyURL(
365 request, layout, locale, originalLocale);
366
367 return new Object[] {redirect, Boolean.TRUE};
368 }
369 }
370 }
371 catch (NoSuchLayoutException nsle) {
372 List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(
373 group.getGroupId(), _private,
374 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
375
376 for (Layout layout : layouts) {
377 if (matches(layout, friendlyURL)) {
378 String redirect = PortalUtil.getLayoutActualURL(
379 layout, mainPath);
380
381 return new Object[] {redirect, Boolean.FALSE};
382 }
383 }
384
385 throw nsle;
386 }
387
388 String actualURL = PortalUtil.getActualURL(
389 group.getGroupId(), _private, mainPath, friendlyURL, params,
390 requestContext);
391
392 return new Object[] {actualURL, Boolean.FALSE};
393 }
394
395 protected Locale setAlternativeLayoutFriendlyURL(
396 HttpServletRequest request, Layout layout, String friendlyURL)
397 throws Exception {
398
399 List<LayoutFriendlyURL> layoutFriendlyURLs =
400 LayoutFriendlyURLLocalServiceUtil.getLayoutFriendlyURLs(
401 layout.getPlid(), friendlyURL, 0, 1);
402
403 if (layoutFriendlyURLs.isEmpty()) {
404 return null;
405 }
406
407 LayoutFriendlyURL layoutFriendlyURL = layoutFriendlyURLs.get(0);
408
409 Locale locale = LocaleUtil.fromLanguageId(
410 layoutFriendlyURL.getLanguageId());
411
412 String alternativeLayoutFriendlyURL =
413 PortalUtil.getLocalizedFriendlyURL(request, layout, locale, locale);
414
415 SessionMessages.add(
416 request, "alternativeLayoutFriendlyURL",
417 alternativeLayoutFriendlyURL);
418
419 PortalMessages.add(
420 request, PortalMessages.KEY_JSP_PATH,
421 "/html/common/themes/layout_friendly_url_redirect.jsp");
422
423 return locale;
424 }
425
426 protected boolean matches(Layout layout, String friendlyURL) {
427 try {
428 Map<Locale, String> friendlyURLMap = layout.getFriendlyURLMap();
429
430 Collection<String> values = friendlyURLMap.values();
431
432 return values.contains(friendlyURL);
433 }
434 catch (SystemException e) {
435 throw new RuntimeException(e);
436 }
437 }
438
439 private static Log _log = LogFactoryUtil.getLog(FriendlyURLServlet.class);
440
441 private String _friendlyURLPathPrefix;
442 private boolean _private;
443 private boolean _user;
444
445 }