KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fulcrum > intake > TurbineIntakeService


1 package org.apache.fulcrum.intake;
2
3 /* ====================================================================
4  * The Apache Software License, Version 1.1
5  *
6  * Copyright (c) 2001 The Apache Software Foundation. All rights
7  * reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution,
22  * if any, must include the following acknowledgment:
23  * "This product includes software developed by the
24  * Apache Software Foundation (http://www.apache.org/)."
25  * Alternately, this acknowledgment may appear in the software itself,
26  * if and wherever such third-party acknowledgments normally appear.
27  *
28  * 4. The names "Apache" and "Apache Software Foundation" and
29  * "Apache Turbine" must not be used to endorse or promote products
30  * derived from this software without prior written permission. For
31  * written permission, please contact apache@apache.org.
32  *
33  * 5. Products derived from this software may not be called "Apache",
34  * "Apache Turbine", nor may "Apache" appear in their name, without
35  * prior written permission of the Apache Software Foundation.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals on behalf of the Apache Software Foundation. For more
53  * information on the Apache Software Foundation, please see
54  * <http://www.apache.org/>.
55  */

56 import java.beans.PropertyDescriptor JavaDoc;
57 import java.io.File JavaDoc;
58 import java.io.FileInputStream JavaDoc;
59 import java.io.FileOutputStream JavaDoc;
60 import java.io.InputStream JavaDoc;
61 import java.io.ObjectInputStream JavaDoc;
62 import java.io.ObjectOutputStream JavaDoc;
63 import java.io.OutputStream JavaDoc;
64 import java.lang.reflect.Method JavaDoc;
65 import java.util.HashMap JavaDoc;
66 import java.util.Iterator JavaDoc;
67 import java.util.List JavaDoc;
68 import java.util.Map JavaDoc;
69
70 import org.apache.commons.pool.KeyedObjectPool;
71 import org.apache.commons.pool.KeyedPoolableObjectFactory;
72 import org.apache.commons.pool.impl.StackKeyedObjectPool;
73
74 import org.apache.fulcrum.BaseService;
75 import org.apache.fulcrum.InitializationException;
76 import org.apache.fulcrum.ServiceException;
77 import org.apache.fulcrum.intake.model.Group;
78 import org.apache.fulcrum.intake.transform.XmlToAppData;
79 import org.apache.fulcrum.intake.xmlmodel.AppData;
80 import org.apache.fulcrum.intake.xmlmodel.XmlGroup;
81
82 /**
83  * This service provides access to input processing objects based
84  * on an XML specification.
85  *
86  * @author <a HREF="mailto:jmcnally@collab.net">John McNally</a>
87  * @version $Id: TurbineIntakeService.java,v 1.1 2004/11/12 10:25:56 epugh Exp $
88  */

