1 16 package org.apache.cocoon.webapps.authentication.context; 17 18 import org.apache.avalon.framework.CascadingRuntimeException; 19 import org.apache.avalon.framework.context.Context; 20 import org.apache.avalon.framework.parameters.Parameters; 21 22 import org.apache.cocoon.ProcessingException; 23 import org.apache.cocoon.components.ContextHelper; 24 import org.apache.cocoon.components.source.SourceUtil; 25 import org.apache.cocoon.environment.Request; 26 import org.apache.cocoon.webapps.authentication.AuthenticationConstants; 27 import org.apache.cocoon.webapps.authentication.components.DefaultAuthenticationManager; 28 import org.apache.cocoon.webapps.authentication.configuration.ApplicationConfiguration; 29 import org.apache.cocoon.webapps.authentication.user.RequestState; 30 import org.apache.cocoon.webapps.authentication.user.UserHandler; 31 import org.apache.cocoon.webapps.session.context.SessionContext; 32 import org.apache.cocoon.webapps.session.context.SimpleSessionContext; 33 import org.apache.cocoon.xml.XMLUtils; 34 import org.apache.cocoon.xml.dom.DOMUtil; 35 36 import org.apache.excalibur.source.SourceParameters; 37 import org.apache.excalibur.source.SourceResolver; 38 import org.apache.excalibur.xml.xpath.XPathProcessor; 39 import org.w3c.dom.Document ; 40 import org.w3c.dom.DocumentFragment ; 41 import org.w3c.dom.Node ; 42 import org.w3c.dom.NodeList ; 43 import org.xml.sax.ContentHandler ; 44 import org.xml.sax.SAXException ; 45 import org.xml.sax.ext.LexicalHandler ; 46 47 import java.io.IOException ; 48 import java.util.ArrayList ; 49 import java.util.HashMap ; 50 import java.util.List ; 51 import java.util.Map ; 52 import java.util.StringTokenizer ; 53 54 60 public class AuthenticationContext implements SessionContext { 61 62 protected String name; 63 protected UserHandler handler; 64 protected SessionContext authContext; 65 protected String handlerName; 66 protected boolean initialized; 67 protected Context context; 68 protected XPathProcessor xpathProcessor; 69 protected SourceResolver resolver; 70 71 protected List roles; 72 73 74 public AuthenticationContext(Context context, XPathProcessor processor, SourceResolver resolver) { 75 this.context = context; 76 this.xpathProcessor = processor; 77 this.resolver = resolver; 78 } 79 80 84 public void init(UserHandler handler) { 85 this.name = AuthenticationConstants.SESSION_CONTEXT_NAME; 86 87 this.handler = handler; 88 this.handlerName = this.handler.getHandlerName(); 89 try { 90 this.authContext = new SimpleSessionContext(this.xpathProcessor, this.resolver); 91 } catch (ProcessingException pe) { 92 throw new CascadingRuntimeException("Unable to create simple context.", pe); 93 } 94 } 95 96 99 protected RequestState getState() { 100 return DefaultAuthenticationManager.getRequestState( this.context ); 101 } 102 103 106 public void init(Document doc) 107 throws ProcessingException { 108 if ( initialized ) { 109 throw new ProcessingException("The context can only be initialized once."); 110 } 111 this.authContext.setNode("/", doc.getFirstChild()); 112 } 113 114 117 public void setup(String value, String load, String save) { 118 } 120 121 124 public String getName() { 125 return this.name; 126 } 127 128 131 public DocumentFragment getXML(String path) 132 throws ProcessingException { 133 if (path == null) { 134 throw new ProcessingException("getXML: Path is required"); 135 } 136 if (!path.startsWith("/")) path = '/' + path; 137 138 final String applicationName = this.getState().getApplicationName(); 139 140 DocumentFragment frag = null; 141 142 if ( path.equals("/") ) { 143 frag = this.authContext.getXML("/authentication"); 145 146 if (frag != null) { 147 Node root = frag.getOwnerDocument().createElementNS(null, "authentication"); 149 Node child; 150 while (frag.hasChildNodes()) { 151 child = frag.getFirstChild(); 152 frag.removeChild(child); 153 root.appendChild(child); 154 } 155 frag.appendChild(root); 156 } 157 158 if (applicationName != null) { 159 DocumentFragment appFrag = this.authContext.getXML("/applications/" + applicationName); 161 if (appFrag != null) { 162 Node root = appFrag.getOwnerDocument().createElementNS(null, "application"); 164 Node child; 165 while (appFrag.hasChildNodes() ) { 166 child = appFrag.getFirstChild(); 167 appFrag.removeChild(child); 168 root.appendChild(child); 169 } 170 appFrag.appendChild(root); 171 172 if (frag == null) { 173 frag = appFrag; 174 } else { 175 while (appFrag.hasChildNodes() ) { 176 child = appFrag.getFirstChild(); 177 appFrag.removeChild(child); 178 child = frag.getOwnerDocument().importNode(child, true); 179 frag.appendChild(child); 180 } 181 } 182 } 183 } 184 185 } else if (path.startsWith("/authentication") ) { 186 frag = this.authContext.getXML(path); 187 188 } else if (path.equals("/application") || path.startsWith("/application/") ) { 189 if (applicationName != null) { 190 String appPath; 191 if (path.equals("/application")) { 192 appPath ="/"; 193 } else { 194 appPath = path.substring("/application".length()); 195 } 196 frag = this.authContext.getXML("/applications/" + applicationName + appPath); 197 } 198 } else { 199 frag = this.authContext.getXML(path); 200 } 201 202 return frag; 203 } 204 205 208 public void setXML(String path, DocumentFragment fragment) 209 throws ProcessingException { 210 if (path == null) { 211 throw new ProcessingException("setXML: Path is required"); 212 } 213 if (!path.startsWith("/")) path = '/' + path; 214 215 final String applicationName = this.getState().getApplicationName(); 216 217 if ( path.equals("/") ) { 218 throw new ProcessingException("Path '/' is not allowed"); 220 221 } else if ( path.startsWith("/authentication") ) { 222 223 this.cleanParametersCache(); 224 this.authContext.setXML(path, fragment); 225 226 } else if (path.equals("/application") 227 || path.startsWith("/application/") ) { 228 229 if (applicationName == null) { 230 throw new ProcessingException("Application is required"); 231 } 232 String appPath; 233 if (path.equals("/application")) { 234 appPath = "/"; 235 } else { 236 appPath = path.substring("/application".length()); 237 } 238 this.authContext.setXML("/applications/" + applicationName + appPath, fragment); 239 240 } else { 241 this.authContext.setXML(path, fragment); 242 } 243 } 244 245 248 public void appendXML(String path, DocumentFragment fragment) 249 throws ProcessingException { 250 if (path == null) { 251 throw new ProcessingException("appendXML: Path is required"); 252 } 253 if (!path.startsWith("/") ) path = '/' + path; 254 255 final String applicationName = this.getState().getApplicationName(); 256 257 if ( path.equals("/") ) { 258 throw new ProcessingException("Path '/' is not allowed"); 260 261 } else if ( path.startsWith("/authentication") ) { 262 263 this.cleanParametersCache(); 264 this.authContext.appendXML(path, fragment); 265 266 } else if (path.equals("/application") 267 || path.startsWith("/application/") ) { 268 269 if (applicationName == null) { 270 throw new ProcessingException("Application is required"); 271 } 272 String appPath; 273 if (path.equals("/application") ) { 274 appPath = "/"; 275 } else { 276 appPath = path.substring("/application".length()); 277 } 278 this.authContext.appendXML("/applications/" + applicationName + appPath, fragment); 279 280 } else { 281 this.authContext.appendXML(path, fragment); 282 } 283 } 284 285 288 public void removeXML(String path) 289 throws ProcessingException { 290 if (path == null) { 291 throw new ProcessingException("removeXML: Path is required"); 292 } 293 if (!path.startsWith("/") ) path = '/' + path; 294 295 final String applicationName = this.getState().getApplicationName(); 296 297 if (path.equals("/") ) { 298 this.cleanParametersCache(); 299 this.authContext.removeXML("/"); 300 301 } else if (path.startsWith("/authentication") ) { 302 303 this.cleanParametersCache(); 304 this.authContext.removeXML(path); 305 306 } else if (path.equals("/application") 307 || path.startsWith("/application/") ) { 308 if (applicationName == null) { 309 throw new ProcessingException("removeXML: Application is required for path " + path); 310 } 311 String appPath; 312 if (path.equals("/application") ) { 313 appPath = "/"; 314 } else { 315 appPath = path.substring("/application".length()); 316 } 317 this.authContext.removeXML("/applications/" + applicationName + appPath); 318 } else { 319 this.authContext.removeXML(path); 320 } 321 } 322 323 326 public void setAttribute(String key, Object value) 327 throws ProcessingException { 328 this.authContext.setAttribute(key, value); 329 } 330 331 334 public Object getAttribute(String key) 335 throws ProcessingException { 336 return this.authContext.getAttribute(key); 337 } 338 339 342 public Object getAttribute(String key, Object defaultObject) 343 throws ProcessingException { 344 return this.authContext.getAttribute(key, defaultObject); 345 } 346 347 350 public Node getSingleNode(String path) 351 throws ProcessingException { 352 throw new ProcessingException("This method is not supported by the authenticaton session context."); 353 } 354 355 358 public NodeList getNodeList(String path) 359 throws ProcessingException { 360 throw new ProcessingException("This method is not supported by the authenticaton session context."); 361 } 362 363 366 public void setNode(String path, Node node) 367 throws ProcessingException { 368 throw new ProcessingException("This method is not supported by the authenticaton session context."); 369 } 370 371 374 public String getValueOfNode(String path) 375 throws ProcessingException { 376 throw new ProcessingException("This method is not supported by the authenticaton session context."); 377 } 378 379 382 public void setValueOfNode(String path, String value) 383 throws ProcessingException { 384 throw new ProcessingException("This method is not supported by the authenticaton session context."); 385 } 386 387 390 public boolean streamXML(String path, ContentHandler contentHandler, 391 LexicalHandler lexicalHandler) 392 throws SAXException , ProcessingException { 393 if (path == null) { 394 throw new ProcessingException("streamXML: Path is required"); 395 } 396 if (!path.startsWith("/") ) path = '/' + path; 397 398 final String applicationName = this.getState().getApplicationName(); 399 400 if (path.equals("/") ) { 401 contentHandler.startElement("", "authentication", "authentication", XMLUtils.EMPTY_ATTRIBUTES); 403 this.authContext.streamXML("/authentication", contentHandler, lexicalHandler); 404 contentHandler.endElement("", "authentication", "authentication"); 405 406 if (applicationName != null) { 407 contentHandler.startElement("", "application", "application", XMLUtils.EMPTY_ATTRIBUTES); 408 this.authContext.streamXML("/applications/" + applicationName, contentHandler, lexicalHandler); 409 contentHandler.endElement("", "application", "application"); 410 } 411 return true; 412 413 } else if (path.startsWith("/authentication") ) { 414 return this.authContext.streamXML(path, contentHandler, lexicalHandler); 415 416 } else if (path.equals("/application") || path.startsWith("/application/") ) { 417 if (applicationName != null) { 418 String appPath; 419 if (path.equals("/application") ) { 420 appPath ="/"; 421 } else { 422 appPath = path.substring("/application".length()); 423 } 424 return this.authContext.streamXML("/applications/" + applicationName + appPath, contentHandler, lexicalHandler); 425 } 426 } else { 427 return this.authContext.streamXML(path, contentHandler, lexicalHandler); 428 } 429 return false; 430 } 431 432 435 public void loadXML(String path, 436 SourceParameters parameters) 437 throws SAXException , ProcessingException, IOException { 438 if (!path.startsWith("/") ) path = '/' + path; 439 440 final String applicationName = this.getState().getApplicationName(); 441 if (path.equals("/") ) { 442 this.loadAuthenticationXML("/authentication", 444 parameters, 445 resolver); 446 if (applicationName != null) { 447 this.loadApplicationXML("/", 448 parameters, 449 resolver); 450 } 451 452 } else if (path.startsWith("/authentication") ) { 453 this.loadAuthenticationXML(path, 454 parameters, 455 resolver); 456 457 } else if (path.equals("/application") && applicationName != null) { 458 this.loadApplicationXML("/", 459 parameters, 460 resolver); 461 } else if (path.startsWith("/application/") && applicationName != null) { 462 this.loadApplicationXML(path.substring(12), parameters, 464 resolver); 465 } else { 466 throw new ProcessingException("loadXML: Path is not valid: " + path); 467 } 468 } 469 470 473 public void saveXML(String path, 474 SourceParameters parameters) 475 throws SAXException , ProcessingException, IOException { 476 if (!path.startsWith("/") ) path = '/' + path; 477 478 final String applicationName = this.getState().getApplicationName(); 479 480 if (path.equals("/") ) { 481 this.saveAuthenticationXML("/authentication", 483 parameters, 484 resolver); 485 if (applicationName != null) { 486 this.saveApplicationXML("/", 487 parameters, 488 resolver); 489 } 490 491 } else if (path.startsWith("/authentication") ) { 492 this.saveAuthenticationXML(path, 493 parameters, 494 resolver); 495 496 } else if (path.equals("/application") && applicationName != null) { 497 this.saveApplicationXML("/", 498 parameters, 499 resolver); 500 } else if (path.startsWith("/application/") && applicationName != null) { 501 this.saveApplicationXML(path.substring(12), parameters, 503 resolver); 504 } else { 505 throw new ProcessingException("saveXML: Path is not valid: " + path); 506 } 507 } 508 509 512 private void cleanParametersCache() 513 throws ProcessingException { 514 this.authContext.setAttribute("cachedmap" , null); 515 this.authContext.setAttribute("cachedpar" , null); 516 } 517 518 521 private void saveAuthenticationXML(String path, 522 SourceParameters parameters, 523 SourceResolver resolver) 524 throws ProcessingException { 525 String authSaveResource = this.handler.getHandlerConfiguration().getSaveResource(); 526 SourceParameters authSaveResourceParameters = this.handler.getHandlerConfiguration().getSaveResourceParameters(); 527 528 if (authSaveResource == null) { 529 throw new ProcessingException("The context " + this.name + " does not support saving."); 530 } 531 532 synchronized(this.authContext) { 533 DocumentFragment fragment = this.getXML(path); 534 if (fragment == null) { 535 fragment = DOMUtil.createDocument().createDocumentFragment(); 537 } 538 if (parameters != null) { 539 parameters = (SourceParameters)parameters.clone(); 540 parameters.add(authSaveResourceParameters); 541 } else if (authSaveResourceParameters != null) { 542 parameters = (SourceParameters)authSaveResourceParameters.clone(); 543 } 544 parameters = this.createParameters(parameters, 545 path, 546 false); 547 SourceUtil.writeDOM(authSaveResource, 548 null, 549 parameters, 550 fragment, 551 resolver, 552 "xml"); 553 } } 555 556 559 private void loadAuthenticationXML(String path, 560 SourceParameters parameters, 561 SourceResolver resolver) 562 throws ProcessingException { 563 String authLoadResource = this.handler.getHandlerConfiguration().getLoadResource(); 564 SourceParameters authLoadResourceParameters = this.handler.getHandlerConfiguration().getLoadResourceParameters(); 565 566 if (authLoadResource == null) { 567 throw new ProcessingException("The context " + this.name + " does not support loading."); 568 } 569 570 synchronized(this.authContext) { 571 572 if (parameters != null) { 573 parameters = (SourceParameters)parameters.clone(); 574 parameters.add(authLoadResourceParameters); 575 } else if (authLoadResourceParameters != null) { 576 parameters = (SourceParameters)authLoadResourceParameters.clone(); 577 } 578 parameters = this.createParameters(parameters, 579 path, 580 false); 581 DocumentFragment frag; 582 583 frag = SourceUtil.readDOM(authLoadResource, 584 null, 585 parameters, 586 resolver); 587 588 this.setXML(path, frag); 589 590 } } 592 593 596 private void loadApplicationXML(String path, 597 SourceParameters parameters, 598 SourceResolver resolver) 599 throws ProcessingException { 600 final String applicationName = this.getState().getApplicationName(); 601 602 final ApplicationConfiguration conf = (ApplicationConfiguration)this.handler.getHandlerConfiguration().getApplications().get( applicationName ); 603 String loadResource = conf.getLoadResource(); 604 SourceParameters loadResourceParameters = conf.getLoadResourceParameters(); 605 if (loadResource == null) { 606 throw new ProcessingException("The context " + this.name + " does not support loading."); 607 } 608 synchronized (this.authContext) { 610 611 if (parameters != null) { 612 parameters = (SourceParameters)parameters.clone(); 613 parameters.add(loadResourceParameters); 614 } else if (loadResourceParameters != null) { 615 parameters = (SourceParameters)loadResourceParameters.clone(); 616 } 617 parameters = this.createParameters(parameters, 618 path, 619 true); 620 DocumentFragment fragment; 621 fragment = SourceUtil.readDOM(loadResource, 622 null, 623 parameters, 624 resolver); 625 this.authContext.setXML("/applications/" + applicationName + '/', fragment); 626 627 } 629 } 630 631 634 private void saveApplicationXML(String path, 635 SourceParameters parameters, 636 SourceResolver resolver) 637 throws ProcessingException { 638 final String applicationName = this.getState().getApplicationName(); 639 final ApplicationConfiguration conf = (ApplicationConfiguration)this.handler.getHandlerConfiguration().getApplications().get( applicationName ); 640 String saveResource = conf.getSaveResource(); 641 SourceParameters saveResourceParameters = conf.getSaveResourceParameters(); 642 643 if (saveResource == null) { 644 throw new ProcessingException("The context " + this.name + " does not support saving."); 645 } 646 synchronized (this.authContext) { 648 649 if (parameters != null) { 650 parameters = (SourceParameters)parameters.clone(); 651 parameters.add(saveResourceParameters); 652 } else if (saveResourceParameters != null) { 653 parameters = (SourceParameters)saveResourceParameters.clone(); 654 } 655 parameters = this.createParameters(parameters, 656 path, 657 true); 658 DocumentFragment fragment = this.getXML("/application" + path); 659 if (fragment == null) { 660 fragment = DOMUtil.createDocument().createDocumentFragment(); 662 } 663 664 SourceUtil.writeDOM(saveResource, 665 null, 666 parameters, 667 fragment, 668 resolver, 669 "xml"); 670 671 } 673 } 674 675 678 private SourceParameters createParameters(SourceParameters parameters, 679 String path, 680 boolean appendAppInfo) 681 throws ProcessingException { 682 if (parameters == null) parameters = new SourceParameters(); 683 684 final String applicationName = this.getState().getApplicationName(); 685 686 this.addParametersFromAuthenticationXML("/data", 688 parameters); 689 690 this.addParametersFromAuthenticationXML("", 692 parameters); 693 694 parameters.setSingleParameterValue("handler", this.handlerName); 696 if ( appendAppInfo ) { 697 if (applicationName != null) parameters.setSingleParameterValue("application", applicationName); 698 } 699 if (path != null) parameters.setSingleParameterValue("path", path); 700 701 return parameters; 702 } 703 704 711 private void addParametersFromAuthenticationXML(String path, 712 SourceParameters parameters) 713 throws ProcessingException { 714 final DocumentFragment fragment = this.authContext.getXML("/authentication" + path); 715 if (fragment != null) { 716 NodeList childs = fragment.getChildNodes(); 717 if (childs != null) { 718 Node current; 719 for(int i = 0; i < childs.getLength(); i++) { 720 current = childs.item(i); 721 722 if (current.getNodeType() == Node.ELEMENT_NODE) { 724 current.normalize(); 725 NodeList valueChilds = current.getChildNodes(); 726 String key; 727 StringBuffer valueBuffer; 728 String value; 729 730 key = current.getNodeName(); 731 valueBuffer = new StringBuffer (); 732 for(int m = 0; m < valueChilds.getLength(); m++) { 733 current = valueChilds.item(m); if (current.getNodeType() == Node.TEXT_NODE) { if (valueBuffer.length() > 0) valueBuffer.append(' '); 736 valueBuffer.append(current.getNodeValue()); 737 } 738 } 739 value = valueBuffer.toString().trim(); 740 if (key != null && value != null && value.length() > 0) { 741 parameters.setParameter(key, value); 742 } 743 } 744 } 745 } 746 } 747 } 748 749 public Map getContextInfo() 750 throws ProcessingException { 751 Map map = (Map )this.authContext.getAttribute( "cachedmap" ); 752 if (map == null) { 753 map = new HashMap (20); 754 Parameters pars = this.createParameters(null, null, false).getFirstParameters(); 755 String [] names = pars.getNames(); 756 if (names != null) { 757 String key; 758 String value; 759 for(int i=0;i<names.length;i++) { 760 key = names[i]; 761 value = pars.getParameter(key, null); 762 if (value != null) map.put(key, value); 763 } 764 } 765 this.authContext.setAttribute("cachedmap", map); 766 } 767 return map; 768 } 769 770 public SourceParameters getContextInfoAsParameters() 771 throws ProcessingException { 772 SourceParameters pars = (SourceParameters)this.authContext.getAttribute( "cachedpar" ); 773 if (pars == null) { 774 pars = this.createParameters(null, null, false); 775 this.authContext.setAttribute("cachedpar", pars); 776 } 777 return pars; 778 } 779 780 783 public void loadApplicationXML(ApplicationConfiguration appConf, 784 SourceResolver resolver) 785 throws ProcessingException { 786 String loadResource = appConf.getLoadResource(); 787 SourceParameters loadResourceParameters = appConf.getLoadResourceParameters(); 788 if ( !this.handler.isApplicationLoaded(appConf) && loadResource != null ) { 789 synchronized (this.authContext) { 790 791 SourceParameters parameters; 792 if (loadResourceParameters != null) { 793 parameters = (SourceParameters)loadResourceParameters.clone(); 794 } else { 795 parameters = new SourceParameters(); 796 } 797 parameters = this.createParameters(parameters, 798 null, 799 true); 800 DocumentFragment fragment; 801 fragment = SourceUtil.readDOM(loadResource, 802 null, 803 parameters, 804 resolver); 805 this.authContext.setXML("/applications/" + appConf.getName() + '/', fragment); 806 807 } } 809 this.handler.setApplicationIsLoaded(appConf); 810 } 811 812 816 public boolean isUserInRole(String role) { 817 if ( this.roles == null ) { 818 this.roles = new ArrayList (); 819 try { 820 final String allRoles = (String )this.getContextInfo().get("roles"); 821 final StringTokenizer st = new StringTokenizer ( allRoles, ","); 822 while ( st.hasMoreElements() ) { 823 this.roles.add(st.nextElement()); 824 } 825 } catch (ProcessingException pe) { 826 } 828 } 829 if ( this.roles.contains( role ) ) { 830 return true; 831 } 832 final Request req = ContextHelper.getRequest(this.context); 833 return req.isUserInRole(role); 834 } 835 } 836 | Popular Tags |