Skip to content

Commit c9ef927

Browse files
WIP commit
1 parent e77f8d3 commit c9ef927

16 files changed

+385
-461
lines changed

src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/CodesignConfig.java

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,74 +28,78 @@
2828
import java.util.ArrayList;
2929
import java.util.List;
3030
import java.util.Optional;
31-
import jdk.jpackage.internal.model.SigningIdentifier;
3231
import jdk.jpackage.internal.model.SigningConfig;
32+
import jdk.jpackage.internal.model.SigningIdentity;
3333
import jdk.jpackage.internal.util.PathUtils;
3434

3535

36-
record CodesignConfig(Optional<SigningIdentifier> identifier,
37-
Optional<Path> entitlements, Optional<Path> keyChain) {
36+
record CodesignConfig(Optional<SigningIdentity> identity,
37+
Optional<Path> entitlements, Optional<Keychain> keychain) {
3838

3939
static final class Builder {
4040

4141
private Builder() {
4242
}
4343

4444
CodesignConfig create() {
45-
return new CodesignConfig(Optional.ofNullable(identifier),
46-
Optional.ofNullable(entitlements), Optional.ofNullable(keyChain));
45+
return new CodesignConfig(Optional.ofNullable(identity),
46+
Optional.ofNullable(entitlements), Optional.ofNullable(keychain));
4747
}
4848

4949
Builder entitlements(Path v) {
5050
entitlements = v;
5151
return this;
5252
}
5353

54-
Builder identifier(SigningIdentifier v) {
55-
identifier = v;
54+
Builder identity(SigningIdentity v) {
55+
identity = v;
5656
return this;
5757
}
5858

59-
Builder keyChain(Path v) {
60-
keyChain = v;
59+
Builder keychain(String v) {
60+
return keychain(new Keychain(v));
61+
}
62+
63+
Builder keychain(Keychain v) {
64+
keychain = v;
6165
return this;
6266
}
6367

6468
Builder from(SigningConfig v) {
65-
return identifier(v.identifier().orElse(null))
69+
return identity(v.identity().orElse(null))
6670
.entitlements(v.entitlements().orElse(null))
67-
.keyChain(v.keyChain().orElse(null));
71+
.keychain(v.keychain().orElse(null));
6872
}
6973

7074
Builder from(CodesignConfig v) {
71-
return identifier(v.identifier().orElse(null))
75+
return identity(v.identity().orElse(null))
7276
.entitlements(v.entitlements().orElse(null))
73-
.keyChain(v.keyChain().orElse(null));
77+
.keychain(v.keychain().orElse(null));
7478
}
7579

76-
private SigningIdentifier identifier;
80+
private SigningIdentity identity;
7781
private Path entitlements;
78-
private Path keyChain;
82+
private Keychain keychain;
7983
}
8084

8185
static Builder build() {
8286
return new Builder();
8387
}
8488

8589
List<String> toCodesignArgs() {
86-
List<String> args = new ArrayList<>(List.of("-s", identifier.map(SigningIdentifier::name).orElse(ADHOC_SIGNING_IDENTIFIER), "-vvvv"));
90+
List<String> args = new ArrayList<>(List.of("-s", identity.map(SigningIdentity::id).orElse(ADHOC_SIGNING_IDENTITY), "-vvvv"));
8791

88-
if (identifier.isPresent()) {
92+
if (identity.isPresent()) {
8993
args.addAll(List.of("--timestamp", "--options", "runtime"));
90-
identifier.flatMap(SigningIdentifier::prefix).ifPresent(identifierPrefix -> {
94+
identity.flatMap(SigningIdentity::prefix).ifPresent(identifierPrefix -> {
9195
args.addAll(List.of("--prefix", identifierPrefix));
9296
});
93-
keyChain.map(PathUtils::normalizedAbsolutePathString).ifPresent(theKeyChain -> args.addAll(List.of("--keychain", theKeyChain)));
94-
entitlements.map(PathUtils::normalizedAbsolutePathString).ifPresent(theEntitlements -> args.addAll(List.of("--entitlements", theEntitlements)));
97+
keychain.map(Keychain::asCliArg).ifPresent(k -> args.addAll(List.of("--keychain", k)));
98+
entitlements.map(PathUtils::normalizedAbsolutePathString).ifPresent(e -> args.addAll(List.of("--entitlements", e)));
9599
}
96100

97101
return args;
98102
}
99103

100-
static final String ADHOC_SIGNING_IDENTIFIER = "-";
104+
static final String ADHOC_SIGNING_IDENTITY = "-";
101105
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
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. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package jdk.jpackage.internal;
27+
28+
import java.io.IOException;
29+
import java.nio.file.Files;
30+
import java.nio.file.Path;
31+
import java.util.List;
32+
import java.util.Objects;
33+
import java.util.stream.Stream;
34+
import jdk.jpackage.internal.util.PathUtils;
35+
36+
record Keychain(String name) {
37+
Keychain {
38+
Objects.requireNonNull(name);
39+
}
40+
41+
Path path() {
42+
final var path = Path.of(name);
43+
if (path.isAbsolute()) {
44+
return path;
45+
} else {
46+
final var dir = Path.of(System.getProperty("user.home")).resolve("Library/Keychains");
47+
final var files = filenames(name).map(dir::resolve).toList();
48+
return files.stream().filter(Files::exists).findFirst().orElseGet(() -> {
49+
// Can't find keychain file in "$HOME/Library/Keychains" folder.
50+
// Detect keychain file name from the name of the login keychain file.
51+
return files.stream().filter(f -> {
52+
final var loginKeycahinFile = f.getParent().resolve("login.keychain" + f.getFileName().toString().substring(name.length()));
53+
return Files.exists(loginKeycahinFile);
54+
}).findFirst().orElseGet(() -> {
55+
// login keychain file doesn't exist, fallback to "$HOME/Library/Keychains/<name>-db" keychain file.
56+
return files.getFirst();
57+
});
58+
});
59+
}
60+
}
61+
62+
String asCliArg() {
63+
final var path = Path.of(name);
64+
if (path.isAbsolute()) {
65+
return PathUtils.normalizedAbsolutePathString(path);
66+
} else {
67+
return name;
68+
}
69+
}
70+
71+
static List<Keychain> listKeychains() {
72+
// Get the current keychain list
73+
final List<String> cmdOutput;
74+
try {
75+
cmdOutput = Executor.of("/usr/bin/security", "list-keychains").saveOutput(true).executeExpectSuccess().getOutput();
76+
} catch (IOException ex) {
77+
throw I18N.buildException().message("message.keychain.error").cause(ex).create(KeychainException::new);
78+
}
79+
80+
// Typical output of /usr/bin/security command is:
81+
// "/Users/foo/Library/Keychains/login.keychain-db"
82+
// "/Library/Keychains/System.keychain"
83+
return cmdOutput.stream().map(String::trim).map(str -> {
84+
// Strip enclosing double quotes
85+
return str.substring(1, str.length() - 1);
86+
}).map(Keychain::new).toList();
87+
}
88+
89+
final static class KeychainException extends RuntimeException {
90+
91+
KeychainException(String msg) {
92+
super(msg);
93+
}
94+
95+
KeychainException(String msg, Throwable cause) {
96+
super(msg, cause);
97+
}
98+
99+
private static final long serialVersionUID = 1L;
100+
}
101+
102+
private static Stream<String> filenames(String name) {
103+
return Stream.of(name + "-db", name);
104+
}
105+
}

0 commit comments

Comments
 (0)