89 public class TurbineIntakeService
90     extends BaseService
91     implements IntakeService
92 {
93     /** Array of group names. */
94     private String JavaDoc[] groupNames;
95
96     /** The cache of group names. */
97     private Map JavaDoc groupNameMap;
98
99     /** The cache of group keys. */
100     private Map JavaDoc groupKeyMap;
101
102     /** The cache of property getters. */
103     private Map JavaDoc getterMap;
104
105     /** The cache of property setters. */
106     private Map JavaDoc setterMap;
107
108     /** Keep a OMTool to be able to retrieve objects */
109     //private OMTool omTool;
110

111     /** The top element of the object tree */
112     private AppData appData;
113
114     /** pools Group objects */
115     KeyedObjectPool keyedPool;
116
117     // a couple integers for a switch statement
118
private static final int GETTER = 0;
119     private static final int SETTER = 1;
120
121     /**
122      * Constructor.
123      */

124     public TurbineIntakeService()
125     {
126     }
127
128     /**
129      * Called the first time the Service is used.
130      *
131      * @param config A ServletConfig.
132      */

133     public void init()
134         throws InitializationException
135     {
136         String JavaDoc xmlPath = getConfiguration()
137             .getString(XML_PATH, XML_PATH_DEFAULT);
138         String JavaDoc appDataPath = getConfiguration()
139             .getString(SERIAL_XML, SERIAL_XML_DEFAULT);
140         
141         String JavaDoc SERIALIZED_ERROR_MSG =
142             "Intake initialization could not be serialized " +
143             "because writing to " + appDataPath + " was not " +
144             "allowed. This will require that the xml file be " +
145             "parsed when restarting the application.";
146
147         if ( xmlPath == null )
148         {
149             String JavaDoc pathError =
150                 "Path to intake.xml was not specified. Check that the" +
151                 " property exists in TR.props and was loaded.";
152             getCategory().error(pathError);
153             throw new InitializationException(pathError);
154         }
155
156         File JavaDoc serialAppData = null;
157         File JavaDoc xmlFile = null;
158         xmlFile = new File JavaDoc(xmlPath);
159         if ( !xmlFile.canRead() )
160         {
161             // If possible, transform paths to be webapp root relative.
162
xmlPath = getRealPath(xmlPath);
163             xmlFile = new File JavaDoc(xmlPath);
164             if ( !xmlFile.canRead() )
165             {
166                 String JavaDoc pathError =
167                     "Could not read input file. Even tried relative to"
168                     + " webapp root.";
169                 getCategory().error(pathError);
170                 throw new InitializationException(pathError);
171             }
172         }
173
174         serialAppData = new File JavaDoc(appDataPath);
175         try
176         {
177             serialAppData.createNewFile();
178             serialAppData.delete();
179         }
180         catch (Exception JavaDoc e)
181         {
182             // If possible, transform paths to be webapp root relative.
183
appDataPath = getRealPath(appDataPath);
184             serialAppData = new File JavaDoc(appDataPath);
185             try
186             {
187                 serialAppData.createNewFile();
188                 serialAppData.delete();
189             }
190             catch (Exception JavaDoc ee)
191             {
192                 getCategory().info(SERIALIZED_ERROR_MSG);
193             }
194         }
195
196         try
197         {
198             if ( serialAppData.exists()
199                  && serialAppData.lastModified() > xmlFile.lastModified() )
200             {
201                 InputStream JavaDoc in = null;
202                 try
203                 {
204                     in = new FileInputStream JavaDoc(serialAppData);
205                     ObjectInputStream JavaDoc p = new ObjectInputStream JavaDoc(in);
206                     appData = (AppData)p.readObject();
207                 }
208                 catch (Exception JavaDoc e)
209                 {
210                     // We got a corrupt file for some reason
211
writeAppData(xmlPath, appDataPath, serialAppData);
212                 }
213                 finally
214                 {
215                     if (in != null)
216                     {
217                         in.close();
218                     }
219                 }
220             }
221             else
222             {
223                 writeAppData(xmlPath, appDataPath, serialAppData);
224             }
225
226             groupNames = new String JavaDoc[appData.getGroups().size()];
227             groupKeyMap = new HashMap JavaDoc();
228             groupNameMap = new HashMap JavaDoc();
229             getterMap = new HashMap JavaDoc();
230             setterMap = new HashMap JavaDoc();
231             // omTool = new OMTool();
232
String JavaDoc pkg = appData.getBasePackage();
233
234             int maxPooledGroups = 0;
235             List JavaDoc glist = appData.getGroups();
236             for ( int i=glist.size()-1; i>=0; i-- )
237             {
238                 XmlGroup g = (XmlGroup)glist.get(i);
239                 String JavaDoc groupName = g.getName();
240                 groupNames[i] = groupName;
241                 groupKeyMap.put(groupName, g.getKey());
242                 groupNameMap.put(g.getKey(), groupName);
243                 maxPooledGroups =
244                     Math.max(maxPooledGroups,
245                              Integer.parseInt(g.getPoolCapacity()));
246                 List JavaDoc classNames = g.getMapToObjects();
247                 Iterator JavaDoc iter2 = classNames.iterator();
248                 while (iter2.hasNext())
249                 {
250                     String JavaDoc className = (String JavaDoc)iter2.next();
251                     if ( !getterMap.containsKey(className) )
252                     {
253                         getterMap.put(className, new HashMap JavaDoc());
254                         setterMap.put(className, new HashMap JavaDoc());
255                     }
256                 }
257             }
258
259             KeyedPoolableObjectFactory factory =
260                 new Group.GroupFactory(appData);
261             keyedPool = new StackKeyedObjectPool(factory, maxPooledGroups);
262
263             setInit(true);
264         }
265         catch (Exception JavaDoc e)
266         {
267             throw new InitializationException(
268                 "TurbineIntakeService failed to initialize", e);
269         }
270     }
271
272     /**
273      * This method writes the appData file into Objects and stores
274      * the information into this classes appData property
275      */

276     private void writeAppData(String JavaDoc xmlPath, String JavaDoc appDataPath, File JavaDoc serialAppData)
277         throws Exception JavaDoc
278     {
279         XmlToAppData xmlApp = new XmlToAppData();
280         appData = xmlApp.parseFile(xmlPath);
281         OutputStream JavaDoc out = null;
282         InputStream JavaDoc in = null;
283         try
284         {
285             // write the appData file out
286
out = new FileOutputStream JavaDoc(serialAppData);
287             ObjectOutputStream JavaDoc p = new ObjectOutputStream JavaDoc(out);
288             p.writeObject(appData);
289             p.flush();
290
291             // read the file back in. for some reason on OSX 10.1
292
// this is necessary.
293
in = new FileInputStream JavaDoc(serialAppData);
294             ObjectInputStream JavaDoc pin = new ObjectInputStream JavaDoc(in);
295             appData = (AppData)pin.readObject();
296         }
297         catch (Exception JavaDoc e)
298         {
299             getCategory().info(
300                 "Intake initialization could not be serialized " +
301                 "because writing to " + appDataPath + " was not " +
302                 "allowed. This will require that the xml file be " +
303                 "parsed when restarting the application.");
304         }
305         finally
306         {
307             if (out != null)
308             {
309                 out.close();
310             }
311             if (in != null)
312             {
313                 in.close();
314             }
315         }
316     }
317
318     /**
319      * Gets an instance of a named group either from the pool
320      * or by calling the Factory Service if the pool is empty.
321      *
322      * @param groupName the name of the group.
323      * @return a Group instance.
324      * @throws ServiceException if recycling fails.
325      */

326     public Group getGroup(String JavaDoc groupName)
327             throws ServiceException
328     {
329         Group group = null;
330         if (groupName == null)
331         {
332             throw new ServiceException (
333                 "Intake TurbineIntakeService.getGroup(groupName) is null");
334         }
335         try
336         {
337             group = (Group)keyedPool.borrowObject(groupName);
338         }
339         catch (Exception JavaDoc e)
340         {
341             new ServiceException(e);
342         }
343         return group;
344     }
345
346
347     /**
348      * Puts a Group back to the pool.
349      *
350      * @param instance the object instance to recycle.
351      * @return true if the instance was accepted.
352      */

353     public void releaseGroup(Group instance)
354     {
355         if (instance != null)
356         {
357             String JavaDoc name = instance.getIntakeGroupName();
358             try
359             {
360                 keyedPool.returnObject(name, instance);
361             }
362             catch (Exception JavaDoc e)
363             {
364                 new ServiceException(e);
365             }
366             //return true;
367
}
368         else
369         {
370             //return false;
371
}
372     }
373
374     /**
375      * Gets the current size of the pool for a group.
376      *
377      * @param name the name of the group.
378      */

379     public int getSize(String JavaDoc name)
380     {
381         return keyedPool.getNumActive(name) + keyedPool.getNumIdle(name);
382     }
383
384     /**
385      * Names of all the defined groups.
386      *
387      * @return array of names.
388      */

389     public String JavaDoc[] getGroupNames()
390     {
391         return groupNames;
392     }
393
394     /**
395      * Gets the key (usually a short identifier) for a group.
396      *
397      * @param groupName the name of the group.
398      * @return the the key.
399      */

400     public String JavaDoc getGroupKey(String JavaDoc groupName)
401     {
402         return (String JavaDoc)groupKeyMap.get(groupName);
403     }
404
405     /**
406      * Gets the group name given its key.
407      *
408      * @param the the key.
409      * @return groupName the name of the group.
410      */

411     public String JavaDoc getGroupName(String JavaDoc groupKey)
412     {
413         return (String JavaDoc)groupNameMap.get(groupKey);
414     }
415
416     /**
417      * Gets the Method that can be used to set a property.
418      *
419      * @param className the name of the object.
420      * @param propName the name of the property.
421      * @return the setter.
422      */

423     public Method JavaDoc getFieldSetter(String JavaDoc className, String JavaDoc propName)
424     {
425         Map JavaDoc settersForClassName = (Map JavaDoc)setterMap.get(className);
426         Method JavaDoc setter = (Method JavaDoc)settersForClassName.get(propName);
427
428         if ( setter == null )
429         {
430             PropertyDescriptor JavaDoc pd = null;
431             synchronized(setterMap)
432             {
433                 try
434                 {
435                     // !FIXME! will throw an exception if the getter is not
436
// available. Need to make this more robust
437
pd = new PropertyDescriptor JavaDoc(propName,
438                                                 Class.forName(className));
439                     setter = pd.getWriteMethod();
440                     ((Map JavaDoc)setterMap.get(className)).put(propName, setter);
441                     if ( setter == null )
442                     {
443                         getCategory().error("Intake: setter for '" + propName
444                                             + "' in class '" + className
445                                             + "' could not be found.");
446                     }
447                 }
448                 catch (Exception JavaDoc e)
449                 {
450                     getCategory().error(e);
451                 }
452             }
453             // we have already completed the reflection on the getter, so
454
// save it so we do not have to repeat
455
synchronized(getterMap)
456             {
457                 try
458                 {
459                     Method JavaDoc getter = pd.getReadMethod();
460                     ((Map JavaDoc)getterMap.get(className)).put(propName, getter);
461                 }
462                 catch (Exception JavaDoc e)
463                 {
464                     // ignore, the getter may not be needed
465
}
466             }
467         }
468         return setter;
469     }
470
471     /**
472      * Gets the Method that can be used to get a property value.
473      *
474      * @param className the name of the object.
475      * @param propName the name of the property.
476      * @return the getter.
477      */

478     public Method JavaDoc getFieldGetter(String JavaDoc className, String JavaDoc propName)
479     {
480         Map JavaDoc gettersForClassName = (Map JavaDoc)getterMap.get(className);
481         Method JavaDoc getter = (Method JavaDoc)gettersForClassName.get(propName);
482
483         if ( getter == null )
484         {
485             PropertyDescriptor JavaDoc pd = null;
486             synchronized(getterMap)
487             {
488                 try
489                 {
490                     // !FIXME! will throw an exception if the setter is not
491
// available. Need to make this more robust
492
pd = new PropertyDescriptor JavaDoc(propName,
493                                                 Class.forName(className));
494                     getter = pd.getReadMethod();
495                     ((Map JavaDoc)getterMap.get(className)).put(propName, getter);
496                     if ( getter == null )
497                     {
498                         getCategory().error("Intake: getter for '" + propName
499                                             + "' in class '" + className
500                                             + "' could not be found.");
501                     }
502                 }
503                 catch (Exception JavaDoc e)
504                 {
505                     getCategory().error(e);
506                 }
507             }
508             // we have already completed the reflection on the setter, so
509
// save it so we do not have to repeat
510
synchronized(setterMap)
511             {
512                 try
513                 {
514                     Method JavaDoc setter = pd.getWriteMethod();
515                     ((Map JavaDoc)setterMap.get(className)).put(propName, setter);
516                 }
517                 catch (Exception JavaDoc e)
518                 {
519                     // ignore, the setter may not be needed
520
}
521             }
522         }
523         return getter;
524     }
525
526 }
527
Popular Tags