1e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes/* 2e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * Licensed to the Apache Software Foundation (ASF) under one or more 3e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * contributor license agreements. See the NOTICE file distributed with 4e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * this work for additional information regarding copyright ownership. 5e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * The ASF licenses this file to You under the Apache License, Version 2.0 6e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * (the "License"); you may not use this file except in compliance with 7e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * the License. You may obtain a copy of the License at 8e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * 9e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 10e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * 11e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * Unless required by applicable law or agreed to in writing, software 12e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 13e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * See the License for the specific language governing permissions and 15e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * limitations under the License. 16e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes */ 17e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 18e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughespackage tests.util; 19e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 20e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.ByteArrayInputStream; 21e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.ByteArrayOutputStream; 22e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.File; 23e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.FileOutputStream; 24e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.IOException; 25e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.InputStream; 26e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.ObjectInputStream; 27e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.ObjectOutputStream; 28e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.OutputStream; 29e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.net.URL; 30e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 31e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes/** 32e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * This class simplifies the serialization test. 33e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes */ 34e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughespublic class SerializationTester { 35e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes 368d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /* 378d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * -------------------------------------------------------------------- 388d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Class variables 398d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * -------------------------------------------------------------------- 408d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 418d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 428d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath // the last deserialized object 438d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath private static Object lastOutput = null; 448d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 458d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /* 468d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * ------------------------------------------------------------------- 478d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Constructors 488d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * ------------------------------------------------------------------- 498d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 508d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 518d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath private SerializationTester() { 528d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 538d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 548d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 558d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /* 568d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * ------------------------------------------------------------------- 578d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Methods 588d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * ------------------------------------------------------------------- 598d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 608d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 618d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /** 628d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Serialize an object and then deserialize it. 638d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * 648d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @param inputObject the input object 658d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @return the deserialized object 668d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 678d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath public static Object getDeserilizedObject(Object inputObject) 688d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath throws IOException, ClassNotFoundException { 698d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath ByteArrayOutputStream bos = new ByteArrayOutputStream(); 708d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath ObjectOutputStream oos = new ObjectOutputStream(bos); 718d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath oos.writeObject(inputObject); 728d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath oos.close(); 738d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 748d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); 758d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath ObjectInputStream ois = new ObjectInputStream(bis); 768d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath Object outputObject = ois.readObject(); 778d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath lastOutput = outputObject; 788d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath ois.close(); 798d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath return outputObject; 808d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 818d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 828d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /** 838d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Tests the serialization and deserialization of const objects. 848d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * 858d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @param inputObject A const object 868d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @return true if the deserialized object is the same as the input object, 878d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * otherwise false 888d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @throws Exception If any occurs. 898d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 908d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath public static boolean assertSame(Object inputObject) throws Exception { 918d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath return inputObject == getDeserilizedObject(inputObject); 928d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 938d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 948d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /** 958d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Tests the serialization and deserialization of instance objects. 968d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * 978d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @param inputObject An object 988d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @return true if the deserialized object is equal to the input object, 998d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * otherwise false 1008d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @throws Exception If any occurs. 1018d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 1028d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath public static boolean assertEquals(Object inputObject) throws Exception { 1038d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath return inputObject.equals(getDeserilizedObject(inputObject)); 1048d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1058d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 1068d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /** 1078d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Tests the serialization compatibility with reference const objects. 1088d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * 1098d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @param obj the object to be checked 1108d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @param fileName the serialization output file generated by reference 1118d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @return true if compatible, otherwise false 1128d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @throws Exception If any occurs. 1138d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 1148d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath public static boolean assertCompabilitySame(Object obj, String fileName) 1158d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath throws Exception { 1168d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath return obj == readObject(obj, fileName); 1178d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1188d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 1198d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /** 1208d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Tests the serialization compatibility with reference for instance 1218d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * objects. 1228d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * 1238d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @param obj the object to be checked 1248d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @param fileName the serialization output file generated by reference 1258d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @return true if compatible, otherwise false 1268d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @throws Exception If any occurs. 1278d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 1288d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath public static boolean assertCompabilityEquals(Object obj, String fileName) 1298d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath throws Exception { 1308d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath return obj.equals(readObject(obj, fileName)); 1318d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1328d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 1338d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /** 1348d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Deserialize an object from a file. 1358d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * 1368d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @param obj the object to be serialized if no serialization file is found 1378d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @param fileName the serialization file 1388d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @return the deserialized object 1398d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @throws Exception If any occurs. 1408d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 1418d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath public static Object readObject(Object obj, String fileName) 1428d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath throws Exception { 1438d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath InputStream input = null; 1448d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath ObjectInputStream oinput = null; 1458d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath URL url = SerializationTester.class.getClassLoader().getResource( 1468d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath fileName); 1478d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath if (null == url) { 1488d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath // serialization file does not exist, create one in the current dir 1498d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath writeObject(obj, new File(fileName).getName()); 1508d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath throw new Error( 1518d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath "Serialization file does not exist, created in the current dir."); 1528d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1538d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath input = url.openStream(); 1548d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath try { 1558d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath oinput = new ObjectInputStream(input); 1568d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath Object newObj = oinput.readObject(); 1578d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath return newObj; 1588d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } finally { 1598d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath try { 1608d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath if (null != oinput) { 1618d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath oinput.close(); 1628d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1638d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } catch (Exception e) { 1648d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath // ignore 1658d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1668d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath try { 1678d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath if (null != input) { 1688d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath input.close(); 1698d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1708d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } catch (Exception e) { 1718d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath // ignore 1728d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1738d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1748d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 1758d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 1768d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /* 1778d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Creates a serialization output. 1788d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * 1798d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @param obj the object to be serialized @param fileName the output file 1808d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @throws Exception If any occurs. 1818d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 1828d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath public static void writeObject(Object obj, String fileName) 1838d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath throws Exception { 1848d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath // String path = SerializationTester.class.getResource(".").getPath(); 1858d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath // if (path.endsWith(".")) { 1868d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath // path = path.substring(0, path.length() - 1); 1878d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath // } 1888d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath // if (!path.endsWith("/")) { 1898d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath // path += "/"; 1908d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath // } 1918d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath // path += fileName; 1928d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath // System.out.println(path); 1938d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath OutputStream output = null; 1948d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath ObjectOutputStream ooutput = null; 1958d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath try { 1968d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath output = new FileOutputStream(fileName); 1978d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath ooutput = new ObjectOutputStream(output); 1988d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath ooutput.writeObject(obj); 1998d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } finally { 2008d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath try { 2018d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath if (null != ooutput) { 2028d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath ooutput.close(); 2038d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 2048d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } catch (Exception e) { 2058d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath // ignore 2068d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 2078d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath try { 2088d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath if (null != output) { 2098d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath output.close(); 2108d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 2118d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } catch (Exception e) { 2128d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath // ignore 2138d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 2148d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 2158d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 2168d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 2178d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /** 2188d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * Gets the last deserialized object. 2198d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * 2208d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * @return the last deserialized object 2218d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 2228d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath public static Object getLastOutput() { 2238d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath return lastOutput; 2248d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 2258d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath 2268d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath /* 2278d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath * For test purpose. 2288d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath */ 2298d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath public static void main(String[] args) { 2308d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath } 231e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes} 232