Skip to content

Commit

Permalink
Use NIO Path API for more presice path handling and checks
Browse files Browse the repository at this point in the history
  • Loading branch information
HannesWell authored and laeubi committed Sep 8, 2022
1 parent 60fca93 commit 5782054
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package org.eclipse.tycho.pomless;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
Expand All @@ -24,9 +23,13 @@
import java.io.StringReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.function.Supplier;

Expand Down Expand Up @@ -83,12 +86,12 @@ public File locatePom(File dir) {

@Override
public boolean accept(Map<String, ?> options) {
String location = PolyglotModelUtil.getLocation(options);
if (location == null || location.endsWith("pom.xml")) {
Optional<Path> location = getLocation(options);
if (location.isEmpty() || getFileName(location.get()).equals("pom.xml")) {
//we want that pom.xml takes precedence over our generated one
return false;
}
return isValidLocation(location);
return isValidLocation(location.get());
}

@Override
Expand All @@ -111,21 +114,20 @@ public ModelWriter getWriter() {

@Override
public Model read(InputStream input, Map<String, ?> options) throws IOException {
String location = PolyglotModelUtil.getLocation(options);
File file = new File(location);
Path file = getLocation(options).orElseThrow(() -> new IOException("Failed to obtain file location"));
try (InputStreamReader stream = new InputStreamReader(input, getPrimaryArtifactCharset())) {
return read(stream, file, options);
}
}

@Override
public Model read(File input, Map<String, ?> options) throws IOException {
File artifactFile = getRealArtifactFile(input);
if (artifactFile.isDirectory()) {
public Model read(File inputFile, Map<String, ?> options) throws IOException {
Path input = inputFile.toPath();
Path artifactFile = getRealArtifactFile(input);
if (Files.isDirectory(artifactFile)) {
return read(new StringReader(""), input, options);
} else if (artifactFile.isFile()) {
try (InputStreamReader stream = new InputStreamReader(new FileInputStream(artifactFile),
getPrimaryArtifactCharset())) {
} else if (Files.isRegularFile(artifactFile)) {
try (Reader stream = Files.newBufferedReader(artifactFile, getPrimaryArtifactCharset())) {
return read(stream, input, options);
}
} else {
Expand All @@ -136,17 +138,17 @@ public Model read(File input, Map<String, ?> options) throws IOException {

@Override
public Model read(Reader input, Map<String, ?> options) throws IOException {
File file = new File(PolyglotModelUtil.getLocation(options));
Path file = getLocation(options).orElseThrow(() -> new IOException("Failed to obtain file location"));
return read(input, file, options);
}

private Model read(Reader artifactReader, File artifactFile, Map<String, ?> options) throws IOException {
private Model read(Reader artifactReader, Path artifactFile, Map<String, ?> options) throws IOException {
Model model = new Model();
model.setModelVersion("4.0.0");
model.setPackaging(getPackaging());
initModel(model, artifactReader, artifactFile);
if (model.getParent() == null) {
model.setParent(findParent(artifactFile.getParentFile(), options));
model.setParent(findParent(artifactFile.getParent(), options));
}
if (model.getVersion() == null) {
//inherit version from parent if not given
Expand All @@ -159,11 +161,11 @@ private Model read(Reader artifactReader, File artifactFile, Map<String, ?> opti
return model;
}

protected File getRealArtifactFile(File polyglotArtifactFile) {
protected Path getRealArtifactFile(Path polyglotArtifactFile) {
return polyglotArtifactFile;
}

protected Parent findParent(File projectRoot, Map<String, ?> projectOptions) throws IOException {
protected Parent findParent(Path projectRoot, Map<String, ?> projectOptions) throws IOException {
Parent parent = (Parent) projectOptions.get(MODEL_PARENT);
if (parent != null) {
//if the parent is given by the options we don't need to search it!
Expand All @@ -172,17 +174,17 @@ protected Parent findParent(File projectRoot, Map<String, ?> projectOptions) thr
Properties buildProperties = getBuildProperties(projectRoot);
// assumption parent pom must be physically located in parent directory if not given by build.properties
String parentRef = buildProperties.getProperty(TYCHO_POMLESS_PARENT_PROPERTY, PARENT_POM_DEFAULT_VALUE);
File fileOrFolder = new File(projectRoot, parentRef).getCanonicalFile();
Path fileOrFolder = projectRoot.resolve(parentRef).toRealPath();
PomReference parentPom;
if (fileOrFolder.isFile()) {
parentPom = locatePomReference(fileOrFolder.getParentFile(), fileOrFolder.getName());
} else if (fileOrFolder.isDirectory()) {
if (Files.isRegularFile(fileOrFolder)) {
parentPom = locatePomReference(fileOrFolder.getParent(), getFileName(fileOrFolder));
} else if (Files.isDirectory(fileOrFolder)) {
parentPom = locatePomReference(fileOrFolder, null);
} else {
throw new FileNotFoundException("parent pom file/folder " + fileOrFolder + " is not accessible");
}
if (parentPom == null) {
throw new FileNotFoundException("No parent pom file found in " + fileOrFolder.getCanonicalPath());
throw new FileNotFoundException("No parent pom file found in " + fileOrFolder.toRealPath());
}
Map<String, Object> options = new HashMap<>(1);
options.put(ModelProcessor.SOURCE, new FileModelSource(parentPom.getPomFile()));
Expand All @@ -201,8 +203,8 @@ protected Parent findParent(File projectRoot, Map<String, ?> projectOptions) thr
version = parentModel.getParent().getVersion();
}
parentReference.setVersion(version);
parentReference.setRelativePath(
projectRoot.getCanonicalFile().toPath().relativize(parentPom.getPomFile().toPath()).toString());
parentReference
.setRelativePath(projectRoot.toRealPath().relativize(parentPom.getPomFile().toPath()).toString());
logger.debug("Derived parent for path " + projectRoot + " is groupId: " + parentReference.getGroupId()
+ ", artifactId: " + parentReference.getArtifactId() + ", relativePath: "
+ parentReference.getRelativePath());
Expand All @@ -218,10 +220,12 @@ protected Parent findParent(File projectRoot, Map<String, ?> projectOptions) thr
* the name hint to use
* @return the {@link PomReference} or <code>null</code>
*/
protected PomReference locatePomReference(File folder, String nameHint) {
protected PomReference locatePomReference(Path folderPath, String nameHint) {
File folder = folderPath.toFile();
PomReference reference = null;
try {
List<ModelProcessor> lookupList = container.lookupList(ModelProcessor.class);

for (ModelProcessor processor : lookupList) {
File pom = processor.locatePom(folder);
if (pom != null && (reference == null || pom.getName().equals(nameHint)) && pom.exists()) {
Expand All @@ -238,7 +242,7 @@ public String getFlavour() {
return getPackaging();
}

protected abstract boolean isValidLocation(String location);
protected abstract boolean isValidLocation(Path location);

protected abstract File getPrimaryArtifact(File dir);

Expand All @@ -254,23 +258,23 @@ protected Charset getPrimaryArtifactCharset() {
return StandardCharsets.UTF_8;
}

protected abstract void initModel(Model model, Reader artifactReader, File artifactFile) throws IOException;
protected abstract void initModel(Model model, Reader artifactReader, Path artifactFile) throws IOException;

protected static Properties getBuildProperties(File dir) throws IOException {
return loadProperties(new File(dir, "build.properties"));
protected static Properties getBuildProperties(Path dir) throws IOException {
return loadProperties(dir.resolve("build.properties"));
}

static Properties loadProperties(File propertiesPath) throws IOException {
static Properties loadProperties(Path propertiesPath) throws IOException {
Properties properties = new Properties();
if (propertiesPath.isFile()) {
try (FileInputStream stream = new FileInputStream(propertiesPath)) {
if (Files.isRegularFile(propertiesPath)) {
try (InputStream stream = Files.newInputStream(propertiesPath)) {
properties.load(stream);
}
}
return properties;
}

static Supplier<Properties> getPropertiesSupplier(File propertiesFile) {
static Supplier<Properties> getPropertiesSupplier(Path propertiesFile) {
return new Supplier<>() {
private Properties properties;

Expand Down Expand Up @@ -299,22 +303,23 @@ static String localizedValue(String value, Supplier<Properties> properties) {

@Override
public Properties getEnhancementProperties(Map<String, ?> options) {
String location = PolyglotModelUtil.getLocation(options);
File file = new File(location);
Optional<Path> file = getLocation(options);
try {
return getEnhancementProperties(file);
if (file.isPresent()) {
return getEnhancementProperties(file.get());
}
} catch (IOException e) {
logger.warn("reading EnhancementProperties encountered a problem and was skipped for this reason", e);
}
return null;
}

protected Properties getEnhancementProperties(File file) throws IOException {
File dir = file.isDirectory() ? file : file.getParentFile();
protected Properties getEnhancementProperties(Path file) throws IOException {
Path dir = Files.isDirectory(file) ? file : file.getParent();
return getBuildProperties(dir);
}

private static void setLocation(Model model, File modelSource) {
private static void setLocation(Model model, Path modelSource) {
InputSource inputSource = new InputSource();
inputSource.setLocation(modelSource.toString());
inputSource.setModelId(model.getParent().getGroupId() + ":" + model.getArtifactId() + ":" + model.getVersion());
Expand Down Expand Up @@ -349,4 +354,19 @@ public void setMultiModuleProjectDirectory(File multiModuleProjectDirectory) {
public void setSnapshotFormat(String snapshotFormat) {
this.snapshotFormat = snapshotFormat;
}

static Optional<Path> getLocation(Map<String, ?> options) {
String location = PolyglotModelUtil.getLocation(options);
if (location != null) {
try {
return Optional.of(Path.of(location));
} catch (InvalidPathException e) {
}
}
return Optional.empty();
}

static String getFileName(Path file) {
return file.getFileName().toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ public abstract class AbstractXMLTychoMapping extends AbstractTychoMapping {
private static final DocumentBuilderFactory FACTORY = DocumentBuilderFactory.newInstance();

@Override
protected void initModel(Model model, Reader artifactReader, File artifactFile) throws IOException {
initModelFromXML(model, parseXML(artifactReader, artifactFile.toURI().toASCIIString()), artifactFile);
protected void initModel(Model model, Reader artifactReader, Path artifactFile) throws IOException {
initModelFromXML(model, parseXML(artifactReader, artifactFile.toUri().toASCIIString()), artifactFile);
}

protected abstract void initModelFromXML(Model model, Element xml, File artifactFile) throws IOException;
protected abstract void initModelFromXML(Model model, Element xml, Path artifactFile) throws IOException;

protected static Element parseXML(Reader artifactReader, String documentURI) throws IOException {
try {
Expand Down Expand Up @@ -102,7 +102,7 @@ public float getPriority() {
protected static Stream<File> filesWithExtension(Path directory, String extension) throws IOException {
Predicate<String> nameFilter = n -> !n.startsWith(".polyglot.") && n.endsWith(extension);
return Files.walk(directory, 1) //
.filter(p -> nameFilter.test(p.getFileName().toString())) //
.filter(p -> nameFilter.test(getFileName(p))) //
.filter(Files::isRegularFile).map(Path::toFile);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
Expand Down Expand Up @@ -57,8 +57,8 @@ public float getPriority() {
}

@Override
protected boolean isValidLocation(String location) {
return location.endsWith(TYCHO_POM);
protected boolean isValidLocation(Path location) {
return getFileName(location).equals(TYCHO_POM);
}

@Override
Expand All @@ -69,36 +69,37 @@ protected File getPrimaryArtifact(File dir) {
}
if (COMMON_NAMES.contains(dir.getName().toLowerCase())) {
logger.debug("Scanning folder " + dir + " for modules");
File[] subFolders = dir.listFiles((FileFilter) File::isDirectory);
if (subFolders != null) {
Set<String> modules = new TreeSet<>();
for (File subfolder : subFolders) {
Set<String> modules = new TreeSet<>();
try (var subFolders = Files.newDirectoryStream(dir.toPath(), Files::isDirectory)) {
for (Path subfolder : subFolders) {
PomReference reference = locatePomReference(subfolder, null);
if (reference != null) {
String name = subfolder.getName();
String name = getFileName(subfolder);
modules.add(name);
logger.debug("Found pom " + reference.getPomFile().getName() + " in subfolder " + name);
}
}
if (!modules.isEmpty()) {
file.deleteOnExit();
Stream<CharSequence> lines = concat(of(TYCHO_AUTOMATIC_GENERATED_FILE_HEADER), modules.stream());
try {
Files.write(file.toPath(), lines::iterator, getPrimaryArtifactCharset());
} catch (IOException e) {
throw new RuntimeException("writing modules file failed", e);
}
return file;
} catch (IOException e) { // assume empty
}
if (!modules.isEmpty()) {
file.deleteOnExit();
Stream<CharSequence> lines = concat(of(TYCHO_AUTOMATIC_GENERATED_FILE_HEADER), modules.stream());
try {
Files.write(file.toPath(), lines::iterator, getPrimaryArtifactCharset());
} catch (IOException e) {
throw new RuntimeException("writing modules file failed", e);
}
return file;
}

} else {
logger.debug("Skip folder " + dir + " because it does not match any common name " + COMMON_NAMES);
}
return null;
}

@Override
protected void initModel(Model model, Reader artifactReader, File artifactFile) throws IOException {
protected void initModel(Model model, Reader artifactReader, Path artifactFile) throws IOException {
logger.debug("Generate aggregator pom for " + artifactFile);
try (BufferedReader reader = new BufferedReader(artifactReader)) {
Stream<String> lines = reader.lines().filter(l -> !l.startsWith("#") && !l.isBlank()).map(String::strip);
Expand All @@ -107,7 +108,7 @@ protected void initModel(Model model, Reader artifactReader, File artifactFile)
logger.debug("Adding module " + line);
model.getModules().add(line);
}
model.setArtifactId(artifactFile.getParentFile().getName());
model.setArtifactId(getFileName(artifactFile.getParent()));
model.setName("[aggregator] " + model.getArtifactId());
}
}
Expand Down
Loading

0 comments on commit 5782054

Please sign in to comment.