1/*
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25 * @test
26 * @summary Test last sorter property
27 * @author Jean-Francois Denise
28 * @modules jdk.jlink/jdk.tools.jlink
29 *          jdk.jlink/jdk.tools.jlink.internal
30 *          jdk.jlink/jdk.tools.jlink.plugin
31 * @run main/othervm LastSorterTest
32 */
33
34import java.util.ArrayList;
35import java.util.Collections;
36import java.util.HashMap;
37import java.util.List;
38import java.util.Map;
39
40import jdk.tools.jlink.internal.ImagePluginConfiguration;
41import jdk.tools.jlink.internal.ImagePluginStack;
42import jdk.tools.jlink.internal.Jlink;
43import jdk.tools.jlink.internal.Jlink.PluginsConfiguration;
44import jdk.tools.jlink.internal.PluginRepository;
45import jdk.tools.jlink.internal.ResourcePoolManager;
46import jdk.tools.jlink.plugin.Plugin;
47import jdk.tools.jlink.plugin.ResourcePool;
48import jdk.tools.jlink.plugin.ResourcePoolBuilder;
49import jdk.tools.jlink.plugin.ResourcePoolEntry;
50
51public class LastSorterTest {
52
53    public LastSorterTest() {
54        for (int i = 1; i <= 6; i++) {
55            PluginRepository.registerPlugin(new SorterPlugin("sorterplugin" + i));
56        }
57    }
58
59    public static void main(String[] args) throws Exception {
60        new LastSorterTest().test();
61    }
62
63    public void test() throws Exception {
64        checkUnknownPlugin();
65
66        checkOrderAfterLastSorter();
67
68        checkPositiveCase();
69
70        checkTwoLastSorters();
71    }
72
73    private void checkTwoLastSorters() throws Exception {
74        List<Plugin> plugins = new ArrayList<>();
75        plugins.add(createPlugin("sorterplugin5", "/a"));
76        plugins.add(createPlugin("sorterplugin6", "/a"));
77        PluginsConfiguration config = new Jlink.PluginsConfiguration(plugins,
78                null, "sorterplugin5");
79
80        ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(config);
81
82        // check order
83        ResourcePoolManager res = fillOutResourceResourcePool();
84
85        try {
86            stack.visitResources(res);
87            throw new AssertionError("Exception expected: Order of resources is already frozen." +
88                    "Plugin sorterplugin6 is badly located");
89        } catch (Exception e) {
90            // expected
91        }
92    }
93
94    private ResourcePoolManager fillOutResourceResourcePool() throws Exception {
95        ResourcePoolManager res = new ResourcePoolManager();
96        res.add(ResourcePoolEntry.create("/eee/bbb/res1.class", new byte[90]));
97        res.add(ResourcePoolEntry.create("/aaaa/bbb/res2.class", new byte[90]));
98        res.add(ResourcePoolEntry.create("/bbb/aa/res1.class", new byte[90]));
99        res.add(ResourcePoolEntry.create("/aaaa/bbb/res3.class", new byte[90]));
100        res.add(ResourcePoolEntry.create("/bbb/aa/res2.class", new byte[90]));
101        res.add(ResourcePoolEntry.create("/fff/bbb/res1.class", new byte[90]));
102        res.add(ResourcePoolEntry.create("/aaaa/bbb/res1.class", new byte[90]));
103        res.add(ResourcePoolEntry.create("/bbb/aa/res3.class", new byte[90]));
104        res.add(ResourcePoolEntry.create("/ccc/bbb/res1.class", new byte[90]));
105        res.add(ResourcePoolEntry.create("/ddd/bbb/res1.class", new byte[90]));
106        return res;
107    }
108
109    private static Plugin createPlugin(String name, String arg) {
110        Map<String, String> conf = new HashMap<>();
111        conf.put(name, arg);
112        return Jlink.newPlugin(name, conf, null);
113    }
114
115    private void checkPositiveCase() throws Exception {
116        List<Plugin> plugins = new ArrayList<>();
117        plugins.add(createPlugin("sorterplugin1", "/c"));
118        plugins.add(createPlugin("sorterplugin2", "/b"));
119        plugins.add(createPlugin("sorterplugin3", "/a"));
120
121        PluginsConfiguration config = new Jlink.PluginsConfiguration(plugins,
122                null, "sorterplugin3");
123
124        ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(config);
125
126        // check order
127        ResourcePoolManager res = fillOutResourceResourcePool();
128
129        stack.visitResources(res);
130    }
131
132    private void checkUnknownPlugin() {
133        List<Plugin> plugins = new ArrayList<>();
134        plugins.add(createPlugin("sorterplugin1", "/1"));
135        plugins.add(createPlugin("sorterplugin2", "/1"));
136        plugins.add(createPlugin("sorterplugin3", "/1"));
137        plugins.add(createPlugin("sorterplugin4", "/1"));
138
139        PluginsConfiguration config = new Jlink.PluginsConfiguration(plugins,
140                null, "sorterplugin5");
141        try {
142            ImagePluginConfiguration.parseConfiguration(config);
143            throw new AssertionError("Unknown plugin should have failed.");
144        } catch (Exception ex) {
145            // XXX OK expected
146        }
147    }
148
149    private void checkOrderAfterLastSorter() throws Exception {
150        List<Plugin> plugins = new ArrayList<>();
151        plugins.add(createPlugin("sorterplugin1", "/c"));
152        plugins.add(createPlugin("sorterplugin2", "/b"));
153        plugins.add(createPlugin("sorterplugin3", "/a"));
154        plugins.add(createPlugin("sorterplugin4", "/d"));
155
156        PluginsConfiguration config = new Jlink.PluginsConfiguration(plugins,
157                null, "sorterplugin3");
158
159        ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(config);
160
161        // check order
162        ResourcePoolManager res = fillOutResourceResourcePool();
163        try {
164            stack.visitResources(res);
165            throw new AssertionError("Order was changed after the last sorter, but no exception occurred");
166        } catch (Exception ex) {
167            // XXX OK expected
168        }
169    }
170
171    public static class SorterPlugin implements Plugin {
172
173        private final String name;
174        private String starts;
175
176        private SorterPlugin(String name) {
177            this.name = name;
178        }
179
180        @Override
181        public ResourcePool transform(ResourcePool resources, ResourcePoolBuilder output) {
182            List<ResourcePoolEntry> paths = new ArrayList<>();
183            resources.entries().forEach(res -> {
184                if (res.path().startsWith(starts)) {
185                    paths.add(0, res);
186                } else {
187                    paths.add(res);
188                }
189            });
190
191            for (ResourcePoolEntry r : paths) {
192                output.add(r);
193            }
194
195            return output.build();
196        }
197
198        @Override
199        public String getName() {
200            return name;
201        }
202
203        @Override
204        public void configure(Map<String, String> config) {
205            String arguments = config.get(name);
206            this.starts = arguments;
207        }
208    }
209}
210