001package org.apache.turbine.services.avaloncomponent;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.File;
023import java.io.IOException;
024
025import org.apache.avalon.framework.activity.Disposable;
026import org.apache.avalon.framework.activity.Initializable;
027import org.apache.avalon.framework.logger.CommonsLogger;
028import org.apache.avalon.framework.logger.Logger;
029import org.apache.avalon.framework.service.ServiceException;
030import org.apache.commons.configuration.Configuration;
031import org.apache.commons.logging.Log;
032import org.apache.commons.logging.LogFactory;
033import org.apache.fulcrum.yaafi.framework.container.ServiceContainer;
034import org.apache.fulcrum.yaafi.framework.factory.ServiceContainerConfiguration;
035import org.apache.fulcrum.yaafi.framework.factory.ServiceContainerFactory;
036import org.apache.turbine.Turbine;
037import org.apache.turbine.services.InitializationException;
038import org.apache.turbine.services.InstantiationException;
039import org.apache.turbine.services.TurbineBaseService;
040
041/**
042 * An implementation of Turbine service initializing the YAAFI container
043 *
044 * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
045 */
046public class TurbineYaafiComponentService
047        extends TurbineBaseService
048        implements AvalonComponentService, Initializable, Disposable
049{
050    /** the logger to be used */
051    private static Log log = LogFactory.getLog(AVALON_LOG_CATEGORY);
052
053    /** property to lookup the container configuration file */
054    public static final String CONTAINER_CONFIGURATION_KEY = "containerConfiguration";
055
056    /** the default value for the container configuration file */
057    public static final String CONTAINER_CONFIGURATION_VALUE = "/WEB-INF/conf/containerConfiguration.xml";
058
059    /** property to lookup the properties file */
060    public static final String COMPONENT_PARAMETERS_KEY = "parameters";
061
062    /** the default value for the parameter file */
063    public static final String COMPONENT_PARAMETERS_VALUE = "/WEB-INF/conf/parameters.properties";
064
065    /** YAFFI container */
066    private ServiceContainer container;
067
068    /**
069     * Load all configured components and initialize them. This is a zero parameter variant which
070     * queries the Turbine Servlet for its config.
071     *
072     * @throws InitializationException Something went wrong in the init stage
073     */
074    @Override
075    public void init() throws InitializationException
076    {
077        try
078        {
079            log.info( "Initializing TurbineYaafiComponentService ..." );
080            initialize();
081            setInit(true);
082        }
083        catch (Exception e)
084        {
085            log.error("Exception caught initialising service: ", e);
086            throw new InitializationException("Initializing TurbineYaafiComponentService failed", e);
087        }
088    }
089
090    /**
091     * Shuts the Component Service down, calls dispose on the components that implement this
092     * interface
093     *
094     */
095    @Override
096    public void shutdown()
097    {
098        log.info( "Disposing TurbineYaafiComponentService ..." );
099        dispose();
100        setInit(false);
101    }
102
103    // -------------------------------------------------------------
104    // Avalon lifecycle interfaces
105    // -------------------------------------------------------------
106
107    /**
108     * Initializes the container
109     *
110     * @throws Exception generic exception
111     */
112    @Override
113    public void initialize() throws Exception
114    {
115        // get the configuration from the baseclass
116
117        Configuration conf = this.getConfiguration();
118
119        // determine the home directory
120        String homePath = Turbine.getRealPath("/");
121        if (homePath == null)
122        {
123            homePath = Turbine.getApplicationRoot();
124        }
125        File home = new File(homePath);
126        log.info("Using the following home : " + home.getAbsolutePath());
127
128        // create the configuration for YAAFI
129        ServiceContainerConfiguration config =
130            this.createServiceContainerConfiguration(conf, home);
131
132        // initialize the container
133        try
134        {
135            this.container = ServiceContainerFactory.create(
136                config
137                );
138        }
139        catch (Exception e)
140        {
141            String msg = "Initializing YAAFI failed";
142            log.error(msg,e);
143            throw e;
144        }
145    }
146
147    /**
148     * Disposes of the container and releases resources
149     */
150    @Override
151    public void dispose()
152    {
153        if (this.container != null)
154        {
155            this.container.dispose();
156            this.container = null;
157        }
158    }
159
160    /**
161     * Returns an instance of the named component
162     *
163     * @param roleName Name of the role the component fills.
164     * @return an instance of the named component
165     */
166    @Override
167    public Object lookup(String roleName) throws ServiceException
168    {
169        return this.container.lookup(roleName);
170    }
171
172    /**
173     * Releases the component.
174     *
175     * @param component the component to release
176     */
177    @Override
178    public void release(Object component)
179    {
180        this.container.release( component );
181    }
182
183    /**
184     * @see org.apache.avalon.framework.service.ServiceManager#hasService(java.lang.String)
185     */
186    @Override
187    public boolean hasService(String roleName)
188    {
189        return this.container.hasService(roleName);
190    }
191
192    /**
193     * Create a ServiceContainerConfiguration based on the Turbine configuration
194     *
195     * @param conf the Turbine configuration
196     * @param applicationRoot the application root directory
197     *
198     * @return the YAAFI configuration
199     * @throws IOException creating the YAAFI configuration failed
200     */
201    protected ServiceContainerConfiguration createServiceContainerConfiguration( Configuration conf, File applicationRoot )
202        throws IOException
203    {
204        ServiceContainerConfiguration result = new ServiceContainerConfiguration();
205
206        result.setApplicationRootDir(applicationRoot.getAbsolutePath());
207        result.setLogger( this.createAvalonLogger() );
208
209        // are we using a "containerConfiguration.xml" ?!
210
211        if( conf.containsKey(CONTAINER_CONFIGURATION_KEY) )
212        {
213            // determine the container configuration file
214
215            String containerConfiguration = conf.getString(
216                CONTAINER_CONFIGURATION_KEY
217                );
218
219            result.loadContainerConfiguration(containerConfiguration);
220        }
221        else if( conf.containsKey(COMPONENT_ROLE_KEY) )
222        {
223            // determine the location of the role configuraton file
224
225            String roleConfigurationFileName = conf.getString(
226                COMPONENT_ROLE_KEY,
227                COMPONENT_ROLE_VALUE
228                );
229
230            // determine the location of component configuration file
231
232            String componentConfigurationFileName = conf.getString(
233                COMPONENT_CONFIG_KEY,
234                COMPONENT_CONFIG_VALUE
235                );
236
237            // determine the location of parameters file
238
239            String parametersFileName = conf.getString(
240                COMPONENT_PARAMETERS_KEY,
241                COMPONENT_PARAMETERS_VALUE
242                );
243
244            result.setComponentRolesLocation( roleConfigurationFileName );
245            result.setComponentConfigurationLocation( componentConfigurationFileName );
246            result.setParametersLocation( parametersFileName );
247        }
248        else
249        {
250            // determine the container configuration file
251
252            String containerConfiguration = conf.getString(
253                CONTAINER_CONFIGURATION_KEY,
254                CONTAINER_CONFIGURATION_VALUE
255                );
256
257            result.loadContainerConfiguration(containerConfiguration);
258        }
259
260        return result;
261    }
262
263    /**
264     * Create the Avalon logger to be passed to YAAFI
265     * @return an Avalon Logger
266     */
267    protected Logger createAvalonLogger()
268    {
269        Logger result = new CommonsLogger(log, AVALON_LOG_CATEGORY);
270        return result;
271    }
272
273    // -------------------------------------------------------------
274    // TurbineServiceProvider
275    // -------------------------------------------------------------
276
277    /**
278     * @see org.apache.turbine.services.TurbineServiceProvider#exists(java.lang.String)
279     */
280    @Override
281    public boolean exists(String roleName)
282    {
283        return this.hasService(roleName);
284    }
285
286    /**
287     * @see org.apache.turbine.services.TurbineServiceProvider#get(java.lang.String)
288     */
289    @Override
290    public Object get(String roleName) throws InstantiationException
291    {
292        try
293        {
294            return this.lookup(roleName);
295        }
296        catch (ServiceException e)
297        {
298            String msg = "Unable to get the following service : " + roleName;
299            log.error(msg);
300            throw new InstantiationException(msg);
301        }
302        catch (Throwable t)
303        {
304            String msg = "Unable to get the following service : " + roleName;
305            log.error(msg,t);
306            throw new InstantiationException(msg,t);
307        }
308    }
309}