Coverage Report - org.apache.myfaces.config.DefaultFacesConfigurationMerger
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultFacesConfigurationMerger
0%
0/399
0%
0/316
17.091
DefaultFacesConfigurationMerger$1
0%
0/22
0%
0/20
17.091
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *   http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package org.apache.myfaces.config;
 20  
 
 21  
 import org.apache.myfaces.config.element.ConfigOthersSlot;
 22  
 import org.apache.myfaces.config.element.FacesConfig;
 23  
 import org.apache.myfaces.config.element.FacesConfigData;
 24  
 import org.apache.myfaces.config.element.FacesConfigNameSlot;
 25  
 import org.apache.myfaces.config.element.OrderSlot;
 26  
 import org.apache.myfaces.config.element.Ordering;
 27  
 import org.apache.myfaces.config.impl.digester.DigesterFacesConfigDispenserImpl;
 28  
 import org.apache.myfaces.config.util.CyclicDependencyException;
 29  
 import org.apache.myfaces.config.util.DirectedAcyclicGraphVerifier;
 30  
 import org.apache.myfaces.config.util.Vertex;
 31  
 import org.apache.myfaces.spi.FacesConfigurationMerger;
 32  
 import org.apache.myfaces.spi.FacesConfigurationProvider;
 33  
 import org.apache.myfaces.spi.FacesConfigurationProviderFactory;
 34  
 
 35  
 import javax.faces.FacesException;
 36  
 import javax.faces.context.ExternalContext;
 37  
 import java.util.ArrayList;
 38  
 import java.util.Collections;
 39  
 import java.util.Comparator;
 40  
 import java.util.Iterator;
 41  
 import java.util.LinkedList;
 42  
 import java.util.List;
 43  
 import java.util.logging.Level;
 44  
 import java.util.logging.Logger;
 45  
 
 46  
 /**
 47  
  * Default impl of the FacesConfigurationMerger-SPI.
 48  
  *
 49  
  * This impl gets all FacesConfig data from the current FacesConfigurationProvider SPI impl and merges
 50  
  * it into one FacesConfigData object using the ordering and sorting rules of the JSF spec.
 51  
  *
 52  
  * @author Jakob Korherr
 53  
  */
 54  0
 public class DefaultFacesConfigurationMerger extends FacesConfigurationMerger
 55  
 {
 56  
 
 57  0
     private static final Logger log = Logger.getLogger(DefaultFacesConfigurationMerger.class.getName());
 58  
 
 59  
     @Override
 60  
     public FacesConfigData getFacesConfigData(ExternalContext externalContext)
 61  
     {
 62  
         // get the FacesConfigProvider SPI impl in order to get the faces-config data for the merging process
 63  0
         FacesConfigurationProvider facesConfigProvider = FacesConfigurationProviderFactory
 64  
                 .getFacesConfigurationProviderFactory(externalContext).getFacesConfigurationProvider(externalContext);
 65  
 
 66  0
         FacesConfigDispenser dispenser = new DigesterFacesConfigDispenserImpl();
 67  
 
 68  
         // standard-faces-config.xml
 69  0
         dispenser.feed(facesConfigProvider.getStandardFacesConfig(externalContext));
 70  
 
 71  
         // META-INF/services/[factory name] factory definitions
 72  0
         dispenser.feed(facesConfigProvider.getMetaInfServicesFacesConfig(externalContext));
 73  
 
 74  
         // WEB-INF/faces-config.xml
 75  0
         FacesConfig webAppFacesConfig = facesConfigProvider.getWebAppFacesConfig(externalContext);
 76  
 
 77  
         //read metadata-complete attribute on WEB-INF/faces-config.xml
 78  0
         boolean metadataComplete = false;
 79  0
         if(webAppFacesConfig != null)
 80  
         {
 81  0
             metadataComplete = Boolean.valueOf(webAppFacesConfig.getMetadataComplete());
 82  
         }
 83  
         else
 84  
         {
 85  
             //assume false if no faces-config.xml was found
 86  
             //metadata-complete can only be specified in faces-config.xml per the JSF 2.0 schema
 87  0
             metadataComplete = false;
 88  
         }
 89  
 
 90  
         // faces-config data from Annotations
 91  0
         FacesConfig annotationFacesConfig = facesConfigProvider
 92  
                 .getAnnotationsFacesConfig(externalContext, metadataComplete);
 93  0
         if (annotationFacesConfig != null)
 94  
         {
 95  0
             dispenser.feed(annotationFacesConfig);
 96  
         }
 97  
 
 98  0
         List<FacesConfig> appConfigResources = new ArrayList<FacesConfig>();
 99  
 
 100  
         // META-INF/faces-config.xml files
 101  0
         appConfigResources.addAll(facesConfigProvider.getClassloaderFacesConfig(externalContext));
 102  
         
 103  
         // faces-config.xml files from javax.faces.CONFIG_FILES
 104  0
         appConfigResources.addAll(facesConfigProvider.getContextSpecifiedFacesConfig(externalContext));
 105  
         
 106  
         // JSF 2.2 ApplicationConfigurationResourceDocumentPopulator FacesConfig
 107  0
         appConfigResources.addAll(facesConfigProvider.
 108  
             getApplicationConfigurationResourceDocumentPopulatorFacesConfig(externalContext));
 109  
 
 110  
         // JSF 2.2 Faces Flow
 111  0
         appConfigResources.addAll(facesConfigProvider.getFacesFlowFacesConfig(externalContext));
 112  
         
 113  
         // apply the ordering and sorting algorithm 
 114  0
         orderAndFeedArtifacts(dispenser, appConfigResources, webAppFacesConfig);
 115  
         
 116  0
         List<FacesConfig> faceletTagLibFacesConfig = 
 117  
             facesConfigProvider.getFaceletTaglibFacesConfig(externalContext);
 118  
         
 119  
         // at last feed facelet taglib faces config. These ones does not need
 120  
         // to be included in the ordering algorithm.
 121  0
         if (faceletTagLibFacesConfig != null && !faceletTagLibFacesConfig.isEmpty())
 122  
         {
 123  0
             for (FacesConfig fc : faceletTagLibFacesConfig)
 124  
             {
 125  0
                 dispenser.feed(fc);
 126  0
             }
 127  
         }
 128  
 
 129  0
         LogMetaInfUtils.logMetaInf();
 130  
 
 131  0
         return dispenser;
 132  
     }
 133  
 
 134  
     protected void orderAndFeedArtifacts(FacesConfigDispenser dispenser,
 135  
                                          List<FacesConfig> appConfigResources,
 136  
                                          FacesConfig webAppConfig)
 137  
         throws FacesException
 138  
     {
 139  0
         if (webAppConfig != null && webAppConfig.getAbsoluteOrdering() != null)
 140  
         {
 141  0
             if (webAppConfig.getOrdering() != null)
 142  
             {
 143  0
                 if (log.isLoggable(Level.WARNING))
 144  
                 {
 145  0
                     log.warning("<ordering> element found in application faces config. " +
 146  
                             "This description will be ignored and the actions described " +
 147  
                             "in <absolute-ordering> element will be taken into account instead.");
 148  
                 }
 149  
             }
 150  
             //Absolute ordering
 151  
 
 152  
             //1. Scan all appConfigResources and create a list
 153  
             //containing all resources not mentioned directly, preserving the
 154  
             //order founded
 155  0
             List<FacesConfig> othersResources = new ArrayList<FacesConfig>();
 156  0
             List<OrderSlot> slots = webAppConfig.getAbsoluteOrdering().getOrderList();
 157  0
             for (FacesConfig resource : appConfigResources)
 158  
             {
 159  
                 // First condition: if faces-config.xml does not have name it is
 160  
                 // 1) pre-JSF-2.0 or
 161  
                 // 2) has no <name> element,
 162  
                 // -> in both cases cannot be ordered
 163  
                 // Second condition : faces-config.xml has a name but <ordering>
 164  
                 // element does not have slot with that name
 165  
                 //  -> resource can be ordered, but will fit into <others /> element
 166  0
                 if ((resource.getName() == null) ||
 167  
                         (resource.getName() != null && !containsResourceInSlot(slots, resource.getName())))
 168  
                 {
 169  0
                     othersResources.add(resource);
 170  
                 }
 171  0
             }
 172  
 
 173  
             //2. Scan slot by slot and merge information according
 174  0
             for (OrderSlot slot : webAppConfig.getAbsoluteOrdering().getOrderList())
 175  
             {
 176  0
                 if (slot instanceof ConfigOthersSlot)
 177  
                 {
 178  
                     //Add all mentioned in othersResources
 179  0
                     for (FacesConfig resource : othersResources)
 180  
                     {
 181  0
                         dispenser.feed(resource);
 182  0
                     }
 183  
                 }
 184  
                 else
 185  
                 {
 186  
                     //Add it to the sorted list
 187  0
                     FacesConfigNameSlot nameSlot = (FacesConfigNameSlot) slot;
 188  
                     // We need to check if the resource is on appConfigResources, otherwise we can
 189  
                     // ignore it safely.
 190  0
                     FacesConfig targetFacesConfig = getFacesConfig(appConfigResources, nameSlot.getName());
 191  0
                     if (targetFacesConfig != null)
 192  
                     {
 193  0
                         dispenser.feed(targetFacesConfig);
 194  
                     }
 195  
                 }
 196  0
             }
 197  0
         }
 198  0
         else if (!appConfigResources.isEmpty())
 199  
         {
 200  
             //Relative ordering
 201  0
             for (FacesConfig resource : appConfigResources)
 202  
             {
 203  0
                 if (resource.getAbsoluteOrdering() != null)
 204  
                 {
 205  0
                     if (log.isLoggable(Level.WARNING))
 206  
                     {
 207  0
                         log.warning("<absolute-ordering> element found in application " +
 208  
                                 "configuration resource "+resource.getName()+". " +
 209  
                                 "This description will be ignored and the actions described " +
 210  
                                 "in <ordering> elements will be taken into account instead.");
 211  
                     }
 212  
                 }
 213  0
             }
 214  
 
 215  0
             List<FacesConfig> postOrderedList = getPostOrderedList(appConfigResources);
 216  
 
 217  0
             List<FacesConfig> sortedList = sortRelativeOrderingList(postOrderedList);
 218  
 
 219  0
             if (sortedList == null)
 220  
             {
 221  
                 //The previous algorithm can't sort correctly, try this one
 222  0
                 sortedList = applySortingAlgorithm(appConfigResources);
 223  
             }
 224  
 
 225  0
             for (FacesConfig resource : sortedList)
 226  
             {
 227  
                 //Feed
 228  0
                 dispenser.feed(resource);
 229  0
             }
 230  
         }
 231  
 
 232  
         //add null check for apps which don't have a faces-config.xml (e.g. tomahawk examples for 1.1/1.2)
 233  0
         if(webAppConfig != null)
 234  
         {
 235  0
             dispenser.feed(webAppConfig);
 236  
         }
 237  0
     }
 238  
 
 239  
     /**
 240  
      * Sort using topological ordering algorithm.
 241  
      *
 242  
      * @param appConfigResources
 243  
      * @return
 244  
      * @throws FacesException
 245  
      */
 246  
     protected List<FacesConfig> applySortingAlgorithm(List<FacesConfig> appConfigResources) throws FacesException
 247  
     {
 248  
 
 249  
         //0. Convert the references into a graph
 250  0
         List<Vertex<FacesConfig>> vertexList = new ArrayList<Vertex<FacesConfig>>();
 251  0
         for (FacesConfig config : appConfigResources)
 252  
         {
 253  0
             Vertex<FacesConfig> v = null;
 254  0
             if (config.getName() != null)
 255  
             {
 256  0
                 v = new Vertex<FacesConfig>(config.getName(), config);
 257  
             }
 258  
             else
 259  
             {
 260  0
                 v = new Vertex<FacesConfig>(config);
 261  
             }
 262  0
             vertexList.add(v);
 263  0
         }
 264  
 
 265  
         //1. Resolve dependencies (before-after rules) and mark referenced vertex
 266  0
         boolean[] referencedVertex = new boolean[vertexList.size()];
 267  
 
 268  0
         for (int i = 0; i < vertexList.size(); i++)
 269  
         {
 270  0
             Vertex<FacesConfig> v = vertexList.get(i);
 271  0
             FacesConfig f = (FacesConfig) v.getNode();
 272  
 
 273  0
             if (f.getOrdering() != null)
 274  
             {
 275  0
                 for (OrderSlot slot : f.getOrdering().getBeforeList())
 276  
                 {
 277  0
                     if (slot instanceof FacesConfigNameSlot)
 278  
                     {
 279  0
                         String name = ((FacesConfigNameSlot) slot).getName();
 280  0
                         int j = DirectedAcyclicGraphVerifier.findVertex(vertexList, name);
 281  0
                         Vertex<FacesConfig> v1 = vertexList.get(j);
 282  0
                         if (v1 != null)
 283  
                         {
 284  0
                             referencedVertex[i] = true;
 285  0
                             referencedVertex[j] = true;
 286  0
                             v1.addDependency(v);
 287  
                         }
 288  
                     }
 289  0
                 }
 290  0
                 for (OrderSlot slot : f.getOrdering().getAfterList())
 291  
                 {
 292  0
                     if (slot instanceof FacesConfigNameSlot)
 293  
                     {
 294  0
                         String name = ((FacesConfigNameSlot) slot).getName();
 295  0
                         int j = DirectedAcyclicGraphVerifier.findVertex(vertexList, name);
 296  0
                         Vertex<FacesConfig> v1 = vertexList.get(j);
 297  0
                         if (v1 != null)
 298  
                         {
 299  0
                             referencedVertex[i] = true;
 300  0
                             referencedVertex[j] = true;
 301  0
                             v.addDependency(v1);
 302  
                         }
 303  
                     }
 304  0
                 }
 305  
             }
 306  
         }
 307  
 
 308  
         //2. Classify into categories
 309  0
         List<Vertex<FacesConfig>> beforeAfterOthersList = new ArrayList<Vertex<FacesConfig>>();
 310  0
         List<Vertex<FacesConfig>> othersList = new ArrayList<Vertex<FacesConfig>>();
 311  0
         List<Vertex<FacesConfig>> referencedList = new ArrayList<Vertex<FacesConfig>>();
 312  
 
 313  0
         for (int i = 0; i < vertexList.size(); i++)
 314  
         {
 315  0
             if (!referencedVertex[i])
 316  
             {
 317  0
                 Vertex<FacesConfig> v = vertexList.get(i);
 318  0
                 FacesConfig f = (FacesConfig) v.getNode();
 319  0
                 boolean added = false;
 320  0
                 if (f.getOrdering() != null)
 321  
                 {
 322  0
                     if (!f.getOrdering().getBeforeList().isEmpty())
 323  
                     {
 324  0
                         added = true;
 325  0
                         beforeAfterOthersList.add(v);
 326  
                     }
 327  0
                     else if (!f.getOrdering().getAfterList().isEmpty())
 328  
                     {
 329  0
                         added = true;
 330  0
                         beforeAfterOthersList.add(v);
 331  
                     }
 332  
                 }
 333  0
                 if (!added)
 334  
                 {
 335  0
                     othersList.add(v);
 336  
                 }
 337  0
             }
 338  
             else
 339  
             {
 340  0
                 referencedList.add(vertexList.get(i));
 341  
             }
 342  
         }
 343  
 
 344  
         //3. Sort all referenced nodes
 345  
         try
 346  
         {
 347  0
             DirectedAcyclicGraphVerifier.topologicalSort(referencedList);
 348  
         }
 349  0
         catch (CyclicDependencyException e)
 350  
         {
 351  0
             e.printStackTrace();
 352  0
         }
 353  
 
 354  
         //4. Add referenced nodes
 355  0
         List<FacesConfig> sortedList = new ArrayList<FacesConfig>();
 356  0
         for (Vertex<FacesConfig> v : referencedList)
 357  
         {
 358  0
             sortedList.add((FacesConfig)v.getNode());
 359  0
         }
 360  
 
 361  
         //5. add nodes without instructions at the end
 362  0
         for (Vertex<FacesConfig> v : othersList)
 363  
         {
 364  0
             sortedList.add((FacesConfig)v.getNode());
 365  0
         }
 366  
 
 367  
         //6. add before/after nodes
 368  0
         for (Vertex<FacesConfig> v : beforeAfterOthersList)
 369  
         {
 370  0
             FacesConfig f = (FacesConfig) v.getNode();
 371  0
             boolean added = false;
 372  0
             if (f.getOrdering() != null && !f.getOrdering().getBeforeList().isEmpty())
 373  
             {
 374  0
                 added = true;
 375  0
                 sortedList.add(0,f);
 376  
             }
 377  0
             if (!added)
 378  
             {
 379  0
                 sortedList.add(f);
 380  
             }
 381  0
         }
 382  
 
 383  
         //Check
 384  0
         for (int i = 0; i < sortedList.size(); i++)
 385  
         {
 386  0
             FacesConfig resource = sortedList.get(i);
 387  
 
 388  0
             if (resource.getOrdering() != null)
 389  
             {
 390  0
                 for (OrderSlot slot : resource.getOrdering().getBeforeList())
 391  
                 {
 392  0
                     if (slot instanceof FacesConfigNameSlot)
 393  
                     {
 394  0
                         String name = ((FacesConfigNameSlot) slot).getName();
 395  0
                         if (name != null && !"".equals(name))
 396  
                         {
 397  0
                             boolean founded = false;
 398  0
                             for (int j = i-1; j >= 0; j--)
 399  
                             {
 400  0
                                 if (name.equals(sortedList.get(j).getName()))
 401  
                                 {
 402  0
                                     founded=true;
 403  0
                                     break;
 404  
                                 }
 405  
                             }
 406  0
                             if (founded)
 407  
                             {
 408  0
                                 log.severe("Circular references detected when sorting " +
 409  
                                           "application config resources. Use absolute ordering instead.");
 410  0
                                 throw new FacesException("Circular references detected when sorting " +
 411  
                                         "application config resources. Use absolute ordering instead.");
 412  
                             }
 413  
                         }
 414  
                     }
 415  0
                 }
 416  0
                 for (OrderSlot slot : resource.getOrdering().getAfterList())
 417  
                 {
 418  0
                     if (slot instanceof FacesConfigNameSlot)
 419  
                     {
 420  0
                         String name = ((FacesConfigNameSlot) slot).getName();
 421  0
                         if (name != null && !"".equals(name))
 422  
                         {
 423  0
                             boolean founded = false;
 424  0
                             for (int j = i+1; j < sortedList.size(); j++)
 425  
                             {
 426  0
                                 if (name.equals(sortedList.get(j).getName()))
 427  
                                 {
 428  0
                                     founded=true;
 429  0
                                     break;
 430  
                                 }
 431  
                             }
 432  0
                             if (founded)
 433  
                             {
 434  0
                                 log.severe("Circular references detected when sorting " +
 435  
                                     "application config resources. Use absolute ordering instead.");
 436  0
                                 throw new FacesException("Circular references detected when sorting " +
 437  
                                     "application config resources. Use absolute ordering instead.");
 438  
                             }
 439  
                         }
 440  
                     }
 441  0
                 }
 442  
             }
 443  
         }
 444  
 
 445  0
         return sortedList;
 446  
     }
 447  
 
 448  
     /**
 449  
      * Sort a list of pre ordered elements. It scans one by one the elements
 450  
      * and apply the conditions mentioned by Ordering object if it is available.
 451  
      *
 452  
      * The preOrderedList ensures that application config resources referenced by
 453  
      * other resources are processed first, making more easier the sort procedure.
 454  
      *
 455  
      * @param preOrderedList
 456  
      * @return
 457  
      */
 458  
     protected List<FacesConfig> sortRelativeOrderingList(List<FacesConfig> preOrderedList)
 459  
     {
 460  0
         List<FacesConfig> sortedList = new ArrayList<FacesConfig>();
 461  
 
 462  0
         for (int i=0; i < preOrderedList.size(); i++)
 463  
         {
 464  0
             FacesConfig resource = preOrderedList.get(i);
 465  0
             if (resource.getOrdering() != null)
 466  
             {
 467  0
                 if (resource.getOrdering().getBeforeList().isEmpty() &&
 468  
                     resource.getOrdering().getAfterList().isEmpty())
 469  
                 {
 470  
                     //No order rules, just put it as is
 471  0
                     sortedList.add(resource);
 472  
                 }
 473  0
                 else if (resource.getOrdering().getBeforeList().isEmpty())
 474  
                 {
 475  
                     //Only after rules
 476  0
                     applyAfterRule(sortedList, resource);
 477  
                 }
 478  0
                 else if (resource.getOrdering().getAfterList().isEmpty())
 479  
                 {
 480  
                     //Only before rules
 481  
 
 482  
                     //Resolve if there is a later reference to this node before
 483  
                     //apply it
 484  0
                     boolean referenceNode = false;
 485  
 
 486  0
                     for (int j = i+1; j < preOrderedList.size(); j++)
 487  
                     {
 488  0
                         FacesConfig pointingResource = preOrderedList.get(j);
 489  0
                         for (OrderSlot slot : pointingResource.getOrdering().getBeforeList())
 490  
                         {
 491  0
                             if (slot instanceof FacesConfigNameSlot &&
 492  
                                     resource.getName().equals(((FacesConfigNameSlot)slot).getName()) )
 493  
                             {
 494  0
                                 referenceNode = true;
 495  
                             }
 496  0
                             if (slot instanceof ConfigOthersSlot)
 497  
                             {
 498  
                                 //No matter if there is a reference, because this rule
 499  
                                 //is not strict and before other ordering is unpredictable.
 500  
                                 //
 501  0
                                 referenceNode = false;
 502  0
                                 break;
 503  
                             }
 504  0
                         }
 505  0
                         if (referenceNode)
 506  
                         {
 507  0
                             break;
 508  
                         }
 509  0
                         for (OrderSlot slot : pointingResource.getOrdering().getAfterList())
 510  
                         {
 511  0
                             if (slot instanceof FacesConfigNameSlot &&
 512  
                                 resource.getName().equals(((FacesConfigNameSlot)slot).getName()) )
 513  
                             {
 514  0
                                 referenceNode = true;
 515  0
                                 break;
 516  
                             }
 517  0
                         }
 518  
                     }
 519  
 
 520  0
                     applyBeforeRule(sortedList, resource, referenceNode);
 521  0
                 }
 522  
                 else
 523  
                 {
 524  
                     //Both before and after rules
 525  
                     //In this case we should compare before and after rules
 526  
                     //and the one with names takes precedence over the other one.
 527  
                     //It both have names references, before rules takes
 528  
                     //precedence over after
 529  
                     //after some action is applied a check of the condition is made.
 530  0
                     int beforeWeight = 0;
 531  0
                     int afterWeight = 0;
 532  0
                     for (OrderSlot slot : resource.getOrdering()
 533  
                             .getBeforeList())
 534  
                     {
 535  0
                         if (slot instanceof FacesConfigNameSlot)
 536  
                         {
 537  0
                             beforeWeight++;
 538  
                         }
 539  0
                     }
 540  0
                     for (OrderSlot slot : resource.getOrdering()
 541  
                             .getAfterList())
 542  
                     {
 543  0
                         if (slot instanceof FacesConfigNameSlot)
 544  
                         {
 545  0
                             afterWeight++;
 546  
                         }
 547  0
                     }
 548  
 
 549  0
                     if (beforeWeight >= afterWeight)
 550  
                     {
 551  0
                         applyBeforeRule(sortedList, resource,false);
 552  
                     }
 553  
                     else
 554  
                     {
 555  0
                         applyAfterRule(sortedList, resource);
 556  
                     }
 557  
 
 558  
 
 559  0
                 }
 560  
             }
 561  
             else
 562  
             {
 563  
                 //No order rules, just put it as is
 564  0
                 sortedList.add(resource);
 565  
             }
 566  
         }
 567  
 
 568  
         //Check
 569  0
         for (int i = 0; i < sortedList.size(); i++)
 570  
         {
 571  0
             FacesConfig resource = sortedList.get(i);
 572  
 
 573  0
             if (resource.getOrdering() != null)
 574  
             {
 575  0
                 for (OrderSlot slot : resource.getOrdering().getBeforeList())
 576  
                 {
 577  0
                     if (slot instanceof FacesConfigNameSlot)
 578  
                     {
 579  0
                         String name = ((FacesConfigNameSlot) slot).getName();
 580  0
                         if (name != null && !"".equals(name))
 581  
                         {
 582  0
                             boolean founded = false;
 583  0
                             for (int j = i-1; j >= 0; j--)
 584  
                             {
 585  0
                                 if (name.equals(sortedList.get(j).getName()))
 586  
                                 {
 587  0
                                     founded=true;
 588  0
                                     break;
 589  
                                 }
 590  
                             }
 591  0
                             if (founded)
 592  
                             {
 593  
                                 //Cyclic reference
 594  0
                                 return null;
 595  
                             }
 596  
                         }
 597  
                     }
 598  0
                 }
 599  0
                 for (OrderSlot slot : resource.getOrdering().getAfterList())
 600  
                 {
 601  0
                     if (slot instanceof FacesConfigNameSlot)
 602  
                     {
 603  0
                         String name = ((FacesConfigNameSlot) slot).getName();
 604  0
                         if (name != null && !"".equals(name))
 605  
                         {
 606  0
                             boolean founded = false;
 607  0
                             for (int j = i+1; j < sortedList.size(); j++)
 608  
                             {
 609  0
                                 if (name.equals(sortedList.get(j).getName()))
 610  
                                 {
 611  0
                                     founded=true;
 612  0
                                     break;
 613  
                                 }
 614  
                             }
 615  0
                             if (founded)
 616  
                             {
 617  
                                 //Cyclic reference
 618  0
                                 return null;
 619  
                             }
 620  
                         }
 621  
                     }
 622  0
                 }
 623  
             }
 624  
         }
 625  
 
 626  0
         return sortedList;
 627  
     }
 628  
 
 629  
     private void applyBeforeRule(List<FacesConfig> sortedList, FacesConfig resource, boolean referenced)
 630  
             throws FacesException
 631  
     {
 632  
         //Only before rules
 633  0
         boolean configOthers = false;
 634  0
         List<String> names = new ArrayList<String>();
 635  
 
 636  0
         for (OrderSlot slot : resource.getOrdering().getBeforeList())
 637  
         {
 638  0
             if (slot instanceof ConfigOthersSlot)
 639  
             {
 640  0
                 configOthers = true;
 641  0
                 break;
 642  
             }
 643  
             else
 644  
             {
 645  0
                 FacesConfigNameSlot nameSlot = (FacesConfigNameSlot) slot;
 646  0
                 names.add(nameSlot.getName());
 647  
             }
 648  0
         }
 649  
 
 650  0
         if (configOthers)
 651  
         {
 652  
             //<before>....<others/></before> case
 653  
             //other reference where already considered when
 654  
             //pre ordered list was calculated, so just add to the end.
 655  
 
 656  
             //There is one very special case, and it is when there
 657  
             //is another resource with a reference on it. In this case,
 658  
             //it is better do not apply this rule and add it to the end
 659  
             //to give the chance to the other one to be applied.
 660  0
             if (resource.getOrdering().getBeforeList().size() > 1)
 661  
             {
 662  
                 //If there is a reference apply it
 663  0
                 sortedList.add(0,resource);
 664  
             }
 665  0
             else if (!referenced)
 666  
             {
 667  
                 //If it is not referenced apply it
 668  0
                 sortedList.add(0,resource);
 669  
             }
 670  
             else
 671  
             {
 672  
                 //if it is referenced bypass the rule and add it to the end
 673  0
                 sortedList.add(resource);
 674  
             }
 675  
         }
 676  
         else
 677  
         {
 678  
             //Scan the nearest reference and add it after
 679  0
             boolean founded = false;
 680  0
             for (int i = 0; i < sortedList.size() ; i++)
 681  
             {
 682  0
                 if (names.contains(sortedList.get(i).getName()))
 683  
                 {
 684  0
                     sortedList.add(i,resource);
 685  0
                     founded = true;
 686  0
                     break;
 687  
                 }
 688  
             }
 689  0
             if (!founded)
 690  
             {
 691  
                 //just add it to the end
 692  0
                 sortedList.add(resource);
 693  
             }
 694  
         }
 695  0
     }
 696  
 
 697  
     private void applyAfterRule(List<FacesConfig> sortedList, FacesConfig resource) throws FacesException
 698  
     {
 699  0
         boolean configOthers = false;
 700  0
         List<String> names = new ArrayList<String>();
 701  
 
 702  0
         for (OrderSlot slot : resource.getOrdering().getAfterList())
 703  
         {
 704  0
             if (slot instanceof ConfigOthersSlot)
 705  
             {
 706  0
                 configOthers = true;
 707  0
                 break;
 708  
             }
 709  
             else
 710  
             {
 711  0
                 FacesConfigNameSlot nameSlot = (FacesConfigNameSlot) slot;
 712  0
                 names.add(nameSlot.getName());
 713  
             }
 714  0
         }
 715  
 
 716  0
         if (configOthers)
 717  
         {
 718  
             //<after>....<others/></after> case
 719  
             //other reference where already considered when
 720  
             //pre ordered list was calculated, so just add to the end.
 721  0
             sortedList.add(resource);
 722  
         }
 723  
         else
 724  
         {
 725  
             //Scan the nearest reference and add it after
 726  0
             boolean founded = false;
 727  0
             for (int i = sortedList.size()-1 ; i >=0 ; i--)
 728  
             {
 729  0
                 if (names.contains(sortedList.get(i).getName()))
 730  
                 {
 731  0
                     if (i+1 < sortedList.size())
 732  
                     {
 733  0
                         sortedList.add(i+1,resource);
 734  
                     }
 735  
                     else
 736  
                     {
 737  0
                         sortedList.add(resource);
 738  
                     }
 739  0
                     founded = true;
 740  0
                     break;
 741  
                 }
 742  
             }
 743  0
             if (!founded)
 744  
             {
 745  
                 //just add it to the end
 746  0
                 sortedList.add(resource);
 747  
             }
 748  
         }
 749  0
     }
 750  
 
 751  
 
 752  
     /**
 753  
      * Pre Sort the appConfigResources, detecting cyclic references, so when sort process
 754  
      * start, it is just necessary to traverse the preOrderedList once. To do that, we just
 755  
      * scan "before" and "after" lists for references, and then those references are traversed
 756  
      * again, so the first elements of the pre ordered list does not have references and
 757  
      * the next elements has references to the already added ones.
 758  
      *
 759  
      * The elements on the preOrderedList looks like this:
 760  
      *
 761  
      * [ no ordering elements , referenced elements ... more referenced elements,
 762  
      *  before others / after others non referenced elements]
 763  
      *
 764  
      * @param appConfigResources
 765  
      * @return
 766  
      */
 767  
     protected List<FacesConfig> getPostOrderedList(final List<FacesConfig> appConfigResources) throws FacesException
 768  
     {
 769  
 
 770  
         //0. Clean up: remove all not found resource references from the ordering
 771  
         //descriptions.
 772  0
         List<String> availableReferences = new ArrayList<String>();
 773  0
         for (FacesConfig resource : appConfigResources)
 774  
         {
 775  0
             String name = resource.getName();
 776  0
             if (name != null && !"".equals(name))
 777  
             {
 778  0
                 availableReferences.add(name);
 779  
             }
 780  0
         }
 781  
 
 782  0
         for (FacesConfig resource : appConfigResources)
 783  
         {
 784  0
             Ordering ordering = resource.getOrdering();
 785  0
             if (ordering != null)
 786  
             {
 787  0
                 for (Iterator<OrderSlot> it =  resource.getOrdering().getBeforeList().iterator();it.hasNext();)
 788  
                 {
 789  0
                     OrderSlot slot = it.next();
 790  0
                     if (slot instanceof FacesConfigNameSlot)
 791  
                     {
 792  0
                         String name = ((FacesConfigNameSlot) slot).getName();
 793  0
                         if (!availableReferences.contains(name))
 794  
                         {
 795  0
                             it.remove();
 796  
                         }
 797  
                     }
 798  0
                 }
 799  0
                 for (Iterator<OrderSlot> it =  resource.getOrdering().getAfterList().iterator();it.hasNext();)
 800  
                 {
 801  0
                     OrderSlot slot = it.next();
 802  0
                     if (slot instanceof FacesConfigNameSlot)
 803  
                     {
 804  0
                         String name = ((FacesConfigNameSlot) slot).getName();
 805  0
                         if (!availableReferences.contains(name))
 806  
                         {
 807  0
                             it.remove();
 808  
                         }
 809  
                     }
 810  0
                 }
 811  
             }
 812  0
         }
 813  
 
 814  0
         List<FacesConfig> appFilteredConfigResources = null;
 815  
 
 816  
         //1. Pre filtering: Sort nodes according to its weight. The weight is the number of named
 817  
         //nodes containing in both before and after lists. The sort is done from the more complex
 818  
         //to the most simple
 819  0
         if (appConfigResources instanceof ArrayList)
 820  
         {
 821  0
             appFilteredConfigResources = (List<FacesConfig>)
 822  
                 ((ArrayList<FacesConfig>)appConfigResources).clone();
 823  
         }
 824  
         else
 825  
         {
 826  0
             appFilteredConfigResources = new ArrayList<FacesConfig>();
 827  0
             appFilteredConfigResources.addAll(appConfigResources);
 828  
         }
 829  0
         Collections.sort(appFilteredConfigResources,
 830  
                 new Comparator<FacesConfig>()
 831  0
                 {
 832  
                     public int compare(FacesConfig o1, FacesConfig o2)
 833  
                     {
 834  0
                         int o1Weight = 0;
 835  0
                         int o2Weight = 0;
 836  0
                         if (o1.getOrdering() != null)
 837  
                         {
 838  0
                             for (OrderSlot slot : o1.getOrdering()
 839  
                                     .getBeforeList())
 840  
                             {
 841  0
                                 if (slot instanceof FacesConfigNameSlot)
 842  
                                 {
 843  0
                                     o1Weight++;
 844  
                                 }
 845  0
                             }
 846  0
                             for (OrderSlot slot : o1.getOrdering()
 847  
                                     .getAfterList())
 848  
                             {
 849  0
                                 if (slot instanceof FacesConfigNameSlot)
 850  
                                 {
 851  0
                                     o1Weight++;
 852  
                                 }
 853  0
                             }
 854  
                         }
 855  0
                         if (o2.getOrdering() != null)
 856  
                         {
 857  0
                             for (OrderSlot slot : o2.getOrdering()
 858  
                                     .getBeforeList())
 859  
                             {
 860  0
                                 if (slot instanceof FacesConfigNameSlot)
 861  
                                 {
 862  0
                                     o2Weight++;
 863  
                                 }
 864  0
                             }
 865  0
                             for (OrderSlot slot : o2.getOrdering()
 866  
                                     .getAfterList())
 867  
                             {
 868  0
                                 if (slot instanceof FacesConfigNameSlot)
 869  
                                 {
 870  0
                                     o2Weight++;
 871  
                                 }
 872  0
                             }
 873  
                         }
 874  0
                         return o2Weight - o1Weight;
 875  
                     }
 876  
                 });
 877  
 
 878  0
         List<FacesConfig> postOrderedList = new LinkedList<FacesConfig>();
 879  0
         List<FacesConfig> othersList = new ArrayList<FacesConfig>();
 880  
 
 881  0
         List<String> nameBeforeStack = new ArrayList<String>();
 882  0
         List<String> nameAfterStack = new ArrayList<String>();
 883  
 
 884  0
         boolean[] visitedSlots = new boolean[appFilteredConfigResources.size()];
 885  
 
 886  
         //2. Scan and resolve conflicts
 887  0
         for (int i = 0; i < appFilteredConfigResources.size(); i++)
 888  
         {
 889  0
             if (!visitedSlots[i])
 890  
             {
 891  0
                 resolveConflicts(appFilteredConfigResources, i, visitedSlots,
 892  
                         nameBeforeStack, nameAfterStack, postOrderedList, othersList, false);
 893  
             }
 894  
         }
 895  
 
 896  
         //Add othersList to postOrderedList so <before><others/></before> and <after><others/></after>
 897  
         //ordering conditions are handled at last if there are not referenced by anyone
 898  0
         postOrderedList.addAll(othersList);
 899  
 
 900  0
         return postOrderedList;
 901  
     }
 902  
 
 903  
     private void resolveConflicts(final List<FacesConfig> appConfigResources, int index, boolean[] visitedSlots,
 904  
             List<String> nameBeforeStack, List<String> nameAfterStack, List<FacesConfig> postOrderedList,
 905  
             List<FacesConfig> othersList, boolean indexReferenced) throws FacesException
 906  
     {
 907  0
         FacesConfig facesConfig = appConfigResources.get(index);
 908  
 
 909  0
         if (nameBeforeStack.contains(facesConfig.getName()))
 910  
         {
 911  
             //Already referenced, just return. Later if there exists a
 912  
             //circular reference, it will be detected and solved.
 913  0
             return;
 914  
         }
 915  
 
 916  0
         if (nameAfterStack.contains(facesConfig.getName()))
 917  
         {
 918  
             //Already referenced, just return. Later if there exists a
 919  
             //circular reference, it will be detected and solved.
 920  0
             return;
 921  
         }
 922  
 
 923  0
         if (facesConfig.getOrdering() != null)
 924  
         {
 925  0
             boolean pointingResource = false;
 926  
 
 927  
             //Deal with before restrictions first
 928  0
             for (OrderSlot slot : facesConfig.getOrdering().getBeforeList())
 929  
             {
 930  0
                 if (slot instanceof FacesConfigNameSlot)
 931  
                 {
 932  0
                     FacesConfigNameSlot nameSlot = (FacesConfigNameSlot) slot;
 933  
                     //The resource pointed is not added yet?
 934  0
                     boolean alreadyAdded = false;
 935  0
                     for (FacesConfig res : postOrderedList)
 936  
                     {
 937  0
                         if (nameSlot.getName().equals(res.getName()))
 938  
                         {
 939  0
                             alreadyAdded = true;
 940  0
                             break;
 941  
                         }
 942  0
                     }
 943  0
                     if (!alreadyAdded)
 944  
                     {
 945  0
                         int indexSlot = -1;
 946  
                         //Find it
 947  0
                         for (int i = 0; i < appConfigResources.size(); i++)
 948  
                         {
 949  0
                             FacesConfig resource = appConfigResources.get(i);
 950  0
                             if (resource.getName() != null && nameSlot.getName().equals(resource.getName()))
 951  
                             {
 952  0
                                 indexSlot = i;
 953  0
                                 break;
 954  
                             }
 955  
                         }
 956  
 
 957  
                         //Resource founded on appConfigResources
 958  0
                         if (indexSlot != -1)
 959  
                         {
 960  0
                             pointingResource = true;
 961  
                             //Add to nameStac
 962  0
                             nameBeforeStack.add(facesConfig.getName());
 963  
 
 964  0
                             resolveConflicts(appConfigResources, indexSlot, visitedSlots,
 965  
                                     nameBeforeStack, nameAfterStack, postOrderedList,
 966  
                                     othersList,true);
 967  
 
 968  0
                             nameBeforeStack.remove(facesConfig.getName());
 969  
                         }
 970  0
                     }
 971  
                     else
 972  
                     {
 973  0
                         pointingResource = true;
 974  
                     }
 975  
                 }
 976  0
             }
 977  
 
 978  0
             for (OrderSlot slot : facesConfig.getOrdering().getAfterList())
 979  
             {
 980  0
                 if (slot instanceof FacesConfigNameSlot)
 981  
                 {
 982  0
                     FacesConfigNameSlot nameSlot = (FacesConfigNameSlot) slot;
 983  
                     //The resource pointed is not added yet?
 984  0
                     boolean alreadyAdded = false;
 985  0
                     for (FacesConfig res : postOrderedList)
 986  
                     {
 987  0
                         if (nameSlot.getName().equals(res.getName()))
 988  
                         {
 989  0
                             alreadyAdded = true;
 990  0
                             break;
 991  
                         }
 992  0
                     }
 993  0
                     if (!alreadyAdded)
 994  
                     {
 995  0
                         int indexSlot = -1;
 996  
                         //Find it
 997  0
                         for (int i = 0; i < appConfigResources.size(); i++)
 998  
                         {
 999  0
                             FacesConfig resource = appConfigResources.get(i);
 1000  0
                             if (resource.getName() != null && nameSlot.getName().equals(resource.getName()))
 1001  
                             {
 1002  0
                                 indexSlot = i;
 1003  0
                                 break;
 1004  
                             }
 1005  
                         }
 1006  
 
 1007  
                         //Resource founded on appConfigResources
 1008  0
                         if (indexSlot != -1)
 1009  
                         {
 1010  0
                             pointingResource = true;
 1011  
                             //Add to nameStac
 1012  0
                             nameAfterStack.add(facesConfig.getName());
 1013  
 
 1014  0
                             resolveConflicts(appConfigResources, indexSlot, visitedSlots,
 1015  
                                     nameBeforeStack, nameAfterStack, postOrderedList,
 1016  
                                     othersList,true);
 1017  
 
 1018  0
                             nameAfterStack.remove(facesConfig.getName());
 1019  
                         }
 1020  0
                     }
 1021  
                     else
 1022  
                     {
 1023  0
                         pointingResource = true;
 1024  
                     }
 1025  
                 }
 1026  0
             }
 1027  
 
 1028  0
             if (facesConfig.getOrdering().getBeforeList().isEmpty() &&
 1029  
                 facesConfig.getOrdering().getAfterList().isEmpty())
 1030  
             {
 1031  
                 //Fits in the category "others", put at beginning
 1032  0
                 postOrderedList.add(0,appConfigResources.get(index));
 1033  
             }
 1034  0
             else if (pointingResource || indexReferenced)
 1035  
             {
 1036  
                 //If the node points to other or is referenced from other,
 1037  
                 //add to the postOrderedList at the end
 1038  0
                 postOrderedList.add(appConfigResources.get(index));
 1039  
             }
 1040  
             else
 1041  
             {
 1042  
                 //Add to othersList
 1043  0
                 othersList.add(appConfigResources.get(index));
 1044  
             }
 1045  0
         }
 1046  
         else
 1047  
         {
 1048  
             //Add at start of the list, since does not have any ordering
 1049  
             //instructions and on the next step makes than "before others" and "after others"
 1050  
             //works correctly
 1051  0
             postOrderedList.add(0,appConfigResources.get(index));
 1052  
         }
 1053  
         //Set the node as visited
 1054  0
         visitedSlots[index] = true;
 1055  0
     }
 1056  
 
 1057  
     private FacesConfig getFacesConfig(List<FacesConfig> appConfigResources, String name)
 1058  
     {
 1059  0
         for (FacesConfig cfg: appConfigResources)
 1060  
         {
 1061  0
             if (cfg.getName() != null && name.equals(cfg.getName()))
 1062  
             {
 1063  0
                 return cfg;
 1064  
             }
 1065  0
         }
 1066  0
         return null;
 1067  
     }
 1068  
 
 1069  
     private boolean containsResourceInSlot(List<OrderSlot> slots, String name)
 1070  
     {
 1071  0
         for (OrderSlot slot: slots)
 1072  
         {
 1073  0
             if (slot instanceof FacesConfigNameSlot)
 1074  
             {
 1075  0
                 FacesConfigNameSlot nameSlot = (FacesConfigNameSlot) slot;
 1076  0
                 if (name.equals(nameSlot.getName()))
 1077  
                 {
 1078  0
                     return true;
 1079  
                 }
 1080  
             }
 1081  0
         }
 1082  0
         return false;
 1083  
     }
 1084  
 
 1085  
 }