package com.ensoftcorp.open;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class ConvertPScout2ToXML {
public static void main(String[] args) throws FileNotFoundException, ParserConfigurationException, IOException, TransformerException {
// String permissionName = "";
// Element permission = null;
// Element call = null;
// create a file object that points at the file to parse
File file = new File(args[0]);
String tag = args[1]; // android api name
// initialization to create xml file
// to store all info of methods in the mapping
DocumentBuilderFactory documentFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentFactory.newDocumentBuilder();
Document document = documentBuilder.newDocument();
Element permissions = document.createElement("permissions");
document.appendChild(permissions);
// read to read the file
Scanner scanner = new Scanner(file);
scanner.nextLine(); // skip the first line which is just a header
HashMap<String, Element> permissionElements = new HashMap<String,Element>();
while (scanner.hasNextLine()) {
// read one line of the input file
String line = scanner.nextLine();
String[] columns = line.split(",");
String callerClass = columns[0];
String callerMethod = columns[1];
String methodDescription = columns[2];
String permissionName = columns[3];
Element permission = null;
if(permissionElements.containsKey(permissionName)){
permission = permissionElements.get(permissionName);
} else {
// define permission elements in xml
permission = document.createElement("permission");
permissions.appendChild(permission);
Attr attribute = document.createAttribute("name");
attribute.setValue(permissionName);
permission.setAttributeNode(attribute);
permissionElements.put(permissionName, permission);
}
// create call elements under permission elements
Element call = document.createElement("call");
permission.appendChild(call);
String qualifiedClass = callerClass.replace("/", ".").trim();
// parse the package
String packageName = qualifiedClass.substring(0, (qualifiedClass.lastIndexOf(".")));
// parse the class
String className = qualifiedClass.substring((qualifiedClass.lastIndexOf(".") + 1), qualifiedClass.length());
// create package elements under call elements
Element pkg = document.createElement("package");
pkg.appendChild(document.createTextNode(packageName));
call.appendChild(pkg);
// create class elements under call elements
Element clazz = document.createElement("class");
clazz.appendChild(document.createTextNode(className));
call.appendChild(clazz);
// create method elements under call elements
Element method = document.createElement("method");
String methodName = callerMethod;
method.appendChild(document.createTextNode(methodName));
call.appendChild(method);
// create returnType elements under call elements
String qualifiedMethodReturnType;
try {
if(methodDescription.endsWith(")V")){
qualifiedMethodReturnType = "void";
} else if(methodDescription.contains("<init>") || (methodDescription.contains("<clinit>"))){
qualifiedMethodReturnType = "void";
} else {
qualifiedMethodReturnType = methodDescription.substring(methodDescription.indexOf(")")+1);
qualifiedMethodReturnType = qualifiedMethodReturnType.replace("/", ".");
qualifiedMethodReturnType = parseJVMDescriptor(qualifiedMethodReturnType);
}
} catch (Exception e) {
System.err.println("Invalid entry: " + methodDescription);
e.printStackTrace();
continue;
}
String unqualifiedMethodReturnType = qualifiedMethodReturnType;
if (qualifiedMethodReturnType.contains(".")) {
unqualifiedMethodReturnType = qualifiedMethodReturnType.substring(qualifiedMethodReturnType.lastIndexOf(".") + 1);
}
Element returnType = document.createElement("returnType");
returnType.appendChild(document.createTextNode(unqualifiedMethodReturnType));
call.appendChild(returnType);
ArrayList<String> parameterArray = new ArrayList<String>();
try {
String[] params = methodDescription.substring(methodDescription.indexOf("(")+1, methodDescription.indexOf(")")).split(";");
for(String param : params){
if(!param.equals("")){
param = param.replace("/", ".");
while(param.length() > 0){
String descriptor = param;
String suffix = "";
while(descriptor.startsWith("[")){
param = param.substring(1);
descriptor = descriptor.substring(1);
suffix+="[]";
}
if(descriptor.startsWith("I")){
descriptor = "int";
param = param.substring(1);
} else if(descriptor.startsWith("J")){
descriptor = "long";
param = param.substring(1);
} else if(descriptor.startsWith("S")){
descriptor = "short";
param = param.substring(1);
} else if(descriptor.startsWith("F")){
descriptor = "float";
param = param.substring(1);
} else if(descriptor.startsWith("D")){
descriptor = "double";
param = param.substring(1);
} else if(descriptor.startsWith("C")){
descriptor = "char";
param = param.substring(1);
} else if(descriptor.startsWith("B")){
descriptor = "byte";
param = param.substring(1);
} else if(descriptor.startsWith("Z")){
descriptor = "boolean";
param = param.substring(1);
} else if(descriptor.startsWith("L")){
// any non-primitive Object
descriptor = descriptor.substring(1);
param = "";
}
descriptor += suffix;
parameterArray.add(descriptor);
}
}
}
} catch (Exception e){
System.err.println("Invalid entry: " + methodDescription);
e.printStackTrace();
continue;
}
// create parameters elements under call elements
Element parameters = document.createElement("parameters");
call.appendChild(parameters);
// create parameter elements under parameters elements
for (String paramName : parameterArray) {
Element parameter = document.createElement("parameter");
parameter.appendChild(document.createTextNode(paramName));
parameters.appendChild(parameter);
}
}
// creating and writing to xml file
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
DOMSource domSource = new DOMSource(document);
String filename = tag + "PermissionMapping.xml";
File outputFile = new File(filename);
StreamResult streamResult = new StreamResult(outputFile);
transformer.transform(domSource, streamResult);
scanner.close();
System.out.println("Wrote: " + outputFile.getAbsolutePath());
}
private static String parseJVMDescriptor(String descriptor){
String suffix = "";
while(descriptor.startsWith("[")){
descriptor = descriptor.substring(1);
suffix+="[]";
}
if(descriptor.equals("I")){
descriptor = "int";
} else if(descriptor.equals("J")){
descriptor = "long";
} else if(descriptor.equals("S")){
descriptor = "short";
} else if(descriptor.equals("F")){
descriptor = "float";
} else if(descriptor.equals("D")){
descriptor = "double";
} else if(descriptor.equals("C")){
descriptor = "char";
} else if(descriptor.equals("B")){
descriptor = "byte";
} else if(descriptor.equals("Z")){
descriptor = "boolean";
} else if(descriptor.startsWith("L")){
// any non-primitive Object
descriptor = descriptor.substring(1);
}
descriptor += suffix;
return descriptor.replace(";", "");
}
}