Skip to content

Instantly share code, notes, and snippets.

@goldmann
Created May 24, 2011 14:46
Show Gist options
  • Save goldmann/988842 to your computer and use it in GitHub Desktop.
Save goldmann/988842 to your computer and use it in GitHub Desktop.
require 'rubygems'
require 'net/http'
require "net/https"
require "uri"
require 'rexml/document'
include REXML
require 'logger'
require 'yaml'
require 'fileutils'
REPOSITORY = "https://repository.jboss.org/nexus"
#REPOSITORY = "http://repository.sonatype.org"
CACHE_DIR = "poms"
abort "Please specify Maven groupId and artifactID (and optionally version), for example: ruby #{File.basename(__FILE__)} org.jboss jboss-parent 6-beta-2" if ARGV.size < 2
@log = Logger.new(STDERR)
@packaged = {}
# just because I don't like it :)
SKIP = [
"javax.servlet.jsp:jsp-api",
"javax.servlet.jsp.jstl:jstl",
"org.eclipse.wst.sse:core",
"org.eclipse.wst.css:core",
"org.jboss.javaee:jboss-jacc-api_JDK4",
"woodstox:wstx-asl",
"${pom.groupId}:activeio-core", #activemq
"org.apache.directory.server:apacheds-core",
"commons-convert:commons-convert", # what's this?
"${pom.groupId}:org.apache.felix.framework", # apache felix
"org.apache.felix:org.apache.felix.main",
"org.subethamail:subethasmtp", # wtf?
"ch.qos.logback:logback-classic",
"com.sleepycat:je",
"${saaj.impl.groupId}:${saaj.impl.artifactId}",
"org.apache.ws.commons.axiom:axiom-impl",
"org.apache.cxf:cxf-xjc-dv",
"org.apache.neethi:neethi",
"org.apache.cxf:cxf-rt-transports-local",
"${cxf.stax.impl.groupId}:${cxf.stax.impl.artifactId}",
"org.springframework:${cxf.spring.mock}",
"org.apache.felix:org.apache.felix.configadmin",
"${pom.groupId}:org.osgi.core",
"${pom.groupId}:org.osgi.compendium",
"org.apache.felix:org.apache.felix.scr",
"org.apache.felix:org.apache.felix.bundlerepository",
"org.apache.santuario:xmlsec",
"org.resteasy:titan-cruise",
"org.jboss.xnio:xnio-testing-support",
"org.eclipse.core:resources",
"${project.groupId}:jboss-as-connector",
"${project.groupId}:jboss-as-ee",
"${project.groupId}:jboss-as-server",
"${project.groupId}:jboss-as-transactions",
"${javax.ejb.groupId}:${javax.ejb.artifactId}",
"${javax.ejb.groupId}:${javax.ejb.artifactId}",
"${javax.ejb.groupId}:${javax.ejb.artifactId}",
"${javax.interceptor.groupId}:${javax.interceptor.artifactId}",
"${project.groupId}:jboss-ejb3-effigy-api",
"${project.groupId}:jboss-ejb3-effigy-common",
"${javax.ejb.groupId}:${javax.ejb.artifactId}",
"${javax.interceptor.groupId}:${javax.interceptor.artifactId}",
"${javax.transaction.groupId}:${javax.transaction.artifactId}",
"${project.groupId}:jboss-ejb3-tx2-spi",
"org.eclipse.core:runtime",
"org.eclipse.core:filesystem",
"org.eclipse:text",
"org.eclipse.team:core",
"com.lowagie:itext",
"jfree:jcommon",
"jfree:jfreechart",
"clipse:jdtcore",
"jruby:jruby",
"com.oracle:oc4j",
"org.jboss.as:jboss-as-managed-beans",
"org.jboss.as:jboss-as-testsuite-protocol-base",
"org.jboss.as:jboss-as-testsuite-protocol-modules",
"${project.groupId}:wagon-http-shared",
"${pom.groupId}:javax.servlet",
"eclipse:jdtcore",
]
def get_body(url)
@log.debug "Reading URL #{url}..."
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
if uri.scheme == 'https'
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
request = Net::HTTP::Get.new(uri.request_uri)
resp = http.request(request)
unless ['200', '301'].include? resp.code
@log.error "Invalid response: #{resp.code}"
abort
end
@log.debug "Data received."
if resp.header['location'].nil?
resp.body
else
get_body(resp.header['location'])
end
end
def read_dependencies(indent, properties, group_id, artifact_id, version = nil)
return if @resolved.include?("#{group_id}:#{artifact_id}")
if SKIP.include?("#{group_id}:#{artifact_id}")
puts "#{' ' * indent} !! => #{group_id}:#{artifact_id}:#{version} => SKIPPING"
return
end
if @packaged.include?("#{group_id}:#{artifact_id}")
puts "#{' ' * indent} !! => #{group_id}:#{artifact_id}:#{version} => #{@packaged["#{group_id}:#{artifact_id}"]}"
return
else
potential_providers = `repoquery "*#{artifact_id}*"`.to_a
potential_providers.each {|p| p.chomp!}
unless potential_providers.empty?
puts "#{' ' * indent} !! => #{group_id}:#{artifact_id}:#{version} => #{potential_providers.join(" or ")}"
@packaged["#{group_id}:#{artifact_id}"] = potential_providers.join(" or ")
return
end
puts "#{' ' * indent} | #{group_id}:#{artifact_id}:#{version}"
end
v = version.nil? ? 'latest' : version
cached_pom = "#{CACHE_DIR}/#{group_id}/#{artifact_id}/#{v}/pom.xml"
if File.exists?(cached_pom)
@log.debug "Reading cached POM: #{cached_pom}..."
body = File.read(cached_pom)
else
url = "#{REPOSITORY}/service/local/data_index?g=#{group_id}&a=#{artifact_id}"
url << "&v=#{version}" unless version.nil?
@log.info "Getting information about #{group_id}:#{artifact_id}:#{version}..."
begin
body = get_body(url)
doc = REXML::Document.new( body )
rescue
@log.error "Error while getting info for #{"#{group_id}:#{artifact_id}:#{version}"}, skipping..."
@errors << "#{group_id}:#{artifact_id}"
return
end
artifact = nil
XPath.each( doc, "//data/artifact" ) do |a|
next if a.elements['pomLink'].nil? or a.elements['pomLink'].text.nil?
artifact = a
break
end
if artifact.nil?
@log.error "POM cannot be found for #{"#{group_id}:#{artifact_id}:#{version}"}, skipping..."
@errors << "#{group_id}:#{artifact_id}"
return
end
pom_link = artifact.elements["pomLink"].text
@log.debug "Reading POM: #{pom_link}..."
body = get_body(pom_link)
FileUtils.mkdir_p(File.dirname(cached_pom))
File.open(cached_pom, 'w') {|f| f.write(body) }
end
doc = REXML::Document.new( body )
properties = {}
XPath.each( doc, "//project/properties/*" ) do |prop|
properties[prop.name] = prop.text
end
['version', 'groupId', 'artifactId'].each do |prop|
e = XPath.first( doc, "/project/#{prop}" )
properties["project.#{prop}"] = e.text unless e.nil?
properties["pom.#{prop}"] = e.text unless e.nil?
properties[prop] = e.text unless e.nil?
end
properties.each do |key, value|
next if value.nil?
body.gsub!("${#{key}}", value)
end
parent = XPath.first( doc, "/project/parent" )
unless parent.nil?
body.gsub!('${project.parent.groupId}', parent.elements['groupId'].text)
body.gsub!('${project.parent.artifactId}', parent.elements['artifactId'].text)
body.gsub!('${project.parent.version}', parent.elements['version'].text)
end
doc = REXML::Document.new( body )
@resolved << "#{group_id}:#{artifact_id}"
XPath.each( doc, "//plugins/plugin" ) do |p|
plugin = { :artifact_id => p.elements['artifactId'].text}
plugin[:version] = p.elements['version'].text unless p.elements['version'].nil?
plugin[:group_id] = p.elements['groupId'].text unless p.elements['groupId'].nil?
end
XPath.each( doc, "//dependencies/dependency" ) do |d|
next if d.elements['artifactId'].nil?
dependency = {:artifact_id => d.elements['artifactId'].text, :scope => 'compile'}
dependency[:group_id] = d.elements['groupId'].text unless d.elements['groupId'].nil?
dependency[:version] = d.elements['version'].text unless d.elements['version'].nil?
dependency[:scope] = d.elements['scope'].text unless d.elements['scope'].nil?
next if dependency[:scope] == 'system'
dependency[:version] = nil if dependency[:version] =~ /^\$\{/
read_dependencies(indent+2, properties, dependency[:group_id], dependency[:artifact_id], dependency[:version])
end
end
@errors = []
@resolved = []
read_dependencies(0, {}, ARGV[0], ARGV[1], ARGV[2])
puts "ERRORS"
@errors.each do |e|
puts " \"#{e}\","
end
puts "PACKAGED"
@packaged.each do |k,v|
puts " \"#{k}\" => \"#{v}\","
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment