Coverage Report - org.apache.myfaces.config.FacesConfigurator
 
Classes in this File Line Coverage Branch Coverage Complexity
FacesConfigurator
0%
0/426
0%
0/172
0
FacesConfigurator$JarInfo
0%
0/15
0%
0/4
0
FacesConfigurator$Version
0%
0/56
0%
0/50
0
 
 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 java.io.BufferedReader;
 22  
 import java.io.File;
 23  
 import java.io.IOException;
 24  
 import java.io.InputStream;
 25  
 import java.io.InputStreamReader;
 26  
 import java.lang.reflect.Constructor;
 27  
 import java.lang.reflect.InvocationTargetException;
 28  
 import java.lang.reflect.Method;
 29  
 import java.net.JarURLConnection;
 30  
 import java.net.URL;
 31  
 import java.net.URLConnection;
 32  
 import java.util.ArrayList;
 33  
 import java.util.Collections;
 34  
 import java.util.HashMap;
 35  
 import java.util.HashSet;
 36  
 import java.util.Iterator;
 37  
 import java.util.List;
 38  
 import java.util.Locale;
 39  
 import java.util.Map;
 40  
 import java.util.Set;
 41  
 import java.util.StringTokenizer;
 42  
 import java.util.TreeMap;
 43  
 import java.util.regex.Matcher;
 44  
 import java.util.regex.Pattern;
 45  
 
 46  
 import javax.el.ELResolver;
 47  
 import javax.faces.FacesException;
 48  
 import javax.faces.FactoryFinder;
 49  
 import javax.faces.application.Application;
 50  
 import javax.faces.application.ApplicationFactory;
 51  
 import javax.faces.application.NavigationHandler;
 52  
 import javax.faces.application.StateManager;
 53  
 import javax.faces.application.ViewHandler;
 54  
 import javax.faces.context.ExternalContext;
 55  
 import javax.faces.el.PropertyResolver;
 56  
 import javax.faces.el.VariableResolver;
 57  
 import javax.faces.event.ActionListener;
 58  
 import javax.faces.event.PhaseListener;
 59  
 import javax.faces.lifecycle.Lifecycle;
 60  
 import javax.faces.lifecycle.LifecycleFactory;
 61  
 import javax.faces.render.RenderKit;
 62  
 import javax.faces.render.RenderKitFactory;
 63  
 import javax.faces.webapp.FacesServlet;
 64  
 
 65  
 import org.apache.commons.logging.Log;
 66  
 import org.apache.commons.logging.LogFactory;
 67  
 import org.apache.myfaces.application.ApplicationFactoryImpl;
 68  
 import org.apache.myfaces.application.ApplicationImpl;
 69  
 import org.apache.myfaces.config.element.ManagedBean;
 70  
 import org.apache.myfaces.config.element.NavigationRule;
 71  
 import org.apache.myfaces.config.element.Renderer;
 72  
 import org.apache.myfaces.config.impl.digester.DigesterFacesConfigDispenserImpl;
 73  
 import org.apache.myfaces.config.impl.digester.DigesterFacesConfigUnmarshallerImpl;
 74  
 import org.apache.myfaces.config.impl.digester.elements.ResourceBundle;
 75  
 import org.apache.myfaces.context.FacesContextFactoryImpl;
 76  
 import org.apache.myfaces.el.DefaultPropertyResolver;
 77  
 import org.apache.myfaces.el.VariableResolverImpl;
 78  
 import org.apache.myfaces.lifecycle.LifecycleFactoryImpl;
 79  
 import org.apache.myfaces.renderkit.RenderKitFactoryImpl;
 80  
 import org.apache.myfaces.renderkit.html.HtmlRenderKitImpl;
 81  
 import org.apache.myfaces.shared_impl.config.MyfacesConfig;
 82  
 import org.apache.myfaces.shared_impl.util.ClassUtils;
 83  
 import org.apache.myfaces.shared_impl.util.LocaleUtils;
 84  
 import org.apache.myfaces.shared_impl.util.StateUtils;
 85  
 import org.apache.myfaces.shared_impl.util.serial.DefaultSerialFactory;
 86  
 import org.apache.myfaces.shared_impl.util.serial.SerialFactory;
 87  
 import org.xml.sax.SAXException;
 88  
 
 89  
 /**
 90  
  * Configures everything for a given context. The FacesConfigurator is independent of the concrete implementations that
 91  
  * lie behind FacesConfigUnmarshaller and FacesConfigDispenser.
 92  
  * 
 93  
  * @author Manfred Geiler (latest modification by $Author: jakobk $)
 94  
  * @version $Revision: 939403 $ $Date: 2010-04-29 12:56:39 -0500 (Thu, 29 Apr 2010) $
 95  
  */
 96  
 @SuppressWarnings("deprecation")
 97  
 public class FacesConfigurator
 98  
 {
 99  0
     private static final Log log = LogFactory.getLog(FacesConfigurator.class);
 100  
 
 101  
     private static final String STANDARD_FACES_CONFIG_RESOURCE = "META-INF/standard-faces-config.xml";
 102  
     private static final String FACES_CONFIG_RESOURCE = "META-INF/faces-config.xml";
 103  
 
 104  
     private static final String META_INF_SERVICES_RESOURCE_PREFIX = "META-INF/services/";
 105  
 
 106  0
     private static final String DEFAULT_RENDER_KIT_CLASS = HtmlRenderKitImpl.class.getName();
 107  0
     private static final String DEFAULT_APPLICATION_FACTORY = ApplicationFactoryImpl.class.getName();
 108  0
     private static final String DEFAULT_FACES_CONTEXT_FACTORY = FacesContextFactoryImpl.class.getName();
 109  0
     private static final String DEFAULT_LIFECYCLE_FACTORY = LifecycleFactoryImpl.class.getName();
 110  0
     private static final String DEFAULT_RENDER_KIT_FACTORY = RenderKitFactoryImpl.class.getName();
 111  
     private static final String DEFAULT_FACES_CONFIG = "/WEB-INF/faces-config.xml";
 112  
 
 113  0
     private static final Set<String> FACTORY_NAMES = new HashSet<String>();
 114  
     {
 115  0
         FACTORY_NAMES.add(FactoryFinder.APPLICATION_FACTORY);
 116  0
         FACTORY_NAMES.add(FactoryFinder.FACES_CONTEXT_FACTORY);
 117  0
         FACTORY_NAMES.add(FactoryFinder.LIFECYCLE_FACTORY);
 118  0
         FACTORY_NAMES.add(FactoryFinder.RENDER_KIT_FACTORY);
 119  
     }
 120  
 
 121  
     private final ExternalContext _externalContext;
 122  
     private FacesConfigUnmarshaller _unmarshaller;
 123  
     private FacesConfigDispenser _dispenser;
 124  
 
 125  
     private RuntimeConfig _runtimeConfig;
 126  
     private static final String JAR_EXTENSION = ".jar";
 127  
     private static final String META_INF_MANIFEST_SUFFIX = "!/META-INF/MANIFEST.MF";
 128  
     private static final String JAR_PREFIX = "jar:";
 129  
 
 130  
     private static long lastUpdate;
 131  
 
 132  
     public static final String MYFACES_API_PACKAGE_NAME = "myfaces-api";
 133  
     public static final String MYFACES_IMPL_PACKAGE_NAME = "myfaces-impl";
 134  
     public static final String MYFACES_TOMAHAWK_PACKAGE_NAME = "tomahawk";
 135  
     public static final String MYFACES_TOMAHAWK12_PACKAGE_NAME = "tomahawk12";
 136  
     public static final String MYFACES_ORCHESTRA_PACKAGE_NAME = "myfaces-orchestra-core";
 137  
     public static final String MYFACES_ORCHESTRA12_PACKAGE_NAME = "myfaces-orchestra-core12";
 138  
     public static final String MYFACES_TRINIDAD_API_PACKAGE_NAME = "trinidad-api";
 139  
     public static final String MYFACES_TRINIDAD_IMPL_PACKAGE_NAME = "trinidad-impl";
 140  
     public static final String MYFACES_TOBAGO_PACKAGE_NAME = "tobago";
 141  
     public static final String MYFACES_TOMAHAWK_SANDBOX_PACKAGE_NAME = "tomahawk-sandbox";
 142  
     public static final String MYFACES_TOMAHAWK_SANDBOX12_PACKAGE_NAME = "tomahawk-sandbox12";
 143  
     public static final String MYFACES_TOMAHAWK_SANDBOX15_PACKAGE_NAME = "tomahawk-sandbox15";
 144  
     public static final String COMMONS_EL_PACKAGE_NAME = "commons-el";
 145  
     public static final String JSP_API_PACKAGE_NAME = "jsp-api";
 146  
     
 147  0
     private static final String[] ARTIFACTS_IDS = 
 148  
         { 
 149  
             MYFACES_API_PACKAGE_NAME, MYFACES_IMPL_PACKAGE_NAME,
 150  
             MYFACES_TOMAHAWK_PACKAGE_NAME, MYFACES_TOMAHAWK12_PACKAGE_NAME,
 151  
             MYFACES_TOMAHAWK_SANDBOX_PACKAGE_NAME, MYFACES_TOMAHAWK_SANDBOX12_PACKAGE_NAME,
 152  
             MYFACES_TOMAHAWK_SANDBOX15_PACKAGE_NAME,
 153  
             MYFACES_ORCHESTRA_PACKAGE_NAME, MYFACES_ORCHESTRA12_PACKAGE_NAME,
 154  
             MYFACES_TRINIDAD_API_PACKAGE_NAME, MYFACES_TRINIDAD_IMPL_PACKAGE_NAME,
 155  
             MYFACES_TOBAGO_PACKAGE_NAME, 
 156  
             COMMONS_EL_PACKAGE_NAME, JSP_API_PACKAGE_NAME
 157  
         };
 158  
     
 159  
     /**
 160  
      * Regular expression used to extract the jar information from the 
 161  
      * files present in the classpath.
 162  
      * <p>The groups found with the regular expression are:</p>
 163  
      * <ul>
 164  
      *   <li>Group 6: file path (required)</li>
 165  
      *   <li>Group 7: artifact id (required)</li>
 166  
      *   <li>Group 8: major version (required)</li>
 167  
      *   <li>Group 10: minor version (optional)</li>
 168  
      *   <li>Group 12: maintenance version (optional)</li>
 169  
      *   <li>Group 14: extra version (optional)</li>
 170  
      *   <li>Group 15: SNAPSHOT marker (optional)</li>
 171  
      * </ul>
 172  
      */
 173  
     public static final String REGEX_LIBRARY = "((jar)?(besjar)?(wsjar)?(zip)?)?:(file:.*/(.+)-" +
 174  
             "(\\d+)(\\.(\\d+)(\\.(\\d+)(\\.(\\d+))?)?)?(-SNAPSHOT)?" +
 175  
             "\\.jar)!/META-INF/MANIFEST.MF";
 176  0
     private static final Pattern REGEX_LIBRARY_PATTERN = Pattern.compile(REGEX_LIBRARY);
 177  
     private static final int REGEX_LIBRARY_FILE_PATH = 6;
 178  
     private static final int REGEX_LIBRARY_ARTIFACT_ID = 7;
 179  
     private static final int REGEX_LIBRARY_MAJOR_VERSION = 8;
 180  
     private static final int REGEX_LIBRARY_MINOR_VERSION = 10;
 181  
     private static final int REGEX_LIBRARY_MAINTENANCE_VERSION = 12;
 182  
     private static final int REGEX_LIBRARY_EXTRA_VERSION = 14;
 183  
     private static final int REGEX_LIBRARY_SNAPSHOT_MARKER = 15;
 184  
 
 185  
     public FacesConfigurator(ExternalContext externalContext)
 186  0
     {
 187  0
         if (externalContext == null)
 188  
         {
 189  0
             throw new IllegalArgumentException("external context must not be null");
 190  
         }
 191  0
         _externalContext = externalContext;
 192  
 
 193  0
     }
 194  
 
 195  
     /**
 196  
      * @param unmarshaller
 197  
      *            the unmarshaller to set
 198  
      */
 199  
     public void setUnmarshaller(FacesConfigUnmarshaller unmarshaller)
 200  
     {
 201  0
         _unmarshaller = unmarshaller;
 202  0
     }
 203  
 
 204  
     /**
 205  
      * @return the unmarshaller
 206  
      */
 207  
     protected FacesConfigUnmarshaller getUnmarshaller()
 208  
     {
 209  0
         if (_unmarshaller == null)
 210  
         {
 211  0
             _unmarshaller = new DigesterFacesConfigUnmarshallerImpl(_externalContext);
 212  
         }
 213  0
         return _unmarshaller;
 214  
     }
 215  
 
 216  
     /**
 217  
      * @param dispenser
 218  
      *            the dispenser to set
 219  
      */
 220  
     public void setDispenser(FacesConfigDispenser dispenser)
 221  
     {
 222  0
         _dispenser = dispenser;
 223  0
     }
 224  
 
 225  
     /**
 226  
      * @return the dispenser
 227  
      */
 228  
     protected FacesConfigDispenser getDispenser()
 229  
     {
 230  0
         if (_dispenser == null)
 231  
         {
 232  0
             _dispenser = new DigesterFacesConfigDispenserImpl();
 233  
         }
 234  0
         return _dispenser;
 235  
     }
 236  
 
 237  
     private long getResourceLastModified(String resource)
 238  
     {
 239  
         try 
 240  
         {
 241  0
             URL url =  _externalContext.getResource(resource);
 242  0
             if (url != null)
 243  
             {
 244  0
                 return getResourceLastModified(url);
 245  
             }
 246  
         }
 247  0
         catch (IOException e)
 248  
         {
 249  0
             log.error("Could not read resource " + resource, e);
 250  0
         }
 251  0
         return 0;
 252  
     }
 253  
 
 254  
     //Taken from trinidad URLUtils
 255  
     private long getResourceLastModified(URL url) throws IOException
 256  
     {
 257  0
         if ("file".equals(url.getProtocol()))
 258  
         {
 259  0
             String externalForm = url.toExternalForm();
 260  
             // Remove the "file:"
 261  0
             File file = new File(externalForm.substring(5));
 262  
 
 263  0
             return file.lastModified();
 264  
         }
 265  
         else
 266  
         {
 267  0
             return getResourceLastModified(url.openConnection());
 268  
         }
 269  
     }
 270  
 
 271  
     //Taken from trinidad URLUtils
 272  
     private long getResourceLastModified(URLConnection connection) throws IOException
 273  
     {
 274  
         long modified;
 275  0
         if (connection instanceof JarURLConnection)
 276  
         {
 277  
             // The following hack is required to work-around a JDK bug.
 278  
             // getLastModified() on a JAR entry URL delegates to the actual JAR file
 279  
             // rather than the JAR entry.
 280  
             // This opens internally, and does not close, an input stream to the JAR
 281  
             // file.
 282  
             // In turn, you cannot close it by yourself, because it's internal.
 283  
             // The work-around is to get the modification date of the JAR file
 284  
             // manually,
 285  
             // and then close that connection again.
 286  
 
 287  0
             URL jarFileUrl = ((JarURLConnection) connection).getJarFileURL();
 288  0
             URLConnection jarFileConnection = jarFileUrl.openConnection();
 289  
 
 290  
             try
 291  
             {
 292  0
                 modified = jarFileConnection.getLastModified();
 293  
             }
 294  
             finally
 295  
             {
 296  0
                 try
 297  
                 {
 298  0
                     jarFileConnection.getInputStream().close();
 299  
                 }
 300  0
                 catch (Exception exception)
 301  
                 {
 302  
                     // Ignored
 303  0
                 }
 304  0
             }
 305  0
         }
 306  
         else
 307  
         {
 308  0
             modified = connection.getLastModified();
 309  
         }
 310  
 
 311  0
         return modified;
 312  
     }    
 313  
     
 314  
     private long getLastModifiedTime()
 315  
     {
 316  0
         long lastModified = 0;
 317  
         long resModified;
 318  
 
 319  0
         resModified = getResourceLastModified(DEFAULT_FACES_CONFIG);
 320  0
         if (resModified > lastModified)
 321  0
             lastModified = resModified;
 322  
 
 323  
 
 324  0
         List<String> configFilesList = getConfigFilesList();
 325  
 
 326  0
         for (String systemId : configFilesList)
 327  
         {
 328  0
             resModified = getResourceLastModified(systemId);
 329  0
             if (resModified > lastModified)
 330  
             {
 331  0
                 lastModified = resModified;
 332  
             }
 333  
 
 334  
         }
 335  
 
 336  0
         return lastModified;
 337  
     }
 338  
 
 339  
     public void update() {
 340  0
         long refreshPeriod = (MyfacesConfig.getCurrentInstance(_externalContext).getConfigRefreshPeriod()) * 1000;
 341  
 
 342  0
         if (refreshPeriod > 0) {
 343  0
             long ttl = lastUpdate + refreshPeriod;
 344  0
             if ((System.currentTimeMillis() > ttl) && (getLastModifiedTime() > ttl)) {
 345  
                 try {
 346  0
                     purgeConfiguration();
 347  
                 }
 348  0
                 catch (NoSuchMethodException e) {
 349  0
                     log.error("Configuration objects do not support clean-up. Update aborted");
 350  
 
 351  
                     // We still want to update the timestamp to avoid running purge on every subsequent
 352  
                     // request after this one.
 353  
                     //
 354  0
                     lastUpdate = System.currentTimeMillis();
 355  
 
 356  0
                     return;
 357  
                 }
 358  0
                 catch (IllegalAccessException e) {
 359  0
                     log.fatal("Error during configuration clean-up" + e.getMessage());
 360  
                 }
 361  0
                 catch (InvocationTargetException e) {
 362  0
                     log.fatal("Error during configuration clean-up" + e.getMessage());
 363  0
                 }
 364  0
                 configure();
 365  
             }
 366  
         }
 367  0
     }
 368  
 
 369  
     private void purgeConfiguration() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
 370  
     {
 371  0
         final Class<?>[] NO_PARAMETER_TYPES = new Class[]{};
 372  0
         final Object[] NO_PARAMETERS = new Object[]{};
 373  
 
 374  
         Method appFactoryPurgeMethod;
 375  
         Method renderKitPurgeMethod;
 376  
         Method lifecyclePurgeMethod;
 377  
 
 378  
         // Check that we have access to all of the necessary purge methods before purging anything
 379  
         //
 380  0
         ApplicationFactory applicationFactory = (ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
 381  0
         appFactoryPurgeMethod = applicationFactory.getClass().getMethod("purgeApplication", NO_PARAMETER_TYPES);
 382  
 
 383  0
         RenderKitFactory renderKitFactory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
 384  0
         renderKitPurgeMethod = renderKitFactory.getClass().getMethod("purgeRenderKit", NO_PARAMETER_TYPES);
 385  
         
 386  0
         LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
 387  0
         lifecyclePurgeMethod = lifecycleFactory.getClass().getMethod("purgeLifecycle", NO_PARAMETER_TYPES);
 388  
 
 389  
         // If there was no exception so far, now we can purge
 390  
         //
 391  0
         appFactoryPurgeMethod.invoke(applicationFactory, NO_PARAMETERS);
 392  0
         renderKitPurgeMethod.invoke(renderKitFactory, NO_PARAMETERS);
 393  0
         RuntimeConfig.getCurrentInstance(_externalContext).purge();
 394  0
         lifecyclePurgeMethod.invoke(lifecycleFactory, NO_PARAMETERS);
 395  
 
 396  
         // factories and serial factory need not be purged...
 397  0
     }
 398  
 
 399  
 
 400  
     public void configure() throws FacesException
 401  
     {
 402  
         try
 403  
         {
 404  0
             feedStandardConfig();
 405  0
             feedMetaInfServicesFactories();
 406  0
             feedClassloaderConfigurations();
 407  0
             feedContextSpecifiedConfig();
 408  0
             feedWebAppConfig();
 409  
 
 410  0
             if (log.isInfoEnabled())
 411  
             {
 412  0
                 logMetaInf();
 413  
             }
 414  
         }
 415  0
         catch (IOException e)
 416  
         {
 417  0
             throw new FacesException(e);
 418  
         }
 419  0
         catch (SAXException e)
 420  
         {
 421  0
             throw new FacesException(e);
 422  0
         }
 423  
 
 424  0
         configureFactories();
 425  0
         configureApplication();
 426  0
         configureRenderKits();
 427  0
         configureRuntimeConfig();
 428  0
         configureLifecycle();
 429  0
         handleSerialFactory();
 430  
 
 431  
         //record the time of update
 432  0
         lastUpdate = System.currentTimeMillis();
 433  0
     }
 434  
 
 435  
     private void feedStandardConfig() throws IOException, SAXException
 436  
     {
 437  0
         InputStream stream = ClassUtils.getResourceAsStream(STANDARD_FACES_CONFIG_RESOURCE);
 438  0
         if (stream == null)
 439  0
             throw new FacesException("Standard faces config " + STANDARD_FACES_CONFIG_RESOURCE + " not found");
 440  0
         if (log.isInfoEnabled())
 441  0
             log.info("Reading standard config " + STANDARD_FACES_CONFIG_RESOURCE);
 442  0
         getDispenser().feed(getUnmarshaller().getFacesConfig(stream, STANDARD_FACES_CONFIG_RESOURCE));
 443  0
         stream.close();
 444  0
     }
 445  
 
 446  
     /**
 447  
      * This method performs part of the factory search outlined in section 10.2.6.1.
 448  
      */
 449  
     @SuppressWarnings("unchecked")
 450  
     protected void logMetaInf()
 451  
     {
 452  
         try
 453  
         {
 454  0
             Map<String, List<JarInfo>> libs = new HashMap<String, List<JarInfo>>(30);
 455  
 
 456  0
             Iterator<URL> it = ClassUtils.getResources("META-INF/MANIFEST.MF", this);
 457  0
             while (it.hasNext())
 458  
             {
 459  0
                 URL url = it.next();
 460  0
                 Matcher matcher = REGEX_LIBRARY_PATTERN.matcher(url.toString());
 461  0
                 if (matcher.matches())
 462  
                 {
 463  
                     // We have a valid JAR
 464  0
                     String artifactId = matcher.group(REGEX_LIBRARY_ARTIFACT_ID);
 465  0
                     List<JarInfo> versions = libs.get(artifactId);
 466  0
                     if (versions == null)
 467  
                     {
 468  0
                         versions = new ArrayList<JarInfo>(2);
 469  0
                         libs.put(artifactId, versions);
 470  
                     }
 471  
 
 472  0
                     String path = matcher.group(REGEX_LIBRARY_FILE_PATH);
 473  
 
 474  0
                     Version version = new Version(matcher.group(REGEX_LIBRARY_MAJOR_VERSION), 
 475  
                             matcher.group(REGEX_LIBRARY_MINOR_VERSION), 
 476  
                             matcher.group(REGEX_LIBRARY_MAINTENANCE_VERSION),
 477  
                             matcher.group(REGEX_LIBRARY_EXTRA_VERSION), 
 478  
                             matcher.group(REGEX_LIBRARY_SNAPSHOT_MARKER));
 479  
 
 480  0
                     JarInfo newInfo = new JarInfo(path, version);
 481  0
                     if (!versions.contains(newInfo))
 482  
                     {
 483  0
                         versions.add(newInfo);
 484  
                     }
 485  
                 }
 486  0
             }
 487  
 
 488  0
             if (log.isInfoEnabled())
 489  
             {
 490  0
                 if (log.isWarnEnabled())
 491  
                 {
 492  0
                     for (String artifactId : ARTIFACTS_IDS)
 493  
                     {
 494  0
                         List<JarInfo> versions = libs.get(artifactId);
 495  0
                         if (versions != null && versions.size() > 1)
 496  
                         {
 497  0
                             StringBuilder builder = new StringBuilder(1024);
 498  0
                             builder.append("You are using the library: ");
 499  0
                             builder.append(artifactId);
 500  0
                             builder.append(" in different versions; first (and probably used) version is: ");
 501  0
                             builder.append(versions.get(0).getVersion());
 502  0
                             builder.append(" loaded from: ");
 503  0
                             builder.append(versions.get(0).getUrl());
 504  0
                             builder.append(", but also found the following versions: ");
 505  
 
 506  0
                             boolean needComma = false;
 507  0
                             for (int i = 1; i < versions.size(); i++)
 508  
                             {
 509  0
                                 JarInfo info = versions.get(i);
 510  0
                                 if (needComma)
 511  
                                 {
 512  0
                                     builder.append(", ");
 513  
                                 }
 514  
 
 515  0
                                 builder.append(info.getVersion());
 516  0
                                 builder.append(" loaded from: ");
 517  0
                                 builder.append(info.getUrl());
 518  
 
 519  0
                                 needComma = true;
 520  
                             }
 521  
 
 522  0
                             log.warn(builder.toString());
 523  
                         }
 524  
                     }
 525  
                 }
 526  
 
 527  0
                 for (String artifactId : ARTIFACTS_IDS)
 528  
                 {
 529  0
                     startLib(artifactId, libs);
 530  
                 }
 531  
             }
 532  
         }
 533  0
         catch (Throwable e)
 534  
         {
 535  0
             throw new FacesException(e);
 536  0
         }
 537  0
     }
 538  
 
 539  
     /**
 540  
      * This method performs part of the factory search outlined in section 10.2.6.1.
 541  
      */
 542  
     protected void feedMetaInfServicesFactories()
 543  
     {
 544  
         try
 545  
         {
 546  0
             for (String factoryName : FACTORY_NAMES)
 547  
             {
 548  0
                 Iterator it = ClassUtils.getResources(META_INF_SERVICES_RESOURCE_PREFIX + factoryName, this);
 549  0
                 while (it.hasNext())
 550  
                 {
 551  0
                     URL url = (URL) it.next();
 552  0
                     InputStream stream = openStreamWithoutCache(url);
 553  0
                     InputStreamReader isr = new InputStreamReader(stream);
 554  0
                     BufferedReader br = new BufferedReader(isr);
 555  
                     String className;
 556  
                     try
 557  
                     {
 558  0
                         className = br.readLine();
 559  
                     }
 560  0
                     catch (IOException e)
 561  
                     {
 562  0
                         throw new FacesException("Unable to read class name from file " + url.toExternalForm(), e);
 563  
                     } finally {
 564  0
                         if (br != null)
 565  
                         {
 566  0
                             br.close();
 567  
                         }
 568  0
                         if (isr != null) {
 569  0
                             isr.close();
 570  
                         }
 571  0
                         if (stream != null) {
 572  0
                             stream.close();
 573  
                         }
 574  
                     }
 575  
 
 576  
 
 577  0
                     if (log.isInfoEnabled())
 578  
                     {
 579  0
                         log.info("Found " + factoryName + " factory implementation: " + className);
 580  
                     }
 581  
 
 582  0
                     if (factoryName.equals(FactoryFinder.APPLICATION_FACTORY))
 583  
                     {
 584  0
                         getDispenser().feedApplicationFactory(className);
 585  
                     }
 586  0
                     else if (factoryName.equals(FactoryFinder.FACES_CONTEXT_FACTORY))
 587  
                     {
 588  0
                         getDispenser().feedFacesContextFactory(className);
 589  
                     }
 590  0
                     else if (factoryName.equals(FactoryFinder.LIFECYCLE_FACTORY))
 591  
                     {
 592  0
                         getDispenser().feedLifecycleFactory(className);
 593  
                     }
 594  0
                     else if (factoryName.equals(FactoryFinder.RENDER_KIT_FACTORY))
 595  
                     {
 596  0
                         getDispenser().feedRenderKitFactory(className);
 597  
                     }
 598  
                     else
 599  
                     {
 600  0
                         throw new IllegalStateException("Unexpected factory name " + factoryName);
 601  
                     }
 602  0
                 }
 603  0
             }
 604  
         }
 605  0
         catch (Throwable e)
 606  
         {
 607  0
             throw new FacesException(e);
 608  0
         }
 609  0
     }
 610  
 
 611  
     private InputStream openStreamWithoutCache(URL url) throws IOException
 612  
     {
 613  0
         URLConnection connection = url.openConnection();
 614  0
         connection.setUseCaches(false);
 615  0
         return connection.getInputStream();
 616  
     }
 617  
 
 618  
     /**
 619  
      * This method fixes MYFACES-208
 620  
      */
 621  
     private void feedClassloaderConfigurations()
 622  
     {
 623  
         try
 624  
         {
 625  0
             Map<String,URL> facesConfigs = new TreeMap<String,URL>();
 626  0
             Iterator it = ClassUtils.getResources(FACES_CONFIG_RESOURCE, this);
 627  0
             while (it.hasNext())
 628  
             {
 629  0
                 URL url = (URL) it.next();
 630  0
                 String systemId = url.toExternalForm();
 631  0
                 facesConfigs.put(systemId,url);
 632  0
             }
 633  
 
 634  0
             for (Map.Entry<String, URL> entry : facesConfigs.entrySet())
 635  
             {
 636  0
                 InputStream stream = null;
 637  
                 try
 638  
                 {
 639  0
                     stream = openStreamWithoutCache(entry.getValue());
 640  0
                     if (log.isInfoEnabled())
 641  
                     {
 642  0
                         log.info("Reading config : " + entry.getKey());
 643  
                     }
 644  0
                     getDispenser().feed(getUnmarshaller().getFacesConfig(stream, entry.getKey()));
 645  
                 }
 646  
                 finally
 647  
                 {
 648  0
                     if (stream != null)
 649  
                     {
 650  0
                         stream.close();
 651  
                     }
 652  
                 }
 653  0
             }
 654  
         }
 655  0
         catch (Throwable e)
 656  
         {
 657  0
             throw new FacesException(e);
 658  0
         }
 659  0
     }
 660  
 
 661  
 
 662  
     private void feedContextSpecifiedConfig() throws IOException, SAXException
 663  
     {
 664  0
         List<String> configFilesList = getConfigFilesList();
 665  0
         for (String systemId : configFilesList)
 666  
         {
 667  0
             InputStream stream = _externalContext.getResourceAsStream(systemId);
 668  0
             if (stream == null)
 669  
             {
 670  0
                 log.error("Faces config resource " + systemId + " not found");
 671  0
                 continue;
 672  
             }
 673  
 
 674  0
             if (log.isInfoEnabled())
 675  
             {
 676  0
                 log.info("Reading config " + systemId);
 677  
             }
 678  0
             getDispenser().feed(getUnmarshaller().getFacesConfig(stream, systemId));
 679  0
             stream.close();
 680  0
         }
 681  0
     }
 682  
 
 683  
     private List<String> getConfigFilesList() {
 684  0
         String configFiles = _externalContext.getInitParameter(FacesServlet.CONFIG_FILES_ATTR);
 685  0
         List<String> configFilesList = new ArrayList<String>();
 686  0
         if (configFiles != null)
 687  
         {
 688  0
             StringTokenizer st = new StringTokenizer(configFiles, ",", false);
 689  0
             while (st.hasMoreTokens())
 690  
             {
 691  0
                 String systemId = st.nextToken().trim();
 692  
 
 693  0
                 if (DEFAULT_FACES_CONFIG.equals(systemId))
 694  
                 {
 695  0
                     if(log.isWarnEnabled())
 696  0
                         log.warn(DEFAULT_FACES_CONFIG + " has been specified in the " +
 697  
                                 FacesServlet.CONFIG_FILES_ATTR + " context parameter of " +
 698  
                                 "the deployment descriptor. This will automatically be removed, " +
 699  
                                 "if we wouldn't do this, it would be loaded twice.  See JSF spec 1.1, 10.3.2");
 700  
                 }
 701  
                 else
 702  0
                     configFilesList.add(systemId);
 703  0
             }
 704  
         }
 705  0
         return configFilesList;
 706  
     }
 707  
 
 708  
     private void feedWebAppConfig() throws IOException, SAXException
 709  
     {
 710  
         // web application config
 711  0
         InputStream stream = _externalContext.getResourceAsStream(DEFAULT_FACES_CONFIG);
 712  0
         if (stream != null)
 713  
         {
 714  0
             if (log.isInfoEnabled())
 715  0
                 log.info("Reading config /WEB-INF/faces-config.xml");
 716  0
             getDispenser().feed(getUnmarshaller().getFacesConfig(stream, DEFAULT_FACES_CONFIG));
 717  0
             stream.close();
 718  
         }
 719  0
     }
 720  
 
 721  
     private void configureFactories()
 722  
     {
 723  0
         FacesConfigDispenser dispenser = getDispenser();
 724  0
         setFactories(FactoryFinder.APPLICATION_FACTORY, dispenser.getApplicationFactoryIterator(),
 725  
                 DEFAULT_APPLICATION_FACTORY);
 726  0
         setFactories(FactoryFinder.FACES_CONTEXT_FACTORY, dispenser.getFacesContextFactoryIterator(),
 727  
                 DEFAULT_FACES_CONTEXT_FACTORY);
 728  0
         setFactories(FactoryFinder.LIFECYCLE_FACTORY, dispenser.getLifecycleFactoryIterator(),
 729  
                 DEFAULT_LIFECYCLE_FACTORY);
 730  0
         setFactories(FactoryFinder.RENDER_KIT_FACTORY, dispenser.getRenderKitFactoryIterator(),
 731  
                 DEFAULT_RENDER_KIT_FACTORY);
 732  0
     }
 733  
 
 734  
     private void setFactories(String factoryName, Iterator factories, String defaultFactory)
 735  
     {
 736  0
         FactoryFinder.setFactory(factoryName, defaultFactory);
 737  0
         while (factories.hasNext())
 738  
         {
 739  0
             String factory = (String) factories.next();
 740  0
             if (!factory.equals(defaultFactory))
 741  0
                 FactoryFinder.setFactory(factoryName, factory);
 742  0
         }
 743  0
     }
 744  
     
 745  
     private void startLib(String artifactId, Map<String, List<JarInfo>> libs)
 746  
     {
 747  0
         List<JarInfo> versions = libs.get(artifactId);
 748  0
         if (versions == null)
 749  
         {
 750  0
             log.info("MyFaces-package : " + artifactId + " not found.");
 751  
         }
 752  
         else
 753  
         {
 754  0
             JarInfo info = versions.get(0);
 755  0
             log.info("Starting up MyFaces-package : " + artifactId + " in version : "
 756  
                      + info.getVersion() + " from path : " + info.getUrl());
 757  
         }
 758  0
     }
 759  
 
 760  
     private void configureApplication()
 761  
     {
 762  0
         Application application = ((ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY))
 763  
                 .getApplication();
 764  0
         FacesConfigDispenser dispenser = getDispenser();
 765  0
         application.setActionListener((ActionListener) getApplicationObject(ActionListener.class, dispenser
 766  
                 .getActionListenerIterator(), null));
 767  
 
 768  0
         if (dispenser.getDefaultLocale() != null)
 769  
         {
 770  0
             application.setDefaultLocale(LocaleUtils.toLocale(dispenser.getDefaultLocale()));
 771  
         }
 772  
 
 773  0
         if (dispenser.getDefaultRenderKitId() != null)
 774  
         {
 775  0
             application.setDefaultRenderKitId(dispenser.getDefaultRenderKitId());
 776  
         }
 777  
 
 778  0
         if (dispenser.getMessageBundle() != null)
 779  
         {
 780  0
             application.setMessageBundle(dispenser.getMessageBundle());
 781  
         }
 782  
 
 783  0
         application.setNavigationHandler((NavigationHandler) getApplicationObject(NavigationHandler.class, dispenser
 784  
                 .getNavigationHandlerIterator(), application.getNavigationHandler()));
 785  
         
 786  0
         application.setStateManager((StateManager) getApplicationObject(StateManager.class, dispenser
 787  
                 .getStateManagerIterator(), application.getStateManager()));
 788  0
         List<Locale> locales = new ArrayList<Locale>();
 789  0
         for (Iterator it = dispenser.getSupportedLocalesIterator(); it.hasNext();)
 790  
         {
 791  0
             locales.add(LocaleUtils.toLocale((String) it.next()));
 792  
         }
 793  0
         application.setSupportedLocales(locales);
 794  
 
 795  0
         application.setViewHandler((ViewHandler) getApplicationObject(ViewHandler.class, dispenser
 796  
                 .getViewHandlerIterator(), application.getViewHandler()));
 797  
 
 798  0
         for (Iterator it = dispenser.getComponentTypes(); it.hasNext();)
 799  
         {
 800  0
             String componentType = (String) it.next();
 801  0
             application.addComponent(componentType, dispenser.getComponentClass(componentType));
 802  0
         }
 803  
 
 804  0
         for (Iterator it = dispenser.getConverterIds(); it.hasNext();)
 805  
         {
 806  0
             String converterId = (String) it.next();
 807  0
             application.addConverter(converterId, dispenser.getConverterClassById(converterId));
 808  0
         }
 809  
 
 810  0
         for (Iterator it = dispenser.getConverterClasses(); it.hasNext();)
 811  
         {
 812  0
             String converterClass = (String) it.next();
 813  
             try
 814  
             {
 815  0
                 application.addConverter(ClassUtils.simpleClassForName(converterClass), dispenser
 816  
                         .getConverterClassByClass(converterClass));
 817  
             }
 818  0
             catch (Exception ex)
 819  
             {
 820  0
                 log.error("Converter could not be added. Reason:", ex);
 821  0
             }
 822  0
         }
 823  
 
 824  0
         if (application instanceof ApplicationImpl)
 825  
         {
 826  0
             for (Iterator it = dispenser.getConverterConfigurationByClassName(); it.hasNext();)
 827  
             {
 828  0
                 String converterClassName = (String) it.next();
 829  
 
 830  0
                 ((ApplicationImpl) application).addConverterConfiguration(converterClassName, dispenser
 831  
                         .getConverterConfiguration(converterClassName));
 832  0
             }
 833  
         }
 834  
 
 835  0
         for (Iterator it = dispenser.getValidatorIds(); it.hasNext();)
 836  
         {
 837  0
             String validatorId = (String) it.next();
 838  0
             application.addValidator(validatorId, dispenser.getValidatorClass(validatorId));
 839  0
         }
 840  
 
 841  0
         RuntimeConfig runtimeConfig = getRuntimeConfig();
 842  
         
 843  0
         runtimeConfig.setPropertyResolverChainHead((PropertyResolver) getApplicationObject(PropertyResolver.class, dispenser
 844  
                 .getPropertyResolverIterator(), new DefaultPropertyResolver()));
 845  
         
 846  0
         runtimeConfig.setVariableResolverChainHead((VariableResolver) getApplicationObject(VariableResolver.class, dispenser
 847  
                 .getVariableResolverIterator(), new VariableResolverImpl()));
 848  0
     }
 849  
 
 850  
     protected RuntimeConfig getRuntimeConfig()
 851  
     {
 852  0
         if(_runtimeConfig == null) 
 853  
         {
 854  0
             _runtimeConfig = RuntimeConfig.getCurrentInstance(_externalContext);
 855  
         }
 856  0
         return _runtimeConfig;
 857  
     }
 858  
     
 859  
     public void setRuntimeConfig(RuntimeConfig runtimeConfig)
 860  
     {
 861  0
         _runtimeConfig = runtimeConfig;
 862  0
     }
 863  
 
 864  
     private Object getApplicationObject(Class interfaceClass, Iterator classNamesIterator, Object defaultObject)
 865  
     {
 866  0
         Object current = defaultObject;
 867  
 
 868  0
         while (classNamesIterator.hasNext())
 869  
         {
 870  0
             String implClassName = (String) classNamesIterator.next();
 871  0
             Class implClass = ClassUtils.simpleClassForName(implClassName);
 872  
 
 873  
             // check, if class is of expected interface type
 874  0
             if (!interfaceClass.isAssignableFrom(implClass))
 875  
             {
 876  0
                 throw new IllegalArgumentException("Class " + implClassName + " is no " + interfaceClass.getName());
 877  
             }
 878  
 
 879  0
             if (current == null)
 880  
             {
 881  
                 // nothing to decorate
 882  0
                 current = ClassUtils.newInstance(implClass);
 883  
             }
 884  
             else
 885  
             {
 886  
                 // let's check if class supports the decorator pattern
 887  
                 try
 888  
                 {
 889  0
                     Constructor delegationConstructor = implClass.getConstructor(new Class[] { interfaceClass });
 890  
                     // impl class supports decorator pattern,
 891  
                     try
 892  
                     {
 893  
                         // create new decorator wrapping current
 894  0
                         current = delegationConstructor.newInstance(new Object[] { current });
 895  
                     }
 896  0
                     catch (InstantiationException e)
 897  
                     {
 898  0
                         log.error(e.getMessage(), e);
 899  0
                         throw new FacesException(e);
 900  
                     }
 901  0
                     catch (IllegalAccessException e)
 902  
                     {
 903  0
                         log.error(e.getMessage(), e);
 904  0
                         throw new FacesException(e);
 905  
                     }
 906  0
                     catch (InvocationTargetException e)
 907  
                     {
 908  0
                         log.error(e.getMessage(), e);
 909  0
                         throw new FacesException(e);
 910  0
                     }
 911  
                 }
 912  0
                 catch (NoSuchMethodException e)
 913  
                 {
 914  
                     // no decorator pattern support
 915  0
                     current = ClassUtils.newInstance(implClass);
 916  0
                 }
 917  
             }
 918  0
         }
 919  
 
 920  0
         return current;
 921  
     }
 922  
 
 923  
     private void configureRuntimeConfig()
 924  
     {
 925  0
         RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(_externalContext);
 926  
 
 927  0
         FacesConfigDispenser dispenser = getDispenser();
 928  0
         for (Iterator iterator = dispenser.getManagedBeans(); iterator.hasNext();)
 929  
         {
 930  0
             ManagedBean bean = (ManagedBean) iterator.next();
 931  
 
 932  0
             if (log.isWarnEnabled() && runtimeConfig.getManagedBean(bean.getManagedBeanName()) != null)
 933  0
                 log.warn("More than one managed bean w/ the name of '" + bean.getManagedBeanName()
 934  
                         + "' - only keeping the last ");
 935  
 
 936  0
             runtimeConfig.addManagedBean(bean.getManagedBeanName(), bean);
 937  
 
 938  0
         }
 939  
 
 940  0
         removePurgedBeansFromSessionAndApplication(runtimeConfig);
 941  
 
 942  0
         for (Iterator iterator = dispenser.getNavigationRules(); iterator.hasNext();)
 943  
         {
 944  0
             NavigationRule rule = (NavigationRule) iterator.next();
 945  0
             runtimeConfig.addNavigationRule(rule);
 946  
 
 947  0
         }
 948  
 
 949  0
         for (Iterator<ResourceBundle> iter = dispenser.getResourceBundles(); iter.hasNext();)
 950  
         {
 951  0
             runtimeConfig.addResourceBundle(iter.next());
 952  
         }
 953  
         
 954  0
         for (Iterator<String> iter = dispenser.getElResolvers(); iter.hasNext();)
 955  
         {
 956  0
             runtimeConfig.addFacesConfigElResolver((ELResolver) ClassUtils.newInstance(iter.next(), ELResolver.class));
 957  
         }
 958  
 
 959  0
     }
 960  
 
 961  
     private void removePurgedBeansFromSessionAndApplication(RuntimeConfig runtimeConfig)
 962  
     {
 963  0
         Map oldManagedBeans = runtimeConfig.getManagedBeansNotReaddedAfterPurge();
 964  0
         if(oldManagedBeans!=null) {
 965  0
             Iterator it=oldManagedBeans.entrySet().iterator();
 966  0
             while(it.hasNext()) {
 967  0
                 Map.Entry entry = (Map.Entry) it.next();
 968  0
                 ManagedBean bean = (ManagedBean) entry.getValue();
 969  
 
 970  0
                 String scope = bean.getManagedBeanScope();
 971  
 
 972  0
                 if(scope!=null && scope.equalsIgnoreCase("session")) {
 973  0
                     _externalContext.getSessionMap().remove(entry.getKey());
 974  
                 }
 975  0
                 else if(scope!=null && scope.equalsIgnoreCase("application")) {
 976  0
                     _externalContext.getApplicationMap().remove(entry.getKey());
 977  
                 }
 978  0
             }
 979  
         }
 980  0
         runtimeConfig.resetManagedBeansNotReaddedAfterPurge();
 981  0
     }
 982  
 
 983  
     private void configureRenderKits()
 984  
     {
 985  0
         RenderKitFactory renderKitFactory = (RenderKitFactory) FactoryFinder
 986  
                 .getFactory(FactoryFinder.RENDER_KIT_FACTORY);
 987  
 
 988  0
         FacesConfigDispenser dispenser = getDispenser();
 989  0
         for (Iterator iterator = dispenser.getRenderKitIds(); iterator.hasNext();)
 990  
         {
 991  0
             String renderKitId = (String) iterator.next();
 992  0
             String renderKitClass = dispenser.getRenderKitClass(renderKitId);
 993  
 
 994  0
             if (renderKitClass == null)
 995  
             {
 996  0
                 renderKitClass = DEFAULT_RENDER_KIT_CLASS;
 997  
             }
 998  
 
 999  0
             RenderKit renderKit = (RenderKit) ClassUtils.newInstance(renderKitClass);
 1000  
 
 1001  0
             for (Iterator renderers = dispenser.getRenderers(renderKitId); renderers.hasNext();)
 1002  
             {
 1003  0
                 Renderer element = (Renderer) renderers.next();
 1004  
                 javax.faces.render.Renderer renderer;
 1005  
                 try
 1006  
                 {
 1007  0
                     renderer = (javax.faces.render.Renderer) ClassUtils.newInstance(element.getRendererClass());
 1008  
                 }
 1009  0
                 catch (Throwable e)
 1010  
                 {
 1011  
                     // ignore the failure so that the render kit is configured
 1012  0
                     log.error("failed to configure class " + element.getRendererClass(), e);
 1013  0
                     continue;
 1014  0
                 }
 1015  
 
 1016  0
                renderKit.addRenderer(element.getComponentFamily(), element.getRendererType(), renderer);
 1017  0
             }
 1018  
 
 1019  0
             renderKitFactory.addRenderKit(renderKitId, renderKit);
 1020  0
         }
 1021  0
     }
 1022  
 
 1023  
     private void configureLifecycle()
 1024  
     {
 1025  
         // create the lifecycle used by the app
 1026  0
         LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder
 1027  
                 .getFactory(FactoryFinder.LIFECYCLE_FACTORY);
 1028  0
         Lifecycle lifecycle = lifecycleFactory.getLifecycle(getLifecycleId());
 1029  
 
 1030  
         // add phase listeners
 1031  0
         for (Iterator iterator = getDispenser().getLifecyclePhaseListeners(); iterator.hasNext();)
 1032  
         {
 1033  0
             String listenerClassName = (String) iterator.next();
 1034  
             try
 1035  
             {
 1036  0
                 lifecycle.addPhaseListener((PhaseListener) ClassUtils.newInstance(listenerClassName));
 1037  
             }
 1038  0
             catch (ClassCastException e)
 1039  
             {
 1040  0
                 log.error("Class " + listenerClassName + " does not implement PhaseListener");
 1041  0
             }
 1042  0
         }
 1043  0
     }
 1044  
 
 1045  
     private String getLifecycleId()
 1046  
     {
 1047  0
         String id = _externalContext.getInitParameter(FacesServlet.LIFECYCLE_ID_ATTR);
 1048  
 
 1049  0
         if (id != null)
 1050  
         {
 1051  0
             return id;
 1052  
         }
 1053  
 
 1054  0
         return LifecycleFactory.DEFAULT_LIFECYCLE;
 1055  
     }
 1056  
 /*
 1057  
     public static class VersionInfo
 1058  
     {
 1059  
         private String artifactId;
 1060  
         private List<JarInfo> jarInfos;
 1061  
 
 1062  
         public VersionInfo(String artifactId)
 1063  
         {
 1064  
             this.artifactId = artifactId;
 1065  
         }
 1066  
 
 1067  
         public String getArtifactId()
 1068  
         {
 1069  
             return packageName;
 1070  
         }
 1071  
 
 1072  
         public void addJarInfo(Matcher matcher)
 1073  
         {
 1074  
             if (jarInfos == null)
 1075  
             {
 1076  
                 jarInfos = new ArrayList<JarInfo>();
 1077  
             }
 1078  
             
 1079  
             String path = matcher.group(1);
 1080  
             
 1081  
             Version version = new Version(matcher.group(3), matcher.group(5), 
 1082  
                                           matcher.group(7), matcher.group(9),
 1083  
                                           matcher.group(10));
 1084  
 
 1085  
             jarInfos.add(new JarInfo(path, version));
 1086  
         }
 1087  
 
 1088  
         public String getLastVersion()
 1089  
         {
 1090  
             if (jarInfos == null)
 1091  
                 return null;
 1092  
             if (jarInfos.size() == 0)
 1093  
                 return null;
 1094  
 
 1095  
             return "";
 1096  
             //return jarInfos.get(jarInfos.size() - 1).getVersion();
 1097  
         }
 1098  
 
 1099  
         /**
 1100  
          * Probably, the first encountered version will be used.
 1101  
          * 
 1102  
          * @return probably used version
 1103  
          *
 1104  
         public String getUsedVersion()
 1105  
         {
 1106  
 
 1107  
             if (jarInfos == null)
 1108  
                 return null;
 1109  
             if (jarInfos.size() == 0)
 1110  
                 return null;
 1111  
             return "";
 1112  
             //return jarInfos.get(0).getVersion();
 1113  
         }
 1114  
 
 1115  
         /**
 1116  
          * Probably, the first encountered version will be used.
 1117  
          * 
 1118  
          * @return probably used classpath
 1119  
          *
 1120  
         public String getUsedVersionPath()
 1121  
         {
 1122  
 
 1123  
             if (jarInfos == null)
 1124  
                 return null;
 1125  
             if (jarInfos.size() == 0)
 1126  
                 return null;
 1127  
 
 1128  
             return jarInfos.get(0).getUrl();
 1129  
 
 1130  
         }
 1131  
     }
 1132  
 */
 1133  0
     private static class JarInfo implements Comparable<JarInfo>
 1134  
     {
 1135  
         private String url;
 1136  
         private Version version;
 1137  
 
 1138  
         public JarInfo(String url, Version version)
 1139  0
         {
 1140  0
             this.url = url;
 1141  0
             this.version = version;
 1142  0
         }
 1143  
 
 1144  
         public Version getVersion()
 1145  
         {
 1146  0
             return version;
 1147  
         }
 1148  
 
 1149  
         public String getUrl()
 1150  
         {
 1151  0
             return url;
 1152  
         }
 1153  
 
 1154  
         public int compareTo(JarInfo info)
 1155  
         {
 1156  0
             return version.compareTo(info.version);
 1157  
         }
 1158  
         
 1159  
         @Override
 1160  
         public boolean equals(Object o)
 1161  
         {
 1162  0
             if (o == this)
 1163  
             {
 1164  0
                 return true;
 1165  
             }
 1166  0
             else if (o instanceof JarInfo)
 1167  
             {
 1168  0
                 JarInfo other = (JarInfo)o;
 1169  0
                 return version.equals(other.version);
 1170  
             }
 1171  
             else
 1172  
             {
 1173  0
                 return false;
 1174  
             }
 1175  
         }
 1176  
         
 1177  
         @Override
 1178  
         public int hashCode()
 1179  
         {
 1180  0
             return version.hashCode();
 1181  
         }
 1182  
     }
 1183  
     
 1184  0
     static class Version implements Comparable<Version>
 1185  
     {
 1186  
         // we have to use Long here, because the version number
 1187  
         // could be something like 20060714150240 and this value
 1188  
         // exceeds an Integer (see MYFACES-2686)
 1189  
         private Long[] parts;
 1190  
         
 1191  
         private boolean snapshot;
 1192  
         
 1193  
         public Version(String major, String minor, String maintenance,
 1194  
                        String extra, String snapshot)
 1195  0
         {
 1196  0
             parts = new Long[4];
 1197  0
             parts[0] = Long.valueOf(major);
 1198  
             
 1199  0
             if (minor != null)
 1200  
             {
 1201  0
                 parts[1] = Long.valueOf(minor);
 1202  
                 
 1203  0
                 if (maintenance != null)
 1204  
                 {
 1205  0
                     parts[2] = Long.valueOf(maintenance);
 1206  
                     
 1207  0
                     if (extra != null)
 1208  
                     {
 1209  0
                         parts[3] = Long.valueOf(extra);
 1210  
                     }
 1211  
                 }
 1212  
             }
 1213  
             
 1214  0
             this.snapshot = snapshot != null;
 1215  0
         }
 1216  
 
 1217  
         public int compareTo(Version v)
 1218  
         {
 1219  0
             for (int i = 0; i < parts.length; i++)
 1220  
             {
 1221  0
                 Long left = parts[i];
 1222  0
                 Long right = v.parts[i];
 1223  0
                 if (left == null)
 1224  
                 {
 1225  0
                     if (right == null)
 1226  
                     {
 1227  0
                         break;
 1228  
                     }
 1229  
                     else
 1230  
                     {
 1231  0
                         return -1;
 1232  
                     }
 1233  
                 }
 1234  
                 else
 1235  
                 {
 1236  0
                     if (right == null)
 1237  
                     {
 1238  0
                         return 1;
 1239  
                     }
 1240  0
                     else if (left < right)
 1241  
                     {
 1242  0
                         return -1;
 1243  
                     }
 1244  0
                     else if (left > right)
 1245  
                     {
 1246  0
                         return 1;
 1247  
                     }
 1248  
                 }
 1249  
             }
 1250  
             
 1251  0
             if (snapshot)
 1252  
             {
 1253  0
                 return v.snapshot ? 0 : -1;
 1254  
             }
 1255  
             else
 1256  
             {
 1257  0
                 return v.snapshot ? 1 : 0;
 1258  
             }
 1259  
         }
 1260  
         
 1261  
         @Override
 1262  
         public boolean equals(Object o)
 1263  
         {
 1264  0
             if (o == this)
 1265  
             {
 1266  0
                 return true;
 1267  
             }
 1268  0
             else if (o instanceof Version)
 1269  
             {
 1270  0
                 Version other = (Version)o;
 1271  0
                 if (snapshot != other.snapshot)
 1272  
                 {
 1273  0
                     return false;
 1274  
                 }
 1275  
                 
 1276  0
                 for (int i = 0; i < parts.length; i++)
 1277  
                 {
 1278  0
                     Long thisPart = parts[i];
 1279  0
                     Long otherPart = other.parts[i];
 1280  0
                     if (thisPart == null ? otherPart != null : !thisPart.equals(otherPart))
 1281  
                     {
 1282  0
                         return false;
 1283  
                     }
 1284  
                 }
 1285  
 
 1286  0
                 return true;
 1287  
             }
 1288  
             else
 1289  
             {
 1290  0
                 return false;
 1291  
             }
 1292  
         }
 1293  
         
 1294  
         @Override
 1295  
         public int hashCode()
 1296  
         {
 1297  0
             int hash = 0;
 1298  0
             for (int i = 0; i < parts.length; i++)
 1299  
             {
 1300  0
                 if (parts[i] != null)
 1301  
                 {
 1302  0
                     hash ^= parts[i].hashCode();
 1303  
                 }
 1304  
             }
 1305  
             
 1306  0
             hash ^= Boolean.valueOf(snapshot).hashCode();
 1307  
             
 1308  0
             return hash;
 1309  
         }
 1310  
         
 1311  
         @Override
 1312  
         public String toString()
 1313  
         {
 1314  0
             StringBuilder builder = new StringBuilder();
 1315  0
             builder.append(parts[0]);
 1316  0
             for (int i = 1; i < parts.length; i++)
 1317  
             {
 1318  0
                 Long val = parts[i];
 1319  0
                 if (val != null)
 1320  
                 {
 1321  0
                     builder.append('.').append(val);
 1322  
                 }
 1323  
             }
 1324  
             
 1325  0
             if (snapshot)
 1326  
             {
 1327  0
                 builder.append("-SNAPSHOT");
 1328  
             }
 1329  
             
 1330  0
             return builder.toString();
 1331  
         }
 1332  
     }
 1333  
 
 1334  
     private void handleSerialFactory()
 1335  
     {
 1336  
 
 1337  0
         String serialProvider = _externalContext.getInitParameter(StateUtils.SERIAL_FACTORY);
 1338  0
         SerialFactory serialFactory = null;
 1339  
 
 1340  0
         if (serialProvider == null)
 1341  
         {
 1342  0
             serialFactory = new DefaultSerialFactory();
 1343  
         }
 1344  
         else
 1345  
         {
 1346  
             try
 1347  
             {
 1348  0
                 serialFactory = (SerialFactory) ClassUtils.newInstance(serialProvider);
 1349  
 
 1350  
             }
 1351  0
             catch (ClassCastException e)
 1352  
             {
 1353  0
                 log.error("Make sure '" + serialProvider + "' implements the correct interface", e);
 1354  
             }
 1355  0
             catch (Exception e)
 1356  
             {
 1357  0
                 log.error(e);
 1358  
             }
 1359  
             finally
 1360  
             {
 1361  0
                 if (serialFactory == null)
 1362  
                 {
 1363  0
                     serialFactory = new DefaultSerialFactory();
 1364  0
                     log.error("Using default serialization provider");
 1365  
                 }
 1366  
             }
 1367  
 
 1368  
         }
 1369  
 
 1370  0
         log.info("Serialization provider : " + serialFactory.getClass());
 1371  0
         _externalContext.getApplicationMap().put(StateUtils.SERIAL_FACTORY, serialFactory);
 1372  
 
 1373  0
     }
 1374  
 
 1375  
 }