View Javadoc
1   /*
2    * Copyright (c) 2002-2017, Mairie de Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  /*
35   * The Apache Software License, Version 1.1
36   *
37   * Copyright (c) 2003 The Apache Software Foundation.  All rights
38   * reserved.
39   *
40   * Redistribution and use in source and binary forms, with or without
41   * modification, are permitted provided that the following conditions
42   * are met:
43   *
44   * 1. Redistributions of source code must retain the above copyright
45   *    notice, this list of conditions and the following disclaimer.
46   *
47   * 2. Redistributions in binary form must reproduce the above copyright
48   *    notice, this list of conditions and the following disclaimer in
49   *    the documentation and/or other materials provided with the
50   *    distribution.
51   *
52   * 3. The end-user documentation included with the redistribution, if
53   *    any, must include the following acknowlegement:
54   *       "This product includes software developed by the
55   *        Apache Software Foundation (http://www.apache.org/)."
56   *    Alternately, this acknowlegement may appear in the software itself,
57   *    if and wherever such third-party acknowlegements normally appear.
58   *
59   * 4. The names "The Jakarta Project", "Pluto", and "Apache Software
60   *    Foundation" must not be used to endorse or promote products derived
61   *    from this software without prior written permission. For written
62   *    permission, please contact apache@apache.org.
63   *
64   * 5. Products derived from this software may not be called "Apache"
65   *    nor may "Apache" appear in their names without prior written
66   *    permission of the Apache Group.
67   *
68   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
69   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
70   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
71   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
72   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
73   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
74   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
75   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
76   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
77   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
78   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
79   * SUCH DAMAGE.
80   * ====================================================================
81   *
82   * This software consists of voluntary contributions made by many
83   * individuals on behalf of the Apache Software Foundation.  For more
84   * information on the Apache Software Foundation, please see
85   * <http://www.apache.org/>.
86   */
87  package fr.paris.lutece.plugins.jsr168.pluto.services.factorymanager;
88  
89  import fr.paris.lutece.portal.service.util.AppLogService;
90  
91  import org.apache.pluto.factory.Factory;
92  import org.apache.pluto.portalImpl.services.factorymanager.FactoryManagerService;
93  import org.apache.pluto.portalImpl.util.Properties;
94  import org.apache.pluto.util.StringUtils;
95  
96  import java.util.HashMap;
97  import java.util.Iterator;
98  import java.util.LinkedList;
99  import java.util.List;
100 import java.util.Map;
101 
102 import javax.servlet.ServletConfig;
103 
104 
105 /**
106  * Manages the life-time of factories registered during container startup.
107  * A service has to derive from {@link Factory} and implement the
108  * <CODE>init()</CODE> and <CODE>destroy()</CODE> methods as appropriate.
109  *
110  * @see Factory
111  */
112 public class FactoryManagerServiceImpl extends FactoryManagerService implements org.apache.pluto.services.factory.FactoryManagerService
113 {
114     private Map _mapFactory = new HashMap(  );
115     private List _lstFactory = new LinkedList(  );
116 
117     /**
118      * Initializes all factories specified in the configuration beginning with 'factory.'.
119      * By specifying a different implementation of the factory the behaviour
120      * of the portlet container can be modified.
121      *
122      * @param config
123      *          the servlet configuration
124      * @param aProperties Defined properties for the factory manager
125      * @exception    Exception
126      *               if initializing any of the factories fails
127      */
128     public void init( ServletConfig config, Properties aProperties )
129         throws Exception
130     {
131         logInfo( "FactoryManager: Loading factories..." );
132 
133         final Map factoryImpls = new HashMap(  );
134         final Map factoryProps = new HashMap(  );
135         final Iterator configNames = aProperties.keys(  );
136         String lastFactoryInterfaceName = null;
137 
138         while ( configNames.hasNext(  ) )
139         {
140             final String configName = (String) configNames.next(  );
141 
142             // NOTE: it's not clean!
143             // Properties must appear after definition of classes in the XML config file.  
144             if ( ( lastFactoryInterfaceName != null ) && configName.startsWith( lastFactoryInterfaceName + "." ) )
145             {
146                 String propertyName = configName.substring( lastFactoryInterfaceName.length(  ) + 1 );
147                 String propertyValue = aProperties.getString( configName );
148                 Map properties = (Map) factoryProps.get( lastFactoryInterfaceName );
149                 properties.put( propertyName, propertyValue );
150             }
151             else
152             {
153                 String factoryInterfaceName = configName;
154                 String factoryImplName = aProperties.getString( configName );
155                 factoryImpls.put( factoryInterfaceName, factoryImplName );
156                 factoryProps.put( factoryInterfaceName, new HashMap(  ) );
157 
158                 // remember interface name to get all properties
159                 lastFactoryInterfaceName = factoryInterfaceName;
160             }
161         }
162 
163         int numAll = 0;
164 
165         for ( Iterator iter = factoryImpls.entrySet(  ).iterator(  ); iter.hasNext(  ); )
166         {
167             Map.Entry implEntry = (Map.Entry) iter.next(  );
168             String factoryInterfaceName = (String) implEntry.getKey(  );
169             String factoryImplName = (String) implEntry.getValue(  );
170 
171             ++numAll;
172 
173             // try to get hold of the factory
174             final Class factoryInterface;
175 
176             try
177             {
178                 factoryInterface = Class.forName( factoryInterfaceName );
179             }
180             catch ( ClassNotFoundException e )
181             {
182                 logError( "FactoryManager: A factory with name " + factoryInterfaceName + " cannot be found.", e );
183 
184                 continue;
185             }
186 
187             try
188             {
189                 Class factoryImpl = Class.forName( factoryImplName );
190                 Factory factory = (Factory) factoryImpl.newInstance(  );
191                 Map props = (Map) factoryProps.get( factoryInterfaceName );
192 
193                 logInfo( StringUtils.nameOf( factoryInterface ) + " initializing..." );
194                 factory.init( config, props );
195                 logInfo( StringUtils.nameOf( factoryInterface ) + " done." );
196 
197                 _mapFactory.put( factoryInterface, factory );
198 
199                 // build up list in reverse order for later destruction
200                 _lstFactory.add( 0, factory );
201             }
202             catch ( ClassNotFoundException e )
203             {
204                 logError( "FactoryManager: A factory implementation with name " + factoryImplName +
205                     " cannot be found.", e );
206                 throw e;
207             }
208             catch ( ClassCastException e )
209             {
210                 logError( "FactoryManager: Factory implementation " + factoryImplName +
211                     " is not a factory of the required type.", e );
212                 throw e;
213             }
214             catch ( InstantiationException e )
215             {
216                 logError( "FactoryManager: Factory implementation " + factoryImplName + " cannot be instantiated.", e );
217                 throw e;
218             }
219             catch ( Exception e )
220             {
221                 logError( "FactoryManager: An unidentified error occurred", e );
222                 throw e;
223             }
224         }
225 
226         logInfo( "FactoryManager: Factories initialized (" + numAll + " successful)." );
227     }
228 
229     /**
230      ** Destroys all services.
231      **
232      ** @param   config
233      **          the servlet configuration
234      **/
235     public void destroy( ServletConfig config )
236     {
237         // destroy the services in reverse order
238         for ( Iterator iterator = _lstFactory.iterator(  ); iterator.hasNext(  ); )
239         {
240             Factory factory = (Factory) iterator.next(  );
241 
242             try
243             {
244                 factory.destroy(  );
245             }
246             catch ( Exception e )
247             {
248                 logError( "FactoryManager: Factory couldn't be destroyed.", e );
249             }
250         }
251 
252         _mapFactory.clear(  );
253         _lstFactory.clear(  );
254     }
255 
256     /**
257      ** Returns the service implementation for the given service class, or
258      ** <code>null</code> if no such service is registered.
259      **
260      ** @param   theClass
261      **          the service class
262      **
263      ** @return   the service implementation
264      **/
265     public Factory getFactory( Class theClass )
266     {
267         // at this state the services map is read-only,
268         // therefore we can go without synchronization
269         return ( (Factory) _mapFactory.get( theClass ) );
270     }
271 
272     /**
273      * Log <code>strMessage</code> as info
274      *
275      * @param strMessage The message to log
276      */
277     private void logInfo( String strMessage )
278     {
279         AppLogService.info( strMessage );
280     }
281 
282     /**
283      * Log <code>message</code> as error
284      *
285      * @param message The message to log
286      * @param t The cause exception
287      */
288     private void logError( Object message, Throwable t )
289     {
290         AppLogService.error( message, t );
291     }
292 }