/* | |
* Copyright 2003-2004 The Apache Software Foundation. | |
// (c) Copyright IBM Corp. 2004, 2005 All Rights Reserved | |
* | |
* 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. | |
*/ | |
package org.apache.axis.tools.trace; | |
import java.io.BufferedReader; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.FileOutputStream; | |
import java.io.FileReader; | |
import java.io.FileWriter; | |
import java.util.Arrays; | |
import java.util.HashSet; | |
import java.util.Iterator; | |
import java.util.Set; | |
import org.apache.axis.tools.common.BodyPart; | |
import org.apache.axis.tools.common.CParsingTool; | |
import org.apache.axis.tools.common.Configuration; | |
import org.apache.axis.tools.common.DirectoryTree; | |
import org.apache.axis.tools.common.FileActor; | |
import org.apache.axis.tools.common.FilePart; | |
import org.apache.axis.tools.common.InputCppSourceCode; | |
import org.apache.axis.tools.common.MethodPart; | |
import org.apache.axis.tools.common.ParsingException; | |
import org.apache.axis.tools.common.Utils; | |
/** | |
* This class is a tool that adds entry/exit/catch trace to C and C++ | |
* source code. It contains a main program:- | |
* | |
* usage: Java TraceInstrumentor -source <dir> -target <dir> -include <dir> | |
*/ | |
public class TraceInstrumentor extends CParsingTool implements FileActor { | |
private static Set cExtensions = | |
new HashSet(Arrays.asList(new Object[] { "c", "cpp", "h", "hpp" })); | |
private TraceInstrumentor(String[] args) throws Exception { | |
super(args); | |
} | |
/** | |
* This method is called by the DirectoryTree with two files: the | |
* input (source) file and the output (target) file. This method parses | |
* the source file and writes out the target files with trace in it. | |
* The depth is how deep in the source directory tree we are. Files are | |
* excluded if they are listed in the configuration because they shouldn't | |
* have trace added to them. | |
*/ | |
public void actOnFile(File source, File target, int depth) | |
throws Exception { | |
String sourceName = source.getName(); | |
int dot = sourceName.lastIndexOf("."); | |
String ext = new String(); | |
if (-1 != dot) | |
ext = sourceName.substring(dot + 1); | |
String targetName = | |
DirectoryTree.maybeAppendSeparator(target.toString()); | |
File outputFile = new File(targetName + sourceName); | |
if (cExtensions.contains(ext) | |
&& !Configuration.fileExcluded(sourceName)) { | |
Utils.outputDebugString("parsing " + source + "..."); | |
// create a tracer to the output file | |
Tracer output = | |
new Tracer(new FileWriter(outputFile, false), depth, headers); | |
// OK, now we have the output file let's read in the input file ! | |
FileReader fr = new FileReader(source); | |
BufferedReader inputFile = new BufferedReader(fr); | |
try { | |
parseFile( | |
new InputCppSourceCode(inputFile, source.getName()), | |
output); | |
} catch (ParsingException pe) { | |
failed = true; | |
} | |
output.flush(); | |
output.close(); | |
inputFile.close(); | |
} else { | |
System.out.println("excluding file " + source); | |
FileInputStream fis = new FileInputStream(source); | |
FileOutputStream fos = new FileOutputStream(outputFile); | |
int b = fis.read(); | |
while (-1 != b) { | |
fos.write(b); | |
b = fis.read(); | |
} | |
} | |
} | |
/** | |
* Parses the given file and adds trace to it, placing the newly traced code | |
* into the outputfile | |
* | |
* @param inputFile the input file reader | |
* @param outputFile the output file writer | |
*/ | |
private void parseFile(InputCppSourceCode inputFile, Tracer outputFile) | |
throws Exception { | |
Iterator it = inputFile.getPartIterator(); | |
while (it.hasNext()) { | |
FilePart fp = (FilePart) (it.next()); | |
if (fp.getType() == FilePart.METHOD) { | |
MethodPart mp = (MethodPart) fp; | |
outputFile.writeTrace(mp.getOriginalSignature() + "{"); | |
outputFile.traceEntry(mp.getSignature()); | |
BodyPart[] bps = mp.getBodyParts(); | |
int returnCount = 0, | |
catchCount = 0, | |
returnIndex = 0, | |
catchIndex = 0; | |
for (int i = 0; i < bps.length - 1; i++) | |
if (bps[i].isReturn()) | |
returnCount++; | |
for (int i = 0; i < bps.length - 1; i++) | |
if (bps[i].isCatch()) | |
catchCount++; | |
for (int i = 0; i < bps.length; i++) { | |
outputFile.writeTrace(bps[i].getCodeFragment()); | |
if (bps[i].isReturn()) { | |
if (returnCount > 1) | |
returnIndex++; | |
outputFile.traceExit( | |
bps[i].getReturnValue(), | |
returnIndex); | |
} else if (bps[i].isCatch()) { | |
if (catchCount > 1) | |
catchIndex++; | |
outputFile.traceCatch( | |
bps[i].getCaughtValue(), | |
catchIndex); | |
} else if (i < bps.length - 1) { | |
if (returnCount > 1) | |
returnIndex++; | |
outputFile.traceExit(returnIndex); | |
} | |
} | |
} else { | |
outputFile.writeTrace(fp.toString()); | |
} | |
} | |
} | |
public static void main(String[] args) { | |
boolean failed = false; | |
try { | |
TraceInstrumentor ti = new TraceInstrumentor(args); | |
File source = ti.checkFile("-source"); | |
File target = ti.maybeCreateDirectory("-target"); | |
ti.headers = ti.preparseHeaders("-include"); | |
DirectoryTree tree = new DirectoryTree(ti, null); | |
tree.walkTree(source, target, 0); | |
failed = ti.failed; | |
} catch (Exception exception) { | |
exception.printStackTrace(); | |
failed = true; | |
} | |
if (failed) { | |
Utils.outputDebugString("Finished! (but encountered problems)"); | |
System.exit(-2); | |
} | |
Utils.outputDebugString("Finished!"); | |
} | |
protected void printUsage() { | |
System.out.println( | |
"usage: Java TraceInstrumentor " | |
+ "-config <file> -source <dir> " | |
+ "-target <dir> -include <dir>"); | |
} | |
} |