Coverage report

  %line %branch
org.apache.turbine.services.intake.TurbineIntakeService
0% 
0% 

 1  
 package org.apache.turbine.services.intake;
 2  
 
 3  
 /*
 4  
  * Copyright 2001-2005 The Apache Software Foundation.
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License")
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  
  * See the License for the specific language governing permissions and
 16  
  * limitations under the License.
 17  
  */
 18  
 
 19  
 import java.beans.IntrospectionException;
 20  
 import java.beans.PropertyDescriptor;
 21  
 
 22  
 import java.io.File;
 23  
 import java.io.FileInputStream;
 24  
 import java.io.FileOutputStream;
 25  
 import java.io.InputStream;
 26  
 import java.io.ObjectInputStream;
 27  
 import java.io.ObjectOutputStream;
 28  
 import java.io.OutputStream;
 29  
 
 30  
 import java.lang.reflect.Method;
 31  
 
 32  
 import java.util.HashMap;
 33  
 import java.util.HashSet;
 34  
 import java.util.Iterator;
 35  
 import java.util.List;
 36  
 import java.util.Map;
 37  
 import java.util.Set;
 38  
 import java.util.Vector;
 39  
 
 40  
 import javax.servlet.ServletConfig;
 41  
 
 42  
 import org.apache.commons.lang.StringUtils;
 43  
 
 44  
 import org.apache.commons.logging.Log;
 45  
 import org.apache.commons.logging.LogFactory;
 46  
 
 47  
 import org.apache.commons.pool.KeyedObjectPool;
 48  
 import org.apache.commons.pool.KeyedPoolableObjectFactory;
 49  
 import org.apache.commons.pool.impl.StackKeyedObjectPool;
 50  
 
 51  
 import org.apache.turbine.Turbine;
 52  
 import org.apache.turbine.services.InitializationException;
 53  
 import org.apache.turbine.services.TurbineBaseService;
 54  
 import org.apache.turbine.services.intake.model.Group;
 55  
 import org.apache.turbine.services.intake.transform.XmlToAppData;
 56  
 import org.apache.turbine.services.intake.xmlmodel.AppData;
 57  
 import org.apache.turbine.services.intake.xmlmodel.XmlGroup;
 58  
 
 59  
 /**
 60  
  * This service provides access to input processing objects based
 61  
  * on an XML specification.
 62  
  *
 63  
  * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
 64  
  * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
 65  
  * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
 66  
  * @version $Id: TurbineIntakeService.java 279823 2005-09-09 17:07:44Z henning $
 67  
  */
 68  
 public class TurbineIntakeService
 69  
         extends TurbineBaseService
 70  
         implements IntakeService
 71  
 {
 72  
     /** Map of groupNames -> appData elements */
 73  
     private Map groupNames;
 74  
 
 75  
     /** The cache of group names. */
 76  
     private Map groupNameMap;
 77  
 
 78  
     /** The cache of group keys. */
 79  
     private Map groupKeyMap;
 80  
 
 81  
     /** The cache of property getters. */
 82  
     private Map getterMap;
 83  
 
 84  
     /** The cache of property setters. */
 85  
     private Map setterMap;
 86  
 
 87  
     /** AppData -> keyed Pools Map */
 88  
     private Map keyedPools;
 89  
 
 90  
     /** Used for logging */
 91  0
     private static Log log = LogFactory.getLog(TurbineIntakeService.class);
 92  
 
 93  
     /**
 94  
      * Constructor. All Components need a public no argument constructor
 95  
      * to be a legal Component.
 96  
      */
 97  
     public TurbineIntakeService()
 98  0
     {
 99  0
     }
 100  
 
 101  
     /**
 102  
      * Called the first time the Service is used.
 103  
      *
 104  
      * @throws InitializationException Something went wrong in the init
 105  
      *         stage
 106  
      */
 107  
     public void init()
 108  
             throws InitializationException
 109  
     {
 110  0
         Vector defaultXmlPathes = new Vector();
 111  0
         defaultXmlPathes.add(XML_PATH_DEFAULT);
 112  
 
 113  0
         List xmlPathes = getConfiguration()
 114  
                 .getList(XML_PATH, defaultXmlPathes);
 115  
 
 116  0
         Map appDataElements = null;
 117  
 
 118  0
         String serialDataPath = getConfiguration()
 119  
                 .getString(SERIAL_XML, SERIAL_XML_DEFAULT);
 120  
 
 121  0
         if (!serialDataPath.equalsIgnoreCase("none"))
 122  
         {
 123  0
             serialDataPath = Turbine.getRealPath(serialDataPath);
 124  
         }
 125  
         else
 126  
         {
 127  0
             serialDataPath = null;
 128  
         }
 129  
 
 130  0
         log.debug("Path for serializing: " + serialDataPath);
 131  
 
 132  0
         groupNames = new HashMap();
 133  0
         groupKeyMap = new HashMap();
 134  0
         groupNameMap = new HashMap();
 135  0
         getterMap = new HashMap();
 136  0
         setterMap = new HashMap();
 137  0
         keyedPools = new HashMap();
 138  
 
 139  0
         if (xmlPathes == null)
 140  
         {
 141  0
             String LOAD_ERROR = "No pathes for XML files were specified. " +
 142  
                     "Check that the property exists in " +
 143  
                     "TurbineResources.props and were loaded.";
 144  
 
 145  0
             log.error(LOAD_ERROR);
 146  0
             throw new InitializationException(LOAD_ERROR);
 147  
         }
 148  
 
 149  0
         Set xmlFiles = new HashSet();
 150  
 
 151  0
         long timeStamp = 0;
 152  
 
 153  0
         for (Iterator it = xmlPathes.iterator(); it.hasNext();)
 154  
         {
 155  
             // Files are webapp.root relative
 156  0
             String xmlPath = Turbine.getRealPath((String) it.next());
 157  0
             File xmlFile = new File(xmlPath);
 158  
 
 159  0
             log.debug("Path for XML File: " + xmlFile);
 160  
 
 161  0
             if (!xmlFile.canRead())
 162  
             {
 163  0
                 String READ_ERR = "Could not read input file " + xmlPath;
 164  
 
 165  0
                 log.error(READ_ERR);
 166  0
                 throw new InitializationException(READ_ERR);
 167  
             }
 168  
 
 169  0
             xmlFiles.add(xmlPath);
 170  
 
 171  0
             log.debug("Added " + xmlPath + " as File to parse");
 172  
 
 173  
             // Get the timestamp of the youngest file to be compared with
 174  
             // a serialized file. If it is younger than the serialized file,
 175  
             // then we have to parse the XML anyway.
 176  0
             timeStamp =
 177  
                     (xmlFile.lastModified() > timeStamp) ? xmlFile.lastModified() : timeStamp;
 178  
         }
 179  
 
 180  0
         Map serializedMap = loadSerialized(serialDataPath, timeStamp);
 181  
 
 182  0
         if (serializedMap != null)
 183  
         {
 184  
             // Use the serialized data as XML groups. Don't parse.
 185  0
             appDataElements = serializedMap;
 186  0
             log.debug("Using the serialized map");
 187  
         }
 188  
         else
 189  
         {
 190  
             // Parse all the given XML files
 191  0
             appDataElements = new HashMap();
 192  
 
 193  0
             for (Iterator it = xmlFiles.iterator(); it.hasNext();)
 194  
             {
 195  0
                 String xmlPath = (String) it.next();
 196  0
                 AppData appData = null;
 197  
 
 198  0
                 log.debug("Now parsing: " + xmlPath);
 199  
                 try
 200  
                 {
 201  0
                     XmlToAppData xmlApp = new XmlToAppData();
 202  0
                     appData = xmlApp.parseFile(xmlPath);
 203  
                 }
 204  0
                 catch (Exception e)
 205  
                 {
 206  0
                     log.error("Could not parse XML file " + xmlPath, e);
 207  
 
 208  0
                     throw new InitializationException("Could not parse XML file " +
 209  
                             xmlPath, e);
 210  0
                 }
 211  
 
 212  0
                 appDataElements.put(appData, xmlPath);
 213  0
                 log.debug("Saving appData for " + xmlPath);
 214  
             }
 215  
 
 216  0
             saveSerialized(serialDataPath, appDataElements);
 217  
         }
 218  
 
 219  
         try
 220  
         {
 221  0
             for (Iterator it = appDataElements.keySet().iterator(); it.hasNext();)
 222  
             {
 223  0
                 AppData appData = (AppData) it.next();
 224  
 
 225  0
                 int maxPooledGroups = 0;
 226  0
                 List glist = appData.getGroups();
 227  
 
 228  0
                 String groupPrefix = appData.getGroupPrefix();
 229  
 
 230  0
                 for (int i = glist.size() - 1; i >= 0; i--)
 231  
                 {
 232  0
                     XmlGroup g = (XmlGroup) glist.get(i);
 233  0
                     String groupName = g.getName();
 234  
 
 235  0
                     boolean registerUnqualified = registerGroup(groupName, g, appData, true);
 236  
 
 237  0
                     if (!registerUnqualclass="keyword">ified)
 238  
                     {
 239  0
                         log.info("Ignored redefinition of Group " + groupName
 240  
                                 + " or Key " + g.getKey()
 241  
                                 + " from " + appDataElements.get(appData));
 242  
                     }
 243  
 
 244  0
                     if (groupPrefix != null)
 245  
                     {
 246  0
                         StringBuffer qualifiedName = new StringBuffer();
 247  0
                         qualifiedName.append(groupPrefix)
 248  
                                 .append(':')
 249  
                                 .append(groupName);
 250  
 
 251  
                         // Add the fully qualified group name. Do _not_ check for
 252  
                         // the existence of the key if the unqualified registration succeeded
 253  
                         // (because then it was added by the registerGroup above).
 254  0
                         if (!registerGroup(qualclass="keyword">ifiedName.toString(), g, appData, !registerUnqualclass="keyword">ified))
 255  
                         {
 256  0
                             log.error("Could not register fully qualified name " + qualifiedName
 257  
                                     + ", maybe two XML files have the same prefix. Ignoring it.");
 258  
                         }
 259  
                     }
 260  
 
 261  0
                     maxPooledGroups =
 262  
                             Math.max(maxPooledGroups,
 263  
                                     Integer.parseInt(g.getPoolCapacity()));
 264  
 
 265  
                 }
 266  
 
 267  0
                 KeyedPoolableObjectFactory factory =
 268  
                         new Group.GroupFactory(appData);
 269  0
                 keyedPools.put(appData, new StackKeyedObjectPool(factory, maxPooledGroups));
 270  
             }
 271  
 
 272  0
             setInit(true);
 273  
         }
 274  0
         catch (Exception e)
 275  
         {
 276  0
             throw new InitializationException(
 277  
                     "TurbineIntakeService failed to initialize", e);
 278  0
         }
 279  0
     }
 280  
 
 281  
     /**
 282  
      * Called the first time the Service is used.
 283  
      *
 284  
      * @param config A ServletConfig.
 285  
      * @deprecated use init() instead.
 286  
      */
 287  
     public void init(ServletConfig config)
 288  
             throws InitializationException
 289  
     {
 290  0
         init();
 291  0
     }
 292  
 
 293  
     /**
 294  
      * Registers a given group name in the system
 295  
      *
 296  
      * @param groupName The name to register the group under
 297  
      * @param group The XML Group to register in
 298  
      * @param appData The app Data object where the group can be found
 299  
      * @param checkKey Whether to check if the key also exists.
 300  
      *
 301  
      * @return true if successful, false if not
 302  
      */
 303  
     private boolean registerGroup(String groupName, XmlGroup group, AppData appData, class="keyword">boolean checkKey)
 304  
     {
 305  0
         if (groupNames.keySet().contains(groupName))
 306  
         {
 307  
             // This name already exists.
 308  0
             return false;
 309  
         }
 310  
 
 311  0
         boolean keyExists = groupNameMap.keySet().contains(group.getKey());
 312  
 
 313  0
         if (checkKey && keyExists)
 314  
         {
 315  
             // The key for this package is already registered for another group
 316  0
             return false;
 317  
         }
 318  
 
 319  0
         groupNames.put(groupName, appData);
 320  
 
 321  0
         groupKeyMap.put(groupName, group.getKey());
 322  
 
 323  0
         if (!keyExists)
 324  
         {
 325  
             // This key does not exist. Add it to the hash.
 326  0
             groupNameMap.put(group.getKey(), groupName);
 327  
         }
 328  
 
 329  0
         List classNames = group.getMapToObjects();
 330  0
         for (Iterator iter2 = classNames.iterator(); iter2.hasNext();)
 331  
         {
 332  0
             String className = (String) iter2.next();
 333  0
             if (!getterMap.containsKey(className))
 334  
             {
 335  0
                 getterMap.put(className, new HashMap());
 336  0
                 setterMap.put(className, new HashMap());
 337  
             }
 338  
         }
 339  0
         return true;
 340  
     }
 341  
 
 342  
     /**
 343  
      * Tries to load a serialized Intake Group file. This
 344  
      * can reduce the startup time of Turbine.
 345  
      *
 346  
      * @param serialDataPath The path of the File to load.
 347  
      *
 348  
      * @return A map with appData objects loaded from the file
 349  
      *          or null if the map could not be loaded.
 350  
      */
 351  
     private Map loadSerialized(String serialDataPath, long timeStamp)
 352  
     {
 353  0
         log.debug("Entered loadSerialized("
 354  
                 + serialDataPath + ", "
 355  
                 + timeStamp + ")");
 356  
 
 357  0
         if (serialDataPath == null)
 358  
         {
 359  0
             return null;
 360  
         }
 361  
 
 362  0
         File serialDataFile = new File(serialDataPath);
 363  
 
 364  0
         if (!serialDataFile.exists())
 365  
         {
 366  0
             log.info("No serialized file found, parsing XML");
 367  0
             return null;
 368  
         }
 369  
 
 370  0
         if (serialDataFile.lastModclass="keyword">ified() <= timeStamp)
 371  
         {
 372  0
             log.info("serialized file too old, parsing XML");
 373  0
             return null;
 374  
         }
 375  
 
 376  0
         InputStream in = null;
 377  0
         Map serialData = null;
 378  
 
 379  
         try
 380  
         {
 381  0
             in = new FileInputStream(serialDataFile);
 382  0
             ObjectInputStream p = new ObjectInputStream(in);
 383  0
             Object o = p.readObject();
 384  
 
 385  0
             if (o instanceof Map)
 386  
             {
 387  0
                 serialData = (Map) o;
 388  
             }
 389  
             else
 390  
             {
 391  
                 // Maybe an old file from intake. Ignore it and try to delete
 392  0
                 log.info("serialized object is not an intake map, ignoring");
 393  0
                 in.close();
 394  0
                 in = null;
 395  0
                 serialDataFile.delete(); // Try to delete the file lying around
 396  
             }
 397  0
         }
 398  0
         catch (Exception e)
 399  
         {
 400  0
             log.error("Serialized File could not be read.", e);
 401  
 
 402  
             // We got a corrupt file for some reason.
 403  
             // Null out serialData to be sure
 404  0
             serialData = null;
 405  0
         }
 406  
         finally
 407  
         {
 408  
             // Could be null if we opened a file, didn't find it to be a
 409  
             // Map object and then nuked it away.
 410  0
             try
 411  
             {
 412  0
                 if (in != null)
 413  
                 {
 414  0
                     in.close();
 415  
                 }
 416  
             }
 417  0
             catch (Exception e)
 418  
             {
 419  0
                 log.error("Exception while closing file", e);
 420  0
             }
 421  0
         }
 422  
 
 423  0
         log.info("Loaded serialized map object, ignoring XML");
 424  0
         return serialData;
 425  
     }
 426  
 
 427  
     /**
 428  
      * Writes a parsed XML map with all the appData groups into a
 429  
      * file. This will speed up loading time when you restart the
 430  
      * Intake Service because it will only unserialize this file instead
 431  
      * of reloading all of the XML files
 432  
      *
 433  
      * @param serialDataPath  The path of the file to write to
 434  
      * @param appDataElements A Map containing all of the XML parsed appdata elements
 435  
      */
 436  
     private void saveSerialized(String serialDataPath, Map appDataElements)
 437  
     {
 438  
 
 439  0
         log.debug("Entered saveSerialized("
 440  
                 + serialDataPath + ", appDataElements)");
 441  
 
 442  0
         if (serialDataPath == null)
 443  
         {
 444  0
             return;
 445  
         }
 446  
 
 447  0
         File serialData = new File(serialDataPath);
 448  
 
 449  
         try
 450  
         {
 451  0
             serialData.createNewFile();
 452  0
             serialData.delete();
 453  
         }
 454  0
         catch (Exception e)
 455  
         {
 456  0
             log.info("Could not create serialized file " + serialDataPath
 457  
                     + ", not serializing the XML data");
 458  0
             return;
 459  0
         }
 460  
 
 461  0
         OutputStream out = null;
 462  0
         InputStream in = null;
 463  
 
 464  
         try
 465  
         {
 466  
             // write the appData file out
 467  0
             out = new FileOutputStream(serialDataPath);
 468  0
             ObjectOutputStream pout = new ObjectOutputStream(out);
 469  0
             pout.writeObject(appDataElements);
 470  0
             pout.flush();
 471  
 
 472  
             // read the file back in. for some reason on OSX 10.1
 473  
             // this is necessary.
 474  0
             in = new FileInputStream(serialDataPath);
 475  0
             ObjectInputStream pin = new ObjectInputStream(in);
 476  0
             Map dummy = (Map) pin.readObject();
 477  
 
 478  0
             log.debug("Serializing successful");
 479  0
         }
 480  0
         catch (Exception e)
 481  
         {
 482  0
             log.info("Could not write serialized file to " + serialDataPath
 483  
                     + ", not serializing the XML data");
 484  0
         }
 485  
         finally
 486  
         {
 487  0
             try
 488  
             {
 489  0
                 if (out != null)
 490  
                 {
 491  0
                     out.close();
 492  
                 }
 493  0
                 if (in != null)
 494  
                 {
 495  0
                     in.close();
 496  
                 }
 497  
             }
 498  0
             catch (Exception e)
 499  
             {
 500  0
                 log.error("Exception while closing file", e);
 501  0
             }
 502  0
         }
 503  0
     }
 504  
 
 505  
     /**
 506  
      * Gets an instance of a named group either from the pool
 507  
      * or by calling the Factory Service if the pool is empty.
 508  
      *
 509  
      * @param groupName the name of the group.
 510  
      * @return a Group instance.
 511  
      * @throws IntakeException if recycling fails.
 512  
      */
 513  
     public Group getGroup(String groupName)
 514  
             throws IntakeException
 515  
     {
 516  0
         Group group = null;
 517  
 
 518  0
         AppData appData = (AppData) groupNames.get(groupName);
 519  
 
 520  0
         if (groupName == null)
 521  
         {
 522  0
             throw new IntakeException(
 523  
                     "Intake TurbineIntakeService.getGroup(groupName) is null");
 524  
         }
 525  0
         if (appData == null)
 526  
         {
 527  0
             throw new IntakeException(
 528  
                     "Intake TurbineIntakeService.getGroup(groupName): No XML definition for Group "
 529  
                     + groupName + " found");
 530  
         }
 531  
         try
 532  
         {
 533  0
             group = (Group) ((KeyedObjectPool) keyedPools.get(appData)).borrowObject(groupName);
 534  
         }
 535  0
         catch (Exception e)
 536  
         {
 537  0
             throw new IntakeException("Could not get group " + groupName, e);
 538  0
         }
 539  0
         return group;
 540  
     }
 541  
 
 542  
     /**
 543  
      * Puts a Group back to the pool.
 544  
      *
 545  
      * @param instance the object instance to recycle.
 546  
      *
 547  
      * @throws IntakeException The passed group name does not exist.
 548  
      */
 549  
     public void releaseGroup(Group instance)
 550  
             throws IntakeException
 551  
     {
 552  0
         if (instance != null)
 553  
         {
 554  0
             String groupName = instance.getIntakeGroupName();
 555  0
             AppData appData = (AppData) groupNames.get(groupName);
 556  
 
 557  0
             if (appData == null)
 558  
             {
 559  0
                 throw new IntakeException(
 560  
                         "Intake TurbineIntakeService.releaseGroup(groupName): "
 561  
                         + "No XML definition for Group " + groupName + " found");
 562  
             }
 563  
 
 564  
             try
 565  
             {
 566  0
                 ((KeyedObjectPool) keyedPools.get(appData)).returnObject(groupName, instance);
 567  
             }
 568  0
             catch (Exception e)
 569  
             {
 570  0
                 new IntakeException("Could not get group " + groupName, e);
 571  0
             }
 572  
         }
 573  0
     }
 574  
 
 575  
     /**
 576  
      * Gets the current size of the pool for a group.
 577  
      *
 578  
      * @param groupName the name of the group.
 579  
      *
 580  
      * @throws IntakeException The passed group name does not exist.
 581  
      */
 582  
     public int getSize(String groupName)
 583  
             throws IntakeException
 584  
     {
 585  0
         AppData appData = (AppData) groupNames.get(groupName);
 586  0
         if (appData == null)
 587  
         {
 588  0
             throw new IntakeException(
 589  
                     "Intake TurbineIntakeService.Size(groupName): No XML definition for Group "
 590  
                     + groupName + " found");
 591  
         }
 592  
 
 593  0
         KeyedObjectPool kop = (KeyedObjectPool) keyedPools.get(groupName);
 594  
 
 595  0
         return kop.getNumActive(groupName)
 596  
                 + kop.getNumIdle(groupName);
 597  
     }
 598  
 
 599  
     /**
 600  
      * Names of all the defined groups.
 601  
      *
 602  
      * @return array of names.
 603  
      */
 604  
     public String[] getGroupNames()
 605  
     {
 606  0
         return (String[]) groupNames.keySet().toArray(new String[0]);
 607  
     }
 608  
 
 609  
     /**
 610  
      * Gets the key (usually a short identifier) for a group.
 611  
      *
 612  
      * @param groupName the name of the group.
 613  
      * @return the the key.
 614  
      */
 615  
     public String getGroupKey(String groupName)
 616  
     {
 617  0
         return (String) groupKeyMap.get(groupName);
 618  
     }
 619  
 
 620  
     /**
 621  
      * Gets the group name given its key.
 622  
      *
 623  
      * @param groupKey the key.
 624  
      * @return groupName the name of the group.
 625  
      */
 626  
     public String getGroupName(String groupKey)
 627  
     {
 628  0
         return (String) groupNameMap.get(groupKey);
 629  
     }
 630  
 
 631  
     /**
 632  
      * Gets the Method that can be used to set a property.
 633  
      *
 634  
      * @param className the name of the object.
 635  
      * @param propName the name of the property.
 636  
      * @return the setter.
 637  
      * @throws ClassNotFoundException
 638  
      * @throws IntrospectionException
 639  
      */
 640  
     public Method getFieldSetter(String className, String propName)
 641  
             throws ClassNotFoundException, IntrospectionException
 642  
     {
 643  0
         Map settersForClassName = (Map) setterMap.get(className);
 644  
 
 645  0
         if (settersForClassName == null)
 646  
         {
 647  0
             throw new IntrospectionException("No setter Map for " + className + " available!");
 648  
         }
 649  
 
 650  0
         Method setter = (Method) settersForClassName.get(propName);
 651  
 
 652  0
         if (setter == null)
 653  
         {
 654  0
             PropertyDescriptor pd = null;
 655  
 
 656  0
             synchronized (setterMap)
 657  
             {
 658  
                 try
 659  
                 {
 660  0
                     pd = new PropertyDescriptor(propName,
 661  
                             Class.forName(className));
 662  
                 }
 663  0
                 catch (IntrospectionException ie)
 664  
                 {
 665  0
                     if (log.isWarnEnabled())
 666  
                     {
 667  0
                         log.warn("Trying to find only a setter for " + propName);
 668  
                     }
 669  
 
 670  0
                     pd = new PropertyDescriptor(propName,
 671  
                             Class.forName(className),
 672  
                             "set" + StringUtils.capitalize(propName),
 673  
                             null); // Java sucks.
 674  0
                 }
 675  
 
 676  0
                 setter = pd.getWriteMethod();
 677  0
                 settersForClassName.put(propName, setter);
 678  
 
 679  0
                 if (setter == null)
 680  
                 {
 681  0
                     log.error("Intake: setter for '" + propName
 682  
                             + "' in class '" + className
 683  
                             + "' could not be found.");
 684  
                 }
 685  0
             }
 686  
 
 687  0
             if (pd.getReadMethod() != null)
 688  
             {
 689  
                 // we have already completed the reflection on the getter, so
 690  
                 // save it so we do not have to repeat
 691  0
                 synchronized (getterMap)
 692  
                 {
 693  0
                     Map gettersForClassName = (Map) getterMap.get(className);
 694  
 
 695  0
                     if (gettersForClassName != null)
 696  
                     {
 697  
                         try
 698  
                         {
 699  0
                             Method getter = pd.getReadMethod();
 700  0
                             if (getter != null)
 701  
                             {
 702  0
                                 gettersForClassName.put(propName, getter);
 703  
                             }
 704  
                         }
 705  0
                         catch (Exception e)
 706  
                         {
 707  
                             // Do nothing
 708  0
                         }
 709  
                     }
 710  0
                 }
 711  
             }
 712  
         }
 713  0
         return setter;
 714  
     }
 715  
 
 716  
     /**
 717  
      * Gets the Method that can be used to get a property value.
 718  
      *
 719  
      * @param className the name of the object.
 720  
      * @param propName the name of the property.
 721  
      * @return the getter.
 722  
      * @throws ClassNotFoundException
 723  
      * @throws IntrospectionException
 724  
      */
 725  
     public Method getFieldGetter(String className, String propName)
 726  
             throws ClassNotFoundException, IntrospectionException
 727  
     {
 728  0
         Map gettersForClassName = (Map) getterMap.get(className);
 729  
 
 730  0
         if (gettersForClassName == null)
 731  
         {
 732  0
             throw new IntrospectionException("No getter Map for " + className + " available!");
 733  
         }
 734  
 
 735  0
         Method getter = (Method) gettersForClassName.get(propName);
 736  
 
 737  0
         if (getter == null)
 738  
         {
 739  0
             PropertyDescriptor pd = null;
 740  
 
 741  0
             synchronized (getterMap)
 742  
             {
 743  
                 try
 744  
                 {
 745  0
                     pd = new PropertyDescriptor(propName,
 746  
                             Class.forName(className));
 747  
                 }
 748  0
                 catch (IntrospectionException ie)
 749  
                 {
 750  0
                     if (log.isWarnEnabled())
 751  
                     {
 752  0
                         log.warn("Trying to find only a getter for " + propName);
 753  
                     }
 754  
 
 755  0
                     pd = new PropertyDescriptor(propName,
 756  
                             Class.forName(className),
 757  
                             "get" + StringUtils.capitalize(propName),
 758  
                             null); // Java sucks some more.
 759  0
                 }
 760  
 
 761  0
                 getter = pd.getReadMethod();
 762  0
                 gettersForClassName.put(propName, getter);
 763  
 
 764  0
                 if (getter == null)
 765  
                 {
 766  0
                     log.error("Intake: getter for '" + propName
 767  
                             + "' in class '" + className
 768  
                             + "' could not be found.");
 769  
                 }
 770  0
             }
 771  
 
 772  0
             if (pd.getWriteMethod() != null)
 773  
             {
 774  
                 // we have already completed the reflection on the setter, so
 775  
                 // save it so we do not have to repeat
 776  0
                 synchronized (setterMap)
 777  
                 {
 778  0
                     Map settersForClassName = (Map) getterMap.get(className);
 779  
 
 780  0
                     if (settersForClassName != null)
 781  
                     {
 782  
                         try
 783  
                         {
 784  0
                             Method setter = pd.getWriteMethod();
 785  0
                             if (setter != null)
 786  
                             {
 787  0
                                 settersForClassName.put(propName, setter);
 788  
                             }
 789  
                         }
 790  0
                         catch (Exception e)
 791  
                         {
 792  
                             // Do nothing
 793  0
                         }
 794  
                     }
 795  0
                 }
 796  
             }
 797  
         }
 798  0
         return getter;
 799  
     }
 800  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.