Permalink
Browse files

Rewritten version of the maven_gemify plugin that leverages the funct…

…ion of the dependency plugin by writing a pom.xml file dynamically.
  • Loading branch information...
ANithian committed Feb 8, 2012
1 parent 54b6240 commit a29d4550dfb2f24372bf6e60f00e633ff92d5d64
Showing with 337 additions and 0 deletions.
  1. +337 −0 lib/bundler/maven_gemify2.rb
@@ -0,0 +1,337 @@
+require 'uri'
+require 'tempfile'
+require 'fileutils'
+require 'rubygems'
+require 'rubygems/builder'
+require 'rubygems/installer'
+require 'set'
+
+# A modified maven_gemify
+module Gem
+
+ class Maven3NotFound < StandardError; end
+
+ #This is some of the worst stuff. I had to this because bundler will search
+ #the index of specifications based on the name given in the GemFile which
+ #includes the "mvn:<groupid>:<artifactid>" syntax. The rest of the ruby gem world
+ #doesn't work on this name so I have to constantly convert to the maven name when
+ #necessary for certain methods
+ class MavenSpec < Gem::Specification
+ alias_method :old_full_name, :full_name
+ alias_method :old_full_gem_path, :full_gem_path
+
+ alias_method :old_ruby, :to_ruby
+
+ def to_ruby
+ old_name=self.name
+ self.name=Maven::Gemify2.mname(old_name)
+ return_results = old_ruby
+ self.name=old_name
+ return_results
+ end
+
+ def full_name
+ if @full_name.nil?
+ #Needs to use the maven_name here not the gemname which has the "mvn:" stuff
+ old_name=self.name
+ self.name=Maven::Gemify2.mname(old_name)
+ return_path = old_full_name
+ self.name=old_name
+ @full_name=return_path
+ end
+ @full_name
+ end
+
+ def full_gem_path
+ if @full_gem_path.nil?
+ #Needs to use the maven_name here not the gemname which has the "mvn:" stuff
+ old_name=self.name
+ self.name=Maven::Gemify2.mname(old_name)
+ return_path = old_full_gem_path
+ self.name=old_name
+ @full_gem_path=return_path
+ end
+ @full_gem_path
+ end
+
+ end
+
+ module Maven
+
+ class Gemify2
+ attr_reader :repositories
+
+ #repositories should be an array of urls
+ def initialize(*repositories)
+ maven # ensure maven initialized
+ @repositories = Set.new
+ if repositories.length > 0
+ @repositories.merge([repositories].flatten)
+ end
+
+ end
+
+ def add_repository(repository_url)
+ @repositories << repository_url
+ end
+
+ @@verbose = false
+ def self.verbose?
+ @@verbose || $DEBUG
+ end
+ def verbose?
+ self.class.verbose?
+ end
+ def self.verbose=(v)
+ @@verbose = v
+ end
+
+ private
+ def self.maven_config
+ @maven_config ||= Gem.configuration["maven"] || {}
+ end
+ def maven_config; self.class.maven_config; end
+
+ def self.java_imports
+ %w(
+ org.codehaus.plexus.classworlds.ClassWorld
+ org.codehaus.plexus.DefaultContainerConfiguration
+ org.codehaus.plexus.DefaultPlexusContainer
+ org.apache.maven.Maven
+ org.apache.maven.repository.RepositorySystem
+ org.apache.maven.execution.DefaultMavenExecutionRequest
+ org.apache.maven.artifact.repository.MavenArtifactRepository
+ org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout
+ org.apache.maven.artifact.repository.ArtifactRepositoryPolicy
+ javax.xml.stream.XMLStreamWriter
+ javax.xml.stream.XMLOutputFactory
+ javax.xml.stream.XMLStreamException
+ ).each {|i| java_import i }
+ end
+
+ def self.create_maven
+ require 'java' # done lazily, so we're not loading it all the time
+ bin = nil
+ if ENV['M2_HOME'] # use M2_HOME if set
+ bin = File.join(ENV['M2_HOME'], "bin")
+ else
+ ENV['PATH'].split(File::PATH_SEPARATOR).detect do |path|
+ mvn = File.join(path, "mvn")
+ if File.exists?(mvn)
+ if File.symlink?(mvn)
+ link = File.readlink(mvn)
+ if link =~ /^\// # is absolute path
+ bin = File.dirname(File.expand_path(link))
+ else # is relative path so join with dir of the maven command
+ bin = File.dirname(File.expand_path(File.join(File.dirname(mvn), link)))
+ end
+ else # is no link so just expand it
+ bin = File.expand_path(path)
+ end
+ else
+ nil
+ end
+ end
+ end
+ bin = "/usr/share/maven2/bin" if bin.nil? # OK let's try debian default
+ if File.exists?(bin)
+ @mvn = File.join(bin, "mvn")
+ if Dir.glob(File.join(bin, "..", "lib", "maven-core-3.*jar")).size == 0
+ begin
+ gem 'ruby-maven', ">=0"
+ bin = File.dirname(Gem.bin_path('ruby-maven', "rmvn"))
+ @mvn = File.join(bin, "rmvn")
+ rescue LoadError
+ bin = nil
+ end
+ end
+ else
+ bin = nil
+ end
+ raise Gem::Maven3NotFound.new("can not find maven3 installation. install ruby-maven with\n\n\tjruby -S gem install ruby-maven\n\n") if bin.nil?
+
+ warn "Using Maven install at #{bin}" if verbose?
+
+ boot = File.join(bin, "..", "boot")
+ lib = File.join(bin, "..", "lib")
+ ext = File.join(bin, "..", "ext")
+ (Dir.glob(lib + "/*jar") + Dir.glob(boot + "/*jar")).each {|path| require path }
+
+ java.lang.System.setProperty("classworlds.conf", File.join(bin, "m2.conf"))
+ java.lang.System.setProperty("maven.home", File.join(bin, ".."))
+ java_imports
+
+ class_world = ClassWorld.new("plexus.core", java.lang.Thread.currentThread().getContextClassLoader());
+ config = DefaultContainerConfiguration.new
+ config.set_class_world class_world
+ config.set_name "ruby-tools"
+ container = DefaultPlexusContainer.new(config);
+ @@execution_request_populator = container.lookup(org.apache.maven.execution.MavenExecutionRequestPopulator.java_class)
+
+ @@settings_builder = container.lookup(org.apache.maven.settings.building.SettingsBuilder.java_class )
+ container.lookup(Maven.java_class)
+ end
+
+ def self.maven
+ @maven ||= create_maven
+ end
+ def maven; self.class.maven; end
+
+ def self.temp_dir
+ @temp_dir ||=
+ begin
+ d=Dir.mktmpdir
+ at_exit {FileUtils.rm_rf(d.dup)}
+ d
+ end
+ end
+
+ def temp_dir
+ self.class.temp_dir
+ end
+
+ def execute(goals, pomFile,props = {})
+ request = DefaultMavenExecutionRequest.new
+ request.set_show_errors(true)
+
+ props.each do |k,v|
+ request.user_properties.put(k.to_s, v.to_s)
+ end
+ request.set_goals(goals)
+ request.set_logging_level 0
+ request.setPom(java.io.File.new(pomFile))
+ if verbose?
+ active_profiles = request.getActiveProfiles.collect{ |p| p.to_s }
+ puts "active profiles:\n\t[#{active_profiles.join(', ')}]"
+ puts "maven goals:"
+ request.goals.each { |g| puts "\t#{g}" }
+ puts "system properties:"
+ request.getUserProperties.map.each { |k,v| puts "\t#{k} => #{v}" }
+ puts
+ end
+ out = java.lang.System.out
+ string_io = java.io.ByteArrayOutputStream.new
+ java.lang.System.setOut(java.io.PrintStream.new(string_io))
+ result = maven.execute request
+ java.lang.System.out = out
+ has_exceptions = false
+ result.exceptions.each do |e|
+ has_exceptions = true
+ e.print_stack_trace
+ string_io.write(e.get_message.to_java_string.get_bytes)
+ end
+ raise string_io.to_s if has_exceptions
+ string_io.to_s
+ end
+
+ def writeElement(xmlWriter,element_name, text)
+ xmlWriter.writeStartElement(element_name.to_java)
+ xmlWriter.writeCharacters(text.to_java)
+ xmlWriter.writeEndElement
+ end
+
+ public
+ def maven_name(gemname)
+ self.class.mname(gemname)
+ end
+ #gemname==mvn:group_id:artifact_id
+ def self.mname(gemname)
+ gemname.gsub("mvn:","").gsub("-","_").gsub(".","_").gsub(":","_")
+ end
+
+ def get_versions(gemname)
+ []
+ end
+
+ def generate_spec(gemname, version)
+ mname = maven_name(gemname)
+ MavenSpec.new do |s|
+ s.name = gemname
+ s.date = '2010-04-28'
+ s.summary = "Hola!"
+ s.description = "A simple hello world gem"
+ s.authors = ["Nick Quaranto"]
+ s.email = 'nick@quaran.to'
+ s.homepage = 'http://rubygems.org/gems/hola'
+ s.version = version
+ s.files = "lib/#{mname}.rb"
+ end
+ end
+
+ def generate_gem(gemname, version)
+ mname = maven_name(gemname)
+ spec_file=generate_spec(gemname,version)
+ # spec_file.name=mname #So that the gem's name is correct
+ gemname=gemname.gsub("mvn:","")
+ maven_parts = gemname.split(":")
+ group_id = maven_parts[0]
+ artifact_id = maven_parts[1]
+
+ FileUtils.mkdir_p(File.join(temp_dir,"lib"))
+ #Generate a dummy POM file that we'll use to run maven against
+ #to resolve deps and generate a classpath
+ pomfile=File.join(temp_dir,"pom.xml")
+ puts "pomfile=#{pomfile}"
+ out = java.io.BufferedOutputStream.new(java.io.FileOutputStream.new(pomfile.to_java))
+ outputFactory = XMLOutputFactory.newFactory()
+ xmlStreamWriter = outputFactory.createXMLStreamWriter(out)
+ xmlStreamWriter.writeStartDocument
+ xmlStreamWriter.writeStartElement("project".to_java)
+
+ writeElement(xmlStreamWriter,"groupId","org.hokiesuns.mavengemify")
+ writeElement(xmlStreamWriter,"artifactId","mavengemify")
+ writeElement(xmlStreamWriter,"modelVersion","4.0.0")
+ writeElement(xmlStreamWriter,"version","1.0-SNAPSHOT")
+
+ #Repositories
+ if @repositories.length > 0
+ xmlStreamWriter.writeStartElement("repositories".to_java)
+ @repositories.each_with_index {|repo,i|
+ xmlStreamWriter.writeStartElement("repository".to_java)
+ writeElement(xmlStreamWriter,"id","repository_#{i}")
+ writeElement(xmlStreamWriter,"url",repo)
+ xmlStreamWriter.writeEndElement #repository
+ }
+ xmlStreamWriter.writeEndElement #repositories
+ end
+ xmlStreamWriter.writeStartElement("dependencies".to_java)
+
+ xmlStreamWriter.writeStartElement("dependency".to_java)
+ writeElement(xmlStreamWriter,"groupId",group_id)
+ writeElement(xmlStreamWriter,"artifactId",artifact_id)
+ writeElement(xmlStreamWriter,"version",version.to_s)
+
+ xmlStreamWriter.writeEndElement #dependency
+
+ xmlStreamWriter.writeEndElement #dependencies
+
+ xmlStreamWriter.writeEndElement #project
+
+ xmlStreamWriter.writeEndDocument
+ xmlStreamWriter.close
+ out.close
+
+ execute(["dependency:resolve","dependency:build-classpath"],pomfile,{"mdep.outputFile" => "cp.txt","mdep.fileSeparator"=>"/"})
+
+ ruby_file = File.new(File.join(temp_dir,"lib/#{mname}.rb"),"w")
+ cp_file = File.new(File.join(temp_dir,"cp.txt"),"r")
+ cp_line = cp_file.gets
+ cp_file.close
+ cp_entries = cp_line.split(";")
+ cp_entries.each{ |entry|
+ ruby_file.puts "require \"#{entry}\""
+ }
+ ruby_file.close
+ old_pwd = Dir.pwd
+ Dir.chdir(temp_dir)
+ gembuilder = Gem::Builder.new(spec_file)
+ gemfile=gembuilder.build
+
+ geminstaller = Gem::Installer.new(gemfile)
+ geminstaller.install
+ Dir.chdir(old_pwd)
+ end
+
+ end
+ end
+end

0 comments on commit a29d455

Please sign in to comment.