blob: ac66ccc250a0346343f7e7262a75655f8ddcde0b [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with this
# work for additional information regarding copyright ownership. The ASF
# licenses this file to you 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.
module Buildr #:nodoc:
module Generate #:nodoc:
task 'generate' do
header = "To use Buildr you need a buildfile. Do you want me to create one?"
options = {}
if Generate.has_eclipse_project?
options["From eclipse .project files"] = Proc.new { Generate.from_eclipse(Dir.pwd).join("\n") }
end
if File.exist?('pom.xml')
options["From Maven2 POM file"] = Proc.new { Generate.from_maven2_pom('pom.xml').join("\n") }
end
options["From directory structure"] = Proc.new { Generate.from_directory(Dir.pwd).join("\n") }
options["Skip"]= nil
script = Buildr::Console.present_menu(header, options)
if script
buildfile = File.expand_path(Buildr::Application::DEFAULT_BUILDFILES.first)
File.open(buildfile, "w") { |file| file.write script }
puts "Created #{buildfile}"
end
end
class << self
def compatibility_option(path)
# compile.options.target = '1.5'
end
def get_project_natures(projectFile)
return nil unless File.exists?(projectFile)
File.open(projectFile) do |f|
root = REXML::Document.new(f).root
return nil if root == nil
natures = root.elements.collect("natures/nature") { |n| n.text }
return natures if natures
end
return nil
end
def get_build_property(path, propertyName)
propertiesFile = File.join(path, 'build.properties')
return nil unless File.exists?(propertiesFile)
inhalt = Hash.from_java_properties(File.read(propertiesFile))
binDef = inhalt[propertyName]
end
def has_eclipse_project?
candidates = Dir.glob("**/.project", File::FNM_DOTMATCH)
return false if candidates.size == 0
candidates.find { |x| get_project_natures(x) }
return candidates.size > 0
end
HEADER = "# Generated by Buildr #{Buildr::VERSION}, change to your liking\n\n"
def getEclipseBuildfileHeader(path, name)
x = <<-EOF
#{"require 'buildr/scala'\n" if Dir.glob(path + "/**/*.scala").size > 0}
#{"require 'buildr/groovy'\n" if Dir.glob(path + "/**/*.groovy").size > 0}
# Version number for this release
VERSION_NUMBER = "1.0.0"
# Group identifier for your projects
GROUP = "#{name}"
COPYRIGHT = ""
# Specify Maven 2.0 remote repositories here, like this:
repositories.remote << "https://repo1.maven.org/maven2"
desc "The #{name.capitalize} project"
define "#{name}" do
project.version = VERSION_NUMBER
project.group = GROUP
manifest["Implementation-Vendor"] = COPYRIGHT
EOF
return x
end
def setLayout(source=nil, output = nil)
script = ""
if source
source = source.sub(/\/$/, '') # remove trailing /
script += <<-EOF
layout[:source, :main, :java] = "#{source}"
layout[:source, :main, :scala] = "#{source}"
EOF
end
if output
output = output.sub(/\/$/, '') # remove trailing /
script += <<-EOF
layout[:target, :main] = "#{output}"
layout[:target, :main, :java] = "#{output}"
layout[:target, :main, :scala] = "#{output}"
EOF
end
return script
end
# tries to read as much information as needed at the moment from an existing Eclipse workspace
# Here are some links to the relevant information
# * http://help.eclipse.org/juno/index.jsp?topic=/org.eclipse.pde.doc.user/reference/pde_feature_generating_build.htm
# * http://wiki.eclipse.org/FAQ_What_is_the_plug-in_manifest_file_%28plugin.xml%29%3F
# * http://help.eclipse.org/juno/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/misc/bundle_manifest.html
# * http://help.eclipse.org/juno/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/misc/plugin_manifest.html
# * http://help.eclipse.org/juno/index.jsp?topic=/org.eclipse.pde.doc.user/tasks/pde_compilation_env.htm
def from_eclipse(path = Dir.pwd, root = true)
# We need two passes to be able to determine the dependencies correctly
Dir.chdir(path) do
name = File.basename(path)
dot_projects = []
mf = nil # avoid reloading manifest
if root
@@allProjects = Hash.new
@@topDir = File.expand_path(Dir.pwd)
script = HEADER.split("\n")
script << "require 'buildr/ide/eclipse'"
header = getEclipseBuildfileHeader(path, name)
script += header.split("\n")
script << " # you may see hints about which jars are missing and should resolve them correctly"
script << " # dependencies << 'junit should be commented out and replace by correct ARTIFACT definition. Eg"
script << " # dependencies << 'junit:junit:jar:4.11'"
script << setLayout('src', 'bin') # default values for eclipse
dot_projects = Dir.glob('**/.project', File::FNM_DOTMATCH).find_all { |dot_project| get_project_natures(dot_project) }
dot_projects.sort.each { |dot_project| from_eclipse(File.dirname(dot_project), false) } if dot_projects
else
# Skip fragments. Buildr cannot handle it without the help of buildr4osgi
return [""] if File.exists?('fragment.xml')
projectName = name
version = ""
mfName = File.join('META-INF', 'MANIFEST.MF')
if File.exists?(mfName)
mf = Packaging::Java::Manifest.parse(IO.readlines(mfName).join(''))
if mf.main['Bundle-SymbolicName']
projectName = mf.main['Bundle-SymbolicName'].split(';')[0]
bundleVersion = mf.main['Bundle-Version']
version = ", :version => \"#{bundleVersion}\"" unless "1.0.0".eql?(bundleVersion)
end
end
# in the first run we just want to know that we exist
unless @@allProjects[projectName]
@@allProjects[projectName] = Dir.pwd
return
end
base_dir = ""
unless File.join(@@topDir, projectName).eql?(File.expand_path(Dir.pwd))
base_dir = ", :base_dir => \"#{File.expand_path(Dir.pwd).sub(@@topDir+File::SEPARATOR, '')}\""
end
script = [%{define "#{projectName}"#{version}#{base_dir} do}]
end
natures = get_project_natures('.project')
if natures && natures.index('org.eclipse.pde.PluginNature')
script << " package(:jar)"
end
script << " dependencies ||= []"
if mf && mf.main['Require-Bundle']
mf.main['Require-Bundle'].split(',').each do
|bundle|
requiredName = bundle.split(';')[0]
if @@allProjects.has_key?(requiredName)
script << " dependencies << projects(\"#{requiredName}\")"
else
script << " # dependencies << '#{requiredName}'"
end
end
end
script << " compile.with dependencies # Add more classpath dependencies" if Dir.glob(File.join('src', '**', '*.java')).size > 0
script << " resources" if File.exist?("rsc")
sourceProp = get_build_property('.', 'source..')
outputProp = get_build_property('.', 'output..')
if (sourceProp && !/src\/+/.match(sourceProp)) or (outputProp && !/bin\/+/.match(outputProp))
setLayout(sourceProp, outputProp) # default values are overridden in this project
end
unless dot_projects.empty?
script << ""
dot_projects.sort.each do |dot_project|
next if File.dirname(File.expand_path(dot_project)).eql?(File.expand_path(Dir.pwd))
next unless get_project_natures(dot_project)
script << from_eclipse(File.dirname(dot_project), false).flatten.map { |line| " " + line } << ""
end
end
script << "end\n\n"
script.flatten
end
end
def from_directory(path = Dir.pwd, root = true)
Dir.chdir(path) do
name = File.basename(path)
if root
script = HEADER.split("\n")
header = getEclipseBuildfileHeader(path, name)
script += header.split("\n")
else
script = [ %{define "#{name}" do} ]
end
script << " compile.with # Add classpath dependencies" if File.exist?("src/main/java")
script << " resources" if File.exist?("src/main/resources")
script << " test.compile.with # Add classpath dependencies" if File.exist?("src/test/java")
script << " test.resources" if File.exist?("src/test/resources")
if File.exist?("src/main/webapp")
script << " package(:war)"
elsif File.exist?("src/main/java")
script << " package(:jar)"
end
dirs = FileList["*"].exclude("src", "target", "report").
select { |file| File.directory?(file) && File.exist?(File.join(file, "src")) }
unless dirs.empty?
script << ""
dirs.sort.each do |dir|
script << from_directory(dir, false).flatten.map { |line| " " + line } << ""
end
end
script << "end"
script.flatten
end
end
def from_maven2_pom(path = 'pom.xml', root = true)
pom = Buildr::POM.load(path)
project = pom.project
artifactId = project['artifactId'].first
description = project['name'] || "The #{artifactId} project"
project_name = File.basename(Dir.pwd)
if root
script = HEADER.split("\n")
settings_file = ENV["M2_SETTINGS"] || File.join(ENV['HOME'], ".m2/settings.xml")
settings = XmlSimple.xml_in(IO.read(settings_file)) if File.exists?(settings_file)
if settings
proxy = settings['proxies'].first['proxy'].find { |proxy|
proxy["active"].nil? || proxy["active"].to_s =~ /true/
} rescue nil
if proxy
url = %{#{proxy["protocol"].first}://#{proxy["host"].first}:#{proxy["port"].first}}
exclude = proxy["nonProxyHosts"].to_s.gsub("|", ",") if proxy["nonProxyHosts"]
script << "options.proxy.http = '#{url}'"
script << "options.proxy.exclude << '#{exclude}'" if exclude
script << ''
# In addition, we need to use said proxies to download artifacts.
Buildr.options.proxy.http = url
Buildr.options.proxy.exclude << exclude if exclude
end
end
repositories = project["repositories"].first["repository"].select { |repository|
legacy = repository["layout"].to_s =~ /legacy/
!legacy
} rescue nil
repositories = [{"name" => "Standard maven2 repository", "url" => "https://repo1.maven.org/maven2"}] if repositories.nil? || repositories.empty?
repositories.each do |repository|
name, url = repository["name"], repository["url"]
script << "# #{name}"
script << "repositories.remote << '#{url}'"
# In addition we need to use said repositores to download artifacts.
Buildr.repositories.remote << url.to_s
end
script << ""
else
script = []
end
script << "desc '#{description}'"
script << "define '#{project_name}' do"
groupId = project['groupId']
script << " project.group = '#{groupId}'" if groupId
version = project['version']
script << " project.version = '#{version}'" if version
#get plugins configurations
plugins = project['build'].first['plugins'].first['plugin'] rescue {}
if plugins
compile_plugin = plugins.find{|pl| (pl['groupId'].nil? or pl['groupId'].first == 'org.apache.maven.plugins') and pl['artifactId'].first == 'maven-compiler-plugin'}
if compile_plugin
source = compile_plugin.first['configuration'].first['source'] rescue nil
target = compile_plugin.first['configuration'].first['target'] rescue nil
script << " compile.options.source = '#{source}'" if source
script << " compile.options.target = '#{target}'" if target
end
end
compile_dependencies = pom.dependencies
dependencies = compile_dependencies.sort.map{|d| "'#{d}'"}.join(', ')
script << " compile.with #{dependencies}" unless dependencies.empty?
test_dependencies = (pom.dependencies(['test']) - compile_dependencies).reject{|d| d =~ /^junit:junit:jar:/ }
#check if we have testng
use_testng = test_dependencies.find{|d| d =~ /^org.testng:testng:jar:/}
if use_testng
script << " test.using :testng"
test_dependencies = pom.dependencies(['test']).reject{|d| d =~ /^org.testng:testng:jar:/ }
end
test_dependencies = test_dependencies.sort.map{|d| "'#{d}'"}.join(', ')
script << " test.with #{test_dependencies}" unless test_dependencies.empty?
packaging = project['packaging'] ? project['packaging'].first : 'jar'
if %w(jar war).include?(packaging)
script << " package :#{packaging}, :id => '#{artifactId}'"
end
modules = project['modules'].first['module'] rescue nil
if modules
script << ""
modules.each do |mod|
script << from_maven2_pom(File.join(File.dirname(path), mod, 'pom.xml'), false).flatten.map { |line| " " + line } << ""
end
end
script << "end"
script.flatten
end
end
end
end