Skip to content

Commit

Permalink
Fix Windows build incompatibilities. WrenSecurity#168
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelhoral committed Feb 6, 2024
1 parent a033c5e commit 84b28d5
Show file tree
Hide file tree
Showing 17 changed files with 324 additions and 122 deletions.
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Test resources sensitive to content length
openidm-external-rest/src/test/resources/*.html text eol=lf
openidm-external-rest/src/test/resources/*.xml text eol=lf
8 changes: 1 addition & 7 deletions openidm-launcher/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
information: "Portions copyright [year] [name of copyright owner]".
Copyright 2012-2013 ForgeRock AS.
Portions Copyright 2020-2023 Wren Security.
Portions Copyright 2020-2024 Wren Security.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
Expand All @@ -39,11 +39,6 @@
<groupId>org.wrensecurity.commons</groupId>
<artifactId>forgerock-util</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>args4j</groupId>
<artifactId>args4j</artifactId>
Expand Down Expand Up @@ -99,7 +94,6 @@
<include>com.googlecode.json-simple:*</include>
<include>org.forgerock.commons:*</include>
<include>org.wrensecurity.commons:*</include>
<include>org.codehaus.plexus:plexus-utils</include>
<include>args4j:args4j</include>
</includes>
<excludes>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
*/
package org.forgerock.commons.launcher;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand All @@ -26,7 +26,6 @@
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkEvent;
Expand All @@ -53,7 +52,7 @@ public abstract class AbstractOSGiFrameworkService implements OSGiFramework {
* @return list of startup bundle handlers.
*/
protected abstract List<BundleHandler> listBundleHandlers(BundleContext context)
throws MalformedURLException;
throws IOException, MalformedURLException;

/**
* @return map of configuration properties.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,26 @@
* information: "Portions copyright [year] [name of copyright owner]".
*
* Copyright 2012-2013 ForgeRock AS.
* Portions Copyright 2020 Wren Security.
* Portions Copyright 2020-2024 Wren Security.
*/
package org.forgerock.commons.launcher;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.List;
import java.util.Stack;
import java.util.Vector;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.codehaus.plexus.util.MatchPatterns;
import org.forgerock.commons.launcher.support.GlobPathMatcher;

/**
* A ConfigurationUtil class contains util methods used by
Expand Down Expand Up @@ -58,19 +62,24 @@ public static Vector<URL> getJarFileListing(URL location, List<String> includes,
return files; // Empty.
}

MatchPatterns includesPatterns = null;
MatchPatterns excludesPatterns = null;
List<PathMatcher> includesPatterns = null;
List<PathMatcher> excludesPatterns = null;

FileSystem fileSystem = FileSystems.getDefault();
if (includes == null) {
// No includes supplied, so set it to 'matches all'
includesPatterns = MatchPatterns.from("**");
includesPatterns = List.of(fileSystem.getPathMatcher("glob:**"));
} else {
includesPatterns = MatchPatterns.from(includes);
includesPatterns = includes.stream()
.map(pattern -> fileSystem.getPathMatcher("glob:" + pattern))
.collect(Collectors.toList());
}
if (excludes == null) {
excludesPatterns = MatchPatterns.from();
excludesPatterns = List.of();
} else {
excludesPatterns = MatchPatterns.from(excludes);
excludesPatterns = excludes.stream()
.map(pattern -> fileSystem.getPathMatcher("glob:" + pattern))
.collect(Collectors.toList());;
}

JarInputStream inputStream = null;
Expand All @@ -86,8 +95,8 @@ public static Vector<URL> getJarFileListing(URL location, List<String> includes,
if (jarEntry != null && !jarEntry.isDirectory()) {
String fileName = jarEntry.getName();

if (includesPatterns.matches(fileName, false)
&& !excludesPatterns.matches(fileName, false)) {
if (includesPatterns.stream().anyMatch(pattern -> pattern.matches(Path.of(fileName)))
&& !excludesPatterns.stream().anyMatch(pattern -> pattern.matches(Path.of(fileName)))) {
files.add(new URL(location, fileName));
}
}
Expand Down Expand Up @@ -140,20 +149,8 @@ public static Vector<URL> getZipFileListing(URL location, List<String> includes,
}
}

MatchPatterns includesPatterns = null;
MatchPatterns excludesPatterns = null;

if (includes == null) {
// No includes supplied, so set it to 'matches all'
includesPatterns = MatchPatterns.from("**");
} else {
includesPatterns = MatchPatterns.from(includes);
}
if (excludes == null) {
excludesPatterns = MatchPatterns.from();
} else {
excludesPatterns = MatchPatterns.from(excludes);
}
GlobPathMatcher includeMatcher = new GlobPathMatcher(includes != null ? includes : List.of("**"));
GlobPathMatcher excludeMatcher = new GlobPathMatcher(excludes != null ? excludes : List.of());

ZipInputStream inputStream = null;
try {
Expand All @@ -167,9 +164,8 @@ public static Vector<URL> getZipFileListing(URL location, List<String> includes,
jarEntry = inputStream.getNextEntry();
if (jarEntry != null && !jarEntry.isDirectory()) {
String fileName = jarEntry.getName();

if (includesPatterns.matches(fileName, false)
&& !excludesPatterns.matches(fileName, false)) {
Path filePath = Path.of(fileName);
if (includeMatcher.matches(filePath) && !excludeMatcher.matches(filePath)) {
files.add(new URL(base, fileName));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* information: "Portions copyright [year] [name of copyright owner]".
*
* Copyright 2012-2013 ForgeRock AS.
* Portions Copyright 2020 Wren Security.
* Portions Copyright 2020-2024 Wren Security.
*/
package org.forgerock.commons.launcher;

Expand All @@ -30,6 +30,7 @@
import java.net.URI;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
Expand All @@ -41,8 +42,7 @@
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.codehaus.plexus.util.DirectoryScanner;
import org.forgerock.commons.launcher.support.DirectoryScanner;
import org.forgerock.json.JsonValue;
import org.forgerock.json.JsonValueTraverseFunction;
import org.json.simple.parser.JSONParser;
Expand Down Expand Up @@ -433,7 +433,7 @@ public void setLauncherConfiguration(JsonValue launcherConfiguration) {

@Override
protected List<BundleHandler> listBundleHandlers(BundleContext context)
throws MalformedURLException {
throws IOException, MalformedURLException {
JsonValue bundle = getLauncherConfiguration().get("bundle");
BundleHandlerBuilder defaultBuilder =
BundleHandlerBuilder.newBuilder(bundle.get("default"));
Expand All @@ -459,22 +459,15 @@ protected List<BundleHandler> listBundleHandlers(BundleContext context)
File inputFile = getFileForPath(location, installDirectory);
result.add(innerBuilder.build(inputFile.toURI().toURL()));
} else {
DirectoryScanner scanner = new DirectoryScanner();
scanner.setBasedir(getFileForPath(location, installDirectory));
if (container.isDefined("includes")) {
List<String> includes = container.get("includes").asList(String.class);
scanner.setIncludes(includes.toArray(new String[includes.size()]));
}
if (container.isDefined("excludes")) {
List<String> includes = container.get("excludes").asList(String.class);
scanner.setExcludes(includes.toArray(new String[includes.size()]));
}
scanner.scan();
List<String> includes = container.get("includes").asList(String.class);
List<String> excludes = container.get("excludes").asList(String.class);

DirectoryScanner scanner = new DirectoryScanner(includes, excludes);

for (String bundleLocation : scanner.getIncludedFiles()) {
Path base = getFileForPath(location, installDirectory).toPath();
for (Path bundleLocation : scanner.scan(base)) {
BundleHandler newHandler =
innerBuilder.build(scanner.getBasedir().toURI().resolve(
bundleLocation.replaceAll("\\\\", "/")).toURL());
innerBuilder.build(bundleLocation.toUri().toURL());
for (BundleHandler handler : result) {
if (newHandler.getBundleUrl().equals(handler.getBundleUrl())) {
if (newHandler.getActions().equals(handler.getActions())
Expand Down Expand Up @@ -521,8 +514,9 @@ protected void loadSystemProperties(JsonValue configuration, URI projectDirector
Properties props =
loadPropertyFile(projectDirectory, systemProperties.expect(String.class)
.defaultTo(SYSTEM_PROPERTIES_FILE_VALUE).asString());
if (props == null)
if (props == null) {
return;
}
// Perform variable substitution on specified properties.
for (Enumeration e = props.propertyNames(); e.hasMoreElements();) {
String name = (String) e.nextElement();
Expand Down Expand Up @@ -559,8 +553,9 @@ protected Map<String, String> loadConfigProperties(JsonValue configuration, URI
Properties props =
loadPropertyFile(projectDirectory, systemProperties.expect(String.class)
.defaultTo(CONFIG_PROPERTIES_FILE_VALUE).asString());
if (props == null)
if (props == null) {
return new HashMap<String, String>(0);
}
// Perform variable substitution on specified properties.
systemProperties = transformer.apply(new JsonValue(props, null));
}
Expand Down Expand Up @@ -595,8 +590,9 @@ protected Map<String, Object> loadBootProperties(JsonValue configuration, URI pr
Properties props =
loadPropertyFile(projectDirectory, bootProperties.expect(String.class)
.defaultTo(BOOT_PROPERTIES_FILE_VALUE).asString());
if (props == null)
if (props == null) {
return new HashMap<String, Object>(0);
}
// Perform variable substitution on specified properties.
return transformer.apply(new JsonValue(props, null)).asMap();
}
Expand Down Expand Up @@ -626,8 +622,9 @@ protected Properties loadPropertyFile(URI projectDirectory, String propertyFile)
System.err.append("Main: Error loading properties from ").println(propertyFile);
System.err.println("Main: " + ex);
try {
if (is != null)
if (is != null) {
is.close();
}
} catch (IOException ex2) {
// Nothing we can do.
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* The contents of this file are subject to the terms of the Common Development and
* Distribution License (the License). You may not use this file except in compliance with the
* License.
*
* You can obtain a copy of the License at legal/CDDLv1.1.txt. See the License for the
* specific language governing permission and limitations under the License.
*
* When distributing Covered Software, include this CDDL Header Notice in each file and include
* the License file at legal/CDDLv1.1.txt. If applicable, add the following below the CDDL
* Header, with the fields enclosed by brackets [] replaced by your own identifying
* information: "Portions copyright [year] [name of copyright owner]".
*
* Copyright 2024 Wren Security
*/
package org.forgerock.commons.launcher.support;

import java.io.IOException;
import java.nio.file.FileVisitOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
* Simple file tree walker based on previously used Plexus Utils' {@code DirectoryScanner}.
*
* <p>
* The implementation does not try to do anything clever to optimize path traversal (e.g. by prefix
* matching to prevent walking into directories that can not contain matching files).
*/
public class DirectoryScanner {

private PathMatcher includes;

private PathMatcher excludes;

public DirectoryScanner(List<String> includes, List<String> excludes) {
this(includes != null ? new GlobPathMatcher(includes) : null,
excludes != null ? new GlobPathMatcher(excludes) : null);
}

public DirectoryScanner(PathMatcher includes, PathMatcher excludes) {
this.includes = includes != null ? includes : new GlobPathMatcher("**");
this.excludes = excludes != null ? excludes : new GlobPathMatcher();
}

public List<Path> scan(Path start) throws IOException {
return Files.walk(start, FileVisitOption.FOLLOW_LINKS)
.map(start::relativize)
.filter(includes::matches)
.filter(Predicate.not(excludes::matches))
.filter(Predicate.not(Files::isDirectory))
.map(start::resolve)
.collect(Collectors.toList());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* The contents of this file are subject to the terms of the Common Development and
* Distribution License (the License). You may not use this file except in compliance with the
* License.
*
* You can obtain a copy of the License at legal/CDDLv1.1.txt. See the License for the
* specific language governing permission and limitations under the License.
*
* When distributing Covered Software, include this CDDL Header Notice in each file and include
* the License file at legal/CDDLv1.1.txt. If applicable, add the following below the CDDL
* Header, with the fields enclosed by brackets [] replaced by your own identifying
* information: "Portions copyright [year] [name of copyright owner]".
*
* Copyright 2024 Wren Security
*/
package org.forgerock.commons.launcher.support;

import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.List;
import java.util.stream.Collectors;

/**
* Glob based path matcher that emulates behavior of previously used {@code MatchPattern} from Plexus Utils.
*
* <p>
* Matcher uses native JRE's path matcher provided by default {@code FileSystem} implementation. This means that
* the behavior might be platform dependent depending on the used patterns.
*
* <p>
* <b>CAUTION:</b> Plexus Utils' {@code MatchPattern} was matching simple filename patterns even in subdirectories.
* This implementation is not matching subdirectories without path traversal wildcard <code>**&#47;</code>.
*/
public class GlobPathMatcher implements PathMatcher {

private final List<PathMatcher> matchers;

public GlobPathMatcher(String... pattern) {
this(List.of(pattern));
}

public GlobPathMatcher(List<String> patterns) {
var fileSystem = FileSystems.getDefault();
this.matchers = patterns.stream()
// make directory wildcard pattern optional and the pattern case insensitive
.map(pattern -> pattern.replace("**/", "{**/,}").toLowerCase())
.map(pattern -> fileSystem.getPathMatcher("glob:" + pattern))
.collect(Collectors.toList());
}

@Override
public boolean matches(Path path) {
var normalized = Path.of(path.toString().toLowerCase());
return matchers.stream().anyMatch(matcher -> matcher.matches(normalized));
}

}
Loading

0 comments on commit 84b28d5

Please sign in to comment.