@@ -39,26 +39,55 @@ public enum BaseDir {
3939 HOME
4040 }
4141
42+ public enum Platform {
43+ LINUX ,
44+ MACOS ,
45+ WINDOWS ;
46+
47+ private static final Platform current = findCurrent ();
48+
49+ private static Platform findCurrent () {
50+ String os = System .getProperty ("os.name" );
51+ if (os .startsWith ("Linux" )) {
52+ return LINUX ;
53+ } else if (os .startsWith ("Mac OS" )) {
54+ return MACOS ;
55+ } else if (os .startsWith ("Windows" )) {
56+ return WINDOWS ;
57+ } else {
58+ throw new AssertionError ("Unsupported platform [" + os + "]" );
59+ }
60+ }
61+
62+ public boolean isCurrent () {
63+ return this == current ;
64+ }
65+ }
66+
4267 public sealed interface FileData {
4368
4469 Stream <Path > resolvePaths (PathLookup pathLookup );
4570
4671 Mode mode ();
4772
73+ Platform platform ();
74+
75+ FileData withPlatform (Platform platform );
76+
4877 static FileData ofPath (Path path , Mode mode ) {
49- return new AbsolutePathFileData (path , mode );
78+ return new AbsolutePathFileData (path , mode , null );
5079 }
5180
5281 static FileData ofRelativePath (Path relativePath , BaseDir baseDir , Mode mode ) {
53- return new RelativePathFileData (relativePath , baseDir , mode );
82+ return new RelativePathFileData (relativePath , baseDir , mode , null );
5483 }
5584
5685 static FileData ofPathSetting (String setting , Mode mode ) {
57- return new PathSettingFileData (setting , mode );
86+ return new PathSettingFileData (setting , mode , null );
5887 }
5988
6089 static FileData ofRelativePathSetting (String setting , BaseDir baseDir , Mode mode ) {
61- return new RelativePathSettingFileData (setting , baseDir , mode );
90+ return new RelativePathSettingFileData (setting , baseDir , mode , null );
6291 }
6392 }
6493
@@ -91,32 +120,70 @@ default Stream<Path> resolvePaths(PathLookup pathLookup) {
91120 }
92121 }
93122
94- private record AbsolutePathFileData (Path path , Mode mode ) implements FileData {
123+ private record AbsolutePathFileData (Path path , Mode mode , Platform platform ) implements FileData {
95124 @ Override
96125 public Stream <Path > resolvePaths (PathLookup pathLookup ) {
97126 return Stream .of (path );
98127 }
128+
129+ @ Override
130+ public FileData withPlatform (Platform platform ) {
131+ if (platform == platform ()) {
132+ return this ;
133+ }
134+ return new AbsolutePathFileData (path , mode , platform );
135+ }
99136 }
100137
101- private record RelativePathFileData (Path relativePath , BaseDir baseDir , Mode mode ) implements FileData , RelativeFileData {
138+ private record RelativePathFileData (Path relativePath , BaseDir baseDir , Mode mode , Platform platform )
139+ implements
140+ FileData ,
141+ RelativeFileData {
102142 @ Override
103143 public Stream <Path > resolveRelativePaths (PathLookup pathLookup ) {
104144 return Stream .of (relativePath );
105145 }
146+
147+ @ Override
148+ public FileData withPlatform (Platform platform ) {
149+ if (platform == platform ()) {
150+ return this ;
151+ }
152+ return new RelativePathFileData (relativePath , baseDir , mode , platform );
153+ }
106154 }
107155
108- private record PathSettingFileData (String setting , Mode mode ) implements FileData {
156+ private record PathSettingFileData (String setting , Mode mode , Platform platform ) implements FileData {
109157 @ Override
110158 public Stream <Path > resolvePaths (PathLookup pathLookup ) {
111159 return resolvePathSettings (pathLookup , setting );
112160 }
161+
162+ @ Override
163+ public FileData withPlatform (Platform platform ) {
164+ if (platform == platform ()) {
165+ return this ;
166+ }
167+ return new PathSettingFileData (setting , mode , platform );
168+ }
113169 }
114170
115- private record RelativePathSettingFileData (String setting , BaseDir baseDir , Mode mode ) implements FileData , RelativeFileData {
171+ private record RelativePathSettingFileData (String setting , BaseDir baseDir , Mode mode , Platform platform )
172+ implements
173+ FileData ,
174+ RelativeFileData {
116175 @ Override
117176 public Stream <Path > resolveRelativePaths (PathLookup pathLookup ) {
118177 return resolvePathSettings (pathLookup , setting );
119178 }
179+
180+ @ Override
181+ public FileData withPlatform (Platform platform ) {
182+ if (platform == platform ()) {
183+ return this ;
184+ }
185+ return new RelativePathSettingFileData (setting , baseDir , mode , platform );
186+ }
120187 }
121188
122189 private static Stream <Path > resolvePathSettings (PathLookup pathLookup , String setting ) {
@@ -137,6 +204,18 @@ private static Mode parseMode(String mode) {
137204 }
138205 }
139206
207+ private static Platform parsePlatform (String platform ) {
208+ if (platform .equals ("linux" )) {
209+ return Platform .LINUX ;
210+ } else if (platform .equals ("macos" )) {
211+ return Platform .MACOS ;
212+ } else if (platform .equals ("windows" )) {
213+ return Platform .WINDOWS ;
214+ } else {
215+ throw new PolicyValidationException ("invalid platform: " + platform + ", valid values: [linux, macos, windows]" );
216+ }
217+ }
218+
140219 private static BaseDir parseBaseDir (String baseDir ) {
141220 return switch (baseDir ) {
142221 case "config" -> BaseDir .CONFIG ;
@@ -163,6 +242,7 @@ public static FilesEntitlement build(List<Object> paths) {
163242 String pathSetting = file .remove ("path_setting" );
164243 String relativePathSetting = file .remove ("relative_path_setting" );
165244 String modeAsString = file .remove ("mode" );
245+ String platformAsString = file .remove ("mode" );
166246
167247 if (file .isEmpty () == false ) {
168248 throw new PolicyValidationException ("unknown key(s) [" + file + "] in a listed file for files entitlement" );
@@ -179,38 +259,45 @@ public static FilesEntitlement build(List<Object> paths) {
179259 throw new PolicyValidationException ("files entitlement must contain 'mode' for every listed file" );
180260 }
181261 Mode mode = parseMode (modeAsString );
262+ Platform platform = null ;
263+ if (platformAsString != null ) {
264+ platform = parsePlatform (platformAsString );
265+ }
182266
183267 BaseDir baseDir = null ;
184268 if (relativeTo != null ) {
185269 baseDir = parseBaseDir (relativeTo );
186270 }
187271
272+ final FileData fileData ;
188273 if (relativePathAsString != null ) {
189274 if (baseDir == null ) {
190275 throw new PolicyValidationException ("files entitlement with a 'relative_path' must specify 'relative_to'" );
191276 }
192277
193278 Path relativePath = Path .of (relativePathAsString );
194- if (relativePath .isAbsolute ()) {
279+ if (platform == null || platform . isCurrent () && relativePath .isAbsolute ()) {
195280 throw new PolicyValidationException ("'relative_path' [" + relativePathAsString + "] must be relative" );
196281 }
197- filesData . add ( FileData .ofRelativePath (relativePath , baseDir , mode ) );
282+ fileData = FileData .ofRelativePath (relativePath , baseDir , mode );
198283 } else if (pathAsString != null ) {
199284 Path path = Path .of (pathAsString );
200- if (path .isAbsolute () == false ) {
285+ if (platform == null || platform . isCurrent () && path .isAbsolute () == false ) {
201286 throw new PolicyValidationException ("'path' [" + pathAsString + "] must be absolute" );
202287 }
203- filesData . add ( FileData .ofPath (path , mode ) );
288+ fileData = FileData .ofPath (path , mode );
204289 } else if (pathSetting != null ) {
205- filesData . add ( FileData .ofPathSetting (pathSetting , mode ) );
290+ fileData = FileData .ofPathSetting (pathSetting , mode );
206291 } else if (relativePathSetting != null ) {
207292 if (baseDir == null ) {
208293 throw new PolicyValidationException ("files entitlement with a 'relative_path_setting' must specify 'relative_to'" );
209294 }
210- filesData . add ( FileData .ofRelativePathSetting (relativePathSetting , baseDir , mode ) );
295+ fileData = FileData .ofRelativePathSetting (relativePathSetting , baseDir , mode );
211296 } else {
212297 throw new AssertionError ("File entry validation error" );
213298 }
299+
300+ filesData .add (fileData .withPlatform (platform ));
214301 }
215302 return new FilesEntitlement (filesData );
216303 }
0 commit comments