com.ph.pr.apps.jaspcleaner
Class JaspCleaner

java.lang.Object
  extended by com.ph.pr.apps.jaspcleaner.JaspCleaner
All Implemented Interfaces:
antlr.ASTVisitor

public class JaspCleaner
extends java.lang.Object
implements antlr.ASTVisitor

The main Victor class...

Author:
"Greg Golberg", Phil Schwarz
See Also:
main(String[]), FogBugzIII

Nested Class Summary
(package private)  class JaspCleaner.CompositePattern
           
(package private)  class JaspCleaner.SignatureComparator
           
 
Field Summary
static boolean _DEBUG
           
private  java.util.HashMap BOXED_PRIMITIVE_TYPES
           
private static java.lang.Class[] DUMMY_CLASS_ARRAY
          For faster performance when we need to cast an array.
private static boolean echoToStdout
           
private  java.lang.String inMethod
           
private  java.util.List javaLines
           
private  java.util.Map javaToJspLine
           
private  java.util.List jspLineOffset
           
private  java.util.List jspLines
           
private  JCClassLoader loader
          Used for loading classes based on import statements.
private  java.util.Map localMethods
          Map of method names to their return types.
private static java.io.PrintStream logPrintStream
           
private static int MAX_PASSES
           
private  java.util.Map newNodeType
          Map of AST to return replacement type (as Class).
private  java.util.Map newVars
          Map of variables (as Strings) to their new types (as Class)
private  java.util.Map nodeText
          Map of AST to textual representation (as String)
private  java.util.Map nodeType
          Map of AST to return type (as Class).
private  java.util.Map pmdReplacements
          Map of regexp patterns to replace from PMD phase.
private  java.util.Set PRIMITIVE_TYPES
           
private  java.util.HashMap PROGID_MAP
           
static char[] REGEX_RESERVED_CHAR
          Reserved characters for regular expressions in java.util.regex package.
private  java.util.Map replacements
          Map of regexp patterns to replace.
(package private) static java.lang.Class UNKNOWN_CLASS
          Unknown Class
private  java.util.Map used
           
private  java.util.HashMap VARIANT_CONVERSIONS
           
private  java.util.HashMap VARIANT_OPERATORS
           
private  java.util.Map vars
          Map of variables to their old types
private  java.util.Properties victorProperties
           
private  java.util.Set visited
           
 
Constructor Summary
JaspCleaner()
           
 
Method Summary
private  void cascadeReplacements()
           
private  void checkForPMDReplacement(antlr.collections.AST ast)
          Check an assignment to see if its LHS has been flagged by PMS as an unused variable.
private  java.util.Map checkForPVectorAddChain(antlr.collections.AST exprContents)
          Check a METHOD_CALL to see if it is a pVector.Add() chain
private  void coerceAssignTypes(antlr.collections.AST ast)
          Check an assignment to see if we can coerce lhs or rhs type
