Skip to content

Commit ad72f86

Browse files
committed
Polish loader and loader-tools
Polish and refactor `spring-boot-loader` and `spring-boot-loader-tools` to make it easier to add indexing and layering support. Closes gh-19766
1 parent 56e3025 commit ad72f86

File tree

11 files changed

+280
-182
lines changed

11 files changed

+280
-182
lines changed

spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarWriter.java

Lines changed: 40 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -56,12 +56,14 @@
5656
*/
5757
public class JarWriter implements LoaderClassesWriter, AutoCloseable {
5858

59-
private static final UnpackHandler NEVER_UNPACK = new NeverUnpackHandler();
60-
6159
private static final String NESTED_LOADER_JAR = "META-INF/loader/spring-boot-loader.jar";
6260

6361
private static final int BUFFER_SIZE = 32 * 1024;
6462

63+
private static final int UNIX_FILE_MODE = UnixStat.FILE_FLAG | UnixStat.DEFAULT_FILE_PERM;
64+
65+
private static final int UNIX_DIR_MODE = UnixStat.DIR_FLAG | UnixStat.DEFAULT_DIR_PERM;
66+
6567
private final JarArchiveOutputStream jarOutput;
6668

6769
private final Set<String> writtenEntries = new HashSet<>();
@@ -121,11 +123,11 @@ public void writeManifest(Manifest manifest) throws IOException {
121123
* @throws IOException if the entries cannot be written
122124
*/
123125
public void writeEntries(JarFile jarFile) throws IOException {
124-
this.writeEntries(jarFile, new IdentityEntryTransformer(), NEVER_UNPACK);
126+
this.writeEntries(jarFile, EntryTransformer.NONE, UnpackHandler.NEVER);
125127
}
126128

127129
void writeEntries(JarFile jarFile, UnpackHandler unpackHandler) throws IOException {
128-
this.writeEntries(jarFile, new IdentityEntryTransformer(), unpackHandler);
130+
this.writeEntries(jarFile, EntryTransformer.NONE, unpackHandler);
129131
}
130132

131133
void writeEntries(JarFile jarFile, EntryTransformer entryTransformer, UnpackHandler unpackHandler)
@@ -244,7 +246,7 @@ public void close() throws IOException {
244246
}
245247

246248
private void writeEntry(JarArchiveEntry entry, EntryWriter entryWriter) throws IOException {
247-
writeEntry(entry, entryWriter, NEVER_UNPACK);
249+
writeEntry(entry, entryWriter, UnpackHandler.NEVER);
248250
}
249251

250252
/**
@@ -257,22 +259,10 @@ private void writeEntry(JarArchiveEntry entry, EntryWriter entryWriter) throws I
257259
*/
258260
private void writeEntry(JarArchiveEntry entry, EntryWriter entryWriter, UnpackHandler unpackHandler)
259261
throws IOException {
260-
String parent = entry.getName();
261-
if (parent.endsWith("/")) {
262-
parent = parent.substring(0, parent.length() - 1);
263-
entry.setUnixMode(UnixStat.DIR_FLAG | UnixStat.DEFAULT_DIR_PERM);
264-
}
265-
else {
266-
entry.setUnixMode(UnixStat.FILE_FLAG | UnixStat.DEFAULT_FILE_PERM);
267-
}
268-
if (parent.lastIndexOf('/') != -1) {
269-
parent = parent.substring(0, parent.lastIndexOf('/') + 1);
270-
if (!parent.isEmpty()) {
271-
writeEntry(new JarArchiveEntry(parent), null, unpackHandler);
272-
}
273-
}
274-
275-
if (this.writtenEntries.add(entry.getName())) {
262+
String name = entry.getName();
263+
writeParentFolderEntries(name);
264+
if (this.writtenEntries.add(name)) {
265+
entry.setUnixMode(name.endsWith("/") ? UNIX_DIR_MODE : UNIX_FILE_MODE);
276266
entryWriter = addUnpackCommentIfNecessary(entry, entryWriter, unpackHandler);
277267
this.jarOutput.putArchiveEntry(entry);
278268
if (entryWriter != null) {
@@ -282,6 +272,16 @@ private void writeEntry(JarArchiveEntry entry, EntryWriter entryWriter, UnpackHa
282272
}
283273
}
284274

275+
private void writeParentFolderEntries(String name) throws IOException {
276+
String parent = name.endsWith("/") ? name.substring(0, name.length() - 1) : name;
277+
while (parent.lastIndexOf('/') != -1) {
278+
parent = parent.substring(0, parent.lastIndexOf('/'));
279+
if (!parent.isEmpty()) {
280+
writeEntry(new JarArchiveEntry(parent + "/"), null, UnpackHandler.NEVER);
281+
}
282+
}
283+
}
284+
285285
private EntryWriter addUnpackCommentIfNecessary(JarArchiveEntry entry, EntryWriter entryWriter,
286286
UnpackHandler unpackHandler) throws IOException {
287287
if (entryWriter == null || !unpackHandler.requiresUnpack(entry.getName())) {
@@ -444,21 +444,15 @@ void setupStoredEntry(JarArchiveEntry entry) {
444444
* An {@code EntryTransformer} enables the transformation of {@link JarEntry jar
445445
* entries} during the writing process.
446446
*/
447+
@FunctionalInterface
447448
interface EntryTransformer {
448449

449-
JarArchiveEntry transform(JarArchiveEntry jarEntry);
450-
451-
}
452-
453-
/**
454-
* An {@code EntryTransformer} that returns the entry unchanged.
455-
*/
456-
private static final class IdentityEntryTransformer implements EntryTransformer {
450+
/**
451+
* No-op entity transformer.
452+
*/
453+
EntryTransformer NONE = (jarEntry) -> jarEntry;
457454

458-
@Override
459-
public JarArchiveEntry transform(JarArchiveEntry jarEntry) {
460-
return jarEntry;
461-
}
455+
JarArchiveEntry transform(JarArchiveEntry jarEntry);
462456

463457
}
464458

@@ -468,23 +462,23 @@ public JarArchiveEntry transform(JarArchiveEntry jarEntry) {
468462
*/
469463
interface UnpackHandler {
470464

471-
boolean requiresUnpack(String name);
465+
UnpackHandler NEVER = new UnpackHandler() {
472466

473-
String sha1Hash(String name) throws IOException;
467+
@Override
468+
public boolean requiresUnpack(String name) {
469+
return false;
470+
}
474471

475-
}
472+
@Override
473+
public String sha1Hash(String name) throws IOException {
474+
throw new UnsupportedOperationException();
475+
}
476476

477-
private static final class NeverUnpackHandler implements UnpackHandler {
477+
};
478478

479-
@Override
480-
public boolean requiresUnpack(String name) {
481-
return false;
482-
}
479+
boolean requiresUnpack(String name);
483480

484-
@Override
485-
public String sha1Hash(String name) {
486-
throw new UnsupportedOperationException();
487-
}
481+
String sha1Hash(String name) throws IOException;
488482

489483
}
490484

spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Layout.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -35,13 +35,26 @@ public interface Layout {
3535
*/
3636
String getLauncherClassName();
3737

38+
/**
39+
* Returns the destination path for a given library.
40+
* @param libraryName the name of the library (excluding any path)
41+
* @param scope the scope of the library
42+
* @return the location of the library relative to the root of the archive (should end
43+
* with '/') or {@code null} if the library should not be included.
44+
*/
45+
default String getLibraryLocation(String libraryName, LibraryScope scope) {
46+
return getLibraryDestination(libraryName, scope);
47+
}
48+
3849
/**
3950
* Returns the destination path for a given library.
4051
* @param libraryName the name of the library (excluding any path)
4152
* @param scope the scope of the library
4253
* @return the destination relative to the root of the archive (should end with '/')
4354
* or {@code null} if the library should not be included.
55+
* @deprecated since 2.3.0 in favor of {@link #getLibraryLocation}
4456
*/
57+
@Deprecated
4558
String getLibraryDestination(String libraryName, LibraryScope scope);
4659

4760
/**

spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Layouts.java

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -67,6 +67,12 @@ public String getLauncherClassName() {
6767
return "org.springframework.boot.loader.JarLauncher";
6868
}
6969

70+
@Override
71+
public String getLibraryLocation(String libraryName, LibraryScope scope) {
72+
return "BOOT-INF/lib/";
73+
}
74+
75+
@Deprecated
7076
@Override
7177
public String getLibraryDestination(String libraryName, LibraryScope scope) {
7278
return "BOOT-INF/lib/";
@@ -123,25 +129,31 @@ public boolean isExecutable() {
123129
*/
124130
public static class War implements Layout {
125131

126-
private static final Map<LibraryScope, String> SCOPE_DESTINATIONS;
132+
private static final Map<LibraryScope, String> SCOPE_LOCATION;
127133

128134
static {
129-
Map<LibraryScope, String> map = new HashMap<>();
130-
map.put(LibraryScope.COMPILE, "WEB-INF/lib/");
131-
map.put(LibraryScope.CUSTOM, "WEB-INF/lib/");
132-
map.put(LibraryScope.RUNTIME, "WEB-INF/lib/");
133-
map.put(LibraryScope.PROVIDED, "WEB-INF/lib-provided/");
134-
SCOPE_DESTINATIONS = Collections.unmodifiableMap(map);
135+
Map<LibraryScope, String> locations = new HashMap<>();
136+
locations.put(LibraryScope.COMPILE, "WEB-INF/lib/");
137+
locations.put(LibraryScope.CUSTOM, "WEB-INF/lib/");
138+
locations.put(LibraryScope.RUNTIME, "WEB-INF/lib/");
139+
locations.put(LibraryScope.PROVIDED, "WEB-INF/lib-provided/");
140+
SCOPE_LOCATION = Collections.unmodifiableMap(locations);
135141
}
136142

137143
@Override
138144
public String getLauncherClassName() {
139145
return "org.springframework.boot.loader.WarLauncher";
140146
}
141147

148+
@Override
149+
public String getLibraryLocation(String libraryName, LibraryScope scope) {
150+
return SCOPE_LOCATION.get(scope);
151+
}
152+
153+
@Deprecated
142154
@Override
143155
public String getLibraryDestination(String libraryName, LibraryScope scope) {
144-
return SCOPE_DESTINATIONS.get(scope);
156+
return SCOPE_LOCATION.get(scope);
145157
}
146158

147159
@Override

0 commit comments

Comments
 (0)