001: package net.firstpartners.nounit.reader.bytecode;
002:
003: /**
004: * Title: NoUnit - Identify Classes that are not being unit Tested
005: *
006: * Copyright (C) 2001 Paul Browne , FirstPartners.net
007: *
008: *
009: * This program is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU General Public License
011: * as published by the Free Software Foundation; either version 2
012: * of the License, or (at your option) any later version.
013: *
014: * This program is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
017: * GNU General Public License for more details.
018: *
019: * You should have received a copy of the GNU General Public License
020: * along with this program; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
022: *
023: * @author Paul Browne
024: * @version 0.7
025: */
026:
027: import java.io.IOException;
028: import java.text.StringCharacterIterator;
029: import java.util.HashMap;
030: import java.util.HashSet;
031:
032: import net.firstpartners.nounit.reader.ISnippetFactory;
033: import net.firstpartners.nounit.snippet.SnippetMethod;
034: import net.firstpartners.nounit.snippet.Snippets;
035: import net.firstpartners.nounit.utility.NoUnitException;
036:
037: import org.gjt.jclasslib.structures.CPInfo;
038: import org.gjt.jclasslib.structures.ClassFile;
039: import org.gjt.jclasslib.structures.InvalidByteCodeException;
040: import org.gjt.jclasslib.structures.MethodInfo;
041:
042: /**
043: * Reads Class Files (Byte Code) and returns them as snippets
044: */
045: public class ByteCodeMethodSnippetFactory extends
046: AbstractByteCodeSnippetFactory implements ISnippetFactory {
047:
048: /**
049: * Inner Store of the classfile being read
050: */
051: private ClassFile innerClassFile;
052:
053: /**
054: * Constructor - Get (and store) source class file
055: * @param sourceClassFile - Compiled Byte Code to read
056: */
057: public ByteCodeMethodSnippetFactory(ClassFile sourceClassFile) {
058: innerClassFile = sourceClassFile;
059: }
060:
061: /**
062: * Get a set of snippets from the current class source
063: * @return snippetSet Collection of ISnippets describing the file
064: */
065: public Snippets getSnippets() throws NoUnitException {
066:
067: //Local Variables
068: Snippets snippetSet = new Snippets();
069: HashSet methodSet = new HashSet();
070:
071: //Add Information
072: try {
073: methodSet = addMethods(methodSet, innerClassFile);
074: } catch (InvalidByteCodeException ibce) {
075: throw new NoUnitException(ibce,
076: "Could not read from Source class file");
077: } catch (IOException ie) {
078: throw new NoUnitException(ie,
079: "Could not open Source class file");
080: }
081: snippetSet.add(methodSet);
082:
083: return snippetSet;
084:
085: }
086:
087: /**
088: * Add the Information about methods to the collection
089: * @param c - Hashset to update
090: * @param infoSource - ClassFile
091: * @return c , updated Hashset
092: */
093: private HashSet addMethods(HashSet c, ClassFile infoSource)
094: throws NoUnitException, InvalidByteCodeException,
095: IOException {
096:
097: //local variables
098: int this DescriptorInPool;
099: String this Name;
100: String this Access;
101: SnippetMethod this Method;
102: MethodInfo[] methodArray;
103: CPInfo[] classPieces;
104: HashMap parameterInfo;
105:
106: //For working out what methods this one calls ...
107: Snippets calls; //info on what this method calls
108: ByteCodeCallsSnippetFactory myCallsFactory;
109:
110: //Check for null
111: if (infoSource == null) {
112: return c;
113: }
114:
115: //Get the source information
116: methodArray = infoSource.getMethods();
117: classPieces = infoSource.getConstantPool();
118:
119: // Loop through and add Method Snippets to Hashset
120: for (int a = 0; a < methodArray.length; a++) {
121:
122: //Get the information about this method
123: this Name = methodArray[a].getName();
124: this Access = methodArray[a].getAccessFlagsVerbose();
125:
126: //Parameter Info
127: this DescriptorInPool = methodArray[a].getDescriptorIndex();
128: parameterInfo = getParameterInfo(this DescriptorInPool,
129: infoSource);
130:
131: //Calls (other Methods) info
132: myCallsFactory = new ByteCodeCallsSnippetFactory(
133: methodArray[a], infoSource);
134: calls = myCallsFactory.getSnippets();
135:
136: //Clean Name
137: this Name = super .tidyNames(this Name);
138:
139: //Build and add this file to the class
140: this Method = new SnippetMethod(this Name, this Access,
141: parameterInfo, calls);
142: c.add(this Method);
143: }
144:
145: return c;
146: }
147:
148: /**
149: * getsParameter info (as HashMap) given set of ClassPieces and pointer
150: * to one we'return intersted in.
151: * @param constantPoolRef - pointer to Constant pool entry we want to read
152: * @param infoSource , ClassFile reference
153: * @return parameters as HashMap of value pairs
154: * e.g. 1,String 2,Integer 3,String etc
155: *
156: */
157: private HashMap getParameterInfo(int constantPoolRef,
158: ClassFile infoSource) throws InvalidByteCodeException {
159:
160: //Internal Variables
161:
162: String this Params = infoSource
163: .getConstantPoolEntryName(constantPoolRef);
164: HashMap parameters = splitTagVerboseIntoHashMap(this Params);
165:
166: return parameters;
167:
168: }
169:
170: /**
171: * Splits a String (from Tag info) into paramters (a hashmap)
172: * @param inTagVerbose
173: * @return splitValues
174: */
175: public HashMap splitTagVerboseIntoHashMap(String inTagVerbose) {
176:
177: //Local Variables
178: int place = 0;
179: char this Letter;
180: StringBuffer tmpBuffer = new StringBuffer();
181: StringCharacterIterator loopString = new StringCharacterIterator(
182: inTagVerbose);
183: HashMap splitValues = new HashMap();
184:
185: //Loop and Split
186: while (loopString.getIndex() < loopString.getEndIndex()) {
187:
188: this Letter = loopString.next();
189:
190: //Add or split?
191: if (this Letter == ';') {
192:
193: splitValues.put(String.valueOf(place), tmpBuffer
194: .toString());
195: tmpBuffer = new StringBuffer();
196: place++;
197:
198: } else {
199: tmpBuffer.append(thisLetter);
200: }
201:
202: }
203: splitValues = cleanValues(splitValues);
204:
205: return splitValues;
206: }
207:
208: }
|