1 16 package com.blandware.atleap.webapp.struts; 17 18 import com.blandware.atleap.common.Constants; 19 import com.blandware.atleap.common.util.ConvertUtil; 20 import com.blandware.atleap.model.core.ContentLocale; 21 import com.blandware.atleap.model.core.ContentPage; 22 import com.blandware.atleap.model.core.Layout; 23 import com.blandware.atleap.model.core.Role; 24 import com.blandware.atleap.service.core.PageManager; 25 import com.blandware.atleap.webapp.util.core.CacheUtil; 26 import com.blandware.atleap.webapp.util.core.GlobalProperties; 27 import com.blandware.atleap.webapp.util.core.LocaleUtil; 28 import com.blandware.atleap.webapp.util.core.TokenUtil; 29 import com.blandware.atleap.webapp.util.core.WebappConstants; 30 import com.blandware.atleap.webapp.util.core.WebappUtil; 31 import com.blandware.atleap.webapp.taglib.core.html.CancelTag; 32 import org.apache.commons.logging.Log; 33 import org.apache.commons.logging.LogFactory; 34 import org.apache.struts.Globals; 35 import org.apache.struts.util.RequestUtils; 36 import org.apache.struts.action.*; 37 import org.apache.struts.config.ActionConfig; 38 import org.apache.struts.config.ForwardConfig; 39 import org.apache.struts.config.ModuleConfig; 40 import org.apache.struts.tiles.TilesRequestProcessor; 41 import org.springframework.context.ApplicationContext; 42 import org.springframework.web.context.support.WebApplicationContextUtils; 43 44 import javax.servlet.ServletException ; 45 import javax.servlet.http.HttpServletRequest ; 46 import javax.servlet.http.HttpServletResponse ; 47 import javax.servlet.http.HttpSession ; 48 import java.io.IOException ; 49 import java.util.ArrayList ; 50 import java.util.Date ; 51 import java.util.Iterator ; 52 import java.util.List ; 53 import java.util.Locale ; 54 import java.util.StringTokenizer ; 55 56 85 public class ContentTilesRequestProcessor extends TilesRequestProcessor { 86 87 90 public static final String DEFINITION_NAME = "com.blandware.atleap.webapp.struts.DEFINITION_NAME"; 91 92 95 public static final String PROCESSED_URI = "com.blandware.atleap.webapp.struts.PROCESSED_URI"; 96 97 100 public static final String PROCESSED_URL = "com.blandware.atleap.webapp.struts.PROCESSED_URL"; 101 102 105 public static final String IS_NOCACHE = "com.blandware.atleap.webapp.struts.IS_NOCACHE"; 106 107 108 111 protected transient final Log log = LogFactory.getLog(ContentTilesRequestProcessor.class); 112 113 114 121 public void init(ActionServlet servlet, ModuleConfig moduleConfig) throws ServletException { 122 super.init(servlet, moduleConfig); 123 if ( log.isDebugEnabled() ) { 124 log.debug("Definitions factory class name: " + definitionsFactory.getClass().getName()); 125 } 126 } 127 128 138 public void process(HttpServletRequest request, 139 HttpServletResponse response) 140 throws IOException , ServletException { 141 142 request = processMultipart(request); 144 145 String path = processPath(request, response); 147 if ( path == null ) { 148 return; 149 } 150 151 if ( log.isDebugEnabled() ) { 152 log.debug("Processing a '" + request.getMethod() + 153 "' for path '" + path + "'"); 154 } 155 156 processLocale(request, response); 158 159 processContent(request, response); 161 processNoCache(request, response); 162 163 if ( !processPreprocess(request, response) ) { 165 return; 166 } 167 168 this.processCachedMessages(request, response); 169 170 ActionMapping mapping = processMapping(request, response, path); 172 if ( mapping == null ) { 173 return; 174 } 175 176 if ( !processRoles(request, response, mapping) ) { 178 return; 179 } 180 181 186 ActionForm form = processActionForm(request, response, mapping); 188 processPopulate(request, response, form, mapping); 189 190 if ( (request.getAttribute(Globals.CANCEL_KEY) == null) ) { 192 if ( !checkToken(request, response, mapping) ) { 193 return; 194 } 195 } 196 197 if ( !processValidate(request, response, form, mapping) ) { 199 return; 200 } else { 201 resetToken(request, mapping); 202 } 203 204 if ( !processForward(request, response, mapping) ) { 206 return; 207 } 208 209 if ( !processInclude(request, response, mapping) ) { 210 return; 211 } 212 213 Action action = processActionCreate(request, response, mapping); 215 if ( action == null ) { 216 return; 217 } 218 219 ActionForward forward = 221 processActionPerform(request, response, 222 action, form, mapping); 223 224 processForwardConfig(request, response, forward); 226 227 } 228 229 237 protected boolean checkToken(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) 238 throws IOException , ServletException { 239 ActionForward forward = mapping.findForward("unsatisfiable"); 240 if (forward == null) { 241 forward = mapping.findForward("unsatisfiableNoReset"); 242 } 243 if ( forward != null ) { 244 if ( !TokenUtil.getInstance().isTokenValid(request, false) ) { 245 request.setAttribute("beginPage", forward.getPath()); 246 processForwardConfig(request, response, mapping.findForward("unsatisfiablePage")); 247 return false; 248 } 249 } 250 return true; 251 } 252 253 259 protected void resetToken(HttpServletRequest request, ActionMapping mapping) { 260 ActionForward forward = mapping.findForward("unsatisfiable"); 261 if ( forward != null ) { 262 TokenUtil.getInstance().resetToken(request); 263 } 264 } 265 266 277 protected boolean processContentPage(String uri, boolean contextRelative, HttpServletRequest request, HttpServletResponse response) 278 throws IOException { 279 if ( log.isDebugEnabled() ) { 280 log.debug("processContentPage(" 281 + uri + ", " 282 + contextRelative + ")"); 283 } 284 285 if ( contextRelative ) { 287 String prefix = moduleConfig.getPrefix(); 288 log.debug("Strip module prefix '" + prefix + "' "); 289 if ( !uri.startsWith(prefix) ) { 290 log.error(getInternal().getMessage("processPath", 291 request.getRequestURI())); 292 try { 293 response.sendError(HttpServletResponse.SC_BAD_REQUEST, 294 getInternal().getMessage 295 ("processPath", request.getRequestURI())); 296 } catch ( IOException ex ) { 297 } 299 return true; 300 } 301 uri = uri.substring(prefix.length()); 302 } 303 304 305 String cpDefinition = null; 306 List roleNames = new ArrayList (); 307 long lastModified = -1; 308 Long cacheMaxAge = null; 309 310 CacheUtil cacheUtil = CacheUtil.getInstance(request); 312 CacheUtil.ContentPageData cpd = cacheUtil.getContentPageFromCache(uri); 313 314 if ( cpd != null ) { 315 cpDefinition = cpd.getCpDefinition(); 316 roleNames = ConvertUtil.convertStringToList(cpd.getRoles(), ",", true); 317 lastModified = cpd.getLastModified(); 318 cacheMaxAge = cpd.getCacheMaxAge(); 319 320 if ( log.isDebugEnabled() ) { 321 log.debug("Retrieving content page from Cache with for uri=" + uri + " with cpDefinition=" + cpDefinition + " and roles=" + roleNames.toString()); 322 } 323 324 } else { 325 ContentPage contentPage = null; 327 try { 328 ApplicationContext applicationCtx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext()); 329 PageManager pageManager = (PageManager) applicationCtx.getBean(Constants.PAGE_MANAGER_BEAN); 330 contentPage = pageManager.findContentPageByUri(uri); 331 } catch ( Exception ex ) { 332 if ( log.isErrorEnabled() ) { 333 log.error("Cannot perfom function because layout could not be found. Cause: " + ex.getLocalizedMessage()); 334 } 335 } 336 337 if ( contentPage != null ) { 339 if ( contentPage.getActive().booleanValue() ) { 340 Layout layout = contentPage.getLayout(); 341 cpDefinition = layout.getCpDefinition(); 342 lastModified = new Date ().getTime(); 343 cacheMaxAge = contentPage.getCacheMaxAge(); 344 if ( cpDefinition != null ) { 345 List roles = contentPage.getRoles(); 347 for ( int i = 0; i < roles.size(); i++ ) { 348 Role role = (Role) roles.get(i); 349 roleNames.add(role.getName()); 350 } 351 352 String roleNamesString = null; 354 if ( roleNames.size() > 0 ) { 355 roleNamesString = ConvertUtil.convertListToString(roleNames, ","); 356 } 357 cpd = new CacheUtil.ContentPageData(cpDefinition, roleNamesString, cacheMaxAge); 358 cacheUtil.putContentPageInCache(cpd, uri); 359 360 if ( log.isDebugEnabled() ) { 361 log.debug("Definition '" + cpDefinition + "' for layout of content page was found in database"); 362 } 363 } 364 } else { 365 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); 367 return true; 368 } 369 } 370 371 } 372 373 if ( cpDefinition == null ) { 375 return false; 376 } 377 378 int maxAge = -1; 380 if ( cacheMaxAge != null ) { 381 maxAge = cacheMaxAge.intValue(); 382 } else { 383 maxAge = ((Integer ) GlobalProperties.getInstance(servlet.getServletContext()).getInteger(WebappConstants.CACHE_CONTENTPAGE_MAXAGE_PROPERTY, -1)).intValue(); 384 } 385 if ( maxAge < 0 ) { 386 response.setHeader("Cache-Control", "no-cache,no-store,max-age=0"); 387 response.setHeader("Pragma", "no-cache"); 388 request.setAttribute(IS_NOCACHE, "true"); 389 } else { 390 String cacheType = "public"; 391 if ( roleNames.size() != 0 ) { 392 cacheType = "private"; 393 } 394 395 String editMode = "false"; 396 if ( Boolean.TRUE.equals(request.getSession().getAttribute(WebappConstants.SITE_EDIT_MODE_ENABLED_KEY)) ) { 397 editMode = "true"; 398 maxAge = 0; 399 } 400 401 response.setHeader("Cache-Control", cacheType + ",max-age=" + maxAge); 402 response.setHeader("Pragma", ""); 403 404 if ( request.getMethod().equals("GET") && lastModified != -1 ) { 406 407 String locale = ((Locale) request.getSession(true).getAttribute(Globals.LOCALE_KEY)).getLanguage(); 409 String username = request.getRemoteUser(); 410 411 412 StringBuffer eTagBuffer = new StringBuffer ("W/\"").append(locale).append("-").append(username).append("-").append(editMode).append("-").append(lastModified).append("\""); 413 String eTag = eTagBuffer.toString(); 414 response.setHeader("ETag", eTag); 415 416 boolean conditionSatisfied = false; 417 String headerValue = request.getHeader("If-None-Match"); 418 if ( headerValue != null ) { 419 if ( !headerValue.equals("*") ) { 420 StringTokenizer commaTokenizer = 421 new StringTokenizer (headerValue, ","); 422 while ( !conditionSatisfied && commaTokenizer.hasMoreTokens() ) { 423 String currentToken = commaTokenizer.nextToken(); 424 if ( currentToken.trim().equals(eTag) ) { 425 conditionSatisfied = true; 426 } 427 } 428 } else { 429 conditionSatisfied = true; 430 } 431 if ( conditionSatisfied ) { 432 response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); 433 return true; 434 } 435 } 436 } 437 } 438 439 boolean granted = false; 441 if ( roleNames != null && roleNames.size() > 0 ) { 442 for ( int i = 0; i < roleNames.size(); i++ ) { 443 String roleName = (String ) roleNames.get(i); 444 if ( request.isUserInRole(roleName) ) { 445 if ( log.isDebugEnabled() ) { 446 log.debug(" User '" + request.getRemoteUser() + 447 "' has role '" + roleName + "', granting access"); 448 } 449 granted = true; 450 break; 451 } 452 } 453 } else { 454 granted = true; 455 if ( log.isDebugEnabled() ) { 456 log.debug("Anonymous user granting access"); 457 } 458 } 459 460 if ( !granted ) { 461 if ( log.isDebugEnabled() ) { 463 log.debug(" User '" + request.getRemoteUser() + 464 "' does not have any required role, denying access"); 465 } 466 response.sendError(HttpServletResponse.SC_FORBIDDEN, 467 getInternal().getMessage("notAuthorized", uri)); 468 return true; 469 } 470 471 request.setAttribute(PROCESSED_URI, uri); 473 request.setAttribute(PROCESSED_URL, getFullUrl(request)); 474 475 try { 476 if ( processTilesDefinition(cpDefinition, contextRelative, request, response) ) { 477 return true; 478 } else { 479 if ( log.isWarnEnabled() ) { 480 log.warn("Cannot process Tiles definition specified in database"); 481 } 482 } 483 } catch ( Exception ex ) { 484 if ( log.isErrorEnabled() ) { 485 log.error("Cannot process Tiles definition " + ex.getLocalizedMessage()); 486 } 487 } 488 489 return false; 490 } 491 492 501 protected void processNoCache(HttpServletRequest request, HttpServletResponse response) { 502 } 504 505 511 protected String getFullUrl(HttpServletRequest request) { 512 StringBuffer requestUrl = request.getRequestURL(); 513 if ( requestUrl == null ) { 514 return null; 515 } 516 String queryString = request.getQueryString(); 517 if ( queryString != null && queryString.length() > 0 ) { 518 requestUrl = requestUrl.append('?').append(queryString); 519 } 520 return requestUrl.toString(); 521 } 522 523 535 protected ActionMapping processMapping(HttpServletRequest request, HttpServletResponse response, String path) 536 throws IOException { 537 ActionMapping mapping = (ActionMapping) 539 moduleConfig.findActionConfig(path); 540 if ( mapping != null ) { 541 response.setHeader("Cache-Control", "no-cache,no-store,max-age=0"); 543 response.setHeader("Pragma", "no-cache"); 544 request.setAttribute(IS_NOCACHE, "true"); 545 546 request.setAttribute(Globals.MAPPING_KEY, mapping); 547 548 request.setAttribute(PROCESSED_URI, path); 550 request.setAttribute(PROCESSED_URL, getFullUrl(request)); 551 552 return (mapping); 553 } 554 555 if ( processContentPage(path, false, request, response) ) { 557 return null; 558 } 559 560 response.setHeader("Cache-Control", "no-cache,no-store,max-age=0"); 562 response.setHeader("Pragma", "no-cache"); 563 request.setAttribute(IS_NOCACHE, "true"); 564 565 ActionConfig configs[] = moduleConfig.findActionConfigs(); 567 for ( int i = 0; i < configs.length; i++ ) { 568 if ( configs[i].getUnknown() ) { 569 mapping = (ActionMapping) configs[i]; 570 request.setAttribute(Globals.MAPPING_KEY, mapping); 571 return (mapping); 572 } 573 } 574 575 String msg = getInternal().getMessage("processInvalid", path); 577 log.error(msg); 578 response.sendError(HttpServletResponse.SC_NOT_FOUND, msg); 579 580 return null; 581 } 582 583 591 protected void processLocale(HttpServletRequest request, HttpServletResponse response) { 592 593 String localeIdentifier = null; 594 HttpSession session = request.getSession(); 595 596 localeIdentifier = request.getParameter("language"); 598 599 boolean canChangeLocale = moduleConfig.getControllerConfig().getLocale(); 601 if ( (localeIdentifier == null || localeIdentifier.trim().length() == 0) && !canChangeLocale ) { 602 return; 603 } 604 605 if ( localeIdentifier == null || localeIdentifier.trim().length() == 0 ) { 608 Locale locale = (Locale) session.getAttribute(Globals.LOCALE_KEY); 609 if ( locale == null ) { 610 locale = request.getLocale(); 612 } 613 if ( locale != null ) { 614 localeIdentifier = locale.getLanguage(); 615 } 616 } 617 618 LocaleUtil localeUtil = LocaleUtil.getInstance(servlet.getServletContext()); 619 if ( localeIdentifier != null && localeIdentifier.trim().length() > 0 ) { 620 List availableLocales = localeUtil.getAvailableLocales(); 621 ContentLocale contentLocale = null; 622 boolean localeFound = false; 623 boolean localeIsActive = false; 624 for ( Iterator i = availableLocales.iterator(); i.hasNext() && !localeFound; ) { 625 contentLocale = (ContentLocale) i.next(); 626 localeFound = contentLocale.getIdentifier().equalsIgnoreCase(localeIdentifier); 627 localeIsActive = contentLocale.getActive().booleanValue(); 628 } 629 if ( !localeFound || !localeIsActive ) { 630 contentLocale = localeUtil.getDefaultLocale(); 631 if ( contentLocale != null ) { 632 localeIdentifier = contentLocale.getIdentifier(); 633 } 634 } 635 } else { 636 ContentLocale contentLocale = localeUtil.getDefaultLocale(); 637 if ( contentLocale != null ) { 638 localeIdentifier = contentLocale.getIdentifier(); 639 } 640 } 641 642 if ( log.isDebugEnabled() ) { 643 log.debug(" Setting user locale '" + localeIdentifier + "'"); 644 } 645 646 response.setHeader("Content-Language", localeIdentifier); 647 648 session.setAttribute(Globals.LOCALE_KEY, new Locale(localeIdentifier)); 649 } 650 651 660 protected boolean processTilesDefinition(String definitionName, boolean contextRelative, HttpServletRequest request, HttpServletResponse response) throws IOException , ServletException { 661 request.setAttribute(DEFINITION_NAME, definitionName); 662 boolean result = super.processTilesDefinition(definitionName, contextRelative, request, response); 663 if ( !result ) { 664 request.removeAttribute(DEFINITION_NAME); 665 } 666 return result; 667 } 668 669 683 protected void processForwardConfig(HttpServletRequest request, HttpServletResponse response, ForwardConfig forward) throws IOException , ServletException { 684 if ( forward == null ) { 686 return; 687 } 688 689 boolean contextRelative = forward.getModule() == null || forward.getModule().trim().length() == 0; 690 691 if ( log.isDebugEnabled() ) { 692 log.debug("processForwardConfig(" + forward.getPath() + ", " + contextRelative + ")"); 693 } 694 695 if ( processTilesDefinition(forward.getPath(), contextRelative, request, response) ) { 697 if ( log.isDebugEnabled() ) { 698 log.debug(" '" + forward.getPath() + "' - processed as definition"); 699 } 700 return; 701 } 702 703 if ( log.isDebugEnabled() ) { 704 log.debug(" '" + forward.getPath() + "' - processed as uri"); 705 } 706 707 709 int urlType = forward.getRedirect() ? WebappConstants.URL_TYPE_DOMAIN_RELATIVE : WebappConstants.URL_TYPE_CONTEXT_RELATIVE; 711 String uri = WebappUtil.getActionForwardURL(forward, null, request, urlType, forward.getRedirect()); 712 713 if ( forward.getRedirect() ) { 714 response.sendRedirect(response.encodeRedirectURL(uri)); 715 } else { 716 doForward(uri, request, response); 717 } 718 719 720 } 721 722 738 protected void processPopulate(HttpServletRequest request, 739 HttpServletResponse response, 740 ActionForm form, 741 ActionMapping mapping) 742 throws ServletException { 743 744 super.processPopulate(request, response, form, mapping); 745 746 if (request.getParameter(CancelTag.BACK_PROPERTY) != null) { 748 request.setAttribute(WebappConstants.BACK_KEY, Boolean.TRUE); 749 } 750 751 } 752 753 771 protected boolean processValidate(HttpServletRequest request, 772 HttpServletResponse response, 773 ActionForm form, 774 ActionMapping mapping) 775 throws IOException , ServletException { 776 if (request.getAttribute(WebappConstants.BACK_KEY) != null) { 778 if (log.isDebugEnabled()) { 779 log.debug(" Got here after pressing 'back', skipping validation"); 780 } 781 return (true); 782 } 783 784 return super.processValidate(request, response, form, mapping); 785 } 786 787 } 788 | Popular Tags |