depgenutil.java

来自「This is a resource based on j2me embedde」· Java 代码 · 共 345 行

JAVA
345
字号
/* * @(#)DepgenUtil.java	1.21 06/10/10 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved.   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER   *    * This program is free software; you can redistribute it and/or   * modify it under the terms of the GNU General Public License version   * 2 only, as published by the Free Software Foundation.    *    * This program is distributed in the hope that it will be useful, but   * WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   * General Public License version 2 for more details (a copy is   * included at /legal/license.txt).    *    * You should have received a copy of the GNU General Public License   * version 2 along with this work; if not, write to the Free Software   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA   * 02110-1301 USA    *    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa   * Clara, CA 95054 or visit www.sun.com if you need additional   * information or have any questions.  * */package util;import dependenceAnalyzer.*;import java.util.Enumeration;import java.util.Vector;/* * Dependence-generation utility functions. * Specific to the interfaces defined in dependenceAnalyzer, * and to the external (String) representation of some of those things. * Actually, this the the framework for building any member- * dependence-analysis-based stuff. */public class DepgenUtil extends LinkerUtil implements dependenceAnalyzer.MemberArcTypes {    protected ClassFileFinder	finder = new ClassFileFinder();    protected ClassnameFilter	filter = new ClassnameFilter();    protected ClassnameFilter	wholeClass;    protected ClassnameFilter	wholeData;    protected MemberDependenceAnalyzer analyzer = new MemberDependenceAnalyzer( finder, filter );    protected MemberName    stringToName( String nameAndType ){	int nameDivision = methodOff( nameAndType );	String classname = nameAndType.substring( 0, nameDivision );	String membername = nameAndType.substring( nameDivision+1 );	return new MemberName(	    analyzer.classByName( sanitizeClassname( classname ) ), 	    sanitizeClassname( membername ) // may include signature.	);    }    protected MemberDependenceNode    stringToNode( String nameAndType ){	return (MemberDependenceNode)(analyzer.addNodeByName( stringToName( nameAndType ) ));    }    /*     * Similar to stringToName, but permits us     * to name constructors (in context) without the bother of     * the magic name. Thus     * "java.lang.String([C)" is, in context, a synonym for     * the more perfectly general "java.lang.String.<init>([C)"     * We will also use the default signature if none is found.     */    protected MemberName    stringToConstructorName( String classAndType ){	int sigDivision  = sigOff( classAndType );	String classname;	String signature;	if ( sigDivision == -1 ){	    classname = classAndType;	    signature = constructorSig;	} else {	    classname = classAndType.substring( 0, sigDivision );	    signature = classAndType.substring( sigDivision );	}	return new MemberName(	    analyzer.classByName( sanitizeClassname( classname ) ), 	    constructorName+sanitizeClassname( signature )	);    }    protected MemberDependenceNode    stringToConstructorNode( String classAndType ){	return (MemberDependenceNode)(analyzer.addNodeByName( stringToConstructorName( classAndType ) ));    }    /*     * Start with a String, return a ClassEntry. Very simple.     */    protected ClassEntry    stringToClass( String classname ){	return analyzer.classByName( sanitizeClassname( classname ) );    }    /*     * To exclude a class or package named by the given string.     * If it ends in *, we treat it as a package name.     * otherwise, it is a class.     */    protected void    excludeClass( String xclassname ){	String classname = sanitizeClassname( xclassname );	filter.includeName( classname );    }    /*     * This is the guts of dependence-based analysis.     * It is only slightly parameterized to allow     * for multiple target sets. In reality,     * there will most likely be only one.     *     * processNode is called after we have determined that the given     * node has not yet be added to our target set, but should be.      * It adds the node to targetList, then processes it,     * looking for other things to be added to the worklist.     * It is called by processNodeList, below.     */    protected void    processNode(	DependenceNode node,	int inclusionFlag,	int initIncludedFlag,	int requiredMask,	Vector targetlist,	Vector worklist    ){	if ( node.state() == DependenceNode.UNANALYZED )	    analyzer.analyzeDependences( node );	if ( node.state() == DependenceNode.ERROR ) return; // cannot cope.	if ( (node.flags&MemberDependenceNode.EXCLUDED) != 0 ) return; // not wanted.	targetlist.addElement( node );	node.flags |= inclusionFlag;	if (  node instanceof ClassEntry ){	    // if we require a class, what we really require is its <clinit>, if any.	    ClassEntry classNode = (ClassEntry)node;	    MemberDependenceNode clinit = classNode.lookupMember( staticInitializerName+staticInitializerSig );	    if ( clinit != null ){		if ( ( clinit.flags&requiredMask) == 0 )		    worklist.addElement( clinit );		    // if we were clever, we'd assign node=clinit and fall through...	    }	    // we also need its superclass	    ClassEntry mySuper = classNode.superClass();	    if ( mySuper!= null ){		if ( (mySuper.flags&requiredMask) == 0 )		    worklist.addElement( mySuper );	    }	    //	    // we also believe that we need its interfaces.	    // I personally believe this is an incorrect requirement	    // by the current JVM implementation, but what can you do?	    //	    Enumeration ilist = classNode.interfaces();	    while ( ilist.hasMoreElements() ){		ClassEntry iface = (ClassEntry) (ilist.nextElement());		if ( (iface.flags&requiredMask) == 0 )		    worklist.addElement( iface );	    }	    //	    // finally (?), if the class is named as one for which we	    // want-all-members or want-all-data, then put all those	    // things on the worklist, as appropriate.	    String className = (String)( classNode.name() );	    boolean wantAllMembers = wholeClass.accept( null, className );	    boolean wantAllData = wantAllMembers || wholeData.accept( null, className );	    if ( wantAllData ){ // ... which is the OR of two conditions...		Enumeration members = classNode.members();		if ( members != null ){		    while ( members.hasMoreElements() ){			MemberDependenceNode mnode = (MemberDependenceNode)(members.nextElement() );			if ( wantAllMembers || ((mnode.flags&MemberDependenceNode.FIELD) != 0 ) ){			    // either we want absolutely everything, or			    // this is data ( and we implcitly want data )			    // so, either way, we want mnode.			    if ( (mnode.flags&requiredMask) == 0 ){				worklist.addElement( mnode );			    }			}		    }		}	    }	    return;	}	MemberDependenceNode mNode = (MemberDependenceNode)node; // the only other kind we recognize.	if (  (mNode.flags&MemberDependenceNode.OVERRIDDEN) != 0 ){	    /*	     * Any methods which override this one, and are members of classes having constructors	     * loaded, must themselves be loaded.	     */	    Enumeration overriders = mNode.overriddenBy();	    while ( overriders.hasMoreElements() ){		MemberDependenceNode t = (MemberDependenceNode)(overriders.nextElement());		if ( (t.flags&requiredMask) != 0 ) continue; // already loaded.		if ( (((MemberName)(t.name())).classEntry.flags&initIncludedFlag) != 0 ){		    // constructor is loaded but the overriding member is not.		    // put it on the list.		    worklist.addElement( t );		}	    }	} else if ( (mNode.flags&MemberDependenceNode.INIT) != 0 ){	    // this is a constructor.	    // if its our first, check for necessary and overriding methods.	    // then note that a constructor has been loaded	    ClassEntry mClass = ((MemberName)(mNode.name())).classEntry;	    if ( ((mClass.flags & initIncludedFlag ) == 0 ) && (mClass.flags&ClassEntry.HAS_OVERRIDING) != 0 ){		Enumeration mMembers = mClass.members();		while ( mMembers.hasMoreElements() ){		    MemberDependenceNode t = (MemberDependenceNode)(mMembers.nextElement());		    if ( (t.flags&(MemberDependenceNode.NO_OVERRIDING|MemberDependenceNode.EXCLUDED)) != 0 )			continue; // not a candidate		    Enumeration tover = t.overrides();		overriders:		    while ( tover.hasMoreElements() ){			MemberDependenceNode u = (MemberDependenceNode)(tover.nextElement());			if ( (u.flags&requiredMask) != 0 ){			    worklist.addElement( t );			    break overriders; // enough!			}		    }		}		mClass.flags |= initIncludedFlag;	    }	}	Enumeration e = node.dependsOn();	while ( e.hasMoreElements() ){	    DependenceNode t = ((DependenceArc)(e.nextElement())).to();	    if ( (t.flags&requiredMask) == 0 ){		worklist.addElement( t );	    }	}    }    /*     * The main entry point to dependence analysis.     * The vector of dependence nodes is used as a starting point,     * and they and everything they depend on are included in the     * resulting vector. This is parameterized by flags used so     * we can work with multiple sets at a time. In practice, this     * will probably never happen.     *     * Parameters are:     *    worklist   -- a Vector of DependenceNode's for which we need to     *		      	build the dependence graphs     *	  inclusionFlag -- a 1-bit mask. This gets ORed into the flag word     *			of all nodes that are required (i.e. are in the     *			dependence set we're     *			calculating. (By using different bits, we allow you     *			to calculate multiple sets within the same graph.)     *			We use this to avoid infinitely recalculating dependences     *			for nodes we've already visited.     *    initIncludedFlag -- a 1-bit mask. This gets ORed into the flag     *			word of all classes for which at least one constructor     *			is required. Is used for part of the overriding     *			induced implicit-dependence calculation.     *	  requiredMask  -- a multi-bit mask, which will certainly include     *			inclusionFlag. Will also include, for instance, a      *			bit noting that a node is part of an interface. This     *			is used to test overridden members, to see if      *			overriders must be required.     *	  verbosity     -- a small integer value. Currently, there is only     *			one message, and it is only printed if (verbosity>1)     *     * Return value is:     *	  a vector of all the nodes added to the required list by this     * 	  calculation.     *     * Caveats:     *	  Note that we keep a lot of state in each node's flag word.     *    We let the caller determine which bits we use, so it is the caller's     *	  responsibility to choose reasonable non-interfering sets.     *    This algorithm might not work if some flag bits are     *    unexpectedly set. If necessary, use clearUserFlags, below.     */    protected Vector    processList(	Vector worklist,	int inclusionFlag,	int initIncludedFlag,	int requiredMask,	int verbosity    ){	Vector target = new Vector();	int targetsize = 0;	while ( worklist.size() != 0 ){	    Enumeration working = worklist.elements();	    Vector newlist = new Vector();	    while ( working.hasMoreElements() ){		DependenceNode node = (DependenceNode)(working.nextElement());		if ( (node.flags&requiredMask) == 0 ){		    processNode( node, inclusionFlag, initIncludedFlag, requiredMask, target, newlist );		}	    }	    int newsize = target.size();	    if ( verbosity > 1 ){		System.out.println(Localizer.getString("depgenutil.iteration_added_new_elements", new Integer(newsize-targetsize)));	    }	    targetsize = newsize;	    worklist = newlist;	}	return target;    }    /*     * If we are asking multiple, hypothetical questions about      * dependence sets, we might want to re-use the same membership     * flags. This requires clearing them before re-use.     * clearUserFlags will iterate through all classes and members,     * clearing the flags given as input.      * This is NOT built into the operation of processList, as multiple     * questions is NOT the expected normal behavior, and has some cost.     */    protected void    clearUserFlags( int flagset ){	int flagmask = ~ flagset;	Enumeration classlist = analyzer.allClasses();	while ( classlist.hasMoreElements() ){	    ClassEntry c = (ClassEntry) (classlist.nextElement());	    c.flags &= flagmask;	    Enumeration memberlist = c.members();	    if ( memberlist == null ) continue;	    while ( memberlist.hasMoreElements() ){		DependenceNode m = (DependenceNode)(memberlist.nextElement());		m.flags &= flagmask;	    }	}    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?