001    package 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    
022    import org.apache.avalon.framework.configuration.Configuration;
023    import org.apache.avalon.framework.configuration.ConfigurationException;
024    import org.apache.avalon.framework.context.Context;
025    import org.apache.avalon.framework.logger.Logger;
026    import org.apache.avalon.framework.parameters.Parameters;
027    import org.apache.avalon.framework.service.ServiceManager;
028    import org.apache.fulcrum.yaafi.framework.role.RoleEntry;
029    import org.apache.fulcrum.yaafi.framework.util.ToStringBuilder;
030    import 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    
039    public 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        /**
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        /**
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        /**
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        /**
167         * @see org.apache.fulcrum.yaafi.framework.component.ServiceComponentLifecycle#reconfigure()
168         */
169        public abstract void reconfigure() throws Exception;
170    
171        /**
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        /**
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        /**
198         * @param logger The logger to set.
199         */
200        public void setLogger(Logger logger)
201        {
202            this.logger = logger;
203        }
204    
205        /**
206         * @param context The context to set.
207         */
208        public void setContext(Context context)
209        {
210            this.context = context;
211        }
212    
213        /**
214         * @param serviceManager The serviceManager to set.
215         */
216        public void setServiceManager(ServiceManager serviceManager)
217        {
218            this.serviceManager = serviceManager;
219        }
220    
221        /**
222         * @param configuration The configuration to set.
223         */
224        public void setConfiguration(Configuration configuration)
225        {
226            this.configuration = configuration;
227        }
228    
229        /**
230         * @param parameters The parameters to set.
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        /**
250         * @see org.apache.fulcrum.yaafi.framework.component.ServiceComponent#getName()
251         */
252        public String getName()
253        {
254            return this.getRoleEntry().getName();
255        }
256    
257        /**
258         * @return Returns the roleEntry.
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 paramaters.
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        /**
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         * @throws InstantiationException th
357         * @throws IllegalAccessException
358         */
359        protected Object createInstance()
360            throws InstantiationException, IllegalAccessException
361        {
362            if( this.getParentLogger().isDebugEnabled() )
363            {
364                this.getParentLogger().debug( "Instantiating the implementation class for " + this.getShorthand() );
365            }
366    
367            this.instance = this.implementationClazz.newInstance();
368            this.proxy = null;
369            return this.instance;
370        }
371    
372        /**
373         * @see org.apache.fulcrum.yaafi.framework.component.ServiceComponent#incarnate()
374         */
375        protected abstract void incarnateInstance() throws Exception;
376    
377        /**
378         * Get either the original service object or the dynamic proxy
379         *
380         * @return Returns the raw instance, i.e. does not incarnate
381         * the instance.
382         */
383        protected Object getRawInstance(boolean useProxy)
384        {
385            if( useProxy && (this.proxy != null) )
386            {
387                return this.proxy;
388            }
389            else
390            {
391                return this.instance;
392            }
393        }
394    
395        /**
396         * @param proxy the service proxy instance
397         */
398        protected void setProxyInstance(Object proxy)
399        {
400            this.proxy = proxy;
401        }
402    }