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.spi;
20
21 import javax.faces.FacesException;
22 import javax.faces.context.ExternalContext;
23 import javax.servlet.ServletContext;
24
25 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
26 import org.apache.myfaces.shared.util.ClassUtils;
27 import org.apache.myfaces.spi.impl.DefaultServiceProviderFinder;
28
29 /**
30 * Factory that provide a ServiceProviderFinder instance, that is used to locate
31 * classes through SPI interface.
32 *
33 * @author Leonardo Uribe
34 * @since 2.0.3
35 *
36 */
37 public class ServiceProviderFinderFactory
38 {
39
40 private final static String SERVICE_PROVIDER_KEY = "org.apache.myfaces.spi.ServiceProviderFinder";
41
42 /**
43 * Define the class name of a custom ServiceProviderFinder implementation.
44 *
45 * <p>This class is used to override the default SPI scanning algorithm, that relies on the thread
46 * context class loader to locate entries under META-INF/services folder.
47 * </p>
48 */
49 @JSFWebConfigParam(since = "2.0.3", desc = "Class name of a custom ServiceProviderFinder implementation.")
50 private static final String SERVICE_PROVIDER_FINDER_PARAM = "org.apache.myfaces.SERVICE_PROVIDER_FINDER";
51
52
53 /**
54 *
55 * @param ectx
56 * @return
57 */
58 public static ServiceProviderFinder getServiceProviderFinder(ExternalContext ectx)
59 {
60 ServiceProviderFinder slp = (ServiceProviderFinder) ectx.getApplicationMap().get(SERVICE_PROVIDER_KEY);
61 if (slp == null)
62 {
63 slp = _getServiceProviderFinderFromInitParam(ectx);
64
65 if (slp == null)
66 {
67 slp = new DefaultServiceProviderFinder();
68 }
69
70 // cache on ApplicationMap
71 setServiceProviderFinder(ectx, slp);
72 }
73 return slp;
74 }
75
76
77 /**
78 * Set a ServiceProviderFinder to the current application, to locate
79 * SPI service providers used by MyFaces.
80 *
81 * This method should be called before the web application is initialized,
82 * specifically before AbstractFacesInitializer.initFaces(ServletContext)
83 * otherwise it will have no effect.
84 *
85 * @param ectx
86 * @param slp
87 */
88 public static void setServiceProviderFinder(ExternalContext ectx, ServiceProviderFinder slp)
89 {
90 ectx.getApplicationMap().put(SERVICE_PROVIDER_KEY, slp);
91 }
92
93 public static void setServiceProviderFinder(ServletContext ctx, ServiceProviderFinder slp)
94 {
95 ctx.setAttribute(SERVICE_PROVIDER_KEY, slp);
96 }
97
98 /**
99 * Gets a ServiceProviderFinder from the web.xml config param.
100 * @param context
101 * @return
102 */
103 private static ServiceProviderFinder _getServiceProviderFinderFromInitParam(ExternalContext context)
104 {
105 String initializerClassName = context.getInitParameter(SERVICE_PROVIDER_FINDER_PARAM);
106 if (initializerClassName != null)
107 {
108 try
109 {
110 // get Class object
111 Class<?> clazz = ClassUtils.classForName(initializerClassName);
112 if (!ServiceProviderFinder.class.isAssignableFrom(clazz))
113 {
114 throw new FacesException("Class " + clazz
115 + " does not implement ServiceProviderFinder");
116 }
117
118 // create instance and return it
119 return (ServiceProviderFinder) ClassUtils.newInstance(clazz);
120 }
121 catch (ClassNotFoundException cnfe)
122 {
123 throw new FacesException("Could not find class of specified ServiceProviderFinder", cnfe);
124 }
125 }
126 return null;
127 }
128
129 }