Skip to content

Commit e5e84c6

Browse files
Add AppImageLayout.rootDirectory()
1 parent 6a39ea9 commit e5e84c6

File tree

4 files changed

+123
-10
lines changed

4 files changed

+123
-10
lines changed

src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/AppImageLayout.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ public interface AppImageLayout {
5555
*/
5656
Path runtimeDirectory();
5757

58+
/**
59+
* Root directory of this app image.
60+
* It should normally be equal to <code>Path.of("")</code> for unresolved layout.
61+
*
62+
* @return the root directory of this app image
63+
*/
64+
Path rootDirectory();
65+
5866
/**
5967
* Creates a copy of this app image resolved at the given root directory.
6068
*
@@ -66,11 +74,11 @@ public interface AppImageLayout {
6674
/**
6775
* Default implementation of {@link AppImageLayout} interface.
6876
*/
69-
record Stub(Path runtimeDirectory) implements AppImageLayout {
77+
record Stub(Path rootDirectory, Path runtimeDirectory) implements AppImageLayout {
7078

7179
@Override
7280
public AppImageLayout resolveAt(Path base) {
73-
return new Stub(resolveNullablePath(base, runtimeDirectory));
81+
return new Stub(resolveNullablePath(base, rootDirectory), resolveNullablePath(base, runtimeDirectory));
7482
}
7583
}
7684

@@ -79,7 +87,8 @@ public AppImageLayout resolveAt(Path base) {
7987
* instance.
8088
*
8189
* It will call every non-static accessible method without parameters and with
82-
* {@link Path} return type of the given {@link AppImageLayout} instance.
90+
* {@link Path} return type of the given {@link AppImageLayout} instance except
91+
* {@link #rootDirectory()} method.
8392
* <p>
8493
* For every call, it will save the return value in the output {@link PathGroup}
8594
* object under the key equals the name of a function used in the call.
@@ -98,6 +107,7 @@ public static PathGroup toPathGroup(AppImageLayout appImageLayout) {
98107
.map(Class::getMethods)
99108
.flatMap(Stream::of)
100109
.filter(m -> !Modifier.isStatic(m.getModifiers()))
110+
.filter(m -> !"rootDirectory".equals(m.getName()))
101111
.filter(m -> {
102112
return m.getReturnType().isAssignableFrom(Path.class) && m.getParameterCount() == 0;
103113
}).<Map.Entry<String, Path>>mapMulti((m, consumer) -> {

src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/ApplicationLayout.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@
2424
*/
2525
package jdk.jpackage.internal.model;
2626

27+
import static jdk.jpackage.internal.util.PathUtils.resolveNullablePath;
28+
2729
import java.nio.file.Path;
2830
import java.util.Objects;
2931
import jdk.jpackage.internal.util.CompositeProxy;
30-
import static jdk.jpackage.internal.util.PathUtils.resolveNullablePath;
3132

3233
/**
3334
* Application app image layout.
@@ -72,6 +73,7 @@ private Builder() {
7273
}
7374

7475
private Builder(ApplicationLayout appLayout) {
76+
rootDirectory = appLayout.rootDirectory();
7577
launchersDirectory = appLayout.launchersDirectory();
7678
appDirectory = appLayout.appDirectory();
7779
runtimeDirectory = appLayout.runtimeDirectory();
@@ -82,6 +84,7 @@ private Builder(ApplicationLayout appLayout) {
8284

8385
public ApplicationLayout create() {
8486

87+
Objects.requireNonNull(rootDirectory);
8588
Objects.requireNonNull(runtimeDirectory);
8689
Objects.requireNonNull(launchersDirectory);
8790
Objects.requireNonNull(appDirectory);
@@ -90,7 +93,7 @@ public ApplicationLayout create() {
9093
Objects.requireNonNull(contentDirectory);
9194

9295
return ApplicationLayout.create(new AppImageLayout.Stub(
93-
runtimeDirectory), new ApplicationLayoutMixin.Stub(
96+
rootDirectory, runtimeDirectory), new ApplicationLayoutMixin.Stub(
9497
launchersDirectory, appDirectory, appModsDirectory,
9598
destktopIntegrationDirectory, contentDirectory));
9699
}
@@ -100,6 +103,7 @@ public Builder setAll(String path) {
100103
}
101104

102105
public Builder setAll(Path path) {
106+
rootDirectory(path);
103107
launchersDirectory(path);
104108
appDirectory(path);
105109
runtimeDirectory(path);
@@ -110,6 +114,7 @@ public Builder setAll(Path path) {
110114
}
111115

112116
public Builder resolveAt(Path base) {
117+
rootDirectory(resolveNullablePath(base, rootDirectory));
113118
launchersDirectory(resolveNullablePath(base, launchersDirectory));
114119
appDirectory(resolveNullablePath(base, appDirectory));
115120
runtimeDirectory(resolveNullablePath(base, runtimeDirectory));
@@ -119,6 +124,15 @@ public Builder resolveAt(Path base) {
119124
return this;
120125
}
121126

127+
public Builder rootDirectory(String v) {
128+
return rootDirectory(Path.of(v));
129+
}
130+
131+
public Builder rootDirectory(Path v) {
132+
rootDirectory = v;
133+
return this;
134+
}
135+
122136
public Builder launchersDirectory(String v) {
123137
return launchersDirectory(Path.of(v));
124138
}
@@ -173,6 +187,7 @@ public Builder contentDirectory(Path v) {
173187
return this;
174188
}
175189

190+
private Path rootDirectory = Path.of("");
176191
private Path launchersDirectory;
177192
private Path appDirectory;
178193
private Path runtimeDirectory;

src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/RuntimeLayout.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -24,20 +24,38 @@
2424
*/
2525
package jdk.jpackage.internal.model;
2626

27+
import static jdk.jpackage.internal.util.PathUtils.resolveNullablePath;
28+
2729
import java.nio.file.Path;
2830
import jdk.jpackage.internal.util.CompositeProxy;
29-
import static jdk.jpackage.internal.util.PathUtils.resolveNullablePath;
3031

3132
/**
3233
* Java runtime app image layout.
3334
* <p>
34-
* Use {@link #DEFAULT} to get the object implementing this interface.
35+
* Use {@link #DEFAULT} field to get the default runtime app image layout or
36+
* {@link #create(Path)} method to create custom runtime app image layout.
3537
*/
3638
public interface RuntimeLayout extends AppImageLayout {
3739

3840
@Override
3941
default RuntimeLayout resolveAt(Path root) {
40-
return create(new AppImageLayout.Stub(resolveNullablePath(root, runtimeDirectory())));
42+
return create(new AppImageLayout.Stub(resolveNullablePath(root, rootDirectory()),
43+
resolveNullablePath(root, runtimeDirectory())));
44+
}
45+
46+
/**
47+
* Creates Java runtime app image layout.
48+
* <p>
49+
* {@link #runtimeDirectory()} method
50+
* called on the created object will return the value of the
51+
* <code>runtimeDirectory<code> parameter. {@link #rootDirectory()} method
52+
* called on the created object will return <code>Path.of("")<code> value.
53+
*
54+
* @param runtimeDirectory Java runtime directory
55+
* @return Java runtime app image layout
56+
*/
57+
static RuntimeLayout create(Path runtimeDirectory) {
58+
return create(new AppImageLayout.Stub(Path.of(""), runtimeDirectory));
4159
}
4260

4361
private static RuntimeLayout create(AppImageLayout layout) {
@@ -51,5 +69,5 @@ private static RuntimeLayout create(AppImageLayout layout) {
5169
* the runtime directory is the same as the directory at which the layout is
5270
* resolved.
5371
*/
54-
static final RuntimeLayout DEFAULT = create(new AppImageLayout.Stub(Path.of("")));
72+
static final RuntimeLayout DEFAULT = create(Path.of(""));
5573
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright (c) 2025, 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+
package jdk.jpackage.internal.model;
25+
26+
import static org.junit.jupiter.api.Assertions.assertEquals;
27+
import static org.junit.jupiter.api.Assertions.assertNotSame;
28+
29+
import java.nio.file.Path;
30+
import java.util.List;
31+
import java.util.Set;
32+
import org.junit.jupiter.api.Test;
33+
34+
35+
public class AppImageLayoutTest {
36+
37+
@Test
38+
public void testStub() {
39+
final var root = Path.of("root");
40+
final var runtime = Path.of("runtime");
41+
final var layout = new AppImageLayout.Stub(root, runtime);
42+
43+
assertEquals(root, layout.rootDirectory());
44+
assertEquals(runtime, layout.runtimeDirectory());
45+
}
46+
47+
@Test
48+
public void testPathGroup() {
49+
final var layout = new AppImageLayout.Stub(Path.of("root"), Path.of("runtime"));
50+
51+
final var pathGroup = AppImageLayout.toPathGroup(layout);
52+
53+
assertEquals(Set.of("runtimeDirectory"), pathGroup.keys());
54+
assertEquals(List.of(layout.runtimeDirectory()), pathGroup.paths());
55+
}
56+
57+
@Test
58+
public void testResolveAt() {
59+
final var dir = Path.of("foo/bar");
60+
61+
final var layout = new AppImageLayout.Stub(Path.of(""), Path.of("runtime"));
62+
63+
final var resolvedLayout = layout.resolveAt(dir);
64+
65+
assertNotSame(layout, resolvedLayout);
66+
67+
assertEquals(dir.resolve(layout.rootDirectory()), resolvedLayout.rootDirectory());
68+
assertEquals(dir.resolve(layout.runtimeDirectory()), resolvedLayout.runtimeDirectory());
69+
}
70+
}

0 commit comments

Comments
 (0)