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