You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by dj...@apache.org on 2009/10/05 20:54:56 UTC
svn commit: r821961 [23/30] - in /geronimo/sandbox/djencks/osgi/framework:
./ buildsupport/ buildsupport/car-maven-plugin/
buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/
buildsupport/geronimo-maven-plugin/src/main/jav...
Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/DAG.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/DAG.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/DAG.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/DAG.java Mon Oct 5 18:54:50 2009
@@ -0,0 +1,266 @@
+package org.apache.geronimo.system.plugin.plexus.util.dag;
+
+/*
+ * Copyright The Codehaus 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.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * DAG = Directed Acyclic Graph
+ *
+ * @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
+ * @version $Id: DAG.java 8010 2009-01-07 12:59:50Z vsiveton $
+ * @todo this class should be reanmed from DAG to Dag
+ */
+public class DAG implements Cloneable, Serializable
+{
+ //------------------------------------------------------------
+ //Fields
+ //------------------------------------------------------------
+ /**
+ * Nodes will be kept in two data strucures at the same time
+ * for faster processing
+ */
+ /**
+ * Maps vertex's label to vertex
+ */
+ private Map vertexMap = new HashMap();
+
+ /**
+ * Conatin list of all verticies
+ */
+ private List vertexList = new ArrayList();
+
+ // ------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------
+
+ /**
+ *
+ */
+ public DAG()
+ {
+ super();
+ }
+
+ // ------------------------------------------------------------
+ // Accessors
+ // ------------------------------------------------------------
+
+ /**
+ * @return
+ */
+ public List getVerticies()
+ {
+ return vertexList;
+ }
+
+
+ public Set getLabels()
+ {
+ final Set retValue = vertexMap.keySet();
+
+ return retValue;
+ }
+
+ // ------------------------------------------------------------
+ // Implementation
+ // ------------------------------------------------------------
+
+ /**
+ * Adds vertex to DAG. If vertex of given label alredy exist in DAG
+ * no vertex is added
+ *
+ * @param label The lable of the Vertex
+ * @return New vertex if vertext of given label was not presenst in the DAG
+ * or exising vertex if vertex of given labale was alredy added to DAG
+ */
+ public Vertex addVertex( final String label )
+ {
+ Vertex retValue = null;
+
+ // check if vertex is alredy in DAG
+ if ( vertexMap.containsKey( label ) )
+ {
+ retValue = ( Vertex ) vertexMap.get( label );
+ }
+ else
+ {
+ retValue = new Vertex( label );
+
+ vertexMap.put( label, retValue );
+
+ vertexList.add( retValue );
+ }
+
+ return retValue;
+ }
+
+ public void addEdge( final String from, final String to ) throws CycleDetectedException
+ {
+ final Vertex v1 = addVertex( from );
+
+ final Vertex v2 = addVertex( to );
+
+ addEdge( v1, v2 );
+ }
+
+ public void addEdge( final Vertex from, final Vertex to ) throws CycleDetectedException
+ {
+
+ from.addEdgeTo( to );
+
+ to.addEdgeFrom( from );
+
+ final List cycle = CycleDetector.introducesCycle( to );
+
+ if ( cycle != null )
+ {
+ // remove edge which introduced cycle
+
+ removeEdge( from, to );
+
+ final String msg = "Edge between '" + from + "' and '" + to + "' introduces to cycle in the graph";
+
+ throw new CycleDetectedException( msg, cycle );
+ }
+ }
+
+
+ public void removeEdge( final String from, final String to )
+ {
+ final Vertex v1 = addVertex( from );
+
+ final Vertex v2 = addVertex( to );
+
+ removeEdge( v1, v2 );
+ }
+
+ public void removeEdge( final Vertex from, final Vertex to )
+ {
+ from.removeEdgeTo( to );
+
+ to.removeEdgeFrom( from );
+ }
+
+
+ public Vertex getVertex( final String label )
+ {
+ final Vertex retValue = ( Vertex ) vertexMap.get( label );
+
+ return retValue;
+ }
+
+ public boolean hasEdge( final String label1, final String label2 )
+ {
+ final Vertex v1 = getVertex( label1 );
+
+ final Vertex v2 = getVertex( label2 );
+
+ final boolean retValue = v1.getChildren().contains( v2 );
+
+ return retValue;
+
+ }
+
+ /**
+ * @param label
+ * @return
+ */
+ public List getChildLabels( final String label )
+ {
+ final Vertex vertex = getVertex( label );
+
+ return vertex.getChildLabels();
+ }
+
+ /**
+ * @param label
+ * @return
+ */
+ public List getParentLabels( final String label )
+ {
+ final Vertex vertex = getVertex( label );
+
+ return vertex.getParentLabels();
+ }
+
+
+ /**
+ * @see java.lang.Object#clone()
+ */
+ public Object clone() throws CloneNotSupportedException
+ {
+ // this is what's failing..
+ final Object retValue = super.clone();
+
+ return retValue;
+ }
+
+
+ /**
+ * Indicates if there is at least one edge leading to or from vertex of given label
+ *
+ * @return <code>true</true> if this vertex is connected with other vertex,<code>false</code> otherwise
+ */
+ public boolean isConnected( final String label )
+ {
+ final Vertex vertex = getVertex( label );
+
+ final boolean retValue = vertex.isConnected();
+
+ return retValue;
+
+ }
+
+
+ /**
+ * Return the list of labels of successor in order decided by topological sort
+ *
+ * @param label The label of the vertex whose predessors are serched
+ *
+ * @return The list of labels. Returned list contains also
+ * the label passed as parameter to this method. This label should
+ * always be the last item in the list.
+ */
+ public List getSuccessorLabels( final String label )
+ {
+ final Vertex vertex = getVertex( label );
+
+ final List retValue;
+
+ //optimization.
+ if ( vertex.isLeaf() )
+ {
+ retValue = new ArrayList( 1 );
+
+ retValue.add( label );
+ }
+ else
+ {
+ retValue = TopologicalSorter.sort( vertex );
+ }
+
+ return retValue;
+ }
+
+
+}
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/DAG.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/DAG.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/DAG.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/TopologicalSorter.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/TopologicalSorter.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/TopologicalSorter.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/TopologicalSorter.java Mon Oct 5 18:54:50 2009
@@ -0,0 +1,122 @@
+package org.apache.geronimo.system.plugin.plexus.util.dag;
+
+/*
+ * Copyright The Codehaus 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.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
+ * @version $Id: TopologicalSorter.java 8010 2009-01-07 12:59:50Z vsiveton $
+ */
+public class TopologicalSorter
+{
+
+ private final static Integer NOT_VISTITED = new Integer( 0 );
+
+ private final static Integer VISITING = new Integer( 1 );
+
+ private final static Integer VISITED = new Integer( 2 );
+
+ /**
+ * @param graph
+ * @return List of String (vertex labels)
+ */
+
+ public static List sort( final DAG graph )
+ {
+ return dfs( graph );
+ }
+
+ public static List sort( final Vertex vertex )
+ {
+ // we need to use addFirst method so we will use LinkedList explicitly
+ final LinkedList retValue = new LinkedList();
+
+ final Map vertexStateMap = new HashMap();
+
+ dfsVisit( vertex, vertexStateMap, retValue );
+
+ return retValue;
+ }
+
+
+ private static List dfs( final DAG graph )
+ {
+ final List verticies = graph.getVerticies();
+
+ // we need to use addFirst method so we will use LinkedList explicitly
+ final LinkedList retValue = new LinkedList();
+
+ final Map vertexStateMap = new HashMap();
+
+ for ( final Iterator iter = verticies.iterator(); iter.hasNext(); )
+ {
+ final Vertex vertex = ( Vertex ) iter.next();
+
+ if ( isNotVisited( vertex, vertexStateMap ) )
+ {
+ dfsVisit( vertex, vertexStateMap, retValue );
+ }
+ }
+
+ return retValue;
+ }
+
+ /**
+ * @param vertex
+ * @param vertexStateMap
+ * @return
+ */
+ private static boolean isNotVisited( final Vertex vertex, final Map vertexStateMap )
+ {
+ if ( !vertexStateMap.containsKey( vertex ) )
+ {
+ return true;
+ }
+ final Integer state = ( Integer ) vertexStateMap.get( vertex );
+
+ return NOT_VISTITED.equals( state );
+ }
+
+
+ private static void dfsVisit( final Vertex vertex, final Map vertexStateMap, final LinkedList list )
+ {
+ vertexStateMap.put( vertex, VISITING );
+
+ final List verticies = vertex.getChildren();
+
+ for ( final Iterator iter = verticies.iterator(); iter.hasNext(); )
+ {
+ final Vertex v = ( Vertex ) iter.next();
+
+ if ( isNotVisited( v, vertexStateMap ) )
+ {
+ dfsVisit( v, vertexStateMap, list );
+ }
+ }
+
+ vertexStateMap.put( vertex, VISITED );
+
+ list.add( vertex.getLabel() );
+ }
+
+}
+
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/TopologicalSorter.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/TopologicalSorter.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/TopologicalSorter.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/Vertex.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/Vertex.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/Vertex.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/Vertex.java Mon Oct 5 18:54:50 2009
@@ -0,0 +1,204 @@
+package org.apache.geronimo.system.plugin.plexus.util.dag;
+
+/*
+ * Copyright The Codehaus 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.io.Serializable;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
+ * @version $Id: Vertex.java 8010 2009-01-07 12:59:50Z vsiveton $
+ */
+public class Vertex implements Cloneable, Serializable
+{
+ //------------------------------------------------------------
+ //Fields
+ //------------------------------------------------------------
+ private String label = null;
+
+ List children = new ArrayList();
+
+ List parents = new ArrayList();
+
+
+ // ------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------
+
+ /**
+ *
+ */
+ public Vertex( final String label )
+ {
+ this.label = label;
+ }
+
+ // ------------------------------------------------------------
+ // Accessors
+ // ------------------------------------------------------------
+
+
+ /**
+ * @return
+ */
+ public String getLabel()
+ {
+ return label;
+ }
+
+ /**
+ * @param vertex
+ */
+ public void addEdgeTo( final Vertex vertex )
+ {
+ children.add( vertex );
+ }
+
+
+ /**
+ * @param vertex
+ */
+ public void removeEdgeTo( final Vertex vertex )
+ {
+ children.remove( vertex );
+ }
+
+
+ /**
+ * @param vertex
+ */
+ public void addEdgeFrom( final Vertex vertex )
+ {
+ parents.add( vertex );
+ }
+
+ public void removeEdgeFrom( final Vertex vertex )
+ {
+
+ parents.remove( vertex );
+
+ }
+
+
+ public List getChildren()
+ {
+ return children;
+ }
+
+
+ /**
+ * Get the labels used by the most direct children.
+ *
+ * @return the labels used by the most direct children.
+ */
+ public List getChildLabels()
+ {
+ final List retValue = new ArrayList( children.size() );
+
+ for ( final Iterator iter = children.iterator(); iter.hasNext(); )
+ {
+ final Vertex vertex = ( Vertex ) iter.next();
+
+ retValue.add( vertex.getLabel() );
+ }
+ return retValue;
+ }
+
+
+ /**
+ * Get the list the most direct ancestors (parents).
+ *
+ * @return list of parents
+ */
+ public List getParents()
+ {
+ return parents;
+ }
+
+
+ /**
+ * Get the labels used by the most direct ancestors (parents).
+ *
+ * @return the labels used parents
+ */
+ public List getParentLabels()
+ {
+ final List retValue = new ArrayList( parents.size() );
+
+ for ( final Iterator iter = parents.iterator(); iter.hasNext(); )
+ {
+ final Vertex vertex = ( Vertex ) iter.next();
+
+ retValue.add( vertex.getLabel() );
+ }
+ return retValue;
+ }
+
+
+ /**
+ * Indicates if given vertex has no child
+ *
+ * @return <code>true</true> if this vertex has no child, <code>false</code> otherwise
+ */
+ public boolean isLeaf()
+ {
+ return children.size() == 0;
+ }
+
+
+ /**
+ * Indicates if given vertex has no parent
+ *
+ * @return <code>true</true> if this vertex has no parent, <code>false</code> otherwise
+ */
+ public boolean isRoot()
+ {
+ return parents.size() == 0;
+ }
+
+
+ /**
+ * Indicates if there is at least one edee leading to or from given vertex
+ *
+ * @return <code>true</true> if this vertex is connected with other vertex,<code>false</code> otherwise
+ */
+ public boolean isConnected()
+ {
+ return isRoot() || isLeaf();
+ }
+
+
+ public Object clone() throws CloneNotSupportedException
+ {
+ // this is what's failing..
+ final Object retValue = super.clone();
+
+ return retValue;
+ }
+
+ public String toString()
+ {
+ return "Vertex{" +
+ "label='" + label + "'" +
+ "}";
+ }
+
+
+}
+
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/Vertex.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/Vertex.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/dag/Vertex.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/ClassMap.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/ClassMap.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/ClassMap.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/ClassMap.java Mon Oct 5 18:54:50 2009
@@ -0,0 +1,519 @@
+package org.apache.geronimo.system.plugin.plexus.util.introspection;
+
+/*
+ * Copyright The Codehaus 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 <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
+ * @author <a href="mailto:bob@werken.com">Bob McWhirter</a>
+ * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
+ * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
+ * @version $Id: ClassMap.java 8010 2009-01-07 12:59:50Z vsiveton $
+ */
+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.
+ * <p/>
+ * 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.
+ * <p/>
+ * 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;
+ }
+ }
+}
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/ClassMap.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/ClassMap.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/ClassMap.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/MethodMap.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/MethodMap.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/MethodMap.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/MethodMap.java Mon Oct 5 18:54:50 2009
@@ -0,0 +1,464 @@
+package org.apache.geronimo.system.plugin.plexus.util.introspection;
+
+/*
+ * Copyright The Codehaus 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 <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
+ * @author <a href="mailto:bob@werken.com">Bob McWhirter</a>
+ * @author <a href="mailto:Christoph.Reck@dlr.de">Christoph Reck</a>
+ * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
+ * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
+ * @version $Id: MethodMap.java 8010 2009-01-07 12:59:50Z vsiveton $
+ */
+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 key The name of the method.
+ * @return List list of methods
+ */
+ public List get(String key)
+ {
+ return (List) methodByNameMap.get(key);
+ }
+
+ /**
+ * <p>
+ * 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.
+ * </p>
+ *
+ * <p>
+ * This turns out to be a relatively rare case
+ * where this is needed - however, functionality
+ * like this is needed.
+ * </p>
+ *
+ * @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;
+ }
+}
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/MethodMap.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/MethodMap.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/MethodMap.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/ReflectionValueExtractor.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/ReflectionValueExtractor.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/ReflectionValueExtractor.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/ReflectionValueExtractor.java Mon Oct 5 18:54:50 2009
@@ -0,0 +1,248 @@
+package org.apache.geronimo.system.plugin.plexus.util.introspection;
+
+/*
+ * Copyright The Codehaus 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.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+import java.util.WeakHashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.geronimo.system.plugin.plexus.util.StringUtils;
+
+/**
+ * <p>Using simple dotted expressions to extract the values from an Object instance,
+ * For example we might want to extract a value like: <code>project.build.sourceDirectory</code></p>
+ *
+ * <p>The implementation supports indexed, nested and mapped properties similar to the JSP way.</p>
+ *
+ * @author <a href="mailto:jason@maven.org">Jason van Zyl </a>
+ * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
+ * @version $Id: ReflectionValueExtractor.java 8010 2009-01-07 12:59:50Z vsiveton $
+ * @see <a href="http://struts.apache.org/1.x/struts-taglib/indexedprops.html">http://struts.apache.org/1.x/struts-taglib/indexedprops.html</a>
+ */
+public class ReflectionValueExtractor
+{
+ private static final Class[] CLASS_ARGS = new Class[0];
+
+ private static final Object[] OBJECT_ARGS = new Object[0];
+
+ /**
+ * Use a WeakHashMap here, so the keys (Class objects) can be garbage collected.
+ * This approach prevents permgen space overflows due to retention of discarded
+ * classloaders.
+ */
+ private static final Map classMaps = new WeakHashMap();
+
+ /**
+ * Indexed properties pattern, ie <code>(\\w+)\\[(\\d+)\\]</code>
+ */
+ private static final Pattern INDEXED_PROPS = Pattern.compile( "(\\w+)\\[(\\d+)\\]" );
+
+ /**
+ * Indexed properties pattern, ie <code>(\\w+)\\((.+)\\)</code>
+ */
+ private static final Pattern MAPPED_PROPS = Pattern.compile( "(\\w+)\\((.+)\\)" );
+
+ private ReflectionValueExtractor()
+ {
+ }
+
+ /**
+ * <p>The implementation supports indexed, nested and mapped properties.</p>
+ *
+ * <ul>
+ * <li>nested properties should be defined by a dot, i.e. "user.address.street"</li>
+ * <li>indexed properties (java.util.List or array instance) should be contains <code>(\\w+)\\[(\\d+)\\]</code>
+ * pattern, i.e. "user.addresses[1].street"</li>
+ * <li>mapped properties should be contains <code>(\\w+)\\((.+)\\)</code> pattern, i.e. "user.addresses(myAddress).street"</li>
+ * <ul>
+ *
+ * @param expression not null expression
+ * @param root not null object
+ * @return the object defined by the expression
+ * @throws Exception if any
+ */
+ public static Object evaluate( String expression, Object root )
+ throws Exception
+ {
+ return evaluate( expression, root, true );
+ }
+
+ /**
+ * <p>The implementation supports indexed, nested and mapped properties.</p>
+ *
+ * <ul>
+ * <li>nested properties should be defined by a dot, i.e. "user.address.street"</li>
+ * <li>indexed properties (java.util.List or array instance) should be contains <code>(\\w+)\\[(\\d+)\\]</code>
+ * pattern, i.e. "user.addresses[1].street"</li>
+ * <li>mapped properties should be contains <code>(\\w+)\\((.+)\\)</code> pattern, i.e. "user.addresses(myAddress).street"</li>
+ * <ul>
+ *
+ * @param expression not null expression
+ * @param root not null object
+ * @return the object defined by the expression
+ * @throws Exception if any
+ */
+ // TODO: don't throw Exception
+ public static Object evaluate( String expression, Object root, boolean trimRootToken )
+ throws Exception
+ {
+ // if the root token refers to the supplied root object parameter, remove it.
+ if ( trimRootToken )
+ {
+ 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() )
+ {
+ // if we have nothing, stop now
+ if ( value == null )
+ {
+ return null;
+ }
+
+ String token = parser.nextToken();
+
+ ClassMap classMap = getClassMap( value.getClass() );
+
+ Method method;
+ Object[] localParams = OBJECT_ARGS;
+
+ // do we have an indexed property?
+ Matcher matcher = INDEXED_PROPS.matcher( token );
+ if ( matcher.find() )
+ {
+ String methodBase = StringUtils.capitalizeFirstLetter( matcher.group( 1 ) );
+ String methodName = "get" + methodBase;
+ method = classMap.findMethod( methodName, CLASS_ARGS );
+ value = method.invoke( value, OBJECT_ARGS );
+ classMap = getClassMap( value.getClass() );
+
+ if ( classMap.getCachedClass().isArray() )
+ {
+ value = Arrays.asList( (Object[]) value );
+ classMap = getClassMap( value.getClass() );
+ }
+
+ if ( value instanceof List )
+ {
+ // use get method on List interface
+ localParams = new Object[1];
+ localParams[0] = Integer.valueOf( matcher.group( 2 ) );
+ method = classMap.findMethod( "get", localParams );
+ }
+ else
+ {
+ throw new Exception( "The token '" + token
+ + "' refers to a java.util.List or an array, but the value seems is an instance of '"
+ + value.getClass() + "'." );
+ }
+ }
+ else
+ {
+ // do we have a mapped property?
+ matcher = MAPPED_PROPS.matcher( token );
+ if ( matcher.find() )
+ {
+ String methodBase = StringUtils.capitalizeFirstLetter( matcher.group( 1 ) );
+ String methodName = "get" + methodBase;
+ method = classMap.findMethod( methodName, CLASS_ARGS );
+ value = method.invoke( value, OBJECT_ARGS );
+ classMap = getClassMap( value.getClass() );
+
+ if ( value instanceof Map )
+ {
+ // use get method on List interface
+ localParams = new Object[1];
+ localParams[0] = matcher.group( 2 );
+ method = classMap.findMethod( "get", localParams );
+ }
+ else
+ {
+ throw new Exception( "The token '" + token
+ + "' refers to a java.util.Map, but the value seems is an instance of '"
+ + value.getClass() + "'." );
+ }
+ }
+ else
+ {
+ String methodBase = StringUtils.capitalizeFirstLetter( token );
+ String methodName = "get" + methodBase;
+ method = classMap.findMethod( methodName, CLASS_ARGS );
+
+ if ( method == null )
+ {
+ // perhaps this is a boolean property??
+ methodName = "is" + methodBase;
+
+ method = classMap.findMethod( methodName, CLASS_ARGS );
+ }
+ }
+ }
+
+ if ( method == null )
+ {
+ return null;
+ }
+
+ try
+ {
+ value = method.invoke( value, localParams );
+ }
+ catch ( InvocationTargetException e )
+ {
+ // catch array index issues gracefully, otherwise release
+ if ( e.getCause() instanceof IndexOutOfBoundsException )
+ {
+ return null;
+ }
+
+ throw e;
+ }
+ }
+
+ return value;
+ }
+
+ private static ClassMap getClassMap( Class clazz )
+ {
+ ClassMap classMap = (ClassMap) classMaps.get( clazz );
+
+ if ( classMap == null )
+ {
+ classMap = new ClassMap( clazz );
+
+ classMaps.put( clazz, classMap );
+ }
+
+ return classMap;
+ }
+}
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/ReflectionValueExtractor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/ReflectionValueExtractor.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/introspection/ReflectionValueExtractor.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/FileInputStreamFacade.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/FileInputStreamFacade.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/FileInputStreamFacade.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/FileInputStreamFacade.java Mon Oct 5 18:54:50 2009
@@ -0,0 +1,43 @@
+package org.apache.geronimo.system.plugin.plexus.util.io;
+
+/*
+ * Copyright The Codehaus 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.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Implementation of {@link InputStreamFacade} for files.
+ */
+public class FileInputStreamFacade implements InputStreamFacade {
+ private final File file;
+
+ /**
+ * Creates a new instance.
+ */
+ public FileInputStreamFacade( File file )
+ {
+ this.file = file;
+ }
+
+ public InputStream getInputStream() throws IOException {
+ return new FileInputStream( file );
+ }
+
+
+}
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/FileInputStreamFacade.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/FileInputStreamFacade.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/FileInputStreamFacade.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/InputStreamFacade.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/InputStreamFacade.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/InputStreamFacade.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/InputStreamFacade.java Mon Oct 5 18:54:50 2009
@@ -0,0 +1,33 @@
+package org.apache.geronimo.system.plugin.plexus.util.io;
+
+/*
+ * Copyright The Codehaus 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.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Interface of a wrapper for input streams. This facade is used
+ * by methods, which are being implemented for files, URL's, or
+ * input streams.
+ */
+public interface InputStreamFacade {
+ /**
+ * Retrieves the actual {@link InputStream}. The caller must assume,
+ * that this method may be invoked only once.
+ */
+ InputStream getInputStream() throws IOException;
+}
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/InputStreamFacade.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/InputStreamFacade.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/InputStreamFacade.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/RawInputStreamFacade.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/RawInputStreamFacade.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/RawInputStreamFacade.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/RawInputStreamFacade.java Mon Oct 5 18:54:50 2009
@@ -0,0 +1,39 @@
+package org.apache.geronimo.system.plugin.plexus.util.io;
+
+/*
+ * Copyright The Codehaus 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.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Implementation of {@link InputStreamFacade} for raw input streams.
+ */
+public class RawInputStreamFacade implements InputStreamFacade {
+ final InputStream stream;
+
+ /**
+ * Creates a new instance.
+ */
+ public RawInputStreamFacade( InputStream stream )
+ {
+ this.stream = stream;
+ }
+
+ public InputStream getInputStream() throws IOException {
+ return stream;
+ }
+}
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/RawInputStreamFacade.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/RawInputStreamFacade.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/RawInputStreamFacade.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/URLInputStreamFacade.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/URLInputStreamFacade.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/URLInputStreamFacade.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/URLInputStreamFacade.java Mon Oct 5 18:54:50 2009
@@ -0,0 +1,40 @@
+package org.apache.geronimo.system.plugin.plexus.util.io;
+
+/*
+ * Copyright The Codehaus 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.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+/**
+ * Implementation of {@link InputStreamFacade} for URL's.
+ */
+public class URLInputStreamFacade implements InputStreamFacade {
+ private final URL url;
+
+ /**
+ * Creates a new instance.
+ */
+ public URLInputStreamFacade( URL url )
+ {
+ this.url = url;
+ }
+
+ public InputStream getInputStream() throws IOException {
+ return url.openStream();
+ }
+}
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/URLInputStreamFacade.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/URLInputStreamFacade.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/io/URLInputStreamFacade.java
------------------------------------------------------------------------------
svn:mime-type = text/plain