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.Logger;
028import org.apache.avalon.framework.service.ServiceException;
029import org.apache.commons.configuration2.Configuration;
030import org.apache.fulcrum.yaafi.framework.container.ServiceContainer;
031import org.apache.fulcrum.yaafi.framework.factory.ServiceContainerConfiguration;
032import org.apache.fulcrum.yaafi.framework.factory.ServiceContainerFactory;
033import org.apache.fulcrum.yaafi.framework.logger.Log4j2Logger;
034import org.apache.logging.log4j.LogManager;
035import org.apache.turbine.services.InitializationException;
036import org.apache.turbine.services.InstantiationException;
037import org.apache.turbine.services.TurbineBaseService;
038
039/**
040 * An implementation of Turbine service initializing the YAAFI container
041 *
042 * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
043 */
044public class TurbineYaafiComponentService
045        extends TurbineBaseService
046        implements AvalonComponentService, Initializable, Disposable
047{
048    /** the logger to be used */
049    private static org.apache.logging.log4j.Logger log = LogManager.getLogger(AVALON_LOG_CATEGORY);
050
051    /** property to lookup the container configuration file */
052    public static final String CONTAINER_CONFIGURATION_KEY = "containerConfiguration";
053
054    /** the default value for the container configuration file */
055    public static final String CONTAINER_CONFIGURATION_VALUE = "/WEB-INF/conf/containerConfiguration.xml";
056
057    /** property to lookup the properties file */
058    public static final String COMPONENT_PARAMETERS_KEY = "parameters";
059
060    /** the default value for the parameter file */
061    public static final String COMPONENT_PARAMETERS_VALUE = "/WEB-INF/conf/parameters.properties";
062
063    /** YAFFI container */
064    private ServiceContainer container;
065
066    /**
067     * Load all configured components and initialize them. This is a zero parameter variant which
068     * queries the Turbine Servlet for its config.
069     *
070     * @throws InitializationException Something went wrong in the init stage
071     */
072    @Override
073    public void init() throws InitializationException
074    {
075        try
076        {
077            log.info( "Initializing TurbineYaafiComponentService ..." );
078            initialize();
079            setInit(true);
080        }
081        catch (Exception e)
082        {
083            log.error("Exception caught initialising service: ", e);
084            throw new InitializationException("Initializing TurbineYaafiComponentService failed", e);
085        }
086    }
087
088    /**
089     * Shuts the Component Service down, calls dispose on the components that implement this
090     * interface
091     *
092     */
093    @Override
094    public void shutdown()
095    {
096        log.info( "Disposing TurbineYaafiComponentService ..." );
097        dispose();
098        setInit(false);
099    }
100
101    // -------------------------------------------------------------
102    // Avalon lifecycle interfaces
103    // -------------------------------------------------------------
104
105    /**
106     * Initializes the container
107     *
108     * @throws Exception generic exception
109     */
110    @Override
111    public void initialize() throws Exception
112    {
113        // get the configuration from the baseclass
114        Configuration conf = this.getConfiguration();
115
116        // determine the home directory
117        File home = new File(getServiceBroker().getApplicationRoot());
118        log.info("Using the following home : {}", home::getAbsolutePath);
119
120        // create the configuration for YAAFI
121        ServiceContainerConfiguration config =
122            this.createServiceContainerConfiguration(conf, home);
123
124        // initialize the container
125        try
126        {
127            this.container = ServiceContainerFactory.create(
128                config
129                );
130            //this.container .service( manager );
131        }
132        catch (Exception e)
133        {
134            log.error("Initializing YAAFI failed", e);
135            throw e;
136        }
137    }
138
139    /**
140     * Disposes of the container and releases resources
141     */
142    @Override
143    public void dispose()
144    {
145        if (this.container != null)
146        {
147            this.container.dispose();
148            this.container = null;
149        }
150    }
151
152    /**
153     * Returns an instance of the named component
154     *
155     * @param roleName Name of the role the component fills.
156     * @return an instance of the named component
157     */
158    @Override
159    public Object lookup(String roleName) throws ServiceException
160    {
161        return this.container.lookup(roleName);
162    }
163
164    /**
165     * Releases the component.
166     *
167     * @param component the component to release
168     */
169    @Override
170    public void release(Object component)
171    {
172        this.container.release( component );
173    }
174
175    /**
176     * @see org.apache.avalon.framework.service.ServiceManager#hasService(java.lang.String)
177     */
178    @Override
179    public boolean hasService(String roleName)
180    {
181        return this.container.hasService(roleName);
182    }
183
184    /**
185     * Create a ServiceContainerConfiguration based on the Turbine configuration
186     *
187     * @param conf the Turbine configuration
188     * @param applicationRoot the application root directory
189     *
190     * @return the YAAFI configuration
191     * @throws IOException creating the YAAFI configuration failed
192     */
193    protected ServiceContainerConfiguration createServiceContainerConfiguration( Configuration conf, File applicationRoot )
194        throws IOException
195    {
196        ServiceContainerConfiguration result = new ServiceContainerConfiguration();
197
198        result.setApplicationRootDir(applicationRoot.getAbsolutePath());
199        result.setLogger( this.createAvalonLogger() );
200
201        // are we using a "containerConfiguration.xml" ?!
202
203        if( conf.containsKey(CONTAINER_CONFIGURATION_KEY) )
204        {
205            // determine the container configuration file
206
207            String containerConfiguration = conf.getString(
208                CONTAINER_CONFIGURATION_KEY
209                );
210
211            result.loadContainerConfiguration(containerConfiguration);
212        }
213        else if( conf.containsKey(COMPONENT_ROLE_KEY) )
214        {
215            // determine the location of the role configuraton file
216
217            String roleConfigurationFileName = conf.getString(
218                COMPONENT_ROLE_KEY,
219                COMPONENT_ROLE_VALUE
220                );
221
222            // determine the location of component configuration file
223
224            String componentConfigurationFileName = conf.getString(
225                COMPONENT_CONFIG_KEY,
226                COMPONENT_CONFIG_VALUE
227                );
228
229            // determine the location of parameters file
230
231            String parametersFileName = conf.getString(
232                COMPONENT_PARAMETERS_KEY,
233                COMPONENT_PARAMETERS_VALUE
234                );
235
236            result.setComponentRolesLocation( roleConfigurationFileName );
237            result.setComponentConfigurationLocation( componentConfigurationFileName );
238            result.setParametersLocation( parametersFileName );
239        }
240        else
241        {
242            // determine the container configuration file
243
244            String containerConfiguration = conf.getString(
245                CONTAINER_CONFIGURATION_KEY,
246                CONTAINER_CONFIGURATION_VALUE
247                );
248
249            result.loadContainerConfiguration(containerConfiguration);
250        }
251
252        return result;
253    }
254
255    /**
256     * Create the Avalon logger to be passed to YAAFI.
257     * @return an Avalon Logger
258     */
259    protected Logger createAvalonLogger()
260    {
261        return new Log4j2Logger(log);
262    }
263
264    // -------------------------------------------------------------
265    // TurbineServiceProvider
266    // -------------------------------------------------------------
267
268    /**
269     * @see org.apache.turbine.services.TurbineServiceProvider#exists(java.lang.String)
270     */
271    @Override
272    public boolean exists(String roleName)
273    {
274        return this.hasService(roleName);
275    }
276
277    /**
278     * @see org.apache.turbine.services.TurbineServiceProvider#get(java.lang.String)
279     */
280    @Override
281    public Object get(String roleName) throws InstantiationException
282    {
283        try
284        {
285            return this.lookup(roleName);
286        }
287        catch (Throwable t)
288        {
289            String msg = "Unable to get the following service : " + roleName;
290            log.error(msg,t);
291            throw new InstantiationException(msg,t);
292        }
293    }
294}