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