Coverage Report - org.codehaus.plexus.component.configurator.converters.composite.CollectionConverter
 
Classes in this File Line Coverage Branch Coverage Complexity
CollectionConverter
77 %
42/54
71 %
20/28
8
 
 1  
 package org.codehaus.plexus.component.configurator.converters.composite;
 2  
 
 3  
 /*
 4  
  * The MIT License
 5  
  *
 6  
  * Copyright (c) 2004, The Codehaus
 7  
  *
 8  
  * Permission is hereby granted, free of charge, to any person obtaining a copy of
 9  
  * this software and associated documentation files (the "Software"), to deal in
 10  
  * the Software without restriction, including without limitation the rights to
 11  
  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 12  
  * of the Software, and to permit persons to whom the Software is furnished to do
 13  
  * so, subject to the following conditions:
 14  
  *
 15  
  * The above copyright notice and this permission notice shall be included in all
 16  
  * copies or substantial portions of the Software.
 17  
  *
 18  
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  
  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 24  
  * SOFTWARE.
 25  
  */
 26  
 
 27  
 import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
 28  
 import org.codehaus.plexus.component.configurator.ConfigurationListener;
 29  
 import org.codehaus.plexus.component.configurator.converters.AbstractConfigurationConverter;
 30  
 import org.codehaus.plexus.component.configurator.converters.ConfigurationConverter;
 31  
 import org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup;
 32  
 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
 33  
 import org.codehaus.plexus.configuration.PlexusConfiguration;
 34  
 import org.codehaus.plexus.util.StringUtils;
 35  
 
 36  
 import java.lang.reflect.Modifier;
 37  
 import java.util.ArrayList;
 38  
 import java.util.Collection;
 39  
 import java.util.HashSet;
 40  
 import java.util.List;
 41  
 import java.util.Map;
 42  
 import java.util.Set;
 43  
 import java.util.SortedSet;
 44  
 import java.util.TreeSet;
 45  
 
 46  
 
 47  
 /**
 48  
  * @author <a href="mailto:michal@codehaus.org">Michal Maczka</a>
 49  
  * @version $Id$
 50  
  */
 51  67
 public class CollectionConverter
 52  
     extends AbstractConfigurationConverter
 53  
 {
 54  
     public boolean canConvert( Class type )
 55  
     {
 56  54
         return Collection.class.isAssignableFrom( type ) && !Map.class.isAssignableFrom( type );
 57  
     }
 58  
 
 59  
     public Object fromConfiguration( ConverterLookup converterLookup, PlexusConfiguration configuration, Class type,
 60  
                                      Class baseType, ClassLoader classLoader, ExpressionEvaluator expressionEvaluator,
 61  
                                      ConfigurationListener listener )
 62  
         throws ComponentConfigurationException
 63  
     {
 64  16
         Object retValue = fromExpression( configuration, expressionEvaluator, type );
 65  16
         if ( retValue != null )
 66  
         {
 67  0
             return retValue;
 68  
         }
 69  
 
 70  16
         Class implementation = getClassForImplementationHint( null, configuration, classLoader );
 71  
 
 72  16
         if ( implementation != null )
 73  
         {
 74  2
             retValue = instantiateObject( implementation );
 75  
         }
 76  
         else
 77  
         {
 78  
             // we can have 2 cases here:
 79  
             //  - provided collection class which is not abstract
 80  
             //     like Vector, ArrayList, HashSet - so we will just instantantiate it
 81  
             // - we have an abtract class so we have to use default collection type
 82  14
             int modifiers = type.getModifiers();
 83  
 
 84  14
             if ( Modifier.isAbstract( modifiers ) )
 85  
             {
 86  10
                 retValue = getDefaultCollection( type );
 87  
             }
 88  
             else
 89  
             {
 90  
                 try
 91  
                 {
 92  4
                     retValue = type.newInstance();
 93  
                 }
 94  0
                 catch ( IllegalAccessException e )
 95  
                 {
 96  0
                     String msg = "An attempt to convert configuration entry " + configuration.getName() + "' into " +
 97  
                         type + " object failed: " + e.getMessage();
 98  
 
 99  0
                     throw new ComponentConfigurationException( msg, e );
 100  
                 }
 101  0
                 catch ( InstantiationException e )
 102  
                 {
 103  0
                     String msg = "An attempt to convert configuration entry " + configuration.getName() + "' into " +
 104  
                         type + " object failed: " + e.getMessage();
 105  
 
 106  0
                     throw new ComponentConfigurationException( msg, e );
 107  4
                 }
 108  
             }
 109  
         }
 110  
         // now we have collection and we have to add some objects to it
 111  
 
 112  38
         for ( int i = 0; i < configuration.getChildCount(); i++ )
 113  
         {
 114  22
             PlexusConfiguration c = configuration.getChild( i );
 115  
             //Object o = null;
 116  
 
 117  22
             String configEntry = c.getName();
 118  
 
 119  22
             String name = fromXML( configEntry );
 120  
 
 121  22
             Class childType = getClassForImplementationHint( null, c, classLoader );
 122  
 
 123  22
             if ( childType == null && name.indexOf( '.' ) > 0 )
 124  
             {
 125  
                 try
 126  
                 {
 127  0
                     childType = classLoader.loadClass( name );
 128  
                 }
 129  0
                 catch ( ClassNotFoundException e )
 130  
                 {
 131  
                     // not found, continue processing
 132  0
                 }
 133  
             }
 134  
 
 135  22
             if ( childType == null )
 136  
             {
 137  
                 // Some classloaders don't create Package objects for classes
 138  
                 // so we have to resort to slicing up the class name
 139  
 
 140  22
                 String baseTypeName = baseType.getName();
 141  
 
 142  22
                 int lastDot = baseTypeName.lastIndexOf( '.' );
 143  
 
 144  
                 String className;
 145  
 
 146  22
                 if ( lastDot == -1 )
 147  
                 {
 148  0
                     className = name;
 149  
                 }
 150  
                 else
 151  
                 {
 152  22
                     String basePackage = baseTypeName.substring( 0, lastDot );
 153  
 
 154  22
                     className = basePackage + "." + StringUtils.capitalizeFirstLetter( name );
 155  
                 }
 156  
 
 157  
                 try
 158  
                 {
 159  22
                     childType = classLoader.loadClass( className );
 160  
                 }
 161  8
                 catch ( ClassNotFoundException e )
 162  
                 {
 163  8
                     if ( c.getChildCount() == 0 )
 164  
                     {
 165  
                         // If no children, try a String.
 166  
                         // TODO: If we had generics we could try that instead - or could the component descriptor list an impl?
 167  8
                         childType = String.class;
 168  
                     }
 169  
                     else
 170  
                     {
 171  0
                         throw new ComponentConfigurationException( "Error loading class '" + className + "'", e );
 172  
                     }
 173  14
                 }
 174  
             }
 175  
 
 176  22
             ConfigurationConverter converter = converterLookup.lookupConverterForType( childType );
 177  
 
 178  22
             Object object = converter.fromConfiguration( converterLookup, c, childType, baseType, classLoader,
 179  
                                                          expressionEvaluator, listener );
 180  
 
 181  22
             Collection collection = (Collection) retValue;
 182  22
             collection.add( object );
 183  
         }
 184  
 
 185  16
         return retValue;
 186  
     }
 187  
 
 188  
     protected Collection getDefaultCollection( Class collectionType )
 189  
     {
 190  10
         Collection retValue = null;
 191  
 
 192  10
         if ( List.class.isAssignableFrom( collectionType ) )
 193  
         {
 194  6
             retValue = new ArrayList();
 195  
         }
 196  4
         else if ( SortedSet.class.isAssignableFrom( collectionType ) )
 197  
         {
 198  2
             retValue = new TreeSet();
 199  
         }
 200  2
         else if ( Set.class.isAssignableFrom( collectionType ) )
 201  
         {
 202  2
             retValue = new HashSet();
 203  
         }
 204  
 
 205  10
         return retValue;
 206  
     }
 207  
 
 208  
 }