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 }