From bc738a21f4af778f1937ea2460505cfd6047aecc Mon Sep 17 00:00:00 2001 From: Brett Leslie Porter Date: Thu, 21 Apr 2005 16:16:25 +0000 Subject: [PATCH] move utils to plexus-utils git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@164078 13f79535-47bb-0310-9956-ffa450edef68 --- .../PluginParameterExpressionEvaluator.java | 2 +- .../apache/maven/project/MavenProject.java | 5 +- .../DefaultModelInheritanceAssembler.java | 3 +- .../DefaultModelDefaultsInjector.java | 5 +- .../RegexBasedModelInterpolator.java | 2 +- .../org/apache/maven/util/Xpp3DomUtils.java | 85 --- .../maven/util/introspection/ClassMap.java | 520 ------------------ .../maven/util/introspection/MethodMap.java | 465 ---------------- .../ReflectionValueExtractor.java | 101 ---- .../ReflectionValueExtractorTest.java | 92 ---- 10 files changed, 7 insertions(+), 1273 deletions(-) delete mode 100644 maven-core/src/main/java/org/apache/maven/util/Xpp3DomUtils.java delete mode 100644 maven-core/src/main/java/org/apache/maven/util/introspection/ClassMap.java delete mode 100644 maven-core/src/main/java/org/apache/maven/util/introspection/MethodMap.java delete mode 100644 maven-core/src/main/java/org/apache/maven/util/introspection/ReflectionValueExtractor.java delete mode 100644 maven-core/src/test/java/org/apache/maven/util/introspection/ReflectionValueExtractorTest.java diff --git a/maven-core/src/main/java/org/apache/maven/plugin/PluginParameterExpressionEvaluator.java b/maven-core/src/main/java/org/apache/maven/plugin/PluginParameterExpressionEvaluator.java index 2d723922c6..428f0bc41c 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/PluginParameterExpressionEvaluator.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/PluginParameterExpressionEvaluator.java @@ -18,10 +18,10 @@ package org.apache.maven.plugin; import org.apache.maven.execution.MavenSession; import org.apache.maven.project.path.PathTranslator; -import org.apache.maven.util.introspection.ReflectionValueExtractor; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; +import org.codehaus.plexus.util.introspection.ReflectionValueExtractor; import java.io.File; diff --git a/maven-core/src/main/java/org/apache/maven/project/MavenProject.java b/maven-core/src/main/java/org/apache/maven/project/MavenProject.java index 9374503309..8a934759cb 100644 --- a/maven-core/src/main/java/org/apache/maven/project/MavenProject.java +++ b/maven-core/src/main/java/org/apache/maven/project/MavenProject.java @@ -37,7 +37,6 @@ import org.apache.maven.model.Plugin; import org.apache.maven.model.PluginManagement; import org.apache.maven.model.Reports; import org.apache.maven.model.Scm; -import org.apache.maven.util.Xpp3DomUtils; import org.codehaus.plexus.util.xml.Xpp3Dom; import java.io.File; @@ -739,8 +738,8 @@ public class MavenProject Xpp3Dom goalConfiguration = (Xpp3Dom) goal.getConfiguration(); if ( goalConfiguration != null ) { - Xpp3Dom newDom = Xpp3DomUtils.copyXpp3Dom( goalConfiguration ); - dom = Xpp3DomUtils.mergeXpp3Dom( newDom, dom ); + Xpp3Dom newDom = new Xpp3Dom( goalConfiguration ); + dom = Xpp3Dom.mergeXpp3Dom( newDom, dom ); } break; } diff --git a/maven-core/src/main/java/org/apache/maven/project/inheritance/DefaultModelInheritanceAssembler.java b/maven-core/src/main/java/org/apache/maven/project/inheritance/DefaultModelInheritanceAssembler.java index 2595cadd82..5f3c76d605 100644 --- a/maven-core/src/main/java/org/apache/maven/project/inheritance/DefaultModelInheritanceAssembler.java +++ b/maven-core/src/main/java/org/apache/maven/project/inheritance/DefaultModelInheritanceAssembler.java @@ -26,7 +26,6 @@ import org.apache.maven.model.Plugin; import org.apache.maven.model.PluginManagement; import org.apache.maven.model.Repository; import org.apache.maven.model.Scm; -import org.apache.maven.util.Xpp3DomUtils; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.xml.Xpp3Dom; @@ -273,7 +272,7 @@ public class DefaultModelInheritanceAssembler { Xpp3Dom childDom = (Xpp3Dom) childGoal.getConfiguration(); Xpp3Dom parentDom = (Xpp3Dom) parentGoal.getConfiguration(); - childGoal.setConfiguration( Xpp3DomUtils.mergeXpp3Dom( childDom, parentDom ) ); + childGoal.setConfiguration( Xpp3Dom.mergeXpp3Dom( childDom, parentDom ) ); } } } diff --git a/maven-core/src/main/java/org/apache/maven/project/injection/DefaultModelDefaultsInjector.java b/maven-core/src/main/java/org/apache/maven/project/injection/DefaultModelDefaultsInjector.java index f9358891c0..96a43ce045 100644 --- a/maven-core/src/main/java/org/apache/maven/project/injection/DefaultModelDefaultsInjector.java +++ b/maven-core/src/main/java/org/apache/maven/project/injection/DefaultModelDefaultsInjector.java @@ -22,7 +22,6 @@ import org.apache.maven.model.Goal; import org.apache.maven.model.Model; import org.apache.maven.model.Plugin; import org.apache.maven.model.PluginManagement; -import org.apache.maven.util.Xpp3DomUtils; import org.codehaus.plexus.util.xml.Xpp3Dom; import java.util.ArrayList; @@ -123,7 +122,7 @@ public class DefaultModelDefaultsInjector Xpp3Dom goalConfiguration = (Xpp3Dom) localGoal.getConfiguration(); Xpp3Dom defaultGoalConfiguration = (Xpp3Dom) defaultGoal.getConfiguration(); localGoal.setConfiguration( - Xpp3DomUtils.mergeXpp3Dom( goalConfiguration, defaultGoalConfiguration ) ); + Xpp3Dom.mergeXpp3Dom( goalConfiguration, defaultGoalConfiguration ) ); } } } @@ -132,7 +131,7 @@ public class DefaultModelDefaultsInjector Xpp3Dom pluginConfiguration = (Xpp3Dom) plugin.getConfiguration(); Xpp3Dom defaultPluginConfiguration = (Xpp3Dom) def.getConfiguration(); - plugin.setConfiguration( Xpp3DomUtils.mergeXpp3Dom( pluginConfiguration, defaultPluginConfiguration ) ); + plugin.setConfiguration( Xpp3Dom.mergeXpp3Dom( pluginConfiguration, defaultPluginConfiguration ) ); } private void injectDependencyDefaults( List dependencies, DependencyManagement dependencyManagement ) diff --git a/maven-core/src/main/java/org/apache/maven/project/interpolation/RegexBasedModelInterpolator.java b/maven-core/src/main/java/org/apache/maven/project/interpolation/RegexBasedModelInterpolator.java index dd2ca0afea..7f9a0ab9d5 100644 --- a/maven-core/src/main/java/org/apache/maven/project/interpolation/RegexBasedModelInterpolator.java +++ b/maven-core/src/main/java/org/apache/maven/project/interpolation/RegexBasedModelInterpolator.java @@ -19,10 +19,10 @@ package org.apache.maven.project.interpolation; import org.apache.maven.model.Model; import org.apache.maven.model.io.xpp3.MavenXpp3Reader; import org.apache.maven.model.io.xpp3.MavenXpp3Writer; -import org.apache.maven.util.introspection.ReflectionValueExtractor; import org.codehaus.plexus.logging.AbstractLogEnabled; import org.codehaus.plexus.logging.Logger; import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.introspection.ReflectionValueExtractor; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import java.io.IOException; diff --git a/maven-core/src/main/java/org/apache/maven/util/Xpp3DomUtils.java b/maven-core/src/main/java/org/apache/maven/util/Xpp3DomUtils.java deleted file mode 100644 index 85078ad0b6..0000000000 --- a/maven-core/src/main/java/org/apache/maven/util/Xpp3DomUtils.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.apache.maven.util; - -import org.codehaus.plexus.util.xml.Xpp3Dom; - -/* - * Copyright 2001-2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * TODO: describe - * - * @author Brett Porter - * @version $Id$ - */ -public class Xpp3DomUtils -{ - private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive ) - { - // TODO: how to mergeXpp3Dom lists rather than override? - // TODO: share this as some sort of assembler, implement a walk interface? - if ( recessive == null ) - { - return; - } - - Xpp3Dom[] children = recessive.getChildren(); - for ( int i = 0; i < children.length; i++ ) - { - Xpp3Dom child = children[i]; - Xpp3Dom childDom = dominant.getChild( child.getName() ); - if ( childDom != null ) - { - mergeIntoXpp3Dom( childDom, child ); - } - else - { - dominant.addChild( copyXpp3Dom( child ) ); - } - } - } - - public static Xpp3Dom copyXpp3Dom( Xpp3Dom src ) - { - // TODO: into Xpp3Dom as a copy constructor - Xpp3Dom dom = new Xpp3Dom( src.getName() ); - dom.setValue( src.getValue() ); - - String[] attributeNames = src.getAttributeNames(); - for ( int i = 0; i < attributeNames.length; i++ ) - { - String attributeName = attributeNames[i]; - dom.setAttribute( attributeName, src.getAttribute( attributeName ) ); - } - - Xpp3Dom[] children = src.getChildren(); - for ( int i = 0; i < children.length; i++ ) - { - dom.addChild( copyXpp3Dom( children[i] ) ); - } - - return dom; - } - - public static Xpp3Dom mergeXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive ) - { - if ( dominant != null ) - { - mergeIntoXpp3Dom( dominant, recessive ); - return dominant; - } - return recessive; - } -} diff --git a/maven-core/src/main/java/org/apache/maven/util/introspection/ClassMap.java b/maven-core/src/main/java/org/apache/maven/util/introspection/ClassMap.java deleted file mode 100644 index b337ba85a0..0000000000 --- a/maven-core/src/main/java/org/apache/maven/util/introspection/ClassMap.java +++ /dev/null @@ -1,520 +0,0 @@ -package org.apache.maven.util.introspection; - -/* ==================================================================== - * Copyright 2001-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Hashtable; -import java.util.Map; - -/** - * A cache of introspection information for a specific class instance. - * Keys {@link java.lang.Method} objects by a concatenation of the - * method name and the names of classes that make up the parameters. - * - * @author Jason van Zyl - * @author Bob McWhirter - * @author Attila Szegedi - * @author Geir Magnusson Jr. - * @version $Id$ - */ -public class ClassMap -{ - private static final class CacheMiss - { - } - - private static final CacheMiss CACHE_MISS = new CacheMiss(); - private static final Object OBJECT = new Object(); - - /** - * Class passed into the constructor used to as - * the basis for the Method map. - */ - - private Class clazz; - - /** - * Cache of Methods, or CACHE_MISS, keyed by method - * name and actual arguments used to find it. - */ - private Map methodCache = new Hashtable(); - - private MethodMap methodMap = new MethodMap(); - - /** - * Standard constructor - */ - public ClassMap( Class clazz ) - { - this.clazz = clazz; - populateMethodCache(); - } - - /** - * @return the class object whose methods are cached by this map. - */ - Class getCachedClass() - { - return clazz; - } - - /** - * Find a Method using the methodKey - * provided. - *

- * Look in the methodMap for an entry. If found, - * it'll either be a CACHE_MISS, in which case we - * simply give up, or it'll be a Method, in which - * case, we return it. - *

- * If nothing is found, then we must actually go - * and introspect the method from the MethodMap. - */ - public Method findMethod( String name, Object[] params ) - throws MethodMap.AmbiguousException - { - String methodKey = makeMethodKey( name, params ); - Object cacheEntry = methodCache.get( methodKey ); - - if ( cacheEntry == CACHE_MISS ) - { - return null; - } - - if ( cacheEntry == null ) - { - try - { - cacheEntry = methodMap.find( name, - params ); - } - catch ( MethodMap.AmbiguousException ae ) - { - /* - * that's a miss :) - */ - - methodCache.put( methodKey, - CACHE_MISS ); - - throw ae; - } - - if ( cacheEntry == null ) - { - methodCache.put( methodKey, - CACHE_MISS ); - } - else - { - methodCache.put( methodKey, - cacheEntry ); - } - } - - // Yes, this might just be null. - - return (Method) cacheEntry; - } - - /** - * Populate the Map of direct hits. These - * are taken from all the public methods - * that our class provides. - */ - private void populateMethodCache() - { - StringBuffer methodKey; - - /* - * get all publicly accessible methods - */ - - Method[] methods = getAccessibleMethods( clazz ); - - /* - * map and cache them - */ - - for ( int i = 0; i < methods.length; i++ ) - { - Method method = methods[i]; - - /* - * now get the 'public method', the method declared by a - * public interface or class. (because the actual implementing - * class may be a facade... - */ - - Method publicMethod = getPublicMethod( method ); - - /* - * it is entirely possible that there is no public method for - * the methods of this class (i.e. in the facade, a method - * that isn't on any of the interfaces or superclass - * in which case, ignore it. Otherwise, map and cache - */ - - if ( publicMethod != null ) - { - methodMap.add( publicMethod ); - methodCache.put( makeMethodKey( publicMethod ), publicMethod ); - } - } - } - - /** - * Make a methodKey for the given method using - * the concatenation of the name and the - * types of the method parameters. - */ - private String makeMethodKey( Method method ) - { - Class[] parameterTypes = method.getParameterTypes(); - - StringBuffer methodKey = new StringBuffer( method.getName() ); - - for ( int j = 0; j < parameterTypes.length; j++ ) - { - /* - * If the argument type is primitive then we want - * to convert our primitive type signature to the - * corresponding Object type so introspection for - * methods with primitive types will work correctly. - */ - if ( parameterTypes[j].isPrimitive() ) - { - if ( parameterTypes[j].equals( Boolean.TYPE ) ) - methodKey.append( "java.lang.Boolean" ); - else if ( parameterTypes[j].equals( Byte.TYPE ) ) - methodKey.append( "java.lang.Byte" ); - else if ( parameterTypes[j].equals( Character.TYPE ) ) - methodKey.append( "java.lang.Character" ); - else if ( parameterTypes[j].equals( Double.TYPE ) ) - methodKey.append( "java.lang.Double" ); - else if ( parameterTypes[j].equals( Float.TYPE ) ) - methodKey.append( "java.lang.Float" ); - else if ( parameterTypes[j].equals( Integer.TYPE ) ) - methodKey.append( "java.lang.Integer" ); - else if ( parameterTypes[j].equals( Long.TYPE ) ) - methodKey.append( "java.lang.Long" ); - else if ( parameterTypes[j].equals( Short.TYPE ) ) - methodKey.append( "java.lang.Short" ); - } - else - { - methodKey.append( parameterTypes[j].getName() ); - } - } - - return methodKey.toString(); - } - - private static String makeMethodKey( String method, Object[] params ) - { - StringBuffer methodKey = new StringBuffer().append( method ); - - for ( int j = 0; j < params.length; j++ ) - { - Object arg = params[j]; - - if ( arg == null ) - { - arg = OBJECT; - } - - methodKey.append( arg.getClass().getName() ); - } - - return methodKey.toString(); - } - - /** - * Retrieves public methods for a class. In case the class is not - * public, retrieves methods with same signature as its public methods - * from public superclasses and interfaces (if they exist). Basically - * upcasts every method to the nearest acccessible method. - */ - private static Method[] getAccessibleMethods( Class clazz ) - { - Method[] methods = clazz.getMethods(); - - /* - * Short circuit for the (hopefully) majority of cases where the - * clazz is public - */ - - if ( Modifier.isPublic( clazz.getModifiers() ) ) - { - return methods; - } - - /* - * No luck - the class is not public, so we're going the longer way. - */ - - MethodInfo[] methodInfos = new MethodInfo[methods.length]; - - for ( int i = methods.length; i-- > 0; ) - { - methodInfos[i] = new MethodInfo( methods[i] ); - } - - int upcastCount = getAccessibleMethods( clazz, methodInfos, 0 ); - - /* - * Reallocate array in case some method had no accessible counterpart. - */ - - if ( upcastCount < methods.length ) - { - methods = new Method[upcastCount]; - } - - int j = 0; - for ( int i = 0; i < methodInfos.length; ++i ) - { - MethodInfo methodInfo = methodInfos[i]; - if ( methodInfo.upcast ) - { - methods[j++] = methodInfo.method; - } - } - return methods; - } - - /** - * Recursively finds a match for each method, starting with the class, and then - * searching the superclass and interfaces. - * - * @param clazz Class to check - * @param methodInfos array of methods we are searching to match - * @param upcastCount current number of methods we have matched - * @return count of matched methods - */ - private static int getAccessibleMethods( Class clazz, MethodInfo[] methodInfos, int upcastCount ) - { - int l = methodInfos.length; - - /* - * if this class is public, then check each of the currently - * 'non-upcasted' methods to see if we have a match - */ - - if ( Modifier.isPublic( clazz.getModifiers() ) ) - { - for ( int i = 0; i < l && upcastCount < l; ++i ) - { - try - { - MethodInfo methodInfo = methodInfos[i]; - - if ( !methodInfo.upcast ) - { - methodInfo.tryUpcasting( clazz ); - upcastCount++; - } - } - catch ( NoSuchMethodException e ) - { - /* - * Intentionally ignored - it means - * it wasn't found in the current class - */ - } - } - - /* - * Short circuit if all methods were upcast - */ - - if ( upcastCount == l ) - { - return upcastCount; - } - } - - /* - * Examine superclass - */ - - Class superclazz = clazz.getSuperclass(); - - if ( superclazz != null ) - { - upcastCount = getAccessibleMethods( superclazz, methodInfos, upcastCount ); - - /* - * Short circuit if all methods were upcast - */ - - if ( upcastCount == l ) - { - return upcastCount; - } - } - - /* - * Examine interfaces. Note we do it even if superclazz == null. - * This is redundant as currently java.lang.Object does not implement - * any interfaces, however nothing guarantees it will not in future. - */ - - Class[] interfaces = clazz.getInterfaces(); - - for ( int i = interfaces.length; i-- > 0; ) - { - upcastCount = getAccessibleMethods( interfaces[i], methodInfos, upcastCount ); - - /* - * Short circuit if all methods were upcast - */ - - if ( upcastCount == l ) - { - return upcastCount; - } - } - - return upcastCount; - } - - /** - * For a given method, retrieves its publicly accessible counterpart. - * This method will look for a method with same name - * and signature declared in a public superclass or implemented interface of this - * method's declaring class. This counterpart method is publicly callable. - * - * @param method a method whose publicly callable counterpart is requested. - * @return the publicly callable counterpart method. Note that if the parameter - * method is itself declared by a public class, this method is an identity - * function. - */ - public static Method getPublicMethod( Method method ) - { - Class clazz = method.getDeclaringClass(); - - /* - * Short circuit for (hopefully the majority of) cases where the declaring - * class is public. - */ - - if ( ( clazz.getModifiers() & Modifier.PUBLIC ) != 0 ) - { - return method; - } - - return getPublicMethod( clazz, method.getName(), method.getParameterTypes() ); - } - - /** - * Looks up the method with specified name and signature in the first public - * superclass or implemented interface of the class. - * - * @param class the class whose method is sought - * @param name the name of the method - * @param paramTypes the classes of method parameters - */ - private static Method getPublicMethod( Class clazz, String name, Class[] paramTypes ) - { - /* - * if this class is public, then try to get it - */ - - if ( ( clazz.getModifiers() & Modifier.PUBLIC ) != 0 ) - { - try - { - return clazz.getMethod( name, paramTypes ); - } - catch ( NoSuchMethodException e ) - { - /* - * If the class does not have the method, then neither its - * superclass nor any of its interfaces has it so quickly return - * null. - */ - return null; - } - } - - /* - * try the superclass - */ - - - Class superclazz = clazz.getSuperclass(); - - if ( superclazz != null ) - { - Method superclazzMethod = getPublicMethod( superclazz, name, paramTypes ); - - if ( superclazzMethod != null ) - { - return superclazzMethod; - } - } - - /* - * and interfaces - */ - - Class[] interfaces = clazz.getInterfaces(); - - for ( int i = 0; i < interfaces.length; ++i ) - { - Method interfaceMethod = getPublicMethod( interfaces[i], name, paramTypes ); - - if ( interfaceMethod != null ) - { - return interfaceMethod; - } - } - - return null; - } - - /** - * Used for the iterative discovery process for public methods. - */ - private static final class MethodInfo - { - Method method; - String name; - Class[] parameterTypes; - boolean upcast; - - MethodInfo( Method method ) - { - this.method = null; - name = method.getName(); - parameterTypes = method.getParameterTypes(); - upcast = false; - } - - void tryUpcasting( Class clazz ) - throws NoSuchMethodException - { - method = clazz.getMethod( name, parameterTypes ); - name = null; - parameterTypes = null; - upcast = true; - } - } -} diff --git a/maven-core/src/main/java/org/apache/maven/util/introspection/MethodMap.java b/maven-core/src/main/java/org/apache/maven/util/introspection/MethodMap.java deleted file mode 100644 index 34b7d4538a..0000000000 --- a/maven-core/src/main/java/org/apache/maven/util/introspection/MethodMap.java +++ /dev/null @@ -1,465 +0,0 @@ -package org.apache.maven.util.introspection; - -/* ==================================================================== - * Copyright 2001-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -/** - * - * @author Jason van Zyl - * @author Bob McWhirter - * @author Christoph Reck - * @author Geir Magnusson Jr. - * @author Attila Szegedi - * @version $Id$ - */ -public class MethodMap -{ - private static final int MORE_SPECIFIC = 0; - private static final int LESS_SPECIFIC = 1; - private static final int INCOMPARABLE = 2; - - /** - * Keep track of all methods with the same name. - */ - Map methodByNameMap = new Hashtable(); - - /** - * Add a method to a list of methods by name. - * For a particular class we are keeping track - * of all the methods with the same name. - */ - public void add(Method method) - { - String methodName = method.getName(); - - List l = get( methodName ); - - if ( l == null) - { - l = new ArrayList(); - methodByNameMap.put(methodName, l); - } - - l.add(method); - - return; - } - - /** - * Return a list of methods with the same name. - * - * @param String key - * @return List list of methods - */ - public List get(String key) - { - return (List) methodByNameMap.get(key); - } - - /** - *

- * Find a method. Attempts to find the - * most specific applicable method using the - * algorithm described in the JLS section - * 15.12.2 (with the exception that it can't - * distinguish a primitive type argument from - * an object type argument, since in reflection - * primitive type arguments are represented by - * their object counterparts, so for an argument of - * type (say) java.lang.Integer, it will not be able - * to decide between a method that takes int and a - * method that takes java.lang.Integer as a parameter. - *

- * - *

- * This turns out to be a relatively rare case - * where this is needed - however, functionality - * like this is needed. - *

- * - * @param methodName name of method - * @param args the actual arguments with which the method is called - * @return the most specific applicable method, or null if no - * method is applicable. - * @throws AmbiguousException if there is more than one maximally - * specific applicable method - */ - public Method find(String methodName, Object[] args) - throws AmbiguousException - { - List methodList = get(methodName); - - if (methodList == null) - { - return null; - } - - int l = args.length; - Class[] classes = new Class[l]; - - for(int i = 0; i < l; ++i) - { - Object arg = args[i]; - - /* - * if we are careful down below, a null argument goes in there - * so we can know that the null was passed to the method - */ - classes[i] = - arg == null ? null : arg.getClass(); - } - - return getMostSpecific(methodList, classes); - } - - /** - * simple distinguishable exception, used when - * we run across ambiguous overloading - */ - public static class AmbiguousException extends Exception - { - } - - - private static Method getMostSpecific(List methods, Class[] classes) - throws AmbiguousException - { - LinkedList applicables = getApplicables(methods, classes); - - if(applicables.isEmpty()) - { - return null; - } - - if(applicables.size() == 1) - { - return (Method)applicables.getFirst(); - } - - /* - * This list will contain the maximally specific methods. Hopefully at - * the end of the below loop, the list will contain exactly one method, - * (the most specific method) otherwise we have ambiguity. - */ - - LinkedList maximals = new LinkedList(); - - for (Iterator applicable = applicables.iterator(); - applicable.hasNext();) - { - Method app = (Method) applicable.next(); - Class[] appArgs = app.getParameterTypes(); - boolean lessSpecific = false; - - for (Iterator maximal = maximals.iterator(); - !lessSpecific && maximal.hasNext();) - { - Method max = (Method) maximal.next(); - - switch(moreSpecific(appArgs, max.getParameterTypes())) - { - case MORE_SPECIFIC: - { - /* - * This method is more specific than the previously - * known maximally specific, so remove the old maximum. - */ - - maximal.remove(); - break; - } - - case LESS_SPECIFIC: - { - /* - * This method is less specific than some of the - * currently known maximally specific methods, so we - * won't add it into the set of maximally specific - * methods - */ - - lessSpecific = true; - break; - } - } - } - - if(!lessSpecific) - { - maximals.addLast(app); - } - } - - if(maximals.size() > 1) - { - // We have more than one maximally specific method - throw new AmbiguousException(); - } - - return (Method)maximals.getFirst(); - } - - /** - * Determines which method signature (represented by a class array) is more - * specific. This defines a partial ordering on the method signatures. - * @param c1 first signature to compare - * @param c2 second signature to compare - * @return MORE_SPECIFIC if c1 is more specific than c2, LESS_SPECIFIC if - * c1 is less specific than c2, INCOMPARABLE if they are incomparable. - */ - private static int moreSpecific(Class[] c1, Class[] c2) - { - boolean c1MoreSpecific = false; - boolean c2MoreSpecific = false; - - for(int i = 0; i < c1.length; ++i) - { - if(c1[i] != c2[i]) - { - c1MoreSpecific = - c1MoreSpecific || - isStrictMethodInvocationConvertible(c2[i], c1[i]); - c2MoreSpecific = - c2MoreSpecific || - isStrictMethodInvocationConvertible(c1[i], c2[i]); - } - } - - if(c1MoreSpecific) - { - if(c2MoreSpecific) - { - /* - * Incomparable due to cross-assignable arguments (i.e. - * foo(String, Object) vs. foo(Object, String)) - */ - - return INCOMPARABLE; - } - - return MORE_SPECIFIC; - } - - if(c2MoreSpecific) - { - return LESS_SPECIFIC; - } - - /* - * Incomparable due to non-related arguments (i.e. - * foo(Runnable) vs. foo(Serializable)) - */ - - return INCOMPARABLE; - } - - /** - * Returns all methods that are applicable to actual argument types. - * @param methods list of all candidate methods - * @param classes the actual types of the arguments - * @return a list that contains only applicable methods (number of - * formal and actual arguments matches, and argument types are assignable - * to formal types through a method invocation conversion). - */ - private static LinkedList getApplicables(List methods, Class[] classes) - { - LinkedList list = new LinkedList(); - - for (Iterator imethod = methods.iterator(); imethod.hasNext();) - { - Method method = (Method) imethod.next(); - - if(isApplicable(method, classes)) - { - list.add(method); - } - - } - return list; - } - - /** - * Returns true if the supplied method is applicable to actual - * argument types. - */ - private static boolean isApplicable(Method method, Class[] classes) - { - Class[] methodArgs = method.getParameterTypes(); - - if(methodArgs.length != classes.length) - { - return false; - } - - for(int i = 0; i < classes.length; ++i) - { - if(!isMethodInvocationConvertible(methodArgs[i], classes[i])) - { - return false; - } - } - - return true; - } - - /** - * Determines whether a type represented by a class object is - * convertible to another type represented by a class object using a - * method invocation conversion, treating object types of primitive - * types as if they were primitive types (that is, a Boolean actual - * parameter type matches boolean primitive formal type). This behavior - * is because this method is used to determine applicable methods for - * an actual parameter list, and primitive types are represented by - * their object duals in reflective method calls. - * - * @param formal the formal parameter type to which the actual - * parameter type should be convertible - * @param actual the actual parameter type. - * @return true if either formal type is assignable from actual type, - * or formal is a primitive type and actual is its corresponding object - * type or an object type of a primitive type that can be converted to - * the formal type. - */ - private static boolean isMethodInvocationConvertible(Class formal, - Class actual) - { - /* - * if it's a null, it means the arg was null - */ - if (actual == null && !formal.isPrimitive()) - { - return true; - } - - /* - * Check for identity or widening reference conversion - */ - - if (actual != null && formal.isAssignableFrom(actual)) - { - return true; - } - - /* - * Check for boxing with widening primitive conversion. Note that - * actual parameters are never primitives. - */ - - if (formal.isPrimitive()) - { - if(formal == Boolean.TYPE && actual == Boolean.class) - return true; - if(formal == Character.TYPE && actual == Character.class) - return true; - if(formal == Byte.TYPE && actual == Byte.class) - return true; - if(formal == Short.TYPE && - (actual == Short.class || actual == Byte.class)) - return true; - if(formal == Integer.TYPE && - (actual == Integer.class || actual == Short.class || - actual == Byte.class)) - return true; - if(formal == Long.TYPE && - (actual == Long.class || actual == Integer.class || - actual == Short.class || actual == Byte.class)) - return true; - if(formal == Float.TYPE && - (actual == Float.class || actual == Long.class || - actual == Integer.class || actual == Short.class || - actual == Byte.class)) - return true; - if(formal == Double.TYPE && - (actual == Double.class || actual == Float.class || - actual == Long.class || actual == Integer.class || - actual == Short.class || actual == Byte.class)) - return true; - } - - return false; - } - - /** - * Determines whether a type represented by a class object is - * convertible to another type represented by a class object using a - * method invocation conversion, without matching object and primitive - * types. This method is used to determine the more specific type when - * comparing signatures of methods. - * - * @param formal the formal parameter type to which the actual - * parameter type should be convertible - * @param actual the actual parameter type. - * @return true if either formal type is assignable from actual type, - * or formal and actual are both primitive types and actual can be - * subject to widening conversion to formal. - */ - private static boolean isStrictMethodInvocationConvertible(Class formal, - Class actual) - { - /* - * we shouldn't get a null into, but if so - */ - if (actual == null && !formal.isPrimitive()) - { - return true; - } - - /* - * Check for identity or widening reference conversion - */ - - if(formal.isAssignableFrom(actual)) - { - return true; - } - - /* - * Check for widening primitive conversion. - */ - - if(formal.isPrimitive()) - { - if(formal == Short.TYPE && (actual == Byte.TYPE)) - return true; - if(formal == Integer.TYPE && - (actual == Short.TYPE || actual == Byte.TYPE)) - return true; - if(formal == Long.TYPE && - (actual == Integer.TYPE || actual == Short.TYPE || - actual == Byte.TYPE)) - return true; - if(formal == Float.TYPE && - (actual == Long.TYPE || actual == Integer.TYPE || - actual == Short.TYPE || actual == Byte.TYPE)) - return true; - if(formal == Double.TYPE && - (actual == Float.TYPE || actual == Long.TYPE || - actual == Integer.TYPE || actual == Short.TYPE || - actual == Byte.TYPE)) - return true; - } - return false; - } -} diff --git a/maven-core/src/main/java/org/apache/maven/util/introspection/ReflectionValueExtractor.java b/maven-core/src/main/java/org/apache/maven/util/introspection/ReflectionValueExtractor.java deleted file mode 100644 index 487d89f0ce..0000000000 --- a/maven-core/src/main/java/org/apache/maven/util/introspection/ReflectionValueExtractor.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.apache.maven.util.introspection; - -/* - * Copyright 2001-2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; -import java.util.StringTokenizer; - -import org.codehaus.plexus.util.StringUtils; - -/** - * Using simple dotted expressions extract the values from a MavenProject - * instance, For example we might want to extract a value like: - * project.build.sourceDirectory - * - * @author Jason van Zyl - * @version $Id$ - */ -public class ReflectionValueExtractor -{ - private static Class[] args = new Class[ 0 ]; - - private static Object[] params = new Object[ 0 ]; - - private static ClassMap classMap; - - private static Map classMaps = new HashMap(); - - private ReflectionValueExtractor() - { - } - - // TODO: don't throw Exception - public static Object evaluate( String expression, Object root ) - throws Exception - { - // ---------------------------------------------------------------------- - // Remove the leading "project" token - // ---------------------------------------------------------------------- - - expression = expression.substring( expression.indexOf( '.' ) + 1 ); - - Object value = root; - - // ---------------------------------------------------------------------- - // Walk the dots and retrieve the ultimate value desired from the - // MavenProject instance. - // ---------------------------------------------------------------------- - - StringTokenizer parser = new StringTokenizer( expression, "." ); - - while ( parser.hasMoreTokens() ) - { - String token = parser.nextToken(); - - classMap = getClassMap( value.getClass() ); - - String methodName = "get" + StringUtils.capitalizeFirstLetter( token ); - - Method method = classMap.findMethod( methodName, args ); - - if ( method == null ) - { - return null; - } - - value = method.invoke( value, params ); - } - - return value; - } - - private static ClassMap getClassMap( Class clazz ) - { - classMap = (ClassMap) classMaps.get( clazz ); - - if ( classMap == null ) - { - classMap = new ClassMap( clazz ); - - classMaps.put( clazz, classMap ); - } - - return classMap; - } -} diff --git a/maven-core/src/test/java/org/apache/maven/util/introspection/ReflectionValueExtractorTest.java b/maven-core/src/test/java/org/apache/maven/util/introspection/ReflectionValueExtractorTest.java deleted file mode 100644 index 1137dba4e1..0000000000 --- a/maven-core/src/test/java/org/apache/maven/util/introspection/ReflectionValueExtractorTest.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.apache.maven.util.introspection; - -/* - * Copyright 2001-2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import org.apache.maven.MavenTestCase; -import org.apache.maven.model.Build; -import org.apache.maven.project.MavenProject; - -import java.io.File; -import java.util.List; - -/** - * @author Jason van Zyl - * @version $Id$ - */ -public class ReflectionValueExtractorTest - extends MavenTestCase -{ - private MavenProject project; - - protected void setUp() - throws Exception - { - super.setUp(); - - File f = getFileForClasspathResource( "pom.xml" ); - - project = getProject( f ); - } - - public void testValueExtraction() - throws Exception - { - // ---------------------------------------------------------------------- - // Top level values - // ---------------------------------------------------------------------- - - assertEquals( "4.0.0", ReflectionValueExtractor.evaluate( "project.modelVersion", project ) ); - - assertEquals( "org.apache.maven", ReflectionValueExtractor.evaluate( "project.groupId", project ) ); - - assertEquals( "maven-core", ReflectionValueExtractor.evaluate( "project.artifactId", project ) ); - - assertEquals( "Maven", ReflectionValueExtractor.evaluate( "project.name", project ) ); - - assertEquals( "2.0-SNAPSHOT", ReflectionValueExtractor.evaluate( "project.version", project ) ); - - // ---------------------------------------------------------------------- - // SCM - // ---------------------------------------------------------------------- - - assertEquals( "scm-connection", ReflectionValueExtractor.evaluate( "project.scm.connection", project ) ); - - // ---------------------------------------------------------------------- - // Dependencies - // ---------------------------------------------------------------------- - - List dependencies = (List) ReflectionValueExtractor.evaluate( "project.dependencies", project ); - - assertNotNull( dependencies ); - - assertEquals( 2, dependencies.size() ); - - // ---------------------------------------------------------------------- - // Build - // ---------------------------------------------------------------------- - - Build build = (Build) ReflectionValueExtractor.evaluate( "project.build", project ); - - assertNotNull( build ); - } - - public void testValueExtractorWithAInvalidExpression() - throws Exception - { - assertNull( ReflectionValueExtractor.evaluate( "project.foo", project ) ); - } -}