package org.glassfish.pfl.tf.tools.enhancer ;
import org.glassfish.pfl.basic.tools.argparser.DefaultValue ;
import org.glassfish.pfl.basic.tools.argparser.Help ;
import org.glassfish.pfl.basic.tools.argparser.ArgParser ;
import org.glassfish.pfl.basic.tools.file.ActionFactory;
import org.glassfish.pfl.basic.tools.file.Scanner ;
import org.glassfish.pfl.basic.tools.file.Recognizer ;
import org.glassfish.pfl.basic.tools.file.FileWrapper ;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.Set;
import org.glassfish.pfl.tf.timer.spi.TimerPointSourceGenerator;
import org.glassfish.pfl.tf.timer.spi.TimingInfoProcessor;
import org.glassfish.pfl.tf.timer.spi.TimerFactory;
import org.glassfish.pfl.basic.contain.Pair;
import org.glassfish.pfl.basic.func.UnaryFunction;
import org.glassfish.pfl.tf.spi.Util;
public class EnhanceTool {
private static int errorCount = 0 ;
private Util util ;
public enum ProcessingMode {
TimingPoints,
UpdateSchemas,
TraceEnhance
}
public interface Arguments {
@DefaultValue( "tfannotations.properties" )
@Help( "Name of resource file containing information "
+ "about tf annotations")
File rf() ;
@DefaultValue( "false" )
@Help( "Debug flag" )
boolean debug() ;
@DefaultValue( "0" )
@Help( "Verbose flag" )
int verbose() ;
@DefaultValue( "false" )
@Help( "Indicates a run that only prints out actions, "
+ "but does not perform them")
boolean dryrun() ;
@DefaultValue( "." )
@Help( "Directory to scan for class file" )
File dir() ;
@DefaultValue( "false")
@Help( "If true, write output to a .class.new file")
boolean newout() ;
@DefaultValue( "TimingPoints" )
@Help( "Control the mode of operation: TimingPoints, UpdateSchema, or TraceEnhance")
ProcessingMode mode() ;
@DefaultValue( "" )
@Help( "The timing point class name")
String timingPointClass() ;
@DefaultValue( "" )
@Help( "The directory in which to write the TimingPoint file")
String timingPointDir() ;
}
private Arguments args ;
private TimingInfoProcessor tip ;
private class EnhancerFileAction implements Scanner.Action {
private UnaryFunction<byte[],byte[]> ea ;
public EnhancerFileAction( UnaryFunction<byte[],byte[]> ea ) {
this.ea = ea ;
}
@Override
public boolean evaluate( FileWrapper fw ) {
try {
util.info( 2, "Processing class " + fw.getName() ) ;
byte[] inputData = fw.readAll() ;
byte[] outputData = ea.evaluate( inputData ) ;
if (outputData != null) {
if (args.newout()) {
String fname = fw.getName() + ".new" ;
util.info( 1, "Writing to class file " + fname ) ;
FileWrapper fwo = new FileWrapper( fname ) ;
fwo.writeAll( outputData ) ;
} else {
util.info( 1, "Writing to class file " + fw.getName() ) ;
fw.writeAll( outputData ) ;
}
}
} catch (Exception exc) {
util.info( 1, "Exception " + exc + " while processing class "
+ fw.getName() ) ;
errorCount++ ;
}
return true ;
}
}
private void generatePropertiesFile( Arguments args,
Set<String> anames ) throws IOException {
final FileWrapper fw = new FileWrapper( args.rf() ) ;
fw.open( FileWrapper.OpenMode.WRITE_EMPTY ) ;
try {
fw.writeLine( "# Trace Facility Annotations" ) ;
fw.writeLine( "# generated by EnhanceTool on " + new Date() ) ;
fw.writeLine( "org.glassfish.tf.annotations.size="
+ anames.size() ) ;
int ctr=1 ;
for (String str : anames) {
String cname = str.replace( '/', '.' ) ;
fw.writeLine( "org.glassfish.tf.annotation."
+ ctr + "=" + cname ) ;
ctr++ ;
}
} finally {
fw.close() ;
}
}
private Scanner.Action makeIgnoreAction(
final boolean trace ) {
return new Scanner.Action() {
@Override
public String toString() {
return "ignore action (ignore files that don't match)" ;
}
@Override
public boolean evaluate(FileWrapper arg) {
if (trace) {
util.info( 1, "Skipping " + arg ) ;
}
return true ;
}
} ;
}
private void doScan( Arguments args, ActionFactory af,
Scanner scanner, Scanner.Action classAct ) throws IOException {
final Recognizer classRecognizer = af.getRecognizerAction() ;
final Scanner.Action ignoreAction = makeIgnoreAction(
args.debug() || args.verbose() > 2 ) ;
classRecognizer.setDefaultAction( ignoreAction ) ;
classRecognizer.addKnownSuffix( "class", classAct ) ;
scanner.scan( classRecognizer ) ;
}
public void run( String[] strs ) {
try {
final ArgParser ap = new ArgParser( Arguments.class ) ;
args = ap.parse( strs, Arguments.class ) ;
util = new Util( args.debug(), args.verbose() ) ;
final String tpname = args.timingPointClass() ;
String pkg = "" ;
String cname = tpname ;
if (tpname.length() > 0) {
int index = tpname.lastIndexOf('.') ;
if (index > 0) {
cname = tpname.substring( index + 1 ) ;
pkg = tpname.substring( 0, index ) ;
}
} else {
cname = "NotUsed" ;
pkg = "no.package" ;
}
tip = new TimingInfoProcessor( cname, pkg ) ;
final ActionFactory af = new ActionFactory( 0, args.dryrun() ) ;
final Scanner scanner = new Scanner( 0, args.dir() ) ;
AnnotationScannerAction annoAct = new AnnotationScannerAction( util,
tip ) ;
doScan( args, af, scanner, annoAct ) ;
Set<String> anames = annoAct.getAnnotationNames() ;
if (args.debug()) {
util.info( 1, "MM Annotations: " + anames ) ;
}
generatePropertiesFile( args, anames ) ;
Transformer ea = new Transformer( util,
args.mode(), tip, anames ) ;
final Scanner.Action act = new EnhancerFileAction( ea ) ;
doScan( args, af, scanner, act ) ;
Pair<String,TimerFactory> res = tip.getResult() ;
if (!args.timingPointDir().equals( "" ) ) {
TimerPointSourceGenerator.generateFile(
args.timingPointDir(), res );
}
} catch (Exception exc) {
if (util == null) {
util = new Util( true, 1 ) ;
}
util.info( 1, "Exception: " + exc ) ;
if (args.debug()) {
exc.printStackTrace() ;
}
}
}
public static void main( String[] strs ) {
(new EnhanceTool()).run( strs ) ;
if (errorCount > 0) {
System.exit(errorCount);
}
}
}