private static void copy(java.io.File from, java.io.File to)
          Copies files.
 void do_ArrayList_getItem(java.util.Map callInfo)
          A getItem() called on a vbarray object will be translated to a get() call on an ArrayList object, but since J-ASP seems to be using arrays with OPTION BASE1, this method will automatically subtract one from index.
 void do_operator_get(java.util.Map callInfo)
           
 void do_operator_Greater(java.util.Map callInfo)
           
 void do_operator_invoke(java.util.Map callInfo)
           
 void do_operator_Is(java.util.Map callInfo)
           
 void do_operator_set(java.util.Map callInfo)
           
 void do_PHUtils_CreateObject(java.util.Map callInfo)
           
 void do_primitive_operator(java.util.Map callInfo)
          Replace primitive-operator equivalents (e.g.
 void do_Server_CreateObject(java.util.Map callInfo)
           
 void do_String_unequals(java.util.Map callInfo)
           
 void do_variant_conversion(java.util.Map callInfo)
           
 void do_variant_set(java.util.Map callInfo)
          For a set() invocation on a variant object, try to determine the type of the object, and replace the set() call with an assignment.
 void do_variant_setObject(java.util.Map callInfo)
           
 void do_vb_Chr(java.util.Map callInfo)
           
 void do_vb_Instr(java.util.Map callInfo)
           
 void do_vb_IsArray(java.util.Map callInfo)
           
 void do_vb_IsEmpty(java.util.Map callInfo)
           
 void do_vb_IsEmptyIsNull(java.util.Map callInfo)
           
 void do_vb_IsNull(java.util.Map callInfo)
           
 void do_vb_LCase(java.util.Map callInfo)
           
 void do_vb_Left(java.util.Map callInfo)
           
 void do_vb_Len(java.util.Map callInfo)
           
 void do_vb_Mid(java.util.Map callInfo)
           
 void do_vb_Replace(java.util.Map callInfo)
           
 void do_vb_Right(java.util.Map callInfo)
           
 void do_vb_RightLeftMid(java.util.Map callInfo)
           
 void do_vb_String(java.util.Map callInfo)
           
 void do_vb_Trim(java.util.Map callInfo)
           
 void do_vb_UBound(java.util.Map callInfo)
          Replace UBound() with size().
 void do_vb_UCase(java.util.Map callInfo)
           
 void do_vb_UCaseLCase(java.util.Map callInfo)
           
private  void doPMD(java.io.File f)
          Perform PMD analysis, and get rid of unused vars.
private  java.lang.String doReplacements(java.lang.String jspPage)
           
private static java.lang.String escapeRegex(java.lang.String pattern)
          Escape all the regexp reserved characters in a string
private  java.lang.String fileToString(java.io.File interJsp)
           
private  java.util.ArrayList findMatchingMethods(java.util.Map callInfo, JaspCleaner.SignatureComparator sc)
           
private  java.lang.String getCanonicalText(antlr.collections.AST ast)
           
private  java.lang.Class guessClassFromHungarianNotation(java.lang.String id)
           
private static java.lang.String[] inclusiveSplit(java.lang.String regex, java.lang.String target)
          Works like String.split(String regex), except that the delimiters that are detected appear as elements in the output array.
private  void insertLineNumbers(java.io.File interJsp, java.io.File linedJsp)
           
private  java.lang.String intString(java.lang.String doubleString)
          Convert a vb string index/length expression from double to int
private  boolean isPrimitiveOperator(java.util.Map callInfo)
          Check if method can be coerced to a primitive (or String) operator If it can be, then callInfo.get("COERCEDTYPE") is updated with the coerced type.
private static void log(java.lang.String s)
          Log the message (currently, to System.out).
private static void logDebug(java.lang.String s)
           
static void main(java.lang.String[] args)
          For each of the JSP files to be converted, the following algorithm is performed: Preprocessthe page Do static semantic analysis of the file (in visit(AST), and processMethodCall(antlr.collections.AST)}, and identify with what types to replace variant types to the best of our ability (see above two methods for heuristics used).
private static java.lang.String makeArgList(java.util.List list)
          Make a comma-separated String out of the contents of the passed List.
private  JaspCleaner.CompositePattern makeMethodCallCP(java.lang.String arg0, java.lang.String method, java.lang.String args)
           
 java.util.List matchArgBoxing(java.util.Map callInfo)
           
private static void postProcess(java.lang.String jspPage, java.io.File to)
          Postprocess, as follows: Replace invocation of default variantconstructors with nothing; i.e., new variant().foo() becomes foo() Replace Netcoole's conversion methods -- static methods of the class vb whose names start with C, e.g., ( vb.CInt(jasp.vbs.variant)-- with their arguments.
private static void preProcess(java.io.File from, java.io.File to)
          Preprocesses the original Netcoole-converted JSP file.
private  java.util.Map processMethodCall(antlr.collections.AST inAst)
          Processes an encountered method call.
private  void propagateNodeText(antlr.collections.AST ast)
          Visit children, accumulating and storing nodeText for this node
private  java.lang.String replaceHTMLComments(java.lang.String jspFragment)
           
private  void setNewVar(java.lang.String ident, java.lang.Class type)
           
static java.lang.String stripEnclosingChar(java.lang.String arg1)
           
static java.lang.String toUpperCamelCase(java.lang.String arg1)
           
 void visit(antlr.collections.AST ast)
          Visitor pattern applied, based on AST.getType()and switch statement, as follows (unless ast is null): Default: call this method on all children of the supplied ast in turn.
private static void write(java.io.File f, java.lang.String s)
          Writes the string into a file.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

UNKNOWN_CLASS

static final java.lang.Class UNKNOWN_CLASS
Unknown Class


localMethods

private final java.util.Map localMethods
Map of method names to their return types.


DUMMY_CLASS_ARRAY

private static final java.lang.Class[] DUMMY_CLASS_ARRAY
For faster performance when we need to cast an array.

See Also:
List.toArray(java.lang.Object[])

REGEX_RESERVED_CHAR

public static final char[] REGEX_RESERVED_CHAR
Reserved characters for regular expressions in java.util.regex package. Why is this not a part of JDK?

See Also:
java.util.regex.Pattern

VARIANT_OPERATORS

private final java.util.HashMap VARIANT_OPERATORS

VARIANT_CONVERSIONS

private final java.util.HashMap VARIANT_CONVERSIONS

PRIMITIVE_TYPES

private final java.util.Set PRIMITIVE_TYPES

BOXED_PRIMITIVE_TYPES

private final java.util.HashMap BOXED_PRIMITIVE_TYPES

PROGID_MAP

private final java.util.HashMap PROGID_MAP

vars

private final java.util.Map vars
Map of variables to their old types


newVars

private final java.util.Map newVars
Map of variables (as Strings) to their new types (as Class)


replacements

private final java.util.Map replacements
Map of regexp patterns to replace.


pmdReplacements

private final java.util.Map pmdReplacements
Map of regexp patterns to replace from PMD phase.


nodeText

private final java.util.Map nodeText
Map of AST to textual representation (as String)


visited

private final java.util.Set visited

nodeType

private final java.util.Map nodeType
Map of AST to return type (as Class). TODO: what of return etc.


newNodeType

private final java.util.Map newNodeType
Map of AST to return replacement type (as Class).


loader

private final JCClassLoader loader
Used for loading classes based on import statements.


used

private final java.util.Map used

victorProperties

private java.util.Properties victorProperties

echoToStdout

private static boolean echoToStdout

logPrintStream

private static java.io.PrintStream logPrintStream

_DEBUG

public static boolean _DEBUG

inMethod

private java.lang.String inMethod

MAX_PASSES

private static final int MAX_PASSES
See Also:
Constant Field Values

javaLines

private final java.util.List javaLines

jspLines

private final java.util.List jspLines

javaToJspLine

private final java.util.Map javaToJspLine

jspLineOffset

private final java.util.List jspLineOffset
Constructor Detail

JaspCleaner

JaspCleaner()
      throws java.lang.Exception
Throws:
java.lang.Exception
Method Detail

makeArgList

private static final java.lang.String makeArgList(java.util.List list)
Make a comma-separated String out of the contents of the passed List.

Parameters:
list - list to convert.
Returns:
comma-separated String (aka ELIST, or arg list, etc.)

escapeRegex

private static final java.lang.String escapeRegex(java.lang.String pattern)
Escape all the regexp reserved characters in a string


processMethodCall

private java.util.Map processMethodCall(antlr.collections.AST inAst)
Processes an encountered method call. Based on the return type, we can determine the type of some variables that this method call is assigned to. The following heuristics are applied here:
  1. Due to the nature and current state of the port, the correct type of parameters may be determined. For instance, if we determine that a method's signature is foo(String, int) and we encounter a method call foo(stringVar, variantVar), we can deduce that variantVar should become an int.
This method proceeds as follows:
  1. XXX
  2. And, finally, just before it's ready to return the Map with details of this method call (as below), it tries to find a method, if any, that is of the form do<method>, where method is the name of the method we are currently processing. For instance, if we are processing a set() call, we'll call #doset(Map). This is done so processing of each particular method call is in its own method instead of crowding this one. If nothing is to be done, well, nothing is done.

Parameters:
ast - AST representing a JavaTokenTypes.METHOD_CALL.
Returns:
a Map of the following mappings:
Key (always a String) Value (if a Class, can be UNKNOWN_CLASS)
"CALLAST" The AST node for the method call itself
"ARG0" The object (String) on which this method is dispatched,
"ARG0AST" The AST node for the object on which this method is dispatched
"CLASS" Class of "ARG0" above
"METHOD" The method name, as String
"ARGLIST" List of arguments (as String s -- such that, for instance, "ARGLIST" for foo(x.bar().baz(),44) is a List of two Strings: "x.bar().baz()" and "44".
"ARGASTLIST" List of arguments (as AST s -- such that, for instance, "ARGLIST" for foo(x.bar().baz(),44) is a List of two ASTs: the DOT that is the root of the subtree for x.bar().baz() and the NUM_INT that represents 44.
"ARGTYPES" A List of types of arguments passed in this method call (corresponding to value of "ARGLIST" above) as Class objects.
"RETURNS" A type (as Class) that this method returns.

isPrimitiveOperator

private boolean isPrimitiveOperator(java.util.Map callInfo)
Check if method can be coerced to a primitive (or String) operator If it can be, then callInfo.get("COERCEDTYPE") is updated with the coerced type.

Parameters:
callInfo -
Returns:
boolean

setNewVar

private void setNewVar(java.lang.String ident,
                       java.lang.Class type)

do_vb_Right

public void do_vb_Right(java.util.Map callInfo)

do_vb_Left

public void do_vb_Left(java.util.Map callInfo)

do_vb_Mid

public void do_vb_Mid(java.util.Map callInfo)

do_vb_UCase

public void do_vb_UCase(java.util.Map callInfo)

do_vb_LCase

public void do_vb_LCase(java.util.Map callInfo)

do_vb_IsEmpty

public void do_vb_IsEmpty(java.util.Map callInfo)

do_vb_IsNull

public void do_vb_IsNull(java.util.Map callInfo)

do_vb_Chr

public void do_vb_Chr(java.util.Map callInfo)

do_vb_IsEmptyIsNull

public void do_vb_IsEmptyIsNull(java.util.Map callInfo)

do_vb_UCaseLCase

public void do_vb_UCaseLCase(java.util.Map callInfo)

do_vb_RightLeftMid

public void do_vb_RightLeftMid(java.util.Map callInfo)
Parameters:
callInfo -

intString

private java.lang.String intString(java.lang.String doubleString)
Convert a vb string index/length expression from double to int

Parameters:
doubleString -
Returns:
String

do_variant_conversion

public void do_variant_conversion(java.util.Map callInfo)

makeMethodCallCP

private JaspCleaner.CompositePattern makeMethodCallCP(java.lang.String arg0,
                                                      java.lang.String method,
                                                      java.lang.String args)
Parameters:
arg0 -
method -
args -
Returns:
CompositePattern

do_primitive_operator

public void do_primitive_operator(java.util.Map callInfo)
Replace primitive-operator equivalents (e.g. Greater()) with corresponding primitive (or String) operator. Assuming that isPrimitiveOperator() has been called on the map prior to entry, there will be an element in the map, "COERCEDTYPE", indicating which type the operator expression has been coerced to.


do_vb_UBound

public void do_vb_UBound(java.util.Map callInfo)
Replace UBound() with size().


do_vb_Len

public void do_vb_Len(java.util.Map callInfo)

do_vb_Trim

public void do_vb_Trim(java.util.Map callInfo)

checkForPVectorAddChain

private java.util.Map checkForPVectorAddChain(antlr.collections.AST exprContents)
Check a METHOD_CALL to see if it is a pVector.Add() chain

Parameters:
exprContents -

do_vb_Instr

public void do_vb_Instr(java.util.Map callInfo)

do_vb_Replace

public void do_vb_Replace(java.util.Map callInfo)

do_vb_String

public void do_vb_String(java.util.Map callInfo)

do_vb_IsArray

public void do_vb_IsArray(java.util.Map callInfo)

do_ArrayList_getItem

public void do_ArrayList_getItem(java.util.Map callInfo)
A getItem() called on a vbarray object will be translated to a get() call on an ArrayList object, but since J-ASP seems to be using arrays with OPTION BASE1, this method will automatically subtract one from index.


do_String_unequals

public void do_String_unequals(java.util.Map callInfo)

do_PHUtils_CreateObject

public void do_PHUtils_CreateObject(java.util.Map callInfo)

do_Server_CreateObject

public void do_Server_CreateObject(java.util.Map callInfo)

do_variant_setObject

public void do_variant_setObject(java.util.Map callInfo)

do_variant_set

public void do_variant_set(java.util.Map callInfo)
For a set() invocation on a variant object, try to determine the type of the object, and replace the set() call with an assignment.

Parameters:
callInfo -

matchArgBoxing

public java.util.List matchArgBoxing(java.util.Map callInfo)

findMatchingMethods

private java.util.ArrayList findMatchingMethods(java.util.Map callInfo,
                                                JaspCleaner.SignatureComparator sc)
Parameters:
callInfo -
sc -
Returns:
List

do_operator_Greater

public void do_operator_Greater(java.util.Map callInfo)

do_operator_Is

public void do_operator_Is(java.util.Map callInfo)

do_operator_invoke

public void do_operator_invoke(java.util.Map callInfo)

do_operator_get

public void do_operator_get(java.util.Map callInfo)

do_operator_set

public void do_operator_set(java.util.Map callInfo)

stripEnclosingChar

public static java.lang.String stripEnclosingChar(java.lang.String arg1)

toUpperCamelCase

public static java.lang.String toUpperCamelCase(java.lang.String arg1)
Parameters:
arg1 -
Returns:

visit

public void visit(antlr.collections.AST ast)
Visitor pattern applied, based on AST.getType()and switch statement, as follows (unless ast is null): Finally, this method is recursively called on the next siblingof this ast.

Specified by:
visit in interface antlr.ASTVisitor
Parameters:
ast - AST to visit.

coerceAssignTypes

private void coerceAssignTypes(antlr.collections.AST ast)
Check an assignment to see if we can coerce lhs or rhs type

Parameters:
ast -

checkForPMDReplacement

private void checkForPMDReplacement(antlr.collections.AST ast)
Check an assignment to see if its LHS has been flagged by PMS as an unused variable. If so generate a replacement to comment out the LHS and assignment operator.

Parameters:
ast -

propagateNodeText

private void propagateNodeText(antlr.collections.AST ast)
Visit children, accumulating and storing nodeText for this node

Parameters:
ast -

getCanonicalText

private java.lang.String getCanonicalText(antlr.collections.AST ast)
Parameters:
ast -
txt -
Returns:

log

private static final void log(java.lang.String s)
Log the message (currently, to System.out).

Parameters:
s - message to log.

logDebug

private static final void logDebug(java.lang.String s)

preProcess

private static void preProcess(java.io.File from,
                               java.io.File to)
                        throws java.io.FileNotFoundException,
                               java.io.IOException
Preprocesses the original Netcoole-converted JSP file.

The preprocessing involves the following:

  1. While preserving indentation and comments, reformat the file so that whitespace is compressed (easier to do regexp replacement later).
  2. Replacing setNull() with assignment of null
This would make it easier to trace types XXX

Parameters:
from - .jsp file to preprocess
to - file to write the output of the preprocessing.
Throws:
java.io.FileNotFoundException - if an error occur accessing files.
java.io.IOException - if an error occur accessing files.

write

private static void write(java.io.File f,
                          java.lang.String s)
                   throws java.io.IOException
Writes the string into a file.

Parameters:
f - file to write to.
s - string to write
Throws:
java.io.IOException - if an error occurs during writing

postProcess

private static void postProcess(java.lang.String jspPage,
                                java.io.File to)
                         throws java.io.FileNotFoundException,
                                java.io.IOException
Postprocess, as follows:
  1. Replace invocation of default variantconstructors with nothing; i.e., new variant().foo() becomes foo()
  2. Replace Netcoole's conversion methods -- static methods of the class vb whose names start with C, e.g., ( vb.CInt(jasp.vbs.variant)-- with their arguments. E.g., vb.CInt(foo) will become foo.
  3. Replace vbarray with ArrayList
  4. Replace Session.setItem with PHShort.setSess
This would make it easier to trace types XXX

Parameters:
jspPage - JSP Page to preprocess
to - file to write the output of the preprocessing.
Throws:
java.io.FileNotFoundException - if an error occur accessing files.
java.io.IOException - if an error occur accessing files.

copy

private static final void copy(java.io.File from,
                               java.io.File to)
                        throws java.io.IOException
Copies files.

Parameters:
from - File to copy
to - File to copy to
Throws:
java.io.IOException - whenever an I/O error occurs.

main

public static void main(java.lang.String[] args)
                 throws java.lang.Exception
For each of the JSP files to be converted, the following algorithm is performed:
  1. Preprocessthe page
  2. Do static semantic analysis of the file (in visit(AST), and processMethodCall(antlr.collections.AST)}, and identify with what types to replace variant types to the best of our ability (see above two methods for heuristics used).
  3. XXX
  4. Postprocessthe page

Parameters:
args - JSP files to be converted.
Throws:
java.lang.Exception

insertLineNumbers

private void insertLineNumbers(java.io.File interJsp,
                               java.io.File linedJsp)
                        throws java.io.IOException
Parameters:
interJsp - - input File - intermediate JSP file
Throws:
java.io.IOException

doReplacements

private java.lang.String doReplacements(java.lang.String jspPage)
                                 throws java.io.FileNotFoundException,
                                        java.io.IOException
Parameters:
cleaner -
interJsp -
Throws:
java.io.FileNotFoundException
java.io.IOException

replaceHTMLComments

private java.lang.String replaceHTMLComments(java.lang.String jspFragment)
Parameters:
jspFragment -
Returns:

fileToString

private java.lang.String fileToString(java.io.File interJsp)
                               throws java.io.FileNotFoundException,
                                      java.io.IOException
Parameters:
interJsp -
Throws:
java.io.FileNotFoundException
java.io.IOException

inclusiveSplit

private static java.lang.String[] inclusiveSplit(java.lang.String regex,
                                                 java.lang.String target)
Works like String.split(String regex), except that the delimiters that are detected appear as elements in the output array. For example: inclusiveSplit(":", "boo:and:foo") will return a 5-element array, {"boo", ":", "and", ":", "foo"}

Parameters:
regex -
target -

doPMD

private void doPMD(java.io.File f)
            throws net.sourceforge.pmd.PMDException,
                   java.io.IOException
Perform PMD analysis, and get rid of unused vars.

Parameters:
f - .java file to analyze
replaceements - Map of replacements.
Throws:
net.sourceforge.pmd.PMDException
java.io.IOException

guessClassFromHungarianNotation

private java.lang.Class guessClassFromHungarianNotation(java.lang.String id)

cascadeReplacements

private void cascadeReplacements()