View Javadoc

1   package org.softevo.jdynpur.eval;
2   
3   import java.io.FileInputStream;
4   import java.io.FileOutputStream;
5   import java.io.IOException;
6   import java.io.OutputStream;
7   import java.util.Collections;
8   import java.util.HashMap;
9   import java.util.HashSet;
10  import java.util.Vector;
11  
12  import javax.xml.parsers.DocumentBuilder;
13  import javax.xml.parsers.DocumentBuilderFactory;
14  import javax.xml.parsers.ParserConfigurationException;
15  import javax.xml.transform.OutputKeys;
16  import javax.xml.transform.Transformer;
17  import javax.xml.transform.TransformerException;
18  import javax.xml.transform.TransformerFactory;
19  import javax.xml.transform.dom.DOMSource;
20  import javax.xml.transform.stream.StreamResult;
21  
22  import org.softevo.jdynpur.eval.PurityTraceAnalyser.ParameterMutabilityInformation;
23  import org.softevo.util.asm.MethodIdentifier;
24  import org.softevo.util.io.ObjectReaderWriter;
25  import org.w3c.dom.DOMImplementation;
26  import org.w3c.dom.Document;
27  import org.w3c.dom.Element;
28  
29  public class PurityResults {
30  
31  	/**
32  	 * The set of methods known to modify the object they were invoked on.
33  	 */
34  	protected HashMap<MethodIdentifier, HashSet<String>> methodsModifyingThisObject = null;
35  
36  	/**
37  	 * The set of <code>MethodIdentifiers</code> known to be pure.
38  	 */
39  	protected HashMap<MethodIdentifier, HashSet<String>> pureMethodIdentifiers = null;
40  
41  	/**
42  	 * The set of <code>MethodIdentifiers</code> known to be impure.
43  	 */
44  	protected HashMap<MethodIdentifier, HashSet<String>> impureMethodIdentifiers = null;
45  
46  	/**
47  	 * The set of executed <code>MethodIdentifiers</code>.
48  	 */
49  	protected HashMap<MethodIdentifier, HashSet<String>> executedMethodIdentifiers = null;
50  
51  	private HashMap<MethodIdentifier, ParameterMutabilityInformation> parameterMutabilityInformation;
52  
53  	public PurityResults() {
54  		methodsModifyingThisObject = new HashMap<MethodIdentifier, HashSet<String>>();
55  		pureMethodIdentifiers = new HashMap<MethodIdentifier, HashSet<String>>();
56  		impureMethodIdentifiers = new HashMap<MethodIdentifier, HashSet<String>>();
57  		executedMethodIdentifiers = new HashMap<MethodIdentifier, HashSet<String>>();
58  		parameterMutabilityInformation = new HashMap<MethodIdentifier, ParameterMutabilityInformation>();
59  	}
60  
61  	public PurityResults(HashMap<MethodIdentifier, HashSet<String>> pureMethodIdentifiers,
62  	                     HashMap<MethodIdentifier, HashSet<String>> impureMethodIdentifiers, 
63  	                     HashMap<MethodIdentifier, HashSet<String>> methodsModifyingThisObject,
64  	                     HashMap<MethodIdentifier, HashSet<String>> executedMethodIdentifiers,
65  	                     HashMap<MethodIdentifier, ParameterMutabilityInformation> parameterMutabilityInformation) {
66  		this();
67  		this.executedMethodIdentifiers.putAll(executedMethodIdentifiers);
68  		this.impureMethodIdentifiers.putAll(impureMethodIdentifiers);
69  		this.methodsModifyingThisObject.putAll(methodsModifyingThisObject);
70  		this.pureMethodIdentifiers.putAll(pureMethodIdentifiers);
71  		if (parameterMutabilityInformation != null) {
72  		  this.parameterMutabilityInformation.putAll(parameterMutabilityInformation);
73  		}
74  	}
75  
76  	public HashMap<MethodIdentifier, HashSet<String>> getExecutedMethodIdentifiers() {
77  		return executedMethodIdentifiers;
78  	}
79  
80  	public HashMap<MethodIdentifier, HashSet<String>> getImpureMethodIdentifiers() {
81  		return impureMethodIdentifiers;
82  	}
83  
84  	public HashMap<MethodIdentifier, HashSet<String>> getMethodsModifyingThisObject() {
85  		return methodsModifyingThisObject;
86  	}
87  
88  	public HashMap<MethodIdentifier, HashSet<String>> getPureMethodIdentifiers() {
89  		return pureMethodIdentifiers;
90  	}
91  
92  	public HashMap<MethodIdentifier, ParameterMutabilityInformation> getParameterMutabilityInformation() {
93  		return parameterMutabilityInformation;
94  	}
95  
96  	public void saveXML(String fileName) throws IOException, ParserConfigurationException, TransformerException {
97  		saveXML(new FileOutputStream(fileName));
98  	}
99  	
100 	public void saveXML(OutputStream outputStream) throws IOException, ParserConfigurationException, TransformerException {
101 		Document targetDocument = null;
102 		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
103 		DocumentBuilder builder = factory.newDocumentBuilder();
104 		DOMImplementation impl = builder.getDOMImplementation();
105 		targetDocument = impl.createDocument(null, "purityresults", null);	
106 		Element root = targetDocument.getDocumentElement();
107 		Element executedMethodsElement = targetDocument.createElement("executedmethods");
108 		root.appendChild(executedMethodsElement);
109 		addMethodElements(executedMethodsElement, targetDocument, executedMethodIdentifiers);
110 		Element methodsModifyingThisElement = targetDocument.createElement("methodsmodifyingself");
111 		root.appendChild(methodsModifyingThisElement);
112 		addMethodElements(methodsModifyingThisElement, targetDocument, methodsModifyingThisObject);
113 		Element impureMethodsElement = targetDocument.createElement("impuremethods");
114 		root.appendChild(impureMethodsElement);
115 		addMethodElements(impureMethodsElement, targetDocument, impureMethodIdentifiers);
116 		Element pureMethodsElement = targetDocument.createElement("puremethods");
117 		root.appendChild(pureMethodsElement);
118 		addMethodElements(pureMethodsElement, targetDocument, pureMethodIdentifiers);
119 		if (parameterMutabilityInformation != null && parameterMutabilityInformation.size() > 0) {
120 		  Element parameterElement = targetDocument.createElement("parametermutability");
121 		  root.appendChild(parameterElement);
122 		  addParameterElements(parameterElement, targetDocument, parameterMutabilityInformation);
123 		}
124 		StreamResult streamResult = new StreamResult(outputStream);
125 		TransformerFactory tf = TransformerFactory.newInstance();
126 		Transformer serializer = tf.newTransformer();
127 		serializer.setOutputProperty(OutputKeys.ENCODING,"ISO-8859-1");
128 		serializer.setOutputProperty(OutputKeys.INDENT,"yes");
129 		DOMSource domSource = new DOMSource(targetDocument);
130 		serializer.transform(domSource, streamResult);
131 	}
132 
133 	protected void addParameterElements(Element parent, Document document,
134 	                                    HashMap<MethodIdentifier, ParameterMutabilityInformation> parameterMutabilityInformation) {
135 		for (MethodIdentifier identifier : parameterMutabilityInformation.keySet()) {
136 			Element identifierElement = document.createElement("method");
137 			parent.appendChild(identifierElement);
138 			identifierElement.setAttribute("classname", identifier.getClassName());
139 			identifierElement.setAttribute("methodname", identifier.getMethodName());
140 			identifierElement.setAttribute("signature", identifier.getSignature());
141 			identifierElement.setAttribute("access", Integer.toString(identifier.getAccess()));
142 			ParameterMutabilityInformation mutabilityInformation = parameterMutabilityInformation.get(identifier);
143 			HashSet<Integer> unmodifiedParameters = mutabilityInformation.getUnmodifiedParameters();
144 			HashSet<Integer> parameterIndexes = mutabilityInformation.getParameters();
145 			HashMap<String, HashSet<Integer>> classNameToUnmodifiedParametersMap = mutabilityInformation.getRuntimeClassNameToUnmodifiedParametersMap();
146 			for (String className : classNameToUnmodifiedParametersMap.keySet()) {
147 				if (parameterIndexes.size() > 0) {
148 					Element classElement = document.createElement("runtimeclass");
149 					classElement.setAttribute("classname", className);
150 					identifierElement.appendChild(classElement);
151 					Vector<Integer> sortedParameters = new Vector<Integer>(parameterIndexes);
152 					Collections.sort(sortedParameters);
153 					for (Integer parameterIndex : sortedParameters) {
154 						Element parameterElement = document.createElement("parameter");
155 						classElement.appendChild(parameterElement);
156 						parameterElement.setAttribute("index", Integer.toString(parameterIndex));
157 						if (unmodifiedParameters.contains(parameterIndex)) {
158 							parameterElement.setAttribute("unmodified", "true");
159 						} else {
160 							parameterElement.setAttribute("unmodified", "false");
161 						}
162 					}
163 				}
164 			}
165 		}
166 	}
167 
168 	protected void addMethodElements(Element parent, Document document, 
169 	                                 HashMap<MethodIdentifier, HashSet<String>> methodIdentifiers) {
170 		for (MethodIdentifier identifier : methodIdentifiers.keySet()) {
171 			Element identifierElement = document.createElement("method");
172 			parent.appendChild(identifierElement);
173 			identifierElement.setAttribute("classname", identifier.getClassName());
174 			identifierElement.setAttribute("methodname", identifier.getMethodName());
175 			identifierElement.setAttribute("signature", identifier.getSignature());
176 			identifierElement.setAttribute("access", Integer.toString(identifier.getAccess()));
177 			HashSet<String> invokedClasses = methodIdentifiers.get(identifier);
178 			for (String className : invokedClasses) {
179 				Element classElement = document.createElement("runtimeclass");
180 				identifierElement.appendChild(classElement);
181 				classElement.setAttribute("classname", className);
182 			}
183 		}
184 	}
185 
186 	public void save(String fileName) throws IOException {
187 		ObjectReaderWriter<HashMap<MethodIdentifier, HashSet<String>>> writer;
188 		FileOutputStream fileOutputStream = null;
189 
190 		try {
191 			fileOutputStream = new FileOutputStream(fileName);
192 			writer = new ObjectReaderWriter<HashMap<MethodIdentifier, HashSet<String>>>();
193 			writer.write(executedMethodIdentifiers, fileOutputStream);
194 			writer.write(pureMethodIdentifiers, fileOutputStream);
195 			writer.write(impureMethodIdentifiers, fileOutputStream);
196 			writer.write(methodsModifyingThisObject, fileOutputStream);
197 		} finally {
198 			if (fileOutputStream != null) {
199 				try {
200 					fileOutputStream.close();
201 				} catch (IOException finalizeException) {
202 					// ignore exception
203 				}
204 			}
205 		}
206 	}
207 
208 	public static PurityResults read(String fileName) throws IOException {
209 		FileInputStream fileInputStream = null;
210 		ObjectReaderWriter<HashMap<MethodIdentifier, HashSet<String>>> reader;
211 		PurityResults result;
212 
213 		reader = new ObjectReaderWriter<HashMap<MethodIdentifier, HashSet<String>>>();
214 		result = new PurityResults();
215 		try {
216 			fileInputStream = new FileInputStream(fileName);
217 			result.executedMethodIdentifiers.putAll(reader.read(fileInputStream));
218 			result.pureMethodIdentifiers.putAll(reader.read(fileInputStream));
219 			result.impureMethodIdentifiers.putAll(reader.read(fileInputStream));
220 			result.methodsModifyingThisObject.putAll(reader.read(fileInputStream));
221 			return result;
222 		} finally {
223 			if (fileInputStream != null) {
224 				try {
225 					fileInputStream.close();
226 				} catch (IOException finalizeException) {
227 					// ignore exception
228 				}
229 			}
230 		}
231 	}
232 }