org.eclipse.jetty.start.fileinits.MavenMetadata Maven / Gradle / Ivy
//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//
package org.eclipse.jetty.start.fileinits;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.jetty.start.StartLog;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* Simple parser for maven-metadata.xml files
*/
public class MavenMetadata
{
private String groupId;
private String artifactId;
private String version;
private String lastUpdated;
private String snapshotTimestamp;
private String snapshotBuildNumber;
private final Map snapshots = new HashMap<>();
public MavenMetadata(Path metadataXml)
throws IOException, ParserConfigurationException, SAXException
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DocumentBuilder builder = factory.newDocumentBuilder();
try (InputStream input = Files.newInputStream(metadataXml))
{
Document doc = builder.parse(input);
parseRoot(doc.getDocumentElement(), metadataXml);
}
}
public String getGroupId()
{
return groupId;
}
public String getArtifactId()
{
return artifactId;
}
public String getVersion()
{
return version;
}
public String getLastUpdated()
{
return lastUpdated;
}
public String getSnapshotTimestamp()
{
return snapshotTimestamp;
}
public String getSnapshotBuildNumber()
{
return snapshotBuildNumber;
}
public Collection getSnapshots()
{
return snapshots.values();
}
public Snapshot getSnapshot(String classifier, String extension)
{
Snapshot snapshot = snapshots.get(asSuffix(classifier, extension));
if (snapshot == null)
{
snapshot = new Snapshot();
snapshot.value = String.format("%s-%s-%s",
getVersion().replaceFirst("-SNAPSHOT$", ""),
snapshotTimestamp, snapshotBuildNumber);
}
return snapshot;
}
/**
* Tests the current time against the provided timestamp.
*
* If the current time is the next day from the provided timestamp,
* it is considered expired.
*
*
* @param lastUpdated the time representing the last update
* @return true if it's the next day from the timestamp (or later)
*/
public static boolean isExpiredTimestamp(String lastUpdated)
{
ZoneId utc = ZoneId.of("UTC");
LocalDate today = LocalDate.now(utc);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").withZone(utc);
try
{
LocalDate lastUpdatedDate = LocalDate.parse(lastUpdated, formatter).atStartOfDay().toLocalDate();
return today.isAfter(lastUpdatedDate);
}
catch (DateTimeParseException e)
{
StartLog.debug(e);
return false;
}
}
private static String asSuffix(String classifier, String type)
{
if (classifier != null)
return String.format("-%s.%s", classifier, type);
else
return String.format(".%s", type);
}
private List listOf(NodeList nodeList)
{
List children = new ArrayList<>();
int length = nodeList.getLength();
for (int i = 0; i < length; i++)
{
children.add(nodeList.item(i));
}
return children;
}
private void parseRoot(Element root, Path metadataXml) throws IOException
{
if (!root.getNodeName().equals("metadata"))
{
throw new IOException("Unrecognized maven-metadata.xml <" + root.getNodeName() + ">: " + metadataXml);
}
listOf(root.getChildNodes()).stream()
.filter((node) -> node.getNodeType() == Node.ELEMENT_NODE)
.map((node) -> (Element)node)
.forEach((elem) ->
{
switch (elem.getNodeName())
{
case "groupId":
this.groupId = elem.getTextContent();
break;
case "artifactId":
this.artifactId = elem.getTextContent();
break;
case "version":
this.version = elem.getTextContent();
break;
case "versioning":
parseVersioning(elem, metadataXml);
break;
}
});
}
private void parseVersioning(Element versioning, Path metadataXml)
{
listOf(versioning.getChildNodes()).stream()
.filter((node) -> node.getNodeType() == Node.ELEMENT_NODE)
.map((node) -> (Element)node)
.forEach((elem) ->
{
switch (elem.getNodeName())
{
case "snapshot":
parseSnapshot(elem);
break;
case "lastUpdated":
this.lastUpdated = elem.getTextContent();
break;
case "snapshotVersions":
parseSnapshotVersions(elem);
break;
}
});
}
private void parseSnapshot(Element snapshot)
{
listOf(snapshot.getChildNodes()).stream()
.filter((node) -> node.getNodeType() == Node.ELEMENT_NODE)
.map((node) -> (Element)node)
.forEach((elem) ->
{
switch (elem.getNodeName())
{
case "timestamp":
this.snapshotTimestamp = elem.getTextContent();
break;
case "buildNumber":
this.snapshotBuildNumber = elem.getTextContent();
break;
}
});
}
private void parseSnapshotVersions(Element snapshotVersions)
{
listOf(snapshotVersions.getChildNodes()).stream()
.filter((node) -> node.getNodeType() == Node.ELEMENT_NODE)
.map((node) -> (Element)node)
.forEach((elem) ->
{
if ("snapshotVersion".equals(elem.getNodeName()))
{
parseSnapshotVersion(elem);
}
});
}
private void parseSnapshotVersion(Element snapshotVersion)
{
Snapshot snapshot = new Snapshot();
listOf(snapshotVersion.getChildNodes()).stream()
.filter((node) -> node.getNodeType() == Node.ELEMENT_NODE)
.map((node) -> (Element)node)
.forEach((elem) ->
{
switch (elem.getNodeName())
{
case "classifier":
snapshot.classifier = elem.getTextContent();
break;
case "extension":
snapshot.extension = elem.getTextContent();
break;
case "value":
snapshot.value = elem.getTextContent();
break;
case "updated":
snapshot.updated = elem.getTextContent();
break;
}
});
snapshots.put(snapshot.toSuffix(), snapshot);
}
public static class Snapshot
{
String classifier;
String extension;
String value;
String updated;
private String toSuffix()
{
return asSuffix(classifier, extension);
}
public String getClassifier()
{
return classifier;
}
public String getExtension()
{
return extension;
}
public String getUpdated()
{
return updated;
}
public String getValue()
{
return value;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy