3636import javax .servlet .http .HttpServletRequest ;
3737import javax .servlet .http .HttpServletResponse ;
3838
39- import org .apache .commons .collections .ExtendedProperties ;
39+ import org .apache .commons .configuration2 .AbstractConfiguration ;
40+ import org .apache .commons .configuration2 .CombinedConfiguration ;
41+ import org .apache .commons .configuration2 .PropertiesConfiguration ;
42+ import org .apache .commons .configuration2 .ex .ConfigurationException ;
43+ import org .apache .commons .configuration2 .tree .OverrideCombiner ;
4044import org .apache .velocity .app .VelocityEngine ;
4145import org .apache .velocity .runtime .RuntimeConstants ;
4246import org .mozilla .javascript .Context ;
@@ -156,7 +160,7 @@ public static boolean isGAE(ServletConfig config) {
156160 transient protected ServletContext _context ;
157161 transient protected ButterflyMounter _mounter ;
158162
159- protected ExtendedProperties _properties ;
163+ protected PropertiesConfiguration _properties ;
160164 protected File _contextDir ;
161165 protected File _homeDir ;
162166 protected File _webInfDir ;
@@ -188,55 +192,38 @@ public void init(ServletConfig config) throws ServletException {
188192
189193 _contextDir = new File (_context .getRealPath ("/" ));
190194 _webInfDir = new File (_contextDir , "WEB-INF" );
191- _properties = new ExtendedProperties ();
195+ _properties = new PropertiesConfiguration ();
192196 _mounter = new ButterflyMounter ();
193197
194198 // Load the butterfly properties
195199 String props = System .getProperty ("butterfly.properties" );
196200 File butterflyProperties = (props == null ) ? new File (_webInfDir , "butterfly.properties" ) : new File (props );
197201
198- BufferedInputStream is = null ;
199- try {
200- is = new BufferedInputStream (new FileInputStream (butterflyProperties ));
201- _properties .load (is );
202- } catch (FileNotFoundException e ) {
202+ try (BufferedInputStream is = new BufferedInputStream (Files .newInputStream (butterflyProperties .toPath ()))){
203+ _properties .read (new InputStreamReader (is , StandardCharsets .UTF_8 ));
204+ } catch (IOException |ConfigurationException e ) {
203205 throw new ServletException ("Could not find butterfly properties file" ,e );
204- } catch (IOException e ) {
205- throw new ServletException ("Could not read butterfly properties file" ,e );
206- } finally {
207- try {
208- is .close ();
209- } catch (Exception e ) {
210- // ignore
211- }
212206 }
213207
214208 // Process eventual properties includes
215209 String includes = _properties .getString ("butterfly.includes" );
216210 if (includes != null ) {
217211 for (String prop : includes .split ("," )) {
218212 File prop_file = (prop .startsWith ("/" )) ? new File (prop ) : new File (_webInfDir , prop );
219- try {
220- is = new BufferedInputStream (new FileInputStream (prop_file ));
221- ExtendedProperties p = new ExtendedProperties ();
222- p .load (is );
223- _properties .combine (p );
224- } catch (Exception e ) {
225- // ignore
226- } finally {
227- try {
228- is .close ();
229- } catch (Exception e ) {
230- // ignore
231- }
213+ try (BufferedInputStream is = new BufferedInputStream (Files .newInputStream (prop_file .toPath ()))){
214+ PropertiesConfiguration p = new PropertiesConfiguration ();
215+ p .read (new InputStreamReader (is , StandardCharsets .UTF_8 ));
216+ _properties .append (p );
217+ } catch (ConfigurationException | IOException e ) {
218+ _logger .warn ("Error loading included properties file: " + prop_file , e );
232219 }
233220 }
234221 }
235222 // Overload with properties set from the command line
236223 // using the -Dkey=value parameters to the JVM
237224 Properties systemProperties = System .getProperties ();
238- for (Iterator < Object > i = systemProperties .keySet (). iterator (); i . hasNext (); ) {
239- String key = (String ) i . next () ;
225+ for (Object o : systemProperties .keySet ()) {
226+ String key = (String ) o ;
240227 String value = systemProperties .getProperty (key );
241228 _properties .setProperty (key , value );
242229 }
@@ -326,8 +313,7 @@ public void configure() {
326313 }
327314 _logger .info ("Butterfly home: {}" , _homeDir );
328315
329- Iterator <String > i = _properties .getKeys (ZONE );
330- while (i .hasNext ()) {
316+ for (Iterator <String > i = _properties .getKeys (ZONE ); i .hasNext (); ) {
331317 String zone = i .next ();
332318 String path = _properties .getString (zone );
333319 zone = zone .substring (ZONE .length () + 1 );
@@ -373,7 +359,7 @@ public void configure() {
373359
374360 _logger .info ("> load modules" );
375361 // load modules from the properties found in the butterfly.properties
376- List <String > paths = _properties .getList (MODULES_PATH );
362+ List <String > paths = _properties .getList (String . class , MODULES_PATH );
377363 for (String path : paths ) {
378364 findModulesIn (absolutize (_homeDir , path .trim ()));
379365 }
@@ -394,16 +380,15 @@ public void configure() {
394380 _logger .info ("< create modules" );
395381
396382 _logger .info ("> load module wirings" );
397- ExtendedProperties wirings = new ExtendedProperties ();
398- try {
399- // Load the wiring properties
400- File moduleWirings = absolutize (_homeDir , _properties .getString ("butterfly.modules.wirings" ,"WEB-INF/modules.properties" ));
401- _logger .info ("Loaded module wirings from: {}" , moduleWirings );
402- _classLoader .watch (moduleWirings ); // reload if the module wirings change
403- FileInputStream fis = new FileInputStream (moduleWirings );
404- wirings .load (fis );
405- fis .close ();
406- } catch (Exception e ) {
383+ PropertiesConfiguration wirings = new PropertiesConfiguration ();
384+
385+ // Load the wiring properties
386+ File moduleWirings = absolutize (_homeDir , _properties .getString ("butterfly.modules.wirings" ,"WEB-INF/modules.properties" ));
387+ _logger .info ("Loaded module wirings from: {}" , moduleWirings );
388+ _classLoader .watch (moduleWirings ); // reload if the module wirings change
389+ try (FileInputStream fis = new FileInputStream (moduleWirings )) {
390+ wirings .read (new InputStreamReader (fis , StandardCharsets .UTF_8 ));
391+ } catch (IOException | ConfigurationException e ) {
407392 _configurationException = new Exception ("Failed to load module wirings" , e );
408393 }
409394 _logger .info ("< load module wirings" );
@@ -526,7 +511,7 @@ public void service(HttpServletRequest request, HttpServletResponse response) th
526511
527512 protected Map <String ,ButterflyModule > _modulesByName = new HashMap <String ,ButterflyModule >();
528513 protected Map <String ,Map <String ,ButterflyModule >> _modulesByInterface = new HashMap <String ,Map <String ,ButterflyModule >>();
529- protected Map <String ,ExtendedProperties > _moduleProperties = new HashMap <String ,ExtendedProperties >();
514+ protected Map <String ,AbstractConfiguration > _moduleProperties = new HashMap <String ,AbstractConfiguration >();
530515 protected Map <String ,Boolean > _created = new HashMap <String ,Boolean >();
531516
532517 final static private String routingCookie = "host" ;
@@ -573,13 +558,13 @@ protected void findModulesIn(File f) {
573558 try {
574559 String name = f .getName ();
575560
576- ExtendedProperties p = new ExtendedProperties ();
561+ PropertiesConfiguration p = new PropertiesConfiguration ();
577562 File propFile = new File (modFile ,"module.properties" );
578563 if (propFile .exists ()) {
579- _classLoader .watch (propFile ); // reload if the the module properties change
580- BufferedInputStream stream = new BufferedInputStream (new FileInputStream (propFile ));
581- p . load ( stream );
582- stream . close ();
564+ _classLoader .watch (propFile ); // reload if the module properties change
565+ try ( BufferedInputStream stream = new BufferedInputStream (Files . newInputStream (propFile . toPath ()))) {
566+ p . read ( new InputStreamReader ( stream , StandardCharsets . UTF_8 ) );
567+ }
583568 }
584569
585570 p .addProperty (PATH_PROP , f .getAbsolutePath ());
@@ -624,7 +609,7 @@ protected ButterflyModule createModule(String name) {
624609 return _modulesByName .get (name );
625610 }
626611
627- ExtendedProperties p = _moduleProperties .get (name );
612+ AbstractConfiguration p = _moduleProperties .get (name );
628613 File path = new File (p .getString (PATH_PROP ));
629614 _logger .debug ("Module path: {}" , path );
630615
@@ -685,8 +670,7 @@ protected ButterflyModule createModule(String name) {
685670 return m ;
686671 }
687672
688- @ SuppressWarnings ("unchecked" )
689- protected void wireModules (ExtendedProperties wirings ) {
673+ protected void wireModules (PropertiesConfiguration wirings ) {
690674 _logger .trace ("> wireModules()" );
691675
692676 _logger .info ("mounting modules" );
@@ -714,21 +698,32 @@ protected void wireModules(ExtendedProperties wirings) {
714698 for (String name : _moduleProperties .keySet ()) {
715699 _logger .trace ("> Expanding properties for module: {}" , name );
716700 ButterflyModule m = _modulesByName .get (name );
717- ExtendedProperties p = _moduleProperties .get (name );
718701 ButterflyModule extended = m .getExtendedModule ();
719702
703+ // Highest priority properties need to be added first, so we need to collect them all first
704+ List <AbstractConfiguration > propertiesList = new ArrayList <>();
705+ propertiesList .add (_moduleProperties .get (name ));
720706 while (extended != null ) {
721707 _logger .trace ("> Merging properties from extended module: {}" , name );
722- ExtendedProperties temp = p ;
723- p = _moduleProperties .get (extended .getName ());
724- p .combine (temp );
708+ AbstractConfiguration p = _moduleProperties .get (extended .getName ());
709+ propertiesList .add (p );
725710 _logger .trace ("< Merging properties from extended module: {} -> {}" , name , p );
726711 extended = extended .getExtendedModule ();
727712 }
713+ AbstractConfiguration p ;
714+ if (propertiesList .size () == 1 ) {
715+ p = propertiesList .get (0 );
716+ } else {
717+ p = new CombinedConfiguration (new OverrideCombiner ());
718+ // Add files in reverse order to maintain priority
719+ for (int i = propertiesList .size () - 1 ; i >= 0 ; i --) {
720+ ((CombinedConfiguration ) p ).addConfiguration (propertiesList .get (i ));
721+ }
722+ }
728723
729- _moduleProperties .put (name ,p );
724+ _moduleProperties .put (name , p );
730725
731- List <String > implementations = p .getList (implementsProperty );
726+ List <String > implementations = p .getList (String . class , implementsProperty );
732727 if (implementations != null ) {
733728 for (String i : implementations ) {
734729 Map <String , ButterflyModule > map = _modulesByInterface .get (i );
@@ -745,11 +740,11 @@ protected void wireModules(ExtendedProperties wirings) {
745740
746741 for (String name : _moduleProperties .keySet ()) {
747742 _logger .trace ("> Inject dependencies in module: {}" , name );
748- ExtendedProperties p = _moduleProperties .get (name );
743+ AbstractConfiguration p = _moduleProperties .get (name );
749744 ButterflyModule m = _modulesByName .get (name );
750745
751- for (Object o : p .keySet () ) {
752- String s = ( String ) o ;
746+ for (Iterator < String > keys = p .getKeys (); keys . hasNext (); ) {
747+ String s = keys . next () ;
753748 if (s .equals (dependencyPrefix )) {
754749 for (Object oo : p .getList (s )) {
755750 String dep = (String ) oo ;
@@ -800,12 +795,12 @@ protected void wireModules(ExtendedProperties wirings) {
800795 _logger .trace ("< wireModules()" );
801796 }
802797
803- @ SuppressWarnings ( "unchecked" )
798+
804799 protected void configureModules () {
805800 _logger .trace ("> configureModules()" );
806801 for (String name : _moduleProperties .keySet ()) {
807802 _logger .trace ("> Configuring module: {}" , name );
808- ExtendedProperties p = _moduleProperties .get (name );
803+ AbstractConfiguration p = _moduleProperties .get (name );
809804 ButterflyModule m = _modulesByName .get (name );
810805
811806 // make the system properties accessible to the modules
@@ -818,16 +813,16 @@ protected void configureModules() {
818813 Properties properties = new Properties ();
819814 File velocityProperties = new File (_webInfDir , "velocity.properties" );
820815 _classLoader .watch (velocityProperties ); // reload if the velocity properties change
821- FileInputStream fis = new FileInputStream (velocityProperties );
822- properties .load (fis );
823- fis . close ();
816+ try ( FileInputStream fis = new FileInputStream (velocityProperties )) {
817+ properties .load (fis );
818+ }
824819
825820 // set properties for resource loading
826- properties .setProperty ("resource.loader " , "butterfly" );
827- properties .setProperty ("butterfly. resource.loader.class" , ButterflyResourceLoader .class .getName ());
828- properties .setProperty ("butterfly. resource.loader.cache" , "true" );
829- properties .setProperty ("butterfly. resource.loader.modificationCheckInterval " , "1" );
830- properties .setProperty ("butterfly. resource.loader.description" , "Butterfly Resource Loader" );
821+ properties .setProperty ("resource.loaders " , "butterfly" );
822+ properties .setProperty ("resource.loader.butterfly .class" , ButterflyResourceLoader .class .getName ());
823+ properties .setProperty ("resource.loader.butterfly .cache" , "true" );
824+ properties .setProperty ("resource.loader.butterfly.modification_check_interval " , "1" );
825+ properties .setProperty ("resource.loader.butterfly .description" , "Butterfly Resource Loader" );
831826
832827 // set properties for macros
833828 properties .setProperty ("velocimacro.library.path" , p .getString ("templating.macros" , "" ));
@@ -854,8 +849,8 @@ protected void configureModules() {
854849 _logger .trace ("< enabling templating" );
855850 }
856851
857- List <String > scriptables = p .getList ("scriptables" );
858- if (scriptables . size () > 0 ) {
852+ List <String > scriptables = p .getList (String . class , "scriptables" );
853+ if (scriptables != null && ! scriptables . isEmpty () ) {
859854 Context context = Context .enter ();
860855
861856 BufferedReader initializerReader = null ;
@@ -887,7 +882,7 @@ protected void configureModules() {
887882 Context .exit ();
888883 }
889884
890- List <String > controllers = p .getList ("controller" , CONTROLLER );
885+ List <String > controllers = p .getList (String . class , "controller" , CONTROLLER );
891886 Set <URL > controllerURLs = new HashSet <URL >(controllers .size ());
892887 for (String controller : controllers ) {
893888 URL controllerURL = m .getResource ("MOD-INF/" + controller );
0 commit comments