1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.apache.harmony.luni.tests.java.io;
19
20import java.io.File;
21import java.io.FileInputStream;
22import java.io.FileNotFoundException;
23import java.io.IOException;
24import java.lang.reflect.Constructor;
25import java.lang.reflect.InvocationTargetException;
26import java.util.Vector;
27import java.util.zip.ZipEntry;
28import java.util.zip.ZipInputStream;
29
30@SuppressWarnings( { "serial", "unused" })
31public class SerializationStressTest5 extends SerializationStressTest {
32
33	transient Throwable current;
34
35	// Use this for retrieving a list of any Throwable Classes that did not get
36	// tested.
37	transient Vector<Class> missedV = new Vector<Class>();
38
39	transient Class[][] params = new Class[][] { { String.class },
40			{ Throwable.class }, { Exception.class },
41			{ String.class, Exception.class }, { String.class, int.class },
42			{ String.class, String.class, String.class },
43			{ String.class, Error.class },
44			{ int.class, boolean.class, boolean.class, int.class, int.class },
45			{} };
46
47	transient Object[][] args = new Object[][] {
48			{ "message" },
49			{ new Throwable() },
50			{ new Exception("exception") },
51			{ "message", new Exception("exception") },
52			{ "message", new Integer(5) },
53			{ "message", "message", "message" },
54			{ "message", new Error("error") },
55			{ new Integer(5), new Boolean(false), new Boolean(false),
56					new Integer(5), new Integer(5) }, {} };
57
58	public SerializationStressTest5(String name) {
59		super(name);
60	}
61
62	public void test_writeObject_Throwables() {
63		try {
64			oos.close();
65		} catch (IOException e) {
66		}
67
68		File javaDir = findJavaDir();
69
70		Vector<File> classFilesVector = new Vector<File>();
71		if (javaDir != null)
72			findClassFiles(javaDir, classFilesVector);
73		else
74			findClassFilesFromZip(classFilesVector);
75
76		if (classFilesVector.size() == 0) {
77			fail("No Class Files Found.");
78		}
79
80		File[] classFilesArray = new File[classFilesVector.size()];
81		classFilesVector.copyInto(classFilesArray);
82
83		Class[] throwableClasses = findThrowableClasses(classFilesArray);
84		findParam(throwableClasses);
85
86		// Use this to print out the list of Throwable classes that weren't
87		// tested.
88		/*
89		 * System.out.println(); Class[] temp = new Class[missedV.size()];
90		 * missedV.copyInto(temp); for (int i = 0; i < temp.length; i++)
91		 * System.out.println(i+1 + ": " + temp[i].getName());
92		 */
93	}
94
95	private File[] makeClassPathArray() {
96		String classPath;
97		if (System.getProperty("java.vendor").startsWith("IBM"))
98			classPath = System.getProperty("org.apache.harmony.boot.class.path");
99		else
100			classPath = System.getProperty("sun.boot.class.path");
101		int instanceOfSep = -1;
102		int nextInstance = classPath.indexOf(File.pathSeparatorChar,
103				instanceOfSep + 1);
104		Vector<File> elms = new Vector<File>();
105		while (nextInstance != -1) {
106			elms.add(new File(classPath.substring(instanceOfSep + 1,
107					nextInstance)));
108			instanceOfSep = nextInstance;
109			nextInstance = classPath.indexOf(File.pathSeparatorChar,
110					instanceOfSep + 1);
111		}
112		elms.add(new File(classPath.substring(instanceOfSep + 1)));
113		File[] result = new File[elms.size()];
114		elms.copyInto(result);
115		return result;
116	}
117
118	private File findJavaDir() {
119		File[] files = makeClassPathArray();
120		for (int i = 0; i < files.length; i++) {
121			if (files[i].isDirectory()) {
122				String[] tempFileNames = files[i].list();
123				for (int j = 0; j < tempFileNames.length; j++) {
124					File tempfile = new File(files[i], tempFileNames[j]);
125					if (tempfile.isDirectory()
126							&& tempFileNames[j].equals("java")) {
127						String[] subdirNames = tempfile.list();
128						for (int k = 0; k < subdirNames.length; k++) {
129							File subdir = new File(tempfile, subdirNames[k]);
130							if (subdir.isDirectory()
131									&& subdirNames[k].equals("lang")) {
132								return tempfile;
133							}
134						}
135					}
136				}
137			}
138		}
139		return null;
140	}
141
142	private void findClassFiles(File dir, Vector<File> v) {
143		String[] classFileNames = dir.list();
144		for (int i = 0; i < classFileNames.length; i++) {
145			File file = new File(dir, classFileNames[i]);
146			if (file.isDirectory())
147				findClassFiles(file, v);
148			else if (classFileNames[i].endsWith(".class"))
149				v.add(file);
150		}
151	}
152
153	private Class[] findThrowableClasses(File[] files) {
154		Class<Throwable> thrClass = Throwable.class;
155		Vector<Class> resultVector = new Vector<Class>();
156		String slash = System.getProperty("file.separator");
157		String begTarget = slash + "java" + slash;
158		String endTarget = ".class";
159		for (int i = 0; i < files.length; i++) {
160			String fileName = files[i].getPath();
161			int instOfBegTarget = fileName.indexOf(begTarget);
162			int instOfEndTarget = fileName.indexOf(endTarget);
163			fileName = fileName.substring(instOfBegTarget + 1, instOfEndTarget);
164			fileName = fileName.replace(slash.charAt(0), '.');
165			try {
166				Class theClass = Class.forName(fileName, false, ClassLoader
167						.getSystemClassLoader());
168				if (thrClass.isAssignableFrom(theClass)) {
169					// java.lang.VirtualMachineError is abstract.
170					// java.io.ObjectStreamException is abstract
171					// java.beans.PropertyVetoException needs a
172					// java.beans.PropertyChangeEvent as a parameter
173					if (!fileName.equals("java.lang.VirtualMachineError")
174							&& !fileName
175									.equals("java.io.ObjectStreamException")
176							&& !fileName
177									.equals("java.beans.PropertyVetoException"))
178						resultVector.add(theClass);
179				}
180			} catch (ClassNotFoundException e) {
181				fail("ClassNotFoundException : " + fileName);
182			}
183		}
184		Class[] result = new Class[resultVector.size()];
185		resultVector.copyInto(result);
186		return result;
187	}
188
189	private void initClass(Class thrC, int num) {
190		Constructor[] cons = thrC.getConstructors();
191		for (int i = 0; i < cons.length; i++) {
192			try {
193				Throwable obj = (Throwable) cons[i].newInstance(args[num]);
194				t_Class(obj, num);
195				break;
196			} catch (IllegalArgumentException e) {
197				// This error should be caught until the correct args is hit.
198			} catch (IllegalAccessException e) {
199				fail(
200						"IllegalAccessException while creating instance of: "
201								+ thrC.getName());
202			} catch (InstantiationException e) {
203				fail(
204						"InstantiationException while creating instance of: "
205								+ thrC.getName());
206			} catch (InvocationTargetException e) {
207				fail(
208						"InvocationTargetException while creating instance of: "
209								+ thrC.getName());
210			}
211			if (i == cons.length - 1) {
212				fail(
213						"Failed to create newInstance of: " + thrC.getName());
214			}
215		}
216	}
217
218	public String getDumpName() {
219		if (current == null) {
220			dumpCount++;
221			return getName();
222		}
223		return getName() + "_" + current.getClass().getName();
224	}
225
226	private void t_Class(Throwable objToSave, int argsNum) {
227		current = objToSave;
228		Object objLoaded = null;
229		try {
230			if (DEBUG)
231				System.out.println("Obj = " + objToSave);
232			try {
233				objLoaded = dumpAndReload(objToSave);
234			} catch (FileNotFoundException e) {
235				// Must be using xload, ignore missing Throwables
236				System.out.println("Ignoring: "
237						+ objToSave.getClass().getName());
238				return;
239			}
240
241			// Has to have worked
242			boolean equals;
243			equals = objToSave.getClass().equals(objLoaded.getClass());
244			assertTrue(MSG_TEST_FAILED + objToSave, equals);
245			if (argsNum == 0 || (argsNum >= 3 && argsNum <= 7)) {
246				equals = ((Throwable) objToSave).getMessage().equals(
247						((Throwable) objLoaded).getMessage());
248				assertTrue("Message Test: " + MSG_TEST_FAILED + objToSave,
249						equals);
250			} else {
251				// System.out.println(((Throwable)objToSave).getMessage());
252				equals = ((Throwable) objToSave).getMessage() == null;
253				assertTrue("Null Test 1: (args=" + argsNum + ") "
254						+ MSG_TEST_FAILED + objToSave, equals);
255				equals = ((Throwable) objLoaded).getMessage() == null;
256				assertTrue("Null Test 2: (args=" + argsNum + ") "
257						+ MSG_TEST_FAILED + objToSave, equals);
258			}
259		} catch (IOException e) {
260			fail("Unexpected IOException in checkIt() : " + e.getMessage());
261		} catch (ClassNotFoundException e) {
262			fail(e.toString() + " - testing " + objToSave.getClass().getName());
263		}
264	}
265
266	private void findParam(Class[] thrC) {
267		for (int i = 0; i < thrC.length; i++) {
268			Constructor con = null;
269			for (int j = 0; j < params.length; j++) {
270				try {
271					con = thrC[i].getConstructor(params[j]);
272				} catch (NoSuchMethodException e) {
273					// This Error will be caught until the right param is found.
274				}
275
276				if (con != null) {
277					// If the param was found, initialize the Class
278					initClass(thrC[i], j);
279					break;
280				}
281				// If the param not found then add to missed Vector.
282				if (j == params.length - 1)
283					missedV.add(thrC[i]);
284			}
285		}
286	}
287
288	private void findClassFilesFromZip(Vector<File> v) {
289		String slash = System.getProperty("file.separator");
290		String javaHome = System.getProperty("java.home");
291		if (!javaHome.endsWith(slash))
292			javaHome += slash;
293
294		String[] wanted = { "java" + slash + "io", "java" + slash + "lang",
295				"java" + slash + "math", "java" + slash + "net",
296				"java" + slash + "security", "java" + slash + "text",
297				"java" + slash + "util", "java" + slash + "beans",
298				"java" + slash + "rmi",
299				// One or more class files in awt make the VM hang after being
300				// loaded.
301				// "java" + slash + "awt",
302				"java" + slash + "sql",
303		// These are (possibly) all of the throwable classes in awt
304		/*
305		 * "java\\awt\\AWTError", "java\\awt\\AWTException",
306		 * "java\\awt\\color\\CMMException",
307		 * "java\\awt\\color\\ProfileDataException",
308		 * "java\\awt\\datatransfer\\MimeTypeParseException",
309		 * "java\\awt\\datatransfer\\UnsupportedFlavorException",
310		 * "java\\awt\\dnd\\InvalidDnDOperationException",
311		 * "java\\awt\\FontFormatException",
312		 * "java\\awt\\geom\\IllegalPathStateException",
313		 * "java\\awt\\geom\\NoninvertibleTransformException",
314		 * "java\\awt\\IllegalComponentStateException",
315		 * "java\\awt\\image\\ImagingOpException",
316		 * "java\\awt\\image\\RasterFormatException",
317		 * "java\\awt\\print\\PrinterAbortException",
318		 * "java\\awt\\print\\PrinterException",
319		 * "java\\awt\\print\\PrinterIOException"
320		 */
321		};
322
323		File[] files = makeClassPathArray();
324		FileInputStream fis = null;
325		ZipInputStream zis = null;
326		ZipEntry ze = null;
327		for (int i = 0; i < files.length; i++) {
328			String fileName = files[i].getPath();
329			if (files[i].exists() && files[i].isFile()
330					&& fileName.endsWith(".jar") || fileName.endsWith(".zip")) {
331				try {
332					fis = new FileInputStream(files[i].getPath());
333				} catch (FileNotFoundException e) {
334					fail("FileNotFoundException trying to open "
335							+ files[i].getPath());
336				}
337				zis = new ZipInputStream(fis);
338				while (true) {
339					try {
340						ze = zis.getNextEntry();
341					} catch (IOException e) {
342						fail("IOException while getting next zip entry: "
343								+ e);
344					}
345					if (ze == null)
346						break;
347					String zeName = ze.getName();
348					if (zeName.endsWith(".class")) {
349						zeName = zeName.replace('/', slash.charAt(0));
350						for (int j = 0; j < wanted.length; j++) {
351							if (zeName.startsWith(wanted[j])) {
352								// When finding class files from directories the
353								// program saves them as files.
354								// To stay consistent we will turn the ZipEntry
355								// classes into instances of files.
356								File tempF = new File(javaHome + zeName);
357								// Making sure that the same class is not added
358								// twice.
359								boolean duplicate = false;
360								for (int k = 0; k < v.size(); k++) {
361									if (v.get(k).equals(tempF))
362										duplicate = true;
363								}
364								if (!duplicate)
365									v.add(tempF);
366								break;
367							}
368						}
369					}
370				}
371				;
372				try {
373					zis.close();
374					fis.close();
375				} catch (IOException e) {
376					fail(
377							"IOException while trying to close InputStreams: "
378									+ e);
379				}
380			}
381		}
382	}
383}
384