ThemisAnalysisMaven.java
/*
* Themis: Java Project Framework
* Copyright 2012-2026. Tony Washer
*
* 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.
*/
package io.github.tonywasher.joceanus.themis.lethe.analysis;
import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
import io.github.tonywasher.joceanus.themis.exc.ThemisDataException;
import io.github.tonywasher.joceanus.themis.exc.ThemisIOException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Maven pom.xml parser.
*/
public class ThemisAnalysisMaven {
/**
* Project filename.
*/
public static final String POM = "pom.xml";
/**
* Document name.
*/
private static final String DOC_NAME = "project";
/**
* Parent element.
*/
private static final String EL_PARENT = "parent";
/**
* Modules element.
*/
private static final String EL_MODULES = "modules";
/**
* Module element.
*/
private static final String EL_MODULE = "module";
/**
* Dependencies element.
*/
private static final String EL_DEPENDENCIES = "dependencies";
/**
* Dependency element.
*/
private static final String EL_DEPENDENCY = "dependency";
/**
* The Id.
*/
private final ThemisAnalysisMavenId theId;
/**
* The modules.
*/
private final List<String> theModules;
/**
* The dependencies.
*/
private final List<ThemisAnalysisMavenId> theDependencies;
/**
* Constructor.
*
* @param pInputStream the input stream to read
* @throws OceanusException on error
*/
public ThemisAnalysisMaven(final InputStream pInputStream) throws OceanusException {
/* Create the module list */
theModules = new ArrayList<>();
theDependencies = new ArrayList<>();
/* Protect against exceptions */
try (BufferedInputStream myInBuffer = new BufferedInputStream(pInputStream)) {
final DocumentBuilderFactory myFactory = DocumentBuilderFactory.newInstance();
myFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
myFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
myFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
final DocumentBuilder myBuilder = myFactory.newDocumentBuilder();
/* Build the document from the input stream */
final Document myDocument = myBuilder.parse(myInBuffer);
theId = parseProjectFile(myDocument);
/* Handle exceptions */
} catch (IOException
| ParserConfigurationException
| SAXException e) {
throw new ThemisIOException("Exception accessing Pom file", e);
}
}
@Override
public String toString() {
return theId.toString();
}
/**
* Obtain the list of modules.
*
* @return the list
*/
public ThemisAnalysisMavenId getMavenId() {
return theId;
}
/**
* Obtain the list of modules.
*
* @return the list
*/
public List<String> getModules() {
return theModules;
}
/**
* Parse the project file.
*
* @param pDocument the document
* @return the MavenId
* @throws OceanusException on error
*/
public ThemisAnalysisMavenId parseProjectFile(final Document pDocument) throws OceanusException {
/* Access the document element */
final Element myDoc = pDocument.getDocumentElement();
/* Check that the document name is correct */
if (!Objects.equals(myDoc.getNodeName(), DOC_NAME)) {
throw new ThemisDataException("Invalid document type");
}
/* Obtain parent definition if any */
final Element myParentEl = getElement(myDoc, EL_PARENT);
final ThemisAnalysisMavenId myParent = myParentEl == null
? null
: new ThemisAnalysisMavenId(myParentEl);
/* Obtain our mavenId */
final ThemisAnalysisMavenId myId = new ThemisAnalysisMavenId(myDoc, myParent);
/* Process modules */
final Element myModules = getElement(myDoc, EL_MODULES);
processModules(myModules);
/* Process dependencies */
final Element myDependencies = getElement(myDoc, EL_DEPENDENCIES);
processDependencies(myDependencies, myId);
/* Return the Id */
return myId;
}
/**
* Obtain element value.
*
* @param pElement the element
* @param pValue the value name
* @return the value
*/
static String getElementValue(final Element pElement,
final String pValue) {
/* Return null if no element */
if (pElement == null) {
return null;
}
/* Loop through the children */
for (Node myChild = pElement.getFirstChild();
myChild != null;
myChild = myChild.getNextSibling()) {
/* Return result if we have a match */
if (myChild instanceof Element
&& pValue.equals(myChild.getNodeName())) {
return myChild.getTextContent();
}
}
/* Not found */
return null;
}
/**
* Obtain element value.
*
* @param pElement the element
* @param pValue the value name
* @return the value
*/
static Element getElement(final Element pElement,
final String pValue) {
/* Return null if no element */
if (pElement == null) {
return null;
}
/* Loop through the children */
for (Node myChild = pElement.getFirstChild();
myChild != null;
myChild = myChild.getNextSibling()) {
/* Return result if we have a match */
if (myChild instanceof Element myElement
&& pValue.equals(myChild.getNodeName())) {
return myElement;
}
}
/* Not found */
return null;
}
/**
* Process modules.
*
* @param pModules the modules
*/
private void processModules(final Element pModules) {
/* Return if no element */
if (pModules == null) {
return;
}
/* Loop through the children */
for (Node myChild = pModules.getFirstChild();
myChild != null;
myChild = myChild.getNextSibling()) {
/* Return result if we have a match */
if (myChild instanceof Element
&& EL_MODULE.equals(myChild.getNodeName())) {
theModules.add(myChild.getTextContent());
}
}
}
/**
* Process dependencies.
*
* @param pDependencies the dependencies
* @param pParent the parentId
*/
private void processDependencies(final Element pDependencies,
final ThemisAnalysisMavenId pParent) {
/* Return if no element */
if (pDependencies == null) {
return;
}
/* Loop through the children */
for (Node myChild = pDependencies.getFirstChild();
myChild != null;
myChild = myChild.getNextSibling()) {
/* Return result if we have a match */
if (myChild instanceof Element myElement
&& EL_DEPENDENCY.equals(myChild.getNodeName())) {
theDependencies.add(new ThemisAnalysisMavenId(myElement, pParent));
}
}
}
}