17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
3aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert * Copyright (C) 1996-2015, International Business Machines Corporation and
4aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert * others. All Rights Reserved.
57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.dev.test.serializable;
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
11aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubertimport java.io.ByteArrayInputStream;
12aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubertimport java.io.ByteArrayOutputStream;
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.File;
147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.FileInputStream;
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.FileNotFoundException;
16aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubertimport java.io.IOException;
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.InputStream;
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.ObjectInputStream;
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.net.JarURLConnection;
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.net.URL;
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Enumeration;
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.MissingResourceException;
237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.jar.JarEntry;
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.jar.JarFile;
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.dev.test.TestFmwk;
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/**
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author emader
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class CompatibilityTest extends TestFmwk
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert{
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public class FolderTarget extends Target
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private Target head = new Target(null);
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private Target tail = head;
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public FolderTarget(String name)
397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super(name);
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public void add(String className, InputStream is)
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            HandlerTarget newTarget = new HandlerTarget(className, is);
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            tail.setNext(newTarget);
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            tail = newTarget;
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected boolean validate()
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return true;
547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected void execute() throws Exception
577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            params.indentLevel += 1;
597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (Target target = head.getNext(); target != null; target = target.getNext())
617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            {
627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                target.run();
637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            params.indentLevel -= 1;
667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public class HandlerTarget extends Target
707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected SerializableTest.Handler handler = null;
727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected InputStream inputStream = null;
737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public HandlerTarget(String name, InputStream is)
757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super(name);
777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            inputStream = is;
787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected boolean validate()
817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            handler = SerializableTest.getHandler(name);
837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return handler != null;
857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected void execute() throws Exception
887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
89aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert            try {
90aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                if (params.inDocMode()) {
91aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                    // nothing to execute
92aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                } else if (!params.stack.included) {
93aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                    ++params.invalidCount;
94aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                } else {
95aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                    params.testCount += 1;
96aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert
97aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                    try {
98aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                        ObjectInputStream in = new ObjectInputStream(inputStream);
99aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                        Object inputObjects[] = (Object[]) in.readObject();
100aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                        Object testObjects[] = handler.getTestObjects();
101aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert
102aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                        in.close();
103aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                        inputStream.close();
104aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert
105aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                        // TODO: add equality test...
106aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                        // The commented out code below does that,
107aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                        // but some test objects don't define an equals() method,
108aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                        // and the default method is the same as the "==" operator...
109aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                        for (int i = 0; i < testObjects.length; i += 1) {
110aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                            // if (! inputObjects[i].equals(testObjects[i])) {
111aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                            // errln("Input object " + i + " failed equality test.");
112aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                            // }
113aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert
114aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                            if (!handler.hasSameBehavior(inputObjects[i], testObjects[i])) {
115aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                                warnln("Input object " + i + " failed behavior test.");
116aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                            }
1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
118aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                    } catch (MissingResourceException e) {
119aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                        warnln("Could not load the data. " + e.getMessage());
120aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                    } catch (Exception e) {
121aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                        e.printStackTrace();
122aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                        errln("Exception: " + e.toString());
1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
125aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert            } finally {
126aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                inputStream.close();
127aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                inputStream = null;
1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final String[][] SKIP_CASES = {
1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // ICU 52+ PluralRules/PluralFormat/CurrencyPluralInfo are not
1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // serialization-compatible with previous versions.
1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {"ICU_50.1", "com.ibm.icu.text.CurrencyPluralInfo.dat"},
1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {"ICU_51.1", "com.ibm.icu.text.CurrencyPluralInfo.dat"},
1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {"ICU_50.1", "com.ibm.icu.text.PluralFormat.dat"},
1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {"ICU_51.1", "com.ibm.icu.text.PluralFormat.dat"},
1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {"ICU_50.1", "com.ibm.icu.text.PluralRules.dat"},
1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {"ICU_51.1", "com.ibm.icu.text.PluralRules.dat"},
1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // GeneralMeasureFormat was in technical preview, but is going away after ICU 52.1.
1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {"ICU_52.1", "com.ibm.icu.text.GeneralMeasureFormat.dat"},
1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // RuleBasedNumberFormat
1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {"ICU_3.6",     "com.ibm.icu.text.RuleBasedNumberFormat.dat"},
1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // ICU 4.8+ MessageFormat is not serialization-compatible with previous versions.
1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {"ICU_3.6",     "com.ibm.icu.text.MessageFormat.dat"},
1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    };
1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private Target getFileTargets(URL fileURL)
1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        File topDir = new File(fileURL.getPath());
1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        File dataDirs[] = topDir.listFiles();
1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        FolderTarget target = null;
1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int d = 0; d < dataDirs.length; d += 1) {
1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            File dataDir = dataDirs[d];
1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (dataDir.isDirectory()) {
1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                FolderTarget newTarget = new FolderTarget(dataDir.getName());
1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                File files[] = dataDir.listFiles();
1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                newTarget.setNext(target);
1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                target = newTarget;
1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                String dataDirName = dataDir.getName();
1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                element_loop:
1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                for (int i = 0; i < files.length; i += 1) {
1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    File file = files[i];
1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    String filename = file.getName();
1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    int ix = filename.indexOf(".dat");
1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (ix > 0) {
1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        String className = filename.substring(0, ix);
1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Skip some cases which do not work well
1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        for (int j = 0; j < SKIP_CASES.length; j++) {
1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (dataDirName.equals(SKIP_CASES[j][0]) && filename.equals(SKIP_CASES[j][1])) {
1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                logln("Skipping test case - " + dataDirName + "/" + className);
1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                continue element_loop;
1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        try {
190aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                            @SuppressWarnings("resource")  // Closed by HandlerTarget.execute().
191aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                            InputStream is = new FileInputStream(file);
1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            target.add(className, is);
1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } catch (FileNotFoundException e) {
1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            errln("Exception: " + e.toString());
1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return target;
2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
204aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert
205aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert    private static InputStream copyInputStream(InputStream in) throws IOException {
206aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert        try {
207aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert            ByteArrayOutputStream out = new ByteArrayOutputStream();
208aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert            byte[] buf = new byte[1024];
209aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert            while (true) {
210aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                int r = in.read(buf);
211aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                if (r == -1) {
212aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                    break;
213aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                }
214aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                out.write(buf, 0, r);
215aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert            }
216aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert            return new ByteArrayInputStream(out.toByteArray());
217aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert        } finally {
218aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert            in.close();
219aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert        }
220aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert    }
221aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert
2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private Target getJarTargets(URL jarURL)
2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String prefix = jarURL.getPath();
2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String currentDir = null;
2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int ix = prefix.indexOf("!/");
2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        FolderTarget target = null;
2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (ix >= 0) {
2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            prefix = prefix.substring(ix + 2);
2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        try {
2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            JarURLConnection conn = (JarURLConnection) jarURL.openConnection();
235aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert            JarFile jarFile = conn.getJarFile();
236aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert            try {
237aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                Enumeration entries = jarFile.entries();
238aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubertelement_loop:
239aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                while (entries.hasMoreElements()) {
240aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                    JarEntry entry = (JarEntry) entries.nextElement();
241aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                    String name = entry.getName();
2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
243aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                    if (name.startsWith(prefix)) {
244aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                        name = name.substring(prefix.length());
2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
246aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                        if (!entry.isDirectory()) {
247aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                            int dx = name.lastIndexOf("/");
248aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                            String dirName = name.substring(1, dx);
249aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                            String filename = name.substring(dx + 1);
2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
251aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                            if (!dirName.equals(currentDir)) {
252aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                                currentDir = dirName;
2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
254aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                                FolderTarget newTarget = new FolderTarget(currentDir);
2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
256aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                                newTarget.setNext(target);
257aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                                target = newTarget;
258aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                            }
2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
260aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                            int xx = filename.indexOf(".dat");
2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
262aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                            if (xx > 0) {
263aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                                String className = filename.substring(0, xx);
2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
265aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                                // Skip some cases which do not work well
266aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                                for (int i = 0; i < SKIP_CASES.length; i++) {
267aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                                    if (dirName.equals(SKIP_CASES[i][0]) && filename.equals(SKIP_CASES[i][1])) {
268aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                                        logln("Skipping test case - " + dirName + "/" + className);
269aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                                        continue element_loop;
270aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                                    }
2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
273aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                                // The InputStream object returned by JarFile.getInputStream() will
274aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                                // no longer be useable after JarFile.close() has been called. It's
275aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                                // therefore necessary to make a copy of it here.
276aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                                target.add(className, copyInputStream(jarFile.getInputStream(entry)));
277aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                            }
2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
281aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert            } finally {
282aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert                jarFile.close();
2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } catch (Exception e) {
2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("jar error: " + e.getMessage());
2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
287aacdd6f022693689b3bf76f70670711f3254a441Fredrik Roubert
2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return target;
2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected Target getTargets(String targetName)
2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        URL dataURL = getClass().getResource("data");
2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String protocol = dataURL.getProtocol();
2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (protocol.equals("jar")) {
2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return getJarTargets(dataURL);
2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (protocol.equals("file")) {
2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return getFileTargets(dataURL);
3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("Don't know how to test " + dataURL);
3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return null;
3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static void main(String[] args)
3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CompatibilityTest test = new CompatibilityTest();
3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        test.run(args);
3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
313