1 18 package org.apache.beehive.netui.pageflow; 19 20 import org.apache.beehive.netui.util.internal.InternalStringBuilder; 21 22 import org.apache.beehive.netui.pageflow.internal.InternalConstants; 23 import org.apache.beehive.netui.pageflow.internal.InternalUtils; 24 import org.apache.beehive.netui.pageflow.internal.PageFlowRequestWrapper; 25 import org.apache.beehive.netui.util.Bundle; 26 import org.apache.beehive.netui.util.internal.DiscoveryUtils; 27 import org.apache.beehive.netui.util.config.ConfigUtil; 28 import org.apache.beehive.netui.util.config.bean.ModuleConfigLocators; 29 import org.apache.beehive.netui.util.config.bean.PageflowConfig; 30 import org.apache.beehive.netui.util.logging.Logger; 31 import org.apache.commons.digester.Digester; 32 import org.apache.struts.Globals; 33 import org.apache.struts.action.ActionServlet; 34 import org.apache.struts.action.DynaActionFormClass; 35 import org.apache.struts.action.RequestProcessor; 36 import org.apache.struts.config.ControllerConfig; 37 import org.apache.struts.config.FormBeanConfig; 38 import org.apache.struts.config.MessageResourcesConfig; 39 import org.apache.struts.config.ModuleConfig; 40 import org.apache.struts.config.ModuleConfigFactory; 41 import org.apache.struts.config.impl.ModuleConfigImpl; 42 import org.apache.struts.util.RequestUtils; 43 import org.xml.sax.InputSource ; 44 45 import javax.servlet.ServletConfig ; 46 import javax.servlet.ServletContext ; 47 import javax.servlet.ServletException ; 48 import javax.servlet.ServletRequest ; 49 import javax.servlet.ServletResponse ; 50 import javax.servlet.UnavailableException ; 51 import javax.servlet.http.HttpServletRequest ; 52 import javax.servlet.http.HttpServletResponse ; 53 import java.io.IOException ; 54 import java.io.InputStream ; 55 import java.io.ObjectInputStream ; 56 import java.io.ObjectOutputStream ; 57 import java.net.MalformedURLException ; 58 import java.net.URL ; 59 import java.util.ArrayList ; 60 import java.util.Collections ; 61 import java.util.Enumeration ; 62 import java.util.HashMap ; 63 import java.util.Map ; 64 import java.util.Iterator ; 65 66 import org.apache.beehive.netui.util.internal.concurrent.InternalConcurrentHashMap; 67 68 69 74 public class AutoRegisterActionServlet extends ActionServlet 75 { 76 80 public static String MODULE_CONFIG_LOCATOR_CLASS_ATTR = "moduleConfigLocators"; 81 82 83 private Map _registeredModules = new InternalConcurrentHashMap(); 84 private transient Digester _cachedConfigDigester = null; 85 private Map _configParams = null; 86 private ModuleConfigLocator[] _moduleConfigLocators = null; 87 88 private static final Logger _log = Logger.getInstance( AutoRegisterActionServlet.class ); 89 90 private static final ModuleConfig NONEXISTANT_MODULE_CONFIG = new NonexistantModuleConfig(); 91 92 93 public void init() 94 throws ServletException 95 { 96 super.init(); 97 setupModuleConfigLocators(); 98 } 99 100 private void setupModuleConfigLocators() 101 { 102 ModuleConfigLocator[] defaultLocators = getDefaultModuleConfigLocators(); 103 ArrayList locators = new ArrayList (); 104 105 for ( int i =0; i < defaultLocators.length; ++i ) 106 { 107 locators.add( defaultLocators[i] ); 108 } 109 110 PageflowConfig pfConfig = ConfigUtil.getConfig().getPageflowConfig(); 114 115 if ( pfConfig != null ) 116 { 117 ModuleConfigLocators mcLocators = pfConfig.getModuleConfigLocators(); 118 119 if ( mcLocators != null ) 120 { 121 ModuleConfigLocators.ModuleConfigLocator[] array = mcLocators.getModuleConfigLocatorArray(); 122 123 for ( int i = 0; i < array.length; i++ ) 124 { 125 addModuleConfigLocator( array[i].getLocatorClass().trim(), locators ); 126 } 127 } 128 } 129 130 String configLocatorList = getServletConfig().getInitParameter( MODULE_CONFIG_LOCATOR_CLASS_ATTR ); 134 135 if ( configLocatorList != null ) 136 { 137 if ( _log.isWarnEnabled() ) 138 { 139 _log.warn( "Found module-config-locators list in context-parameter " + MODULE_CONFIG_LOCATOR_CLASS_ATTR 140 + ", which is deprecated. Please use the <module-config-locators> element in " 141 + InternalConstants.NETUI_CONFIG_PATH + " instead." ); 142 } 143 144 String [] configLocatorClassNames = configLocatorList.split( "," ); 145 146 for ( int i = 0; i < configLocatorClassNames.length; ++i ) 147 { 148 addModuleConfigLocator( configLocatorClassNames[i].trim(), locators ); 149 } 150 } 151 152 _moduleConfigLocators = ( ModuleConfigLocator[] ) locators.toArray( new ModuleConfigLocator[locators.size()] ); 153 } 154 155 private static void addModuleConfigLocator( String locatorClassName, ArrayList locators ) 156 { 157 try 158 { 159 Class locatorClass = DiscoveryUtils.loadImplementorClass( locatorClassName, ModuleConfigLocator.class ); 160 161 if ( locatorClass != null ) { 163 ModuleConfigLocator locator = ( ModuleConfigLocator ) locatorClass.newInstance(); 164 locators.add( locator ); 165 } 166 } 167 catch ( IllegalAccessException e ) 168 { 169 _log.error( "Could not create an instance of specified module-config-locator " + locatorClassName, e ); 170 } 171 catch ( InstantiationException e ) 172 { 173 _log.error( "Could not create an instance of specified module-config-locator " + locatorClassName, e ); 174 } 175 } 176 177 184 protected ModuleConfigLocator[] getDefaultModuleConfigLocators() 185 { 186 return new ModuleConfigLocator[0]; 187 } 188 189 195 public ModuleConfigLocator[] getModuleConfigLocators() 196 { 197 return _moduleConfigLocators; 198 } 199 200 205 public static interface ModuleConfigLocator 206 { 207 213 public String getModuleConfigPath( String moduleName ); 214 } 215 216 225 public String getModuleConfPath( String modulePath ) 226 { 227 if ( _moduleConfigLocators != null ) 228 { 229 for ( int i = 0; i < _moduleConfigLocators.length; ++i ) 230 { 231 ModuleConfigLocator locator = _moduleConfigLocators[i]; 232 String moduleConfigPath = locator.getModuleConfigPath( modulePath ); 233 234 try 235 { 236 if ( getConfigResource( moduleConfigPath ) != null ) return moduleConfigPath; 237 } 238 catch ( MalformedURLException e ) 239 { 240 _log.error( "ModuleConfigLocator " + locator.getClass().getName() 241 + " returned an invalid path: " + moduleConfigPath + '.', e ); 242 } 243 } 244 } 245 246 return null; 247 } 248 249 private boolean isAutoLoadModulePath( String modulePath, String prefix ) 250 { 251 if ( _moduleConfigLocators != null ) 252 { 253 for ( int i = 0; i < _moduleConfigLocators.length; ++i ) 254 { 255 ModuleConfigLocator locator = _moduleConfigLocators[i]; 256 if ( modulePath.equals( locator.getModuleConfigPath( prefix ) ) ) return true; 257 } 258 } 259 260 return false; 261 } 262 263 private void writeObject( ObjectOutputStream stream ) 269 throws IOException 270 { 271 if ( _log.isInfoEnabled() ) 272 { 273 _log.info( "serializing ActionServlet " + this ); 274 } 275 276 if ( _configParams != null ) 277 { 278 stream.writeObject( _configParams ); 279 } 280 else 281 { 282 ServletConfig servletConfig = getServletConfig(); 283 assert servletConfig != null; 284 HashMap params = new HashMap (); 285 286 for ( Enumeration e = servletConfig.getInitParameterNames(); e.hasMoreElements(); ) 287 { 288 String name = ( String ) e.nextElement(); 289 params.put( name, servletConfig.getInitParameter( name ) ); 290 } 291 292 stream.writeObject( params ); 293 } 294 } 295 296 private void readObject( ObjectInputStream stream ) 298 throws IOException , ClassNotFoundException 299 { 300 if ( _log.isInfoEnabled() ) _log.info( "deserializing ActionServlet " + this ); 301 _configParams = ( Map ) stream.readObject(); 302 } 303 304 public String getInitParameter( String s ) 305 { 306 if ( getServletConfig() == null ) 307 { 308 assert _configParams != null; return ( String ) _configParams.get( s ); 310 } 311 312 return super.getInitParameter( s ); 313 } 314 315 public Enumeration getInitParameterNames() 316 { 317 if ( getServletConfig() == null ) 318 { 319 assert _configParams != null; return Collections.enumeration( _configParams.keySet() ); 321 } 322 323 return super.getInitParameterNames(); 324 } 325 326 333 protected ModuleConfig initModuleConfig 334 ( String prefix, String paths ) throws ServletException 335 { 336 337 if ( _log.isDebugEnabled() ) 338 { 339 _log.debug( "Initializing module path '" + prefix + "' configuration from '" + paths + '\'' ); 340 } 341 342 ModuleConfig moduleConfig = null; 344 InputStream input = null; 345 String mapping; 346 347 try 348 { 349 ModuleConfigFactory factoryObject = 350 ModuleConfigFactory.createFactory(); 351 moduleConfig = factoryObject.createModuleConfig( prefix ); 352 353 mapping = getServletConfig().getInitParameter( "mapping" ); 355 if ( mapping != null ) 356 { 357 moduleConfig.setActionMappingClass( mapping ); 358 } 359 360 Digester digester = initConfigDigester(); 362 363 while ( paths.length() > 0 ) 365 { 366 digester.push( moduleConfig ); 367 String path; 368 int comma = paths.indexOf( ',' ); 369 if ( comma >= 0 ) 370 { 371 path = paths.substring( 0, comma ).trim(); 372 paths = paths.substring( comma + 1 ); 373 } 374 else 375 { 376 path = paths.trim(); 377 paths = ""; 378 } 379 if ( path.length() < 1 ) 380 { 381 break; 382 } 383 384 URL url = getConfigResource( path ); 385 386 if ( url != null ) 390 { 391 InputSource is = new InputSource ( url.toExternalForm() ); 392 input = getConfigResourceAsStream( path ); 393 is.setByteStream( input ); 394 395 try 397 { 398 digester.parse( is ); 399 getServletContext().setAttribute( Globals.MODULE_KEY + prefix, moduleConfig ); 400 } 401 catch ( Exception e ) 402 { 403 _log.error( Bundle.getString( "PageFlow_Struts_ModuleParseError", path ), e ); 404 } 405 input.close(); 406 } 407 else 408 { 409 if ( prefix.equals( "" ) && isAutoLoadModulePath( path, prefix ) ) 416 { 417 if ( _log.isInfoEnabled() ) 418 { 419 _log.info( "There is no root module at " + path + "; initializing a default module." ); 420 } 421 422 moduleConfig.setControllerConfig( new MissingRootModuleControllerConfig() ); 427 } 428 else 429 { 430 _log.error( Bundle.getString( "PageFlow_Struts_MissingModuleConfig", path ) ); 431 } 432 } 433 } 434 435 } 436 catch ( Throwable t ) 437 { 438 _log.error( internal.getMessage( "configParse", paths ), t ); 439 throw new UnavailableException ( internal.getMessage( "configParse", paths ) ); 440 } 441 finally 442 { 443 if ( input != null ) 444 { 445 try 446 { 447 input.close(); 448 } 449 catch ( IOException e ) 450 { 451 } 453 } 454 } 455 456 FormBeanConfig fbs[] = moduleConfig.findFormBeanConfigs(); 459 for ( int i = 0; i < fbs.length; i++ ) 460 { 461 if ( fbs[i].getDynamic() ) 462 { 463 DynaActionFormClass.createDynaActionFormClass( fbs[i] ); 464 } 465 } 466 467 if ( prefix.length() < 1 ) 470 { 471 defaultControllerConfig( moduleConfig ); 472 defaultMessageResourcesConfig( moduleConfig ); 473 } 474 475 return moduleConfig; 478 479 } 480 481 static class MissingRootModuleControllerConfig extends ControllerConfig 482 { 483 public MissingRootModuleControllerConfig() 484 { 485 setProcessorClass( PageFlowRequestProcessor.class.getName() ); 486 } 487 } 488 489 490 498 protected URL getConfigResource( String path ) 499 throws MalformedURLException 500 { 501 URL resource = getServletContext().getResource( path ); 502 if ( resource != null ) return resource; 503 if ( path.startsWith( "/" ) ) path = path.substring( 1 ); 504 return Thread.currentThread().getContextClassLoader().getResource( path ); 505 } 506 507 514 protected InputStream getConfigResourceAsStream( String path ) 515 { 516 InputStream stream = getServletContext().getResourceAsStream( path ); 517 if ( stream != null ) return stream; 518 if ( path.startsWith( "/" ) ) path = path.substring( 1 ); 519 return Thread.currentThread().getContextClassLoader().getResourceAsStream( path ); 520 } 521 522 530 protected synchronized ModuleConfig registerModule( String modulePath, String configFilePath ) 531 throws ServletException 532 { 533 if ( _log.isInfoEnabled() ) 534 { 535 _log.info( "Dynamically registering module " + modulePath + ", config XML " + configFilePath ); 536 } 537 538 if ( _log.isInfoEnabled() ) 539 { 540 InternalStringBuilder msg = new InternalStringBuilder( "Dynamically registering module " ).append( modulePath ); 541 _log.info( msg.append( ", config XML " ).append( configFilePath ).toString() ); 542 } 543 544 if ( _cachedConfigDigester == null ) 545 { 546 _cachedConfigDigester = initConfigDigester(); 547 } 548 549 configDigester = _cachedConfigDigester; 550 ModuleConfig ac = initModuleConfig( modulePath, configFilePath ); 551 initModuleMessageResources( ac ); 552 initModuleDataSources( ac ); 553 initModulePlugIns( ac ); 554 ac.freeze(); 555 configDigester = null; 556 557 if ( _log.isDebugEnabled() ) 558 { 559 _log.debug( "Finished registering module " + modulePath + ", config XML " + configFilePath ); 560 } 561 562 return ac; 563 } 564 565 570 protected void process( HttpServletRequest request, HttpServletResponse response ) 571 throws IOException , ServletException 572 { 573 PageFlowRequestWrapper requestWrapper = PageFlowRequestWrapper.wrapRequest( request ); 578 request = requestWrapper; 579 580 ServletContext servletContext = getServletContext(); 581 String modulePath = PageFlowUtils.getModulePathForRelativeURI( InternalUtils.getDecodedServletPath( request ) ); 582 ModuleConfig registeredApp; 583 584 registeredApp = getModuleConfig( modulePath, request, response ); 588 589 if ( registeredApp != null ) 594 { 595 ModuleConfig moduleConfig = InternalUtils.selectModule( modulePath, request, servletContext ); 599 RequestProcessor requestProcessor = getRequestProcessor( moduleConfig ); 600 requestProcessor.process( request, response ); 601 } 602 else 603 { 604 605 ModuleConfig moduleConfig = null; 609 610 if ( InternalUtils.getModuleConfig( RequestUtils.getModuleName( request, servletContext ), servletContext ) != null ) 611 { 612 String modulePrefix = RequestUtils.getModuleName( request, servletContext ); 613 moduleConfig = InternalUtils.selectModule( modulePrefix, request, servletContext ); 614 } 615 616 String servletPath = InternalUtils.getDecodedServletPath( request ); 617 RequestProcessor rp = moduleConfig != null ? getRequestProcessor( moduleConfig ) : null; 618 619 if ( rp != null && moduleCanHandlePath( moduleConfig, rp, servletPath ) ) 620 { 621 rp.process( request, response ); 622 } 623 else 624 { 625 if ( processUnhandledAction( request, response, servletPath ) ) return; 626 627 String originalServletPath = requestWrapper.getOriginalServletPath(); 628 if ( originalServletPath != null ) 629 { 630 servletPath = originalServletPath; 631 modulePath = PageFlowUtils.getModulePathForRelativeURI( originalServletPath ); 632 } 633 634 if ( _log.isErrorEnabled() ) 635 { 636 InternalStringBuilder msg = new InternalStringBuilder( "No module configuration registered for " ); 637 msg.append( servletPath ).append( " (module path " ).append( modulePath ).append( ")." ); 638 _log.error( msg.toString() ); 639 } 640 641 if ( modulePath.length() == 0 ) modulePath = "/"; 645 InternalUtils.sendDevTimeError( "PageFlow_NoModuleConf", null, HttpServletResponse.SC_NOT_FOUND, 646 request, response, servletContext, 647 new Object []{ servletPath, modulePath } ); 648 } 649 } 650 } 651 652 655 protected boolean moduleCanHandlePath( ModuleConfig moduleConfig, RequestProcessor rp, String servletPath ) 656 { 657 return true; 658 } 659 660 663 protected Digester initConfigDigester() throws ServletException 664 { 665 _cachedConfigDigester = super.initConfigDigester(); 666 return _cachedConfigDigester; 667 } 668 669 public void destroy() 670 { 671 _registeredModules.clear(); 672 super.destroy(); 673 } 674 675 void ensureModuleSelected( String modulePath, HttpServletRequest request, ServletResponse response ) 676 throws IOException , ServletException 677 { 678 if ( getModuleConfig( modulePath, request, response ) != null ) 679 { 680 InternalUtils.selectModule( modulePath, request, getServletContext() ); 681 } 682 } 683 684 694 protected ModuleConfig getModuleConfig( String modulePath, ServletRequest request, 695 ServletResponse response ) 696 throws IOException , ServletException 697 { 698 ensureModuleRegistered( modulePath, request ); 699 700 ModuleConfig mc = ( ModuleConfig ) _registeredModules.get( modulePath ); 701 702 if ( mc.getPrefix() == null ) 703 { 704 assert mc instanceof NonexistantModuleConfig : mc.getClass().getName(); 705 mc = null; 706 } 707 708 return mc; 709 } 710 711 720 public ModuleConfig ensureModuleRegistered( String modulePath, ServletRequest request ) 721 throws IOException , ServletException 722 { 723 ModuleConfig ac = ( ModuleConfig ) _registeredModules.get( modulePath ); 734 735 if ( ac == null ) 736 { 737 ac = ( ModuleConfig ) getServletContext().getAttribute( Globals.MODULE_KEY + modulePath ); 742 743 if ( ac == null ) 744 { 745 String moduleConfPath = getModuleConfPath( modulePath ); 750 751 if ( moduleConfPath != null ) 752 { 753 ac = registerModule( modulePath, moduleConfPath ); 754 } 755 } 756 757 if ( ac == null ) 758 { 759 _registeredModules.put( modulePath, NONEXISTANT_MODULE_CONFIG ); 760 } 762 else 763 { 764 _registeredModules.put( modulePath, ac ); 765 getServletContext().setAttribute( Globals.MODULE_KEY + modulePath, ac ); 766 } 767 } 768 769 return ac; 770 } 771 772 private static class NonexistantModuleConfig extends ModuleConfigImpl 773 { 774 public NonexistantModuleConfig() 775 { 776 super( ( String ) null ); 777 } 778 } 779 780 785 795 private void defaultControllerConfig(ModuleConfig config) { 796 797 String value = null; 798 ControllerConfig cc = config.getControllerConfig(); 799 800 value = getServletConfig().getInitParameter("bufferSize"); 801 if (value != null) { 802 cc.setBufferSize(Integer.parseInt(value)); 803 } 804 805 value = getServletConfig().getInitParameter("content"); 806 if (value != null) { 807 cc.setContentType(value); 808 } 809 810 value = getServletConfig().getInitParameter("locale"); 811 if (value != null) { 813 if ("true".equalsIgnoreCase(value) || "yes".equalsIgnoreCase(value)) { 814 cc.setLocale(true); 815 } else { 816 cc.setLocale(false); 817 } 818 } 819 820 value = getServletConfig().getInitParameter("maxFileSize"); 821 if (value != null) { 822 cc.setMaxFileSize(value); 823 } 824 825 value = getServletConfig().getInitParameter("nocache"); 826 if (value != null) { 827 if ("true".equalsIgnoreCase(value) || "yes".equalsIgnoreCase(value)) { 828 cc.setNocache(true); 829 } else { 830 cc.setNocache(false); 831 } 832 } 833 834 value = getServletConfig().getInitParameter("multipartClass"); 835 if (value != null) { 836 cc.setMultipartClass(value); 837 } 838 839 value = getServletConfig().getInitParameter("tempDir"); 840 if (value != null) { 841 cc.setTempDir(value); 842 } 843 844 } 845 846 856 private void defaultMessageResourcesConfig(ModuleConfig config) { 857 858 String value = null; 859 860 MessageResourcesConfig mrc = 861 config.findMessageResourcesConfig(Globals.MESSAGES_KEY); 862 if (mrc == null) { 863 mrc = new MessageResourcesConfig(); 864 mrc.setKey(Globals.MESSAGES_KEY); 865 config.addMessageResourcesConfig(mrc); 866 } 867 value = getServletConfig().getInitParameter("application"); 868 if (value != null) { 869 mrc.setParameter(value); 870 } 871 value= getServletConfig().getInitParameter("factory"); 872 if (value != null) { 873 mrc.setFactory(value); 874 } 875 value = getServletConfig().getInitParameter("null"); 876 if (value != null) { 877 if (value.equalsIgnoreCase("true") || 878 value.equalsIgnoreCase("yes")) { 879 mrc.setNull(true); 880 } else { 881 mrc.setNull(false); 882 } 883 } 884 } 885 886 891 public void clearRegisteredModules() 892 { 893 ServletContext servletContext = getServletContext(); 894 895 for ( Iterator ii = _registeredModules.keySet().iterator(); ii.hasNext(); ) 896 { 897 String modulePrefix = ( String ) ii.next(); 898 servletContext.removeAttribute( Globals.MODULE_KEY + modulePrefix ); 899 } 900 901 _registeredModules.clear(); 902 } 903 904 908 protected boolean processUnhandledAction( HttpServletRequest request, HttpServletResponse response, String uri ) 909 throws IOException , ServletException 910 { 911 return false; 912 } 913 } 914 | Popular Tags |