001package org.apache.fulcrum.yaafi.framework.component;
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 org.apache.avalon.framework.configuration.Configuration;
023import org.apache.avalon.framework.configuration.ConfigurationException;
024import org.apache.avalon.framework.context.Context;
025import org.apache.avalon.framework.logger.Logger;
026import org.apache.avalon.framework.parameters.Parameters;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.apache.fulcrum.yaafi.framework.role.RoleEntry;
029import org.apache.fulcrum.yaafi.framework.util.ToStringBuilder;
030import org.apache.fulcrum.yaafi.framework.util.Validate;
031
032/**
033 * This class implements am abstract base service component singleton with
034 * an arbitrary lifecycle.
035 *
036 * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
037 */
038
039public abstract class ServiceComponentImpl
040    implements ServiceComponent
041{
042    /** the information from the role configuration file */
043    private RoleEntry roleEntry;
044
045    /** the actual implementation class of the service component */
046    private Class<?> implementationClazz;
047
048    /** the instance of the implementation class of the service component */
049    private Object instance;
050
051    /** the proxy of the instance if any */
052    private Object proxy;
053
054    /** the Avalon logger of the container */
055    private Logger parentLogger;
056
057    /** the Avalon logger to be passed to the service component instance */
058    private Logger logger;
059
060    /** The Avalon ServiceManager passed to the service component instance */
061    private ServiceManager serviceManager;
062
063    /** The Avalon Context passed to the service component instance */
064    private Context context;
065
066    /** The Avalon Configuration passed to the service component instance */
067    private Configuration configuration;
068
069    /** The Avalon Parameters passed to the service component instance */
070    private Parameters parameters;
071
072    /**
073     * Constructor to parse the configuration.
074     *
075     * @param roleEntry The information extracted from the role configuration file
076     * @param parentLogger the logger of the service container
077     * @param logger The logger for the service instance
078     */
079    public ServiceComponentImpl(
080        RoleEntry roleEntry, Logger parentLogger, Logger logger)
081    {
082        Validate.notNull( roleEntry, "roleEntry" );
083        Validate.notNull( parentLogger, "parentLogger" );
084        Validate.notNull( logger, "logger" );
085
086        this.roleEntry = roleEntry;
087        this.parentLogger = parentLogger;
088        this.logger = logger;
089    }
090
091    /////////////////////////////////////////////////////////////////////////
092    // Service Component Lifecycle Implementation
093    /////////////////////////////////////////////////////////////////////////
094
095    /* (non-Javadoc)
096     * @see org.apache.fulcrum.yaafi.framework.component.ServiceComponentLifecycle#loadImplemtationClass(java.lang.ClassLoader)
097     */
098    public void loadImplemtationClass(ClassLoader classLoader)
099        throws ClassNotFoundException
100    {
101        ClassLoader currClassLoader = null;
102
103        if( classLoader != null )
104        {
105            currClassLoader = classLoader;
106        }
107        else
108        {
109            currClassLoader = this.getClass().getClassLoader();
110        }
111
112        try
113        {
114            this.implementationClazz = currClassLoader.loadClass(
115                this.getRoleEntry().getImplementationClazzName()
116                );
117        }
118
119        catch(ClassNotFoundException e)
120        {
121            String msg = "Failed to load the implementation class "
122                + this.getRoleEntry().getImplementationClazzName();
123
124            this.getParentLogger().error(msg,e);
125
126            throw e;
127        }
128    }
129
130    /* (non-Javadoc)
131     * @see org.apache.fulcrum.yaafi.framework.component.ServiceComponentLifecycle#getInstance()
132     */
133    public Object getInstance()
134        throws Exception
135    {
136        if( this.isInstantiated() == false )
137        {
138            this.createInstance();
139            this.incarnateInstance();
140        }
141
142        return this.getRawInstance(true);
143    }
144
145    /* (non-Javadoc)
146     * @see org.apache.fulcrum.yaafi.framework.component.ServiceComponentLifecycle#incarnate()
147     */
148    public void incarnate() throws Exception
149    {
150        try
151        {
152            if( this.isEarlyInit() )
153            {
154                this.getInstance();
155            }
156        }
157        catch(Throwable t)
158        {
159            String msg = "Failed initialize "
160                + this.getRoleEntry().getImplementationClazzName();
161
162            throw new ConfigurationException(msg,t);
163        }
164    }
165
166    /* (non-Javadoc)
167     * @see org.apache.fulcrum.yaafi.framework.component.ServiceComponentLifecycle#reconfigure()
168     */
169    public abstract void reconfigure() throws Exception;
170
171    /* (non-Javadoc)
172     * @see org.apache.fulcrum.yaafi.framework.component.ServiceComponentLifecycle#decommision()
173     */
174    public void decommision() throws Exception
175    {
176        this.instance = null;
177        this.proxy = null;
178    }
179
180    /* (non-Javadoc)
181     * @see org.apache.fulcrum.yaafi.framework.component.ServiceComponentLifecycle#dispose()
182     */
183    public void dispose()
184    {
185        this.roleEntry = null;
186        this.implementationClazz = null;
187        this.instance = null;
188        this.proxy = null;
189        this.parentLogger = null;
190        this.logger = null;
191        this.serviceManager = null;
192        this.context = null;
193        this.configuration = null;
194        this.parameters = null;
195    }
196
197    /* (non-Javadoc)
198     * @see org.apache.fulcrum.yaafi.framework.component.ServiceComponentLifecycle#setLogger(org.apache.avalon.framework.logger.Logger)
199     */
200    public void setLogger(Logger logger)
201    {
202        this.logger = logger;
203    }
204
205    /* (non-Javadoc)
206     * @see org.apache.fulcrum.yaafi.framework.component.ServiceComponentLifecycle#setContext(org.apache.avalon.framework.context.Context)
207     */
208    public void setContext(Context context)
209    {
210        this.context = context;
211    }
212
213    /* (non-Javadoc)
214     * @see org.apache.fulcrum.yaafi.framework.component.ServiceComponentLifecycle#setServiceManager(org.apache.avalon.framework.service.ServiceManager)
215     */
216    public void setServiceManager(ServiceManager serviceManager)
217    {
218        this.serviceManager = serviceManager;
219    }
220
221    /* (non-Javadoc)
222     * @see org.apache.fulcrum.yaafi.framework.component.ServiceComponentLifecycle#setConfiguration(org.apache.avalon.framework.configuration.Configuration)
223     */
224    public void setConfiguration(Configuration configuration)
225    {
226        this.configuration = configuration;
227    }
228
229    /* (non-Javadoc)
230     * @see org.apache.fulcrum.yaafi.framework.component.ServiceComponentLifecycle#setParameters(org.apache.avalon.framework.parameters.Parameters)
231     */
232    public void setParameters(Parameters parameters)
233    {
234        this.parameters = parameters;
235    }
236
237    /////////////////////////////////////////////////////////////////////////
238    // Generated getters and setters
239    /////////////////////////////////////////////////////////////////////////
240
241    /**
242     * @return Return true if the service is created on startup
243     */
244    public boolean isEarlyInit()
245    {
246        return this.getRoleEntry().isEarlyInit();
247    }
248
249    /* (non-Javadoc)
250     * @see org.apache.fulcrum.yaafi.framework.component.ServiceComponent#getName()
251     */
252    public String getName()
253    {
254        return this.getRoleEntry().getName();
255    }
256
257    /* (non-Javadoc)
258     * @see org.apache.fulcrum.yaafi.framework.component.ServiceComponent#getRoleEntry()
259     */
260    public RoleEntry getRoleEntry()
261    {
262        return roleEntry;
263    }
264
265    /**
266     * @return Returns the logger.
267     */
268    public Logger getLogger()
269    {
270        return this.logger;
271    }
272
273    /**
274     * @return Returns the parentLogger.
275     */
276    public Logger getParentLogger()
277    {
278        return parentLogger;
279    }
280
281    /**
282     * @return Returns the implementationClazz.
283     */
284    public Class<?> getImplementationClazz()
285    {
286        return this.implementationClazz;
287    }
288
289    /**
290     * @return Returns the configuration.
291     */
292    public Configuration getConfiguration()
293    {
294        return configuration;
295    }
296
297    /**
298     * @return Returns the context.
299     */
300    public Context getContext()
301    {
302        return context;
303    }
304
305    /**
306     * @return Returns the parameters.
307     */
308    public Parameters getParamaters()
309    {
310        return parameters;
311    }
312
313    /**
314     * @return Returns the serviceManager.
315     */
316    public ServiceManager getServiceManager()
317    {
318        return serviceManager;
319    }
320
321    /**
322     * @return the shorthand of the service
323     */
324    public String getShorthand()
325    {
326        return roleEntry.getShorthand();
327    }
328
329    /////////////////////////////////////////////////////////////////////////
330    // Class implementation
331    /////////////////////////////////////////////////////////////////////////
332
333    /* (non-Javadoc)
334     * @see java.lang.Object#toString()
335     */
336    public String toString()
337    {
338        ToStringBuilder toStringBuilder = new ToStringBuilder(this);
339        toStringBuilder.append("roleEntry",this.roleEntry);
340        toStringBuilder.append("instance",this.instance);
341        toStringBuilder.append("proxy",this.proxy);
342        return toStringBuilder.toString();
343    }
344
345    /**
346     * @return Returns <b>true</b> if the service instance was already instantiated.
347     */
348    protected final boolean isInstantiated()
349    {
350        return ( this.instance != null ? true : false );
351    }
352
353    /**
354     * Create an instance of the service component implementation class
355     * 
356     * @return instance of the service component class
357     * @throws InstantiationException if unable to instantiate
358     * @throws IllegalAccessException if unable to access
359     */
360    protected Object createInstance()
361        throws InstantiationException, IllegalAccessException
362    {
363        if( this.getParentLogger().isDebugEnabled() )
364        {
365            this.getParentLogger().debug( "Instantiating the implementation class for " + this.getShorthand() );
366        }
367
368        this.instance = this.implementationClazz.newInstance();
369        this.proxy = null;
370        return this.instance;
371    }
372
373    /**
374     * @see org.apache.fulcrum.yaafi.framework.component.ServiceComponent#incarnate()
375     * @throws Exception generic exception
376     */
377    protected abstract void incarnateInstance() throws Exception;
378
379    /**
380     * Get either the original service object or the dynamic proxy
381     *
382     * @param useProxy set to true if using a proxy
383     * @return Returns the raw instance, i.e. does not incarnate
384     * the instance.
385     */
386    protected Object getRawInstance(boolean useProxy)
387    {
388        if( useProxy && this.proxy != null)
389            return this.proxy;
390        else
391            return this.instance;
392    }
393
394    /**
395     * @param proxy the service proxy instance
396     */
397    protected void setProxyInstance(Object proxy)
398    {
399        this.proxy = proxy;
400    }
401}