@@ -42,6 +42,31 @@ public enum BaseDir {
4242 HOME
4343 }
4444
45+ public enum Platform {
46+ LINUX ,
47+ MACOS ,
48+ WINDOWS ;
49+
50+ private static final Platform current = findCurrent ();
51+
52+ private static Platform findCurrent () {
53+ String os = System .getProperty ("os.name" );
54+ if (os .startsWith ("Linux" )) {
55+ return LINUX ;
56+ } else if (os .startsWith ("Mac OS" )) {
57+ return MACOS ;
58+ } else if (os .startsWith ("Windows" )) {
59+ return WINDOWS ;
60+ } else {
61+ throw new AssertionError ("Unsupported platform [" + os + "]" );
62+ }
63+ }
64+
65+ public boolean isCurrent () {
66+ return this == current ;
67+ }
68+ }
69+
4570 public sealed interface FileData {
4671
4772 Stream <Path > resolvePaths (PathLookup pathLookup );
@@ -50,22 +75,26 @@ public sealed interface FileData {
5075
5176 boolean exclusive ();
5277
53- FileData withExclusive ();
78+ FileData withExclusive (boolean exclusive );
79+
80+ Platform platform ();
81+
82+ FileData withPlatform (Platform platform );
5483
5584 static FileData ofPath (Path path , Mode mode ) {
56- return new AbsolutePathFileData (path , mode , false );
85+ return new AbsolutePathFileData (path , mode , null , false );
5786 }
5887
5988 static FileData ofRelativePath (Path relativePath , BaseDir baseDir , Mode mode ) {
60- return new RelativePathFileData (relativePath , baseDir , mode , false );
89+ return new RelativePathFileData (relativePath , baseDir , mode , null , false );
6190 }
6291
6392 static FileData ofPathSetting (String setting , Mode mode ) {
64- return new PathSettingFileData (setting , mode , false );
93+ return new PathSettingFileData (setting , mode , null , false );
6594 }
6695
6796 static FileData ofRelativePathSetting (String setting , BaseDir baseDir , Mode mode ) {
68- return new RelativePathSettingFileData (setting , baseDir , mode , false );
97+ return new RelativePathSettingFileData (setting , baseDir , mode , null , false );
6998 }
7099
71100 /**
@@ -149,62 +178,94 @@ private static Stream<Path> relativePathsCombination(Path[] baseDirs, Stream<Pat
149178 return paths .stream ();
150179 }
151180
152- private record AbsolutePathFileData (Path path , Mode mode , boolean exclusive ) implements FileData {
181+ private record AbsolutePathFileData (Path path , Mode mode , Platform platform , boolean exclusive ) implements FileData {
153182
154183 @ Override
155- public AbsolutePathFileData withExclusive () {
156- return new AbsolutePathFileData (path , mode , true );
184+ public AbsolutePathFileData withExclusive (boolean exclusive ) {
185+ return new AbsolutePathFileData (path , mode , platform , exclusive );
157186 }
158187
159188 @ Override
160189 public Stream <Path > resolvePaths (PathLookup pathLookup ) {
161190 return Stream .of (path );
162191 }
192+
193+ @ Override
194+ public FileData withPlatform (Platform platform ) {
195+ if (platform == platform ()) {
196+ return this ;
197+ }
198+ return new AbsolutePathFileData (path , mode , platform , exclusive );
199+ }
163200 }
164201
165- private record RelativePathFileData (Path relativePath , BaseDir baseDir , Mode mode , boolean exclusive )
202+ private record RelativePathFileData (Path relativePath , BaseDir baseDir , Mode mode , Platform platform , boolean exclusive )
166203 implements
167204 FileData ,
168205 RelativeFileData {
169206
170207 @ Override
171- public RelativePathFileData withExclusive () {
172- return new RelativePathFileData (relativePath , baseDir , mode , true );
208+ public RelativePathFileData withExclusive (boolean exclusive ) {
209+ return new RelativePathFileData (relativePath , baseDir , mode , platform , exclusive );
173210 }
174211
175212 @ Override
176213 public Stream <Path > resolveRelativePaths (PathLookup pathLookup ) {
177214 return Stream .of (relativePath );
178215 }
216+
217+ @ Override
218+ public FileData withPlatform (Platform platform ) {
219+ if (platform == platform ()) {
220+ return this ;
221+ }
222+ return new RelativePathFileData (relativePath , baseDir , mode , platform , exclusive );
223+ }
179224 }
180225
181- private record PathSettingFileData (String setting , Mode mode , boolean exclusive ) implements FileData {
226+ private record PathSettingFileData (String setting , Mode mode , Platform platform , boolean exclusive ) implements FileData {
182227
183228 @ Override
184- public PathSettingFileData withExclusive () {
185- return new PathSettingFileData (setting , mode , true );
229+ public PathSettingFileData withExclusive (boolean exclusive ) {
230+ return new PathSettingFileData (setting , mode , platform , exclusive );
186231 }
187232
188233 @ Override
189234 public Stream <Path > resolvePaths (PathLookup pathLookup ) {
190235 return resolvePathSettings (pathLookup , setting );
191236 }
237+
238+ @ Override
239+ public FileData withPlatform (Platform platform ) {
240+ if (platform == platform ()) {
241+ return this ;
242+ }
243+ return new PathSettingFileData (setting , mode , platform , exclusive );
244+ }
192245 }
193246
194- private record RelativePathSettingFileData (String setting , BaseDir baseDir , Mode mode , boolean exclusive )
247+ private record RelativePathSettingFileData (String setting , BaseDir baseDir , Mode mode , Platform platform , boolean exclusive )
195248 implements
196249 FileData ,
197250 RelativeFileData {
198251
199252 @ Override
200- public RelativePathSettingFileData withExclusive () {
201- return new RelativePathSettingFileData (setting , baseDir , mode , true );
253+ public RelativePathSettingFileData withExclusive (boolean exclusive ) {
254+ return new RelativePathSettingFileData (setting , baseDir , mode , platform , exclusive );
202255 }
203256
204257 @ Override
205258 public Stream <Path > resolveRelativePaths (PathLookup pathLookup ) {
206259 return resolvePathSettings (pathLookup , setting );
207260 }
261+
262+ @ Override
263+ public FileData withPlatform (Platform platform ) {
264+ if (platform == platform ()) {
265+ return this ;
266+ }
267+ return new RelativePathSettingFileData (setting , baseDir , mode , platform , exclusive );
268+ }
208269 }
209270
210271 private static Stream <Path > resolvePathSettings (PathLookup pathLookup , String setting ) {
@@ -225,6 +286,18 @@ private static Mode parseMode(String mode) {
225286 }
226287 }
227288
289+ private static Platform parsePlatform (String platform ) {
290+ if (platform .equals ("linux" )) {
291+ return Platform .LINUX ;
292+ } else if (platform .equals ("macos" )) {
293+ return Platform .MACOS ;
294+ } else if (platform .equals ("windows" )) {
295+ return Platform .WINDOWS ;
296+ } else {
297+ throw new PolicyValidationException ("invalid platform: " + platform + ", valid values: [linux, macos, windows]" );
298+ }
299+ }
300+
228301 private static BaseDir parseBaseDir (String baseDir ) {
229302 return switch (baseDir ) {
230303 case "config" -> BaseDir .CONFIG ;
@@ -252,6 +325,7 @@ public static FilesEntitlement build(List<Object> paths) {
252325 String pathSetting = (String ) file .remove ("path_setting" );
253326 String relativePathSetting = (String ) file .remove ("relative_path_setting" );
254327 String modeAsString = (String ) file .remove ("mode" );
328+ String platformAsString = (String ) file .remove ("platform" );
255329 Boolean exclusiveBoolean = (Boolean ) file .remove ("exclusive" );
256330 boolean exclusive = exclusiveBoolean != null && exclusiveBoolean ;
257331
@@ -270,27 +344,32 @@ public static FilesEntitlement build(List<Object> paths) {
270344 throw new PolicyValidationException ("files entitlement must contain 'mode' for every listed file" );
271345 }
272346 Mode mode = parseMode (modeAsString );
347+ Platform platform = null ;
348+ if (platformAsString != null ) {
349+ platform = parsePlatform (platformAsString );
350+ }
273351
274352 BaseDir baseDir = null ;
275353 if (relativeTo != null ) {
276354 baseDir = parseBaseDir (relativeTo );
277355 }
278356
279- FileData fileData ;
357+ final FileData fileData ;
280358 if (relativePathAsString != null ) {
281359 if (baseDir == null ) {
282360 throw new PolicyValidationException ("files entitlement with a 'relative_path' must specify 'relative_to'" );
283361 }
284-
362+ Path relativePath = Path . of ( relativePathAsString );
285363 if (FileData .isAbsolutePath (relativePathAsString )) {
286364 throw new PolicyValidationException ("'relative_path' [" + relativePathAsString + "] must be relative" );
287365 }
288- fileData = FileData .ofRelativePath (Path . of ( relativePathAsString ) , baseDir , mode );
366+ fileData = FileData .ofRelativePath (relativePath , baseDir , mode );
289367 } else if (pathAsString != null ) {
368+ Path path = Path .of (pathAsString );
290369 if (FileData .isAbsolutePath (pathAsString ) == false ) {
291370 throw new PolicyValidationException ("'path' [" + pathAsString + "] must be absolute" );
292371 }
293- fileData = FileData .ofPath (Path . of ( pathAsString ) , mode );
372+ fileData = FileData .ofPath (path , mode );
294373 } else if (pathSetting != null ) {
295374 fileData = FileData .ofPathSetting (pathSetting , mode );
296375 } else if (relativePathSetting != null ) {
@@ -301,7 +380,7 @@ public static FilesEntitlement build(List<Object> paths) {
301380 } else {
302381 throw new AssertionError ("File entry validation error" );
303382 }
304- filesData .add (exclusive ? fileData .withExclusive () : fileData );
383+ filesData .add (fileData .withPlatform ( platform ). withExclusive (exclusive ) );
305384 }
306385 return new FilesEntitlement (filesData );
307386 }
0 commit comments