1 13 package info.magnolia.cms.filters; 14 15 import info.magnolia.cms.beans.config.ConfigLoader; 16 import info.magnolia.cms.beans.config.Template; 17 import info.magnolia.cms.beans.config.TemplateManager; 18 import info.magnolia.cms.beans.config.TemplateRendererManager; 19 import info.magnolia.cms.beans.config.URI2RepositoryManager; 20 import info.magnolia.cms.beans.config.URI2RepositoryMapping; 21 import info.magnolia.cms.beans.runtime.File; 22 import info.magnolia.cms.beans.runtime.TemplateRenderer; 23 import info.magnolia.cms.core.*; 24 import info.magnolia.cms.security.AccessDeniedException; 25 import info.magnolia.cms.security.Permission; 26 import info.magnolia.cms.security.AccessManager; 27 import info.magnolia.context.MgnlContext; 28 29 import java.io.IOException ; 30 import java.io.InputStream ; 31 32 import javax.jcr.PathNotFoundException; 33 import javax.jcr.PropertyType; 34 import javax.jcr.RepositoryException; 35 import javax.jcr.Value; 36 import javax.servlet.Filter ; 37 import javax.servlet.FilterChain ; 38 import javax.servlet.FilterConfig ; 39 import javax.servlet.ServletException ; 40 import javax.servlet.ServletOutputStream ; 41 import javax.servlet.ServletRequest ; 42 import javax.servlet.ServletResponse ; 43 import javax.servlet.http.HttpServletRequest ; 44 import javax.servlet.http.HttpServletResponse ; 45 46 import org.apache.commons.io.IOUtils; 47 import org.apache.commons.lang.StringUtils; 48 import org.apache.commons.lang.exception.NestableRuntimeException; 49 import org.apache.commons.lang.math.NumberUtils; 50 import org.slf4j.Logger; 51 import org.slf4j.LoggerFactory; 52 53 54 59 public class MgnlCmsFilter implements Filter { 60 61 private static final String BYPASS_PARAM = "bypass"; 62 63 private static Logger log = LoggerFactory.getLogger(MgnlCmsFilter.class); 64 65 private String [] bypass; 66 67 private static final String NODE_DATA_TEMPLATE = "nodeDataTemplate"; 68 69 private static final String VERSION_NUMBER = "mgnlVersion"; 71 72 75 public void destroy() { 76 } 78 79 82 public void init(FilterConfig filterConfig) throws ServletException { 83 this.bypass = StringUtils.split(filterConfig.getInitParameter(BYPASS_PARAM), ", "); 84 if (this.bypass == null) { 85 this.bypass = new String [0]; 86 } 87 } 88 89 public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException , 90 ServletException { 91 92 HttpServletRequest request = (HttpServletRequest ) req; 93 HttpServletResponse response = (HttpServletResponse ) resp; 94 95 String requestURI = Path.getURI(request); 96 String pathInfo = request.getPathInfo(); 97 98 if (pathInfo == null && !startsWithAny(bypass, requestURI)) { 99 handle(request, response); 100 } else { 101 chain.doFilter(request, response); 104 } 105 } 106 107 114 public boolean handle(HttpServletRequest request, HttpServletResponse response) throws IOException , 115 ServletException { 116 117 if (ConfigLoader.isBootstrapping()) { 118 response.getWriter().write("Magnolia bootstrapping has failed, check bootstrap.log in magnolia/logs"); return false; 121 } 122 123 setHandleAndMapping(request); 124 125 try { 126 authorize(request); 127 boolean success = collect(request); 129 130 if (success) { 131 132 Template template = (Template) request.getAttribute(Aggregator.TEMPLATE); 133 134 if (template != null) { 135 try { 136 String type = template.getType(); 137 TemplateRenderer renderer = TemplateRendererManager.getInstance().getRenderer(type); 138 139 if (renderer == null) { 140 throw new RuntimeException ("No renderer found for type " + type); 141 } 142 renderer.renderTemplate(template, request, response); 143 } 144 catch (IOException e) { 145 log.error(e.getMessage(), e); 146 throw e; 147 } 148 catch (ServletException e) { 149 log.error(e.getMessage(), e); 150 throw e; 151 } 152 catch (Exception e) { 153 log.error(e.getMessage(), e); 155 if (!response.isCommitted()) { 156 response.reset(); 157 response.setContentType("text/html"); 158 } 159 throw new NestableRuntimeException(e); 160 } 161 } 162 else { 163 handleResourceRequest(request, response); 165 } 166 167 } 168 else { 169 if (log.isDebugEnabled()) { 170 log.debug( 171 "Resource not found, redirecting request for [{}] to 404 URI", request.getRequestURI()); } 173 174 if (!response.isCommitted()) { 175 response.sendError(HttpServletResponse.SC_NOT_FOUND); 176 } 177 else { 178 log.info("Unable to redirect to 404 page, response is already committed. URI was {}", request.getRequestURI()); 180 } 181 return false; 182 } 183 } 184 catch (AccessDeniedException e) { 185 log.debug(e.getMessage()); 187 if (!response.isCommitted()) 188 response.sendError(HttpServletResponse.SC_FORBIDDEN); 189 return false; 190 } 191 catch (RepositoryException e) { 192 log.error(e.getMessage(), e); 193 throw new ServletException (e.getMessage(), e); 194 } 195 196 return true; 197 } 198 199 203 protected void setHandleAndMapping(HttpServletRequest request) { 204 String uri = Path.getURI(request); 205 int firstDotPos = StringUtils.indexOf(uri, '.', StringUtils.lastIndexOf(uri, '/')); 206 String handle; 207 String selector; 208 String extension; 209 if (firstDotPos > -1) { 210 int lastDotPos = StringUtils.lastIndexOf(uri, '.'); 211 handle = StringUtils.substring(uri, 0, firstDotPos); 212 selector = StringUtils.substring(uri, firstDotPos + 1, lastDotPos); 213 extension = StringUtils.substring(uri, lastDotPos + 1); 214 } 215 else { 216 handle = uri; 218 selector = ""; 219 extension = ""; 220 } 221 222 URI2RepositoryMapping mapping = URI2RepositoryManager.getInstance().getMapping(uri); 223 224 handle = mapping.getHandle(handle); 226 227 request.setAttribute(Aggregator.REPOSITORY, mapping.getRepository()); 228 request.setAttribute(Aggregator.MAPPING, mapping); 229 request.setAttribute(Aggregator.HANDLE, handle); 230 request.setAttribute(Aggregator.SELECTOR, selector); 231 request.setAttribute(Aggregator.EXTENSION, extension); 232 } 233 234 239 protected void authorize(HttpServletRequest request) throws AccessDeniedException { 240 AccessManager accessManager = MgnlContext.getAccessManager(getRepository(request)); 241 if (null != accessManager) { 242 Access.isGranted(accessManager, Path.getHandle(request), Permission.READ); 243 } 244 } 245 246 250 protected String getRepository(HttpServletRequest req) { 251 return (String ) req.getAttribute(Aggregator.REPOSITORY); 252 } 253 254 260 protected void handleResourceRequest(HttpServletRequest request, HttpServletResponse response) throws IOException { 261 262 String resourceHandle = (String ) request.getAttribute(Aggregator.HANDLE); 263 264 log.debug("handleResourceRequest, resourceHandle=\"{}\"", resourceHandle); 266 if (StringUtils.isNotEmpty(resourceHandle)) { 267 268 HierarchyManager hm = MgnlContext.getHierarchyManager(getRepository(request)); 269 270 InputStream is = null; 271 try { 272 is = getNodedataAstream(resourceHandle, hm, response); 273 if (null != is) { 274 sendUnCompressed(is, response); 279 IOUtils.closeQuietly(is); 280 return; 281 } 282 } 283 catch (IOException e) { 284 if (log.isDebugEnabled()) { 287 log.debug( 288 "Exception while dispatching resource " + e.getClass().getName() + ": " + e.getMessage(), e); } 290 } 291 catch (Exception e) { 292 log.error("Exception while dispatching resource " + e.getClass().getName() + ": " + e.getMessage(), e); } 294 finally { 295 IOUtils.closeQuietly(is); 296 } 297 } 298 if (log.isDebugEnabled()) { 299 log.debug("Resource not found, redirecting request for [{}] to 404 URI", request.getRequestURI()); } 301 302 if (!response.isCommitted()) { 303 response.sendError(HttpServletResponse.SC_NOT_FOUND); 304 } 305 else { 306 log.info("Unable to redirect to 404 page, response is already committed"); } 308 309 } 310 311 317 private void sendUnCompressed(InputStream is, HttpServletResponse response) throws IOException { 318 ServletOutputStream os = response.getOutputStream(); 319 byte[] buffer = new byte[8192]; 320 int read; 321 while ((read = is.read(buffer)) > 0) { 322 os.write(buffer, 0, read); 323 } 324 os.flush(); 325 IOUtils.closeQuietly(os); 326 } 327 328 334 private InputStream getNodedataAstream(String path, HierarchyManager hm, HttpServletResponse res) { 335 336 log.debug("getNodedataAstream for path \"{}\"", path); 338 try { 339 NodeData atom = hm.getNodeData(path); 340 if (atom != null) { 341 if (atom.getType() == PropertyType.BINARY) { 342 343 String sizeString = atom.getAttribute("size"); if (NumberUtils.isNumber(sizeString)) { 345 res.setContentLength(Integer.parseInt(sizeString)); 346 } 347 } 348 349 Value value = atom.getValue(); 350 if (value != null) { 351 return value.getStream(); 352 } 353 } 354 355 log.warn("Resource not found: [{}]", path); 357 } 358 catch (PathNotFoundException e) { 359 log.warn("Resource not found: [{}]", path); } 361 catch (RepositoryException e) { 362 log.error("RepositoryException while reading Resource [" + path + "]", e); } 364 return null; 365 } 366 367 372 protected boolean collect(HttpServletRequest request) throws PathNotFoundException, RepositoryException { 373 String handle = Path.getHandle(request); 374 String extension = Path.getExtension(request); 375 String repository = getRepository(request); 376 HierarchyManager hierarchyManager = MgnlContext.getHierarchyManager(repository); 377 378 Content requestedPage = null; 379 NodeData requestedData = null; 380 Template template = null; 381 382 if (hierarchyManager.isPage(handle)) { 383 requestedPage = hierarchyManager.getContent(handle); 384 385 if (request.getParameter(VERSION_NUMBER) != null) { 387 try { 389 requestedPage = requestedPage.getVersionedContent(request.getParameter(VERSION_NUMBER)); 390 } 391 catch (RepositoryException re) { 392 log.debug(re.getMessage(), re); 393 log.error("Unable to get versioned state, rendering current state of {}", handle); 394 } 395 } 396 397 String templateName = requestedPage.getMetaData().getTemplate(); 398 399 if (StringUtils.isBlank(templateName)) { 400 log.error("No template configured for page [{}].", requestedPage.getHandle()); } 402 403 template = TemplateManager.getInstance().getInfo(templateName, extension); 404 405 if (template == null) { 406 log.error("Template [{}] for page [{}] not found.", templateName, 408 requestedPage.getHandle()); 409 } 410 } 411 else { 412 if (hierarchyManager.isNodeData(handle)) { 413 requestedData = hierarchyManager.getNodeData(handle); 414 } 415 else { 416 int lastIndexOfSlash = handle.lastIndexOf("/"); 419 if (lastIndexOfSlash > 0) { 420 421 handle = StringUtils.substringBeforeLast(handle, "/"); 423 try { 424 requestedData = hierarchyManager.getNodeData(handle); 425 request.setAttribute(Aggregator.HANDLE, handle); 427 428 431 } 432 catch (PathNotFoundException e) { 433 return false; 435 } 436 catch (RepositoryException e) { 437 log.debug(e.getMessage(), e); 438 return false; 439 } 440 } 441 } 442 443 if (requestedData != null) { 444 String templateName = requestedData.getAttribute(NODE_DATA_TEMPLATE); 445 446 if (!StringUtils.isEmpty(templateName)) { 447 template = TemplateManager.getInstance().getInfo(templateName, extension); 448 } 449 } 450 else { 451 return false; 452 } 453 } 454 455 if (requestedPage != null) { 457 request.setAttribute(Aggregator.ACTPAGE, requestedPage); 458 request.setAttribute(Aggregator.CURRENT_ACTPAGE, requestedPage); 459 } 460 if ((requestedData != null) && (requestedData.getType() == PropertyType.BINARY)) { 461 File file = new File(); 462 file.setProperties(requestedData); 463 file.setNodeData(requestedData); 464 request.setAttribute(Aggregator.FILE, file); 465 } 466 467 request.setAttribute(Aggregator.TEMPLATE, template); 468 469 return true; 470 } 471 472 boolean startsWithAny(String [] array, String check) { 473 for (int j = 0; j < array.length; j++) { 474 String string = array[j]; 475 if (check.startsWith(string)) { 476 return true; 477 } 478 } 479 return false; 480 } 481 482 } 483 | Popular Tags |