/* * Licensed under the Apache License, Version 2.0 (the "License"); * * You may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * limitations under the License. * * Contributions from 2013-2017 where performed either by US government * employees, or under US Veterans Health Administration contracts. * * US Veterans Health Administration contributions by government employees * are work of the U.S. Government and are not subject to copyright * protection in the United States. Portions contributed by government * employees are USGovWork (17USC ยง105). Not subject to copyright. * * Contribution by contractors to the US Veterans Health Administration * during this period are contractually contributed under the * Apache License, Version 2.0. * * See: https://www.usa.gov/government-works * * Contributions prior to 2013: * * Copyright (C) International Health Terminology Standards Development Organisation. * Licensed under the Apache License, Version 2.0. * */ package sh.isaac.api.util.metainf; //~--- JDK imports ------------------------------------------------------------ import java.io.File; import java.io.FileReader; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.Locale; import java.util.Properties; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.glassfish.hk2.api.MultiException; //~--- non-JDK imports -------------------------------------------------------- import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import sh.isaac.api.ConfigurationService; import sh.isaac.api.LookupService; //~--- classes ---------------------------------------------------------------- /** * {@link MetaInfReader}. * * @author <a href="mailto:daniel.armbrust.list@gmail.com">Dan Armbrust</a> */ public class MetaInfReader { /** The Constant LOG. */ private static final Logger LOG = LoggerFactory.getLogger(MetaInfReader.class); //~--- methods ------------------------------------------------------------- /** * Read db metadata. * * @return the maven artifact info * @throws IOException Signals that an I/O exception has occurred. */ public static MavenArtifactInfo readDbMetadata() throws IOException { try { final MavenArtifactInfo isaacDbDependency = new MavenArtifactInfo();; // Read the db metadata final AtomicBoolean readDbMetadataFromProperties = new AtomicBoolean(false); final AtomicBoolean readDbMetadataFromPom = new AtomicBoolean(false); final java.nio.file.Path dbLocation = LookupService.get() .getService(ConfigurationService.class) .getChronicleFolderPath() .getParent(); // find the pom.properties file in the hierarchy final File dbMetadata = new File(dbLocation.toFile(), "META-INF"); final AtomicReference<String> metadataVersion = new AtomicReference<>(""); if (dbMetadata.isDirectory()) { Files.walkFileTree(dbMetadata.toPath(), new SimpleFileVisitor<java.nio.file.Path>() { /** * @see java.nio.file.SimpleFileVisitor#visitFile(java.lang.Object, java.nio.file.attribute.BasicFileAttributes) */ @Override public FileVisitResult visitFile(java.nio.file.Path path, BasicFileAttributes attrs) throws IOException { final File f = path.toFile(); if (f.isFile() && f.getName().toLowerCase(Locale.ENGLISH).equals("pom.properties")) { final Properties p = new Properties(); FileReader fileReader = null; try { p.load(fileReader = new FileReader(f)); } finally { if (fileReader != null) { fileReader.close(); } } isaacDbDependency.setValues(p.getProperty("project.groupId"), p.getProperty("project.artifactId"), p.getProperty("project.version"), p.getProperty("resultArtifactClassifier"), p.getProperty("chronicles.type")); metadataVersion.set(p.getProperty("isaac-metadata.version")); readDbMetadataFromProperties.set(true); return readDbMetadataFromPom.get() ? FileVisitResult.TERMINATE : FileVisitResult.CONTINUE; } else if (f.isFile() && f.getName().toLowerCase(Locale.ENGLISH).equals("pom.xml")) { final DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder; Document dDoc = null; final XPath xPath = XPathFactory.newInstance() .newXPath(); try { domFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); builder = domFactory.newDocumentBuilder(); dDoc = builder.parse(f); { final NodeList dbLicensesNodes = ((NodeList) xPath.evaluate("/project/licenses/license/name", dDoc, XPathConstants.NODESET)); LOG.debug("Found {} license names in DB pom.xml", dbLicensesNodes.getLength()); for (int i = 0; i < dbLicensesNodes.getLength(); i++) { final Node currentLicenseNameNode = dbLicensesNodes.item(i); final String name = currentLicenseNameNode.getTextContent(); final MavenLicenseInfo license = new MavenLicenseInfo(name, ((Node) xPath.evaluate( "/project/licenses/license[name='" + name + "']/url", dDoc, XPathConstants.NODE)).getTextContent(), ((Node) xPath.evaluate( "/project/licenses/license[name='" + name + "']/comments", dDoc, XPathConstants.NODE)).getTextContent()); isaacDbDependency.dbLicenses.add(license); LOG.debug("Extracted license \"{}\" from DB pom.xml: {}", name, license.toString()); } } { final NodeList dbDependenciesNodes = ((NodeList) xPath.evaluate( "/project/dependencies/dependency/artifactId", dDoc, XPathConstants.NODESET)); LOG.debug("Found {} dependency artifactIds in DB pom.xml", dbDependenciesNodes.getLength()); for (int i = 0; i < dbDependenciesNodes.getLength(); i++) { final Node currentDbDependencyArtifactIdNode = dbDependenciesNodes.item(i); final String artifactId = currentDbDependencyArtifactIdNode.getTextContent(); final String groupId = ((Node) xPath.evaluate( "/project/dependencies/dependency[artifactId='" + artifactId + "']/groupId", dDoc, XPathConstants.NODE)).getTextContent(); final String version = ((Node) xPath.evaluate( "/project/dependencies/dependency[artifactId='" + artifactId + "']/version", dDoc, XPathConstants.NODE)).getTextContent(); String classifier = null; try { classifier = ((Node) xPath.evaluate( "/project/dependencies/dependency[artifactId='" + artifactId + "']/classifier", dDoc, XPathConstants.NODE)).getTextContent(); } catch (final Throwable t) { LOG.debug("Problem reading \"classifier\" element for {}", artifactId); } String type = null; try { type = ((Node) xPath.evaluate( "/project/dependencies/dependency[artifactId='" + artifactId + "']/type", dDoc, XPathConstants.NODE)).getTextContent(); } catch (final Throwable t) { LOG.debug("Problem reading \"type\" element for {}", artifactId); } final MavenArtifactInfo dependencyInfo = new MavenArtifactInfo(groupId, artifactId, version, classifier, type); isaacDbDependency.dbDependencies.add(dependencyInfo); LOG.debug("Extracted dependency \"{}\" from DB pom.xml: {}", artifactId, dependencyInfo.toString()); } } } catch (XPathExpressionException | SAXException | ParserConfigurationException e) { throw new IOException(e); } readDbMetadataFromPom.set(true); return readDbMetadataFromProperties.get() ? FileVisitResult.TERMINATE : FileVisitResult.CONTINUE; } return FileVisitResult.CONTINUE; } }); } if (readDbMetadataFromProperties.get()) { // Due to a quirk in how the DB poms are set up, we need to fill in this property for (final MavenArtifactInfo dependency: isaacDbDependency.dbDependencies) { if ((dependency.version != null) && "${isaac-metadata.version}".equals(dependency.version)) { dependency.version = metadataVersion.get(); break; } } LOG.debug( "Successfully read db properties from maven config files. dbGroupId: {} dbArtifactId: {} dbVersion: {} dbClassifier: {} dbType: {}", isaacDbDependency.groupId, isaacDbDependency.artifactId, isaacDbDependency.version, isaacDbDependency.classifier, isaacDbDependency.type); } else { LOG.error("Failed to read the metadata about the database from the database package: \n" + dbMetadata.getAbsolutePath()); } return isaacDbDependency; } catch (final IOException e) { throw e; } catch (final MultiException e) { throw new IOException(e); } } }