# This class will handle all the reactor-operation # class ReactorHandler @@xml_file @@cordinateArr @@flag = false @@projectsWithExternalConfiguration = Array.new @@allProjectRepos = Array.new # This api will generate effective-pom and implements flatten out process # # If parent tag is not prersent then effective-pom will not be generated # def createEffectivePom(project_directory_path, externalPomUrl, isMBP = false) reactorProjectPOM = Dir.getwd + "/pom.xml" if (File.exists?(reactorProjectPOM)) reactorProjectDoc = parse_xml_from_file(reactorProjectPOM) reactorProjectDoc.css("repositories/repository").each do |eachRepo| eachUrl = eachRepo.at_css("url").text eachUrl = eachUrl.end_with?("/") ? eachUrl.chop : eachUrl if !(@@allProjectRepos.include? eachUrl) @@allProjectRepos.push(eachUrl) end end end eachModuleArr = Array.new if isMBP eachModuleArr.push("#{project_directory_path}/pom.xml") else eachModuleArr = fetchGidArtifactIdAndVersionFromChildModule(project_directory_path, false) end parentPomHandler = ParentPomHandler.new cordinatesArr = nil if (!externalPomUrl.nil?) and (externalPomUrl.include? "https://" or externalPomUrl.include? "http://") cordinatesArr = parentPomHandler.makeCordinateFromUrl(externalPomUrl) end eachModuleArr.each do |eachPom| isIdentical = false pom_document = parse_xml_from_file(eachPom) if tag_exists?("parent", pom_document) @@cordinateArr = parentPomHandler.fetch_mbp_cordinates_found_in_ancestor(pom_document) if ((@@cordinateArr.length == 0) and ((!externalPomUrl.nil?) and (externalPomUrl.include? "https://" or externalPomUrl.include? "http://"))) orginalCordinateArr = parentPomHandler.makeOriginalPomUrl(pom_document) isIdentical = parentPomHandler.compareTwoCordinatesArr(cordinatesArr, orginalCordinateArr) elsif (@@cordinateArr.length > 0) isIdentical = true end if !isIdentical eachPomPath = eachPom.sub("/pom.xml", "") Dir.chdir(eachPomPath) { result = `mvn help:effective-pom -Doutput=effective_pom.xml` puts result # Maven out-put generate_temp_xml() @@projectsWithExternalConfiguration.push(eachPomPath) basicInfoHandler = BasicInfoHandler.new basicInfoHandler.handleGrpAndArtifact(eachPomPath) basicInfoHandler.handleModelVersion(eachPomPath) basicInfoHandler.handleInceptionYearDescAndOrganization(eachPomPath) basicInfoHandler.handleProjectUrl(eachPomPath) basicInfoHandler.handleDevelopersContributorsMailingLists(eachPomPath) basicInfoHandler.handleScmIssueManagementCiManagement(eachPomPath) basicInfoHandler.handleDistributionManagement(eachPomPath) basicInfoHandler.handleRepositories(eachPomPath) basicInfoHandler.handlePluginRepositories(eachPomPath) pluginHandler = PluginHandler.new pluginHandler.addBuildTag() pluginHandler.addReportingTag() propertyHandler = PropertyHandler.new propertyHandler.handleProperties(eachPomPath) dependencyHandler = DependencyHandler.new dependencyHandler.projectPomDependencyHandler() tempDependencyList = dependencyHandler.getTempDependencyList() childDependencyMap = dependencyHandler.getOriginalDependencyMap() parentDependencyMap = dependencyHandler.getImmediateParentDependencyMap() grandParentDependencyMap = dependencyHandler.getgrandParentDependencyMap() dependencyHandler.findPlaceHolderWithinPoms(tempDependencyList, childDependencyMap, parentDependencyMap, grandParentDependencyMap) project_end() tempPropertyMap = propertyHandler.getTempPropertyMap() childPropertyMap = propertyHandler.getOriginalPropertyMap() parentPropertyMap = propertyHandler.getImidiateParentPropertyMap() grandparentPropertyMap = propertyHandler.getgrandParentPropertyMap() propertyHandler.findPlaceHolderWithinProperties(tempPropertyMap, childPropertyMap, parentPropertyMap, grandparentPropertyMap) pluginHandler.removePluginManagementTag() pluginList = pluginHandler.getGrpAndArtifactIdOfPlugins() pluginHandler.compareWithOriginalPomPlugin(pluginList) pluginHandler.compareWithParentPomPlugin(pluginList) pluginHandler.compareWithGrandParentPomPlugin(pluginList) pluginHandler.removeExtraTag("build") #Reporting plugin reportSwitch = "reporting" pluginList = pluginHandler.getGrpAndArtifactIdOfPlugins(reportSwitch) pluginHandler.compareWithOriginalPomPlugin(pluginList, reportSwitch) pluginHandler.compareWithParentPomPlugin(pluginList, reportSwitch) pluginHandler.compareWithGrandParentPomPlugin(pluginList, reportSwitch) pluginHandler.removeExtraTag("reporting") #Site and eclipse plugin handleSiteAndEclipsePlugin(eachPomPath) closeFileObj() basicInfoHandler.renamePom(eachPomPath) basicInfoHandler.renameTemp(eachPomPath) puts "Original pom is reanamed to pom_back.xml" } else puts "Provided parent URL and external configuration are same" end else eachPomPath = eachPom.sub("/pom.xml", "") index = eachPomPath.rindex("/") projectName = eachPomPath[index + 1, eachPomPath.length - 1] puts "No parent found for #{projectName} project" end end puts "Effective pom generation is completed" end def getReactPOMRepos() return @@allProjectRepos end def handleSiteAndEclipsePlugin(project_directory_path) siteAndEclipsePluginHandler = SiteAndEclipsePluginHandler.new siteAndEclipsePluginHandler.managePlugins(project_directory_path, "org.apache.maven.plugins:maven-site-plugin") siteAndEclipsePluginHandler.managePlugins(project_directory_path, "org.apache.maven.plugins:maven-eclipse-plugin") end def makeReator(project_directory_path) mvnReactorization = MvnReactorization.new mvnReactorization.makeReactor(project_directory_path) end def manageDepedency(project_directory_path) dependencyManagementHandler = DependencyManagementHandler.new dependencyManagementHandler.handleDependencyManagement(project_directory_path) end def managePlugins(project_directory_path) pluginManagementHandler = PluginManagementHandler.new pluginManagementHandler.comparePluginManagementFromChildModule(project_directory_path) pluginManagementHandler.handlePluginManagement(project_directory_path) pluginManagementHandler.findCommonPluginFromPluginManagement(project_directory_path) end def plugiConfigHandler(project_directory_path) pluginConfigurationHandler = PluginConfigurationHandler.new pluginConfigurationHandler.mergePluginConfiguration(project_directory_path, @@projectsWithExternalConfiguration) end def mergeRepository(project_directory_path) mergeRepository = MergeRepository.new #Repositories commonUrlList = mergeRepository.findCommonRepos(project_directory_path, "repositories/repository") rootRepo = mergeRepository.makeFullRepoFromCommonRepo(project_directory_path, "repositories/repository", commonUrlList) mergeRepository.addRepoIntoReactorPom(project_directory_path, rootRepo, "repositories") mergeRepository.deleteRepoFromChildModule(project_directory_path, "repositories") mergeRepository.renameDuplicateRepoId(project_directory_path, "repositories/repository") #PluginRepositories commonUrlList = mergeRepository.findCommonRepos(project_directory_path, "pluginRepositories/pluginRepository") rootRepo = mergeRepository.makeFullRepoFromCommonRepo(project_directory_path, "pluginRepositories/pluginRepository", commonUrlList) mergeRepository.addRepoIntoReactorPom(project_directory_path, rootRepo, "pluginRepositories") mergeRepository.deleteRepoFromChildModule(project_directory_path, "pluginRepositories") mergeRepository.renameDuplicateRepoId(project_directory_path, "pluginRepositories/pluginRepository") puts "Renamed repo is done" end def handleInterDependency(project_directory_path) interDependencyHandler = InterDependencyHandler.new interDependencyHandler.handleInterDependecy(project_directory_path) end def handleDeveloperAndContributors(project_directory_path) developerAndContributors = DeveloperAndContributors.new commonDevelopers = developerAndContributors.findCommonDevelopers(project_directory_path, "developers/developer") developersAndContributorsList = developerAndContributors.mergeDeveloperAndContributors(project_directory_path, commonDevelopers, "developers/developer") developerAndContributors.addDeveloperAndContributersInReator(project_directory_path, developersAndContributorsList, "developers") developerAndContributors.removeCommonDevelopersAndContributorsFromChild(project_directory_path, commonDevelopers, "developers/developer") #developerAndContributors.removeEmptyTags(project_directory_path,"developers") #Contributors commonDevelopers = developerAndContributors.findCommonDevelopers(project_directory_path, "contributors/contributor") developersAndContributorsList = developerAndContributors.mergeDeveloperAndContributors(project_directory_path, commonDevelopers, "contributors/contributor") developerAndContributors.addDeveloperAndContributersInReator(project_directory_path, developersAndContributorsList, "contributors") developerAndContributors.removeCommonDevelopersAndContributorsFromChild(project_directory_path, commonDevelopers, "contributors/contributor") #developerAndContributors.removeEmptyTags(project_directory_path,"contributors") end def sortPomExecutor() pluginManagementHandler = PluginManagementHandler.new pluginManagementHandler.executeShortPom() end def handleTeamSpecificParent(project_directory_path, externalPomUrl) if ((!externalPomUrl.nil?) and (externalPomUrl.include? "https://" or externalPomUrl.include? "http://")) parentPomHandler = ParentPomHandler.new parentPomHandler.setParentInreactor(project_directory_path, externalPomUrl) end end # This api will return the list of projects path of individual projects # def fetchGidArtifactIdAndVersionFromChildModule(project_directory_path, retDecision) alldir = Dir.entries(project_directory_path) pomFilePath = Array.new alldir.each do |fileLtst| if File.directory? fileLtst if !(File.basename(fileLtst) == "." || File.basename(fileLtst) == "..") innerFileLtst = Dir.entries(fileLtst) innerFileLtst.each do |eachInner| fileName = File.basename(eachInner) if fileName == "pom.xml" pomFilePath.push("#{File.expand_path(fileLtst)}/#{fileName}") end end end end end if (retDecision) mvnReactorization = MvnReactorization.new finalSnapShot = mvnReactorization.findHighestVersionOfPom(pomFilePath) fullDetails = mvnReactorization.getDetails(pomFilePath[0]) fullDetails[2] = finalSnapShot return fullDetails else return pomFilePath end end # Adding parent POM path def moveCommonProperties (project_directory_path, parent_pom_path) if parent_pom_path.to_s.strip.empty? moveCommonPropertiesToRootPom = MoveCommonPropertiesToRootPom.new commonProperties = moveCommonPropertiesToRootPom.findCommonProperties(project_directory_path) moveCommonPropertiesToRootPom.writeCommonPropertiesToReactorPom(project_directory_path,commonProperties) moveCommonPropertiesToRootPom.removeCommonPropertiesfromModules(project_directory_path,commonProperties) else propertyManager = PropertyManager.new propertyManager.restructure(project_directory_path, parent_pom_path) end end def createDistributionManagmentInReactorPom(project_directory_path, externalPomUrl) moveDistributionManagement = MoveDistributionManagement.new moveDistributionManagement.moveDistributionManagementFromFirstModule(project_directory_path, externalPomUrl) end def removeEmptyTags(project_directory_path) pomPathArr = fetchGidArtifactIdAndVersionFromChildModule(project_directory_path, false) mvnReactorization = MvnReactorization.new pomPathArr.each do |eachPomPath| pom_document = parse_xml_from_file(eachPomPath) clean(pom_document.at("project")) mvnReactorization.write_nokogiri_to_xml(eachPomPath, pom_document) end end def clean(node) node.children.each do |child| clean(child) child.remove if child.content.gsub(/\s+/, "").empty? end end def dmpmForexternalConfiguration(project_directory_path, externalPomUrl) if @@flag dmAndPMManagementForExternalConfiguration = DMAndPMManagementForExternalConfiguration.new cordinateArr = dmAndPMManagementForExternalConfiguration.getParentCordinates(externalPomUrl, "dependency") dmAndPMManagementForExternalConfiguration.comparetheVersionWithParent(project_directory_path, cordinateArr, "dependencies/dependency") dmAndPMManagementForExternalConfiguration.comparetheVersionWithParent(project_directory_path, cordinateArr, "dependencyManagement/dependencies/dependency") cordinateArr = dmAndPMManagementForExternalConfiguration.getParentCordinates(externalPomUrl, "plugins") dmAndPMManagementForExternalConfiguration.comparethePluginVersionWithParent(project_directory_path, cordinateArr, "project/build/plugins/plugin") dmAndPMManagementForExternalConfiguration.comaprePluginVersionWihReactorPom(project_directory_path, cordinateArr, "project/build/pluginManagement/plugins/plugin") end end def handleTeamSpecificParent(project_directory_path, externalConfigUrl) parentPomHandler = ParentPomHandler.new if (!externalConfigUrl.nil?) begin Nokogiri::HTML(open(externalConfigUrl)) #This is to validate the url rescue raise "Parent POM URL is not valid !!!" end cordinatesArr = parentPomHandler.makeCordinateFromUrl(externalConfigUrl) @@flag = parentPomHandler.putParentInReactorPom(cordinatesArr, project_directory_path) end end def validateProjectsEligiblity(project_directory_path) validateProjects = ValidateProjects.new validateProjects.checkEligiblityForReactorization(project_directory_path) end # This api checks a particular tag present or not and return boolean value # def tag_exists?(tag, pom_nokogiri, data = nil) temp = pom_nokogiri.dup temp.remove_namespaces! if data.nil? # Searching only for tag when data is not supplied !temp.xpath("//#{tag}").empty? else # Searching for entire the node with given tag and data at_parameter = "#{tag}:contains('#{data}')" found_match = temp.at(at_parameter) # Confirming that whole string matches as contains can # report success if even a part of string matches !found_match.nil? && found_match.text.strip == data end rescue Nokogiri::XML::XPath::SyntaxError, RuntimeError, NoMethodError, TypeError # Rescue is hit only when # Supplied tag is either empty or nil or # Supplied pom_nokogiri is nil raise "Either tag or pom object supplied is empty or nil" end # This api generate blank temp.xml inside the individual projects # def generate_temp_xml() dest = "temp.xml" File.write("temp.xml", "") end def project_end() tempXml = "temp.xml" file = File.open(tempXml) contents = file.read if !contents.include? "" File.write(tempXml, "", File.size(tempXml), mode: "a") end end # This api is used to create dom object of pom # def parse_xml_from_file(file_path) @@xml_file = File.open(file_path) Nokogiri::XML(@@xml_file, &:strict) rescue Errno::ENOENT raise Errno::ENOENT, "Couldn't locate a file at that path, please check the path!" rescue Nokogiri::XML::SyntaxError => e raise Nokogiri::XML::SyntaxError, "The following errors occurred while parsing your XML file: \n" + e.message end def closeFileObj() @@xml_file.close @@xml_file.closed? end def removeTagsWithHardCodedPath(project_directory_path) pomList = fetchGidArtifactIdAndVersionFromChildModule(project_directory_path, false) projectDirPath = project_directory_path.gsub('\\', "/") pomList.each do |eachPomPath| pomDocument = parse_xml_from_file(eachPomPath) pomDocument.css("project").each do |plugin| plugin.xpath("//*[not(child::*)]").each do |eachLeafNode| leafNodeText = eachLeafNode.text().gsub('\\', "/") if leafNodeText.include?(projectDirPath) eachLeafNode.remove end end end mvnReactorization = MvnReactorization.new mvnReactorization.write_nokogiri_to_xml(eachPomPath, pomDocument) end end def checkIdenticalParent(project_directory_path) eachModuleArr = fetchGidArtifactIdAndVersionFromChildModule(project_directory_path,false) validateProjects = ValidateProjects.new cordinateArr = Array.new cordinates = validateProjects.checkEligiblityForReactorization(project_directory_path) if !cordinates.nil? cordinates.each do |key,indx| cordinatesArr = key.split(":") cordinateArr.push(cordinatesArr[0]) cordinateArr.push(cordinatesArr[1]) cordinateArr.push(cordinatesArr[2]) end if cordinateArr.length == 3 eachModuleArr.each do |eachPom| pom_document = parse_xml_from_file(eachPom) if !pom_document.at("project/parent").nil? pom_document.at("project/parent").remove File.write(eachPom,pom_document) end end end end if cordinateArr.length==3 puts "#{cordinateArr[0]}:#{cordinateArr[1]}:#{cordinateArr[2]} parent is removed from child modules" end return cordinateArr end def addParentInReactorPom(project_directory_path,cordinateArr) if cordinateArr.length == 3 reactorPom = "#{project_directory_path}/pom.xml" pom_document = parse_xml_from_file(reactorPom) nokObj = Nokogiri::XML::Node projectNode = pom_document.at("project") grpIdNode = nokObj.new("groupId",projectNode) grpIdNode.content=cordinateArr[0] artifactIdNode = nokObj.new("artifactId",projectNode) artifactIdNode.content = cordinateArr[1] versionNode = nokObj.new("version",projectNode) versionNode.content = cordinateArr[2] parentNode = nokObj.new("parent",projectNode) parentNode.add_child(grpIdNode) parentNode.add_child(artifactIdNode) parentNode.add_child(versionNode) modelVersionNode = pom_document.at_css('modelVersion') modelVersionNode.add_previous_sibling("\n") modelVersionNode.add_previous_sibling(parentNode.to_xml) File.write(reactorPom, pom_document.to_xml) puts "Parent tag is added in reactor pom" end end end