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
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
228 }
229 }
230 }
231 }
232 }