Skip to content

Commit

Permalink
Fix eclipse-jkube#195: Added MigrateMojo for migrating projects from FMP
Browse files Browse the repository at this point in the history
  • Loading branch information
rohanKanojia committed Jun 19, 2020
1 parent d290c13 commit ad7b9c8
Show file tree
Hide file tree
Showing 11 changed files with 844 additions and 5 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Usage:
* Fix #192: Removed `@Deprecated` fields from ClusterAccess
* Fix #190: Removed `@Deprecated` fields from AssemblyConfiguration
* Fix #189: Removed `@Deprecated` fields from BuildConfiguration

* Fix #195: Added MigrateMojo for migrating projects from FMP to JKube

### 1.0.0-alpha-4 (2020-06-08)
* Fix #173: Use OpenShift compliant git/vcs annotations
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/**
* Copyright (c) 2019 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at:
*
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.jkube.kit.common.service;

import org.eclipse.jkube.kit.common.KitLogger;
import org.eclipse.jkube.kit.common.util.XMLUtil;
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;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.xpath.XPathExpressionException;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;

public class MigrateService {
private File projectBasedir;
private static final String POM_XML = "pom.xml";
private static final String FABRIC8 = "fabric8";
private static final String JKUBE = "jkube";
private static final String DEFAULT_FABRIC8_RESOURCE_FRAGMENT_DIRECTORY = "src/main/" + FABRIC8;
private static final String DEFAULT_RESOURCE_FRAGMENT_DIRECTORY = "src/main/" + JKUBE;
private static final String ARTIFACT_ID = "artifactId";
private static final String GROUP_ID = "groupId";
private static final String VERSION = "version";
private static final String FABRIC8_MAVEN_PLUGIN_ARTIFACT_ID = FABRIC8 + "-maven-plugin";
private static final String POM_PROJECT_PATH = "/project";
private static final String POM_PROFILES_PATH = POM_PROJECT_PATH + "/profiles";
private static final String POM_PLUGINS_PATH = "/build/plugins";
private static final String POM_PROPERTIES_PATH = "/properties";
private static final String POM_PLUGIN_PATH = "/plugin";
private KitLogger logger;

public MigrateService(File projectBaseDirectory, KitLogger logger) {
this.projectBasedir = projectBaseDirectory;
this.logger = logger;
}

public void migrate(String pluginGroupId, String pluginArtifactId, String pluginVersion) throws IOException, ParserConfigurationException, SAXException, TransformerException, XPathExpressionException {
File pomFile = getPomFile();
String pomContent = new String(Files.readAllBytes(pomFile.toPath()), StandardCharsets.UTF_8);
String modifiedPomContent = searchAndReplaceEnricherRefsInPomToJKube(pomContent);
Files.write(pomFile.toPath(), modifiedPomContent.getBytes(StandardCharsets.UTF_8));
if (pomContainsFMP(pomContent)) {
Document dom = XMLUtil.readXML(pomFile);

// Check Whether plugin is present in project.build.plugins
modifyFMPPluginSectionInsideBuild(dom, pluginGroupId, pluginArtifactId, pluginVersion);
// Check Whether plugin is present in project.profiles.build.plugins
modifyFMPSectionInsideProfile(dom, pluginGroupId, pluginArtifactId, pluginVersion);
// Rename all Fabric8 related properties to JKube
modifyFMPPropertiesInsidePom(dom);

XMLUtil.writeXML(dom, pomFile);
renameResourceFragmentDirectoryToJKube();
} else {
logger.warn("Unable to find Fabric8 Maven Plugin inside pom");
}
}

private String searchAndReplaceEnricherRefsInPomToJKube(String pomContent) {
pomContent = pomContent.replace("fmp-", JKUBE + "-");
pomContent = pomContent.replace("f8-", JKUBE + "-");

return pomContent;
}

private boolean pomContainsFMP(String pomContent) {
return pomContent.contains(FABRIC8_MAVEN_PLUGIN_ARTIFACT_ID);
}

private File getPomFile() {
return new File(projectBasedir, POM_XML);
}

private File getResourceFragmentDirectory(File projectBasedir) {
return new File(projectBasedir, DEFAULT_FABRIC8_RESOURCE_FRAGMENT_DIRECTORY);
}

private void modifyFMPPluginSectionInsideBuild(Document dom, String pluginGroupId, String pluginArtifactId, String pluginVersion) throws XPathExpressionException {
convertFMPNodeToJKube(dom, pluginGroupId, pluginArtifactId, pluginVersion, POM_PROJECT_PATH + POM_PLUGINS_PATH);
}

private void modifyFMPSectionInsideProfile(Document dom, String pluginGroupId, String pluginArtifactId, String pluginVersion) throws XPathExpressionException {
Node profilesNode = XMLUtil.getNodeFromDocument(dom, POM_PROFILES_PATH);
if (profilesNode != null) {
NodeList nodeList = profilesNode.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
convertFMPNodeToJKube(dom, pluginGroupId, pluginArtifactId, pluginVersion, POM_PROFILES_PATH + "/profile[" + i + "]" + POM_PLUGINS_PATH);
}
}
}

private void convertFMPNodeToJKube(Document dom, String pluginGroupId, String pluginArtifactId, String pluginVersion, String parentXPathExpression) throws XPathExpressionException {
Node fmpNode = XMLUtil.getNodeFromDocument(dom, parentXPathExpression + POM_PLUGIN_PATH + "[artifactId='" + FABRIC8_MAVEN_PLUGIN_ARTIFACT_ID + "']");
if (fmpNode != null) {
Element fmpNodeElem = (Element) fmpNode;
Node artifactNode = fmpNodeElem.getElementsByTagName(ARTIFACT_ID).item(0);
Node groupNode = fmpNodeElem.getElementsByTagName(GROUP_ID).item(0);
Node versionNode = fmpNodeElem.getElementsByTagName(VERSION).item(0);
logger.info("Found Fabric8 Maven Plugin in pom with version " + versionNode.getTextContent());
groupNode.setTextContent(pluginGroupId);
artifactNode.setTextContent(pluginArtifactId);
versionNode.setTextContent(pluginVersion);
}
}

private void renameResourceFragmentDirectoryToJKube() {
File resourceFragmentDir = getResourceFragmentDirectory(projectBasedir);
if (resourceFragmentDir.exists()) {
File jkubeResourceDir = new File(projectBasedir, DEFAULT_RESOURCE_FRAGMENT_DIRECTORY);
boolean isRenamed = resourceFragmentDir.renameTo(jkubeResourceDir);
if (!isRenamed) {
logger.warn("Unable to rename resource fragment directory in project");
} else {
logger.info("Renamed " + DEFAULT_FABRIC8_RESOURCE_FRAGMENT_DIRECTORY + " to " + DEFAULT_RESOURCE_FRAGMENT_DIRECTORY);
}
}
}

private void modifyFMPPropertiesInsidePom(Document dom) throws XPathExpressionException {
Node propertiesNode = XMLUtil.getNodeFromDocument(dom, POM_PROJECT_PATH + POM_PROPERTIES_PATH);
if (propertiesNode != null) {
NodeList nodeList = propertiesNode.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
Node property = nodeList.item(i);
if (property.getNodeName().contains(FABRIC8)) {
String nodeName = property.getNodeName();
nodeName = nodeName.replace(FABRIC8, JKUBE);
dom.renameNode(property, null, nodeName);
}
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/**
* Copyright (c) 2019 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at:
*
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.jkube.kit.common.util;

import org.w3c.dom.Document;
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 javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class XMLUtil {
private static List<String> featuresToDisable = Arrays.asList("http://apache.org/xml/features/nonvalidating/load-external-dtd",
"http://apache.org/xml/features/disallow-doctype-decl",
"http://xml.org/sax/features/external-general-entities",
"http://xml.org/sax/features/external-parameter-entities");

private XMLUtil() { }

public static Document createNewDocument() throws ParserConfigurationException {
DocumentBuilderFactory documentBuilderFactory = getDocumentBuilderFactory();
return documentBuilderFactory.newDocumentBuilder().newDocument();
}

public static Document readXML(File xmlFile) throws ParserConfigurationException, IOException, SAXException {
DocumentBuilderFactory documentBuilderFactory = getDocumentBuilderFactory();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();

return documentBuilder.parse(xmlFile);
}

public static void writeXML(Document document, File xmlFile) throws TransformerException {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
Transformer transformer = transformerFactory.newTransformer();
document.setXmlStandalone(true);
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(xmlFile);
transformer.transform(source, result);
}

public static Node getNodeFromDocument(Document doc, String xPathExpression) throws XPathExpressionException {
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
return (Node) xpath.compile(xPathExpression).evaluate(doc, XPathConstants.NODE);
}

public static String getNodeValueFromDocument(Document doc, String xPathExpression) throws XPathExpressionException {
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
return (String) xpath.compile(xPathExpression).evaluate(doc, XPathConstants.STRING);
}

private static DocumentBuilderFactory getDocumentBuilderFactory() throws ParserConfigurationException {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setAttribute(XMLConstants.FEATURE_SECURE_PROCESSING, true);
documentBuilderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
documentBuilderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
for (String feature : featuresToDisable) {
documentBuilderFactory.setFeature(feature, false);
}
documentBuilderFactory.setXIncludeAware(false);
documentBuilderFactory.setExpandEntityReferences(false);
return documentBuilderFactory;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/**
* Copyright (c) 2019 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at:
*
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.jkube.kit.common.service;

import mockit.Mocked;
import org.apache.commons.io.FileUtils;
import org.eclipse.jkube.kit.common.KitLogger;
import org.eclipse.jkube.kit.common.util.XMLUtil;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.w3c.dom.Document;

import java.io.File;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class MigrateServiceTest {
@Mocked
KitLogger logger;

@Rule
public TemporaryFolder folder = new TemporaryFolder();

@Test
public void testPomPluginMigrationInBuild() throws Exception {
// Given
File projectPom = new File(getClass().getResource("/test-project/pom.xml").toURI());
File pomFile = folder.newFile("pom.xml");
FileUtils.copyFile(projectPom, pomFile);
MigrateService migrateService = new MigrateService(folder.getRoot(), logger);

// When
migrateService.migrate("org.eclipse.jkube", "kubernetes-maven-plugin", "1.0.0-SNAPSHOT");

// Then
Document document = XMLUtil.readXML(pomFile);
assertTrue(pomFile.exists());
assertEquals("org.eclipse.jkube", XMLUtil.getNodeValueFromDocument(document, "/project/build/plugins/plugin[2]/groupId"));
assertEquals("kubernetes-maven-plugin", XMLUtil.getNodeValueFromDocument(document, "/project/build/plugins/plugin[2]/artifactId"));
assertEquals("1.0.0-SNAPSHOT", XMLUtil.getNodeValueFromDocument(document, "/project/build/plugins/plugin[2]/version"));
}


@Test
public void testPomPluginMigrationInProfile() throws Exception {
// Given
File projectPom = new File(getClass().getResource("/test-project-profile/pom.xml").toURI());
File pomFile = folder.newFile("pom.xml");
FileUtils.copyFile(projectPom, pomFile);
MigrateService migrateService = new MigrateService(folder.getRoot(), logger);

// When
migrateService.migrate("org.eclipse.jkube", "kubernetes-maven-plugin", "1.0.0-SNAPSHOT");

// Then
Document document = XMLUtil.readXML(pomFile);
assertTrue(pomFile.exists());
assertEquals("org.eclipse.jkube", XMLUtil.getNodeValueFromDocument(document, "/project/profiles/profile[1]/build/plugins/plugin[1]/groupId"));
assertEquals("kubernetes-maven-plugin", XMLUtil.getNodeValueFromDocument(document, "/project/profiles/profile[1]/build/plugins/plugin[1]/artifactId"));
assertEquals("1.0.0-SNAPSHOT", XMLUtil.getNodeValueFromDocument(document, "/project/profiles/profile[1]/build/plugins/plugin[1]/version"));
}

@Test
public void testProjectResourceFragmentDirectoryRename() throws Exception {
// Given
File projectPom = new File(getClass().getResource("/test-project-profile/pom.xml").toURI());
File pomFile = folder.newFile("pom.xml");
folder.newFolder("src", "main", "fabric8");
FileUtils.copyFile(projectPom, pomFile);
MigrateService migrateService = new MigrateService(folder.getRoot(), logger);

// When
migrateService.migrate("org.eclipse.jkube", "kubernetes-maven-plugin", "1.0.0-SNAPSHOT");

// Then
Document document = XMLUtil.readXML(pomFile);
assertTrue(pomFile.exists());
assertTrue(new File(folder.getRoot(), "src/main/jkube").exists());
assertEquals("org.eclipse.jkube", XMLUtil.getNodeValueFromDocument(document, "/project/profiles/profile[1]/build/plugins/plugin[1]/groupId"));
assertEquals("kubernetes-maven-plugin", XMLUtil.getNodeValueFromDocument(document, "/project/profiles/profile[1]/build/plugins/plugin[1]/artifactId"));
assertEquals("1.0.0-SNAPSHOT", XMLUtil.getNodeValueFromDocument(document, "/project/profiles/profile[1]/build/plugins/plugin[1]/version"));
}
}
Loading

0 comments on commit ad7b9c8

Please sign in to comment.