blob: cade7094a6990db454d8285b77e5ce801be92d55 [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 IntellijIdea
def self.new_document(value)
REXML::Document.new(value, :attribute_quote => :quote)
end
# Abstract base class for IdeaModule and IdeaProject
class IdeaFile
DEFAULT_SUFFIX = ""
DEFAULT_LOCAL_REPOSITORY_ENV_OVERRIDE = "MAVEN_REPOSITORY"
attr_reader :buildr_project
attr_writer :suffix
attr_writer :id
attr_accessor :template
attr_accessor :local_repository_env_override
def initialize
@local_repository_env_override = DEFAULT_LOCAL_REPOSITORY_ENV_OVERRIDE
end
def suffix
@suffix ||= DEFAULT_SUFFIX
end
def filename
buildr_project.path_to("#{name}.#{extension}")
end
def id
@id ||= buildr_project.name.split(':').last
end
def add_component(name, attrs = {}, &xml)
self.components << create_component(name, attrs, &xml)
end
# IDEA can not handle text content with indents so need to removing indenting
# Can not pass true as third argument as the ruby library seems broken
def write(f)
document.write(f, -1, false, true)
end
protected
def name
"#{self.id}#{suffix}"
end
def relative(path)
::Buildr::Util.relative_path(File.expand_path(path.to_s), self.base_directory)
end
def base_directory
buildr_project.path_to
end
def resolve_path_from_base(path, base_variable)
m2repo = Buildr::Repositories.instance.local
if path.to_s.index(m2repo) == 0 && !self.local_repository_env_override.nil?
return path.sub(m2repo, "$#{self.local_repository_env_override}$")
else
begin
return "#{base_variable}/#{relative(path)}"
rescue ArgumentError
# ArgumentError happens on windows when self.base_directory and path are on different drives
return path
end
end
end
def file_path(path)
"file://#{resolve_path(path)}"
end
def create_component(name, attrs = {})
target = StringIO.new
Builder::XmlMarkup.new(:target => target, :indent => 2).component({:name => name}.merge(attrs)) do |xml|
yield xml if block_given?
end
Buildr::IntellijIdea.new_document(target.string).root
end
def components
@components ||= []
end
def create_composite_component(name, attrs, components)
return nil if components.empty?
component = self.create_component(name, attrs)
components.each do |element|
element = element.call if element.is_a?(Proc)
component.add_element element
end
component
end
def add_to_composite_component(components)
components << lambda do
target = StringIO.new
yield Builder::XmlMarkup.new(:target => target, :indent => 2)
Buildr::IntellijIdea.new_document(target.string).root
end
end
def load_document(filename)
Buildr::IntellijIdea.new_document(File.read(filename))
end
def document
if File.exist?(self.filename)
doc = load_document(self.filename)
else
doc = base_document
inject_components(doc, self.initial_components)
end
if self.template
template_doc = load_document(self.template)
REXML::XPath.each(template_doc, "//component") do |element|
inject_component(doc, element)
end
end
inject_components(doc, self.default_components.compact + self.components)
# Sort the components in the same order the idea sorts them
sorted = doc.root.get_elements('//component').sort { |s1, s2| s1.attribute('name').value <=> s2.attribute('name').value }
doc = base_document
sorted.each do |element|
doc.root.add_element element
end
doc
end
def inject_components(doc, components)
components.each do |component|
# execute deferred components
component = component.call if Proc === component
inject_component(doc, component) if component
end
end
# replace overridden component (if any) with specified component
def inject_component(doc, component)
doc.root.delete_element("//component[@name='#{component.attributes['name']}']")
doc.root.add_element component
end
end
# IdeaModule represents an .iml file
class IdeaModule < IdeaFile
DEFAULT_TYPE = "JAVA_MODULE"
attr_accessor :type
attr_accessor :group
attr_reader :facets
attr_writer :jdk_version
def initialize
super()
@type = DEFAULT_TYPE
end
def buildr_project=(buildr_project)
@id = nil
@facets = []
@skip_content = false
@buildr_project = buildr_project
end
def jdk_version
@jdk_version || buildr_project.compile.options.source || "1.6"
end
def extension
"iml"
end
def main_source_directories
@main_source_directories ||= [
buildr_project.compile.sources,
buildr_project.resources.sources
].flatten.compact
end
def test_source_directories
@test_source_directories ||= [
buildr_project.test.compile.sources,
buildr_project.test.resources.sources
].flatten.compact
end
def excluded_directories
@excluded_directories ||= [
buildr_project.resources.target,
buildr_project.test.resources.target,
buildr_project.path_to(:target, :main),
buildr_project.path_to(:target, :test),
buildr_project.path_to(:reports)
].flatten.compact
end
attr_writer :main_output_dir
def main_output_dir
@main_output_dir ||= buildr_project._(:target, :main, :idea, :classes)
end
attr_writer :test_output_dir
def test_output_dir
@test_output_dir ||= buildr_project._(:target, :test, :idea, :classes)
end
def main_dependencies
@main_dependencies ||= buildr_project.compile.dependencies
end
def test_dependencies
@test_dependencies ||= buildr_project.test.compile.dependencies
end
def add_facet(name, type)
add_to_composite_component(self.facets) do |xml|
xml.facet(:name => name, :type => type) do |xml|
yield xml if block_given?
end
end
end
def skip_content?
!!@skip_content
end
def skip_content!
@skip_content = true
end
def add_gwt_facet(modules = {}, options = {})
name = options[:name] || "GWT"
detected_gwt_version = nil
if options[:gwt_dev_artifact]
a = Buildr.artifact(options[:gwt_dev_artifact])
a.invoke
detected_gwt_version = a.to_s
end
settings =
{
:webFacet => "Web",
:compilerMaxHeapSize => "512",
:compilerParameters => "-draftCompile -localWorkers 2 -strict",
:gwtScriptOutputStyle => "PRETTY"
}.merge(options[:settings] || {})
buildr_project.compile.dependencies.each do |d|
if d.to_s =~ /\/com\/google\/gwt\/gwt-dev\/(.*)\//
detected_gwt_version = d.to_s
break
end
end unless detected_gwt_version
if detected_gwt_version
settings[:gwtSdkUrl] = resolve_path(File.dirname(detected_gwt_version))
settings[:gwtSdkType] = "maven"
else
settings[:gwtSdkUrl] = "file://$GWT_TOOLS$"
end
add_facet(name, "gwt") do |f|
f.configuration do |c|
settings.each_pair do |k, v|
c.setting :name => k.to_s, :value => v.to_s
end
c.packaging do |d|
modules.each_pair do |k, v|
d.module :name => k, :enabled => v
end
end
end
end
end
def add_web_facet(options = {})
name = options[:name] || "Web"
default_webroots = {}
buildr_project.assets.paths.each {|p| default_webroots[p] = "/" }
webroots = options[:webroots] || default_webroots
default_deployment_descriptors = []
['web.xml', 'sun-web.xml', 'glassfish-web.xml', 'jetty-web.xml', 'geronimo-web.xml',
'context.xml', 'weblogic.xml',
'jboss-deployment-structure.xml', 'jboss-web.xml',
'ibm-web-bnd.xml', 'ibm-web-ext.xml', 'ibm-web-ext-pme.xml'].
each do |descriptor|
webroots.each_pair do |path, relative_url|
next unless relative_url == "/"
d = "#{path}/WEB-INF/#{descriptor}"
default_deployment_descriptors << d if File.exist?(d)
end
end
deployment_descriptors = options[:deployment_descriptors] || default_deployment_descriptors
add_facet(name, "web") do |f|
f.configuration do |c|
c.descriptors do |d|
deployment_descriptors.each do |deployment_descriptor|
d.deploymentDescriptor :name => File.basename(deployment_descriptor), :url => file_path(deployment_descriptor)
end
end
c.webroots do |w|
webroots.each_pair do |webroot, relative_url|
w.root :url => file_path(webroot), :relative => relative_url
end
end
end
default_enable_jsf = webroots.keys.any?{|webroot| File.exist?("#{webroot}/WEB-INF/faces-config.xml")}
enable_jsf = options[:enable_jsf].nil? ? default_enable_jsf : options[:enable_jsf]
enable_jsf = false if root_project.ipr? && root_project.ipr.version >= '13'
f.facet(:type => 'jsf', :name => 'JSF') do |jsf|
jsf.configuration
end if enable_jsf
end
end
def add_jruby_facet(options = {})
name = options[:name] || "JRuby"
ruby_version_file = buildr_project._('.ruby-version')
default_jruby_version = File.exist?(ruby_version_file) ? "rbenv: #{IO.read(ruby_version_file).strip}" : 'jruby-1.6.7.2'
jruby_version = options[:jruby_version] || default_jruby_version
add_facet(name, "JRUBY") do |f|
f.configuration do |c|
c.JRUBY_FACET_CONFIG_ID :NAME => "JRUBY_SDK_NAME", :VALUE => jruby_version
c.LOAD_PATH :number => "0"
c.I18N_FOLDERS :number => "0"
end
end
end
def add_jpa_facet(options = {})
name = options[:name] || "JPA"
source_roots = [buildr_project.iml.main_source_directories, buildr_project.compile.sources, buildr_project.resources.sources].flatten.compact
default_deployment_descriptors = []
['orm.xml', 'persistence.xml'].
each do |descriptor|
source_roots.each do |path|
d = "#{path}/META-INF/#{descriptor}"
default_deployment_descriptors << d if File.exist?(d)
end
end
deployment_descriptors = options[:deployment_descriptors] || default_deployment_descriptors
factory_entry = options[:factory_entry] || buildr_project.name.to_s
validation_enabled = options[:validation_enabled].nil? ? true : options[:validation_enabled]
if options[:provider_enabled]
provider = options[:provider_enabled]
else
provider = nil
{'org.hibernate.ejb.HibernatePersistence' => 'Hibernate',
'org.eclipse.persistence.jpa.PersistenceProvider' => 'EclipseLink'}.
each_pair do |match, candidate_provider|
deployment_descriptors.each do |descriptor|
if File.exist?(descriptor) && /#{Regexp.escape(match)}/ =~ IO.read(descriptor)
provider = candidate_provider
end
end
end
end
add_facet(name, "jpa") do |f|
f.configuration do |c|
if provider
c.setting :name => "validation-enabled", :value => validation_enabled
c.setting :name => "provider-name", :value => provider
end
c.tag!('datasource-mapping') do |ds|
ds.tag!('factory-entry', :name => factory_entry)
end
deployment_descriptors.each do |descriptor|
c.deploymentDescriptor :name => File.basename(descriptor), :url => file_path(descriptor)
end
end
end
end
def add_ejb_facet(options = {})
name = options[:name] || "EJB"
default_ejb_roots = [buildr_project.iml.main_source_directories, buildr_project.compile.sources, buildr_project.resources.sources].flatten.compact
ejb_roots = options[:ejb_roots] || default_ejb_roots
default_deployment_descriptors = []
['ejb-jar.xml', 'glassfish-ejb-jar.xml', 'ibm-ejb-jar-bnd.xml', 'ibm-ejb-jar-ext-pme.xml', 'ibm-ejb-jar-ext.xml',
'jboss.xml', 'jbosscmp-jdbc.xml', 'openejb-jar.xml', 'sun-cmp-mapping.xml', 'sun-ejb-jar.xml',
'weblogic-cmp-rdbms-jar.xml', 'weblogic-ejb-jar.xml'].
each do |descriptor|
ejb_roots.each do |path|
d = "#{path}/WEB-INF/#{descriptor}"
default_deployment_descriptors << d if File.exist?(d)
end
end
deployment_descriptors = options[:deployment_descriptors] || default_deployment_descriptors
add_facet(name, "ejb") do |facet|
facet.configuration do |c|
c.descriptors do |d|
deployment_descriptors.each do |deployment_descriptor|
d.deploymentDescriptor :name => File.basename(deployment_descriptor), :url => file_path(deployment_descriptor)
end
end
c.ejbRoots do |e|
ejb_roots.each do |ejb_root|
e.root :url => file_path(ejb_root)
end
end
end
end
end
protected
def root_project
p = buildr_project
while p.parent
p = p.parent
end
p
end
def test_dependency_details
main_dependencies_paths = main_dependencies.map(&:to_s)
target_dir = buildr_project.compile.target.to_s
test_dependencies.select { |d| d.to_s != target_dir }.collect do |d|
dependency_path = d.to_s
export = main_dependencies_paths.include?(dependency_path)
source_path = nil
if d.respond_to?(:to_spec_hash)
source_spec = d.to_spec_hash.merge(:classifier => 'sources')
source_path = Buildr.artifact(source_spec).to_s
source_path = nil unless File.exist?(source_path)
end
[dependency_path, export, source_path]
end
end
def base_document
target = StringIO.new
Builder::XmlMarkup.new(:target => target).module(:version => "4", :relativePaths => "true", :type => self.type)
Buildr::IntellijIdea.new_document(target.string)
end
def initial_components
[]
end
def default_components
[
lambda { module_root_component },
lambda { facet_component }
]
end
def facet_component
create_composite_component("FacetManager", {}, self.facets)
end
def module_root_component
create_component("NewModuleRootManager", "inherit-compiler-output" => "false") do |xml|
generate_compile_output(xml)
generate_content(xml) unless skip_content?
generate_initial_order_entries(xml)
project_dependencies = []
self.test_dependency_details.each do |dependency_path, export, source_path|
next unless export
generate_lib(xml, dependency_path, export, source_path, project_dependencies)
end
self.test_dependency_details.each do |dependency_path, export, source_path|
next if export
generate_lib(xml, dependency_path, export, source_path, project_dependencies)
end
xml.orderEntryProperties
end
end
def generate_lib(xml, dependency_path, export, source_path, project_dependencies)
project_for_dependency = Buildr.projects.detect do |project|
[project.packages, project.compile.target, project.resources.target, project.test.compile.target, project.test.resources.target].flatten.
detect { |artifact| artifact.to_s == dependency_path }
end
if project_for_dependency
if project_for_dependency.iml? &&
!project_dependencies.include?(project_for_dependency) &&
project_for_dependency != self.buildr_project
generate_project_dependency(xml, project_for_dependency.iml.name, export, !export)
end
project_dependencies << project_for_dependency
else
generate_module_lib(xml, url_for_path(dependency_path), export, (source_path ? url_for_path(source_path) : nil), !export)
end
end
def jar_path(path)
"jar://#{resolve_path(path)}!/"
end
def url_for_path(path)
if path =~ /jar$/i
jar_path(path)
else
file_path(path)
end
end
def resolve_path(path)
resolve_path_from_base(path, "$MODULE_DIR$")
end
def generate_compile_output(xml)
xml.output(:url => file_path(self.main_output_dir.to_s))
xml.tag!("output-test", :url => file_path(self.test_output_dir.to_s))
xml.tag!("exclude-output")
end
def generate_content(xml)
xml.content(:url => "file://$MODULE_DIR$") do
# Source folders
{
:main => self.main_source_directories,
:test => self.test_source_directories
}.each do |kind, directories|
directories.map { |dir| dir.to_s }.compact.sort.uniq.each do |dir|
xml.sourceFolder :url => file_path(dir), :isTestSource => (kind == :test ? 'true' : 'false')
end
end
# Exclude target directories
self.net_excluded_directories.
collect { |dir| file_path(dir) }.
select { |dir| relative_dir_inside_dir?(dir) }.
sort.each do |dir|
xml.excludeFolder :url => dir
end
end
end
def relative_dir_inside_dir?(dir)
!dir.include?("../")
end
def generate_initial_order_entries(xml)
xml.orderEntry :type => "sourceFolder", :forTests => "false"
xml.orderEntry :type => "jdk", :jdkName => jdk_version, :jdkType => "JavaSDK"
end
def generate_project_dependency(xml, other_project, export, test = false)
attribs = {:type => 'module', "module-name" => other_project}
attribs[:exported] = '' if export
attribs[:scope] = 'TEST' if test
xml.orderEntry attribs
end
def generate_module_lib(xml, path, export, source_path, test = false)
attribs = {:type => 'module-library'}
attribs[:exported] = '' if export
attribs[:scope] = 'TEST' if test
xml.orderEntry attribs do
xml.library do
xml.CLASSES do
xml.root :url => path
end
xml.JAVADOC
xml.SOURCES do
if source_path
xml.root :url => source_path
end
end
end
end
end
# Don't exclude things that are subdirectories of other excluded things
def net_excluded_directories
net = []
all = self.excluded_directories.map { |dir| buildr_project._(dir.to_s) }.sort_by { |d| d.size }
all.each_with_index do |dir, i|
unless all[0 ... i].find { |other| dir =~ /^#{other}/ }
net << dir
end
end
net
end
end
# IdeaModule represents an .ipr file
class IdeaProject < IdeaFile
attr_accessor :extra_modules
attr_accessor :artifacts
attr_accessor :data_sources
attr_accessor :configurations
attr_writer :jdk_version
attr_writer :version
def initialize(buildr_project)
super()
@buildr_project = buildr_project
@extra_modules = []
@artifacts = []
@data_sources = []
@configurations = []
end
def version
@version || "12"
end
def jdk_version
@jdk_version ||= buildr_project.compile.options.source || "1.6"
end
def add_artifact(name, type, build_on_make = false)
add_to_composite_component(self.artifacts) do |xml|
xml.artifact(:name => name, :type => type, :"build-on-make" => build_on_make) do |xml|
yield xml if block_given?
end
end
end
def add_configuration(name, type, factory_name, default = false)
add_to_composite_component(self.configurations) do |xml|
xml.configuration(:name => name, :type => type, :factoryName => factory_name, :default => default) do |xml|
yield xml if block_given?
end
end
end
def add_postgres_data_source(name, options = {})
if options[:url].nil? && options[:database]
default_url = "jdbc:postgresql://#{(options[:host] || "127.0.0.1")}:#{(options[:port] || "5432")}/#{options[:database]}"
end
params = {
:driver => 'org.postgresql.Driver',
:url => default_url,
:username => ENV["USER"],
:dialect => 'PostgreSQL',
:classpath => ["org.postgresql:postgresql:jar:9.2-1003-jdbc4"]
}.merge(options)
add_data_source(name, params)
end
def add_sql_server_data_source(name, options = {})
if options[:url].nil? && options[:database]
default_url = "jdbc:jtds:sqlserver://#{(options[:host] || "127.0.0.1")}:#{(options[:port] || "1433")}/#{options[:database]}"
end
params = {
:driver => 'net.sourceforge.jtds.jdbc.Driver',
:url => default_url,
:username => ENV["USER"],
:dialect => 'TSQL',
:classpath => ['net.sourceforge.jtds:jtds:jar:1.2.7']
}.merge(options)
add_data_source(name, params)
end
def add_data_source(name, options = {})
add_to_composite_component(self.data_sources) do |xml|
data_source_options = {
:source => "LOCAL",
:name => name,
:uuid => Buildr::Util.uuid
}
classpath = options[:classpath] || []
xml.tag!("data-source", data_source_options) do |xml|
xml.tag!("synchronize", (options[:synchronize]||"true"))
xml.tag!("jdbc-driver", options[:driver]) if options[:driver]
xml.tag!("jdbc-url", options[:url]) if options[:url]
xml.tag!("user-name", options[:username]) if options[:username]
xml.tag!("user-password", encrypt(options[:password])) if options[:password]
xml.tag!("default-dialect", options[:dialect]) if options[:dialect]
xml.libraries do |xml|
classpath.each do |classpath_element|
a = Buildr.artifact(classpath_element)
a.invoke
xml.library do |xml|
xml.tag!("url", resolve_path(a.to_s))
end
end
end if classpath.size > 0
end
end
end
def add_exploded_war_artifact(project, options = {})
artifact_name = to_artifact_name(project, options)
artifacts = options[:artifacts] || []
add_artifact(artifact_name, "exploded-war", build_on_make(options)) do |xml|
dependencies = (options[:dependencies] || ([project] + project.compile.dependencies)).flatten
libraries, projects = partition_dependencies(dependencies)
emit_output_path(xml, artifact_name, options)
xml.root :id => "root" do
xml.element :id => "directory", :name => "WEB-INF" do
xml.element :id => "directory", :name => "classes" do
artifact_content(xml, project, projects, options)
end
xml.element :id => "directory", :name => "lib" do
emit_libraries(xml, libraries)
emit_jar_artifacts(xml, artifacts)
end
end
if options[:enable_war].nil? || options[:enable_war] || (options[:war_module_names] && options[:war_module_names].size > 0)
module_names = options[:war_module_names] || [project.iml.id]
module_names.each do |module_name|
facet_name = options[:war_facet_name] || "Web"
xml.element :id => "javaee-facet-resources", :facet => "#{module_name}/web/#{facet_name}"
end
end
if options[:enable_gwt] || (options[:gwt_module_names] && options[:gwt_module_names].size > 0)
module_names = options[:gwt_module_names] || [project.iml.id]
module_names.each do |module_name|
facet_name = options[:gwt_facet_name] || "GWT"
xml.element :id => "gwt-compiler-output", :facet => "#{module_name}/gwt/#{facet_name}"
end
end
end
end
end
def add_exploded_ear_artifact(project, options ={})
artifact_name = to_artifact_name(project, options)
add_artifact(artifact_name, "exploded-ear", build_on_make(options)) do |xml|
dependencies = (options[:dependencies] || ([project] + project.compile.dependencies)).flatten
libraries, projects = partition_dependencies(dependencies)
emit_output_path(xml, artifact_name, options)
xml.root :id => "root" do
emit_module_output(xml, projects)
xml.element :id => "directory", :name => "lib" do
emit_libraries(xml, libraries)
end
end
end
end
def add_jar_artifact(project, options = {})
artifact_name = to_artifact_name(project, options)
dependencies = (options[:dependencies] || [project]).flatten
libraries, projects = partition_dependencies(dependencies)
raise "Unable to add non-project dependencies (#{libraries.inspect}) to jar artifact" if libraries.size > 0
jar_name = "#{artifact_name}.jar"
add_artifact(jar_name, "jar", build_on_make(options)) do |xml|
emit_output_path(xml, artifact_name, options)
xml.root(:id => "archive", :name => jar_name) do
artifact_content(xml, project, projects, options)
end
end
end
def add_exploded_ejb_artifact(project, options = {})
artifact_name = to_artifact_name(project, options)
add_artifact(artifact_name, "exploded-ejb", build_on_make(options)) do |xml|
dependencies = (options[:dependencies] || [project]).flatten
libraries, projects = partition_dependencies(dependencies)
raise "Unable to add non-project dependencies (#{libraries.inspect}) to ejb artifact" if libraries.size > 0
emit_output_path(xml, artifact_name, options)
xml.root :id => "root" do
artifact_content(xml, project, projects, options)
end
end
end
def add_gwt_configuration(launch_page, project, options = {})
name = options[:name] || "Run #{launch_page}"
shell_parameters = options[:shell_parameters] || ""
vm_parameters = options[:vm_parameters] || "-Xmx512m"
add_configuration(name, "GWT.ConfigurationType", "GWT Configuration") do |xml|
xml.module(:name => project.iml.id)
xml.option(:name => "RUN_PAGE", :value => launch_page)
xml.option(:name => "SHELL_PARAMETERS", :value => shell_parameters)
xml.option(:name => "VM_PARAMETERS", :value => vm_parameters)
xml.RunnerSettings(:RunnerId => "Run")
xml.ConfigurationWrapper(:RunnerId => "Run")
xml.method()
end
end
protected
def artifact_content(xml, project, projects, options)
emit_module_output(xml, projects)
emit_jpa_descriptors(xml, project, options)
emit_ejb_descriptors(xml, project, options)
end
def extension
"ipr"
end
def base_document
target = StringIO.new
Builder::XmlMarkup.new(:target => target).project(:version => "4")
Buildr::IntellijIdea.new_document(target.string)
end
def default_components
[
lambda { modules_component },
vcs_component,
artifacts_component,
lambda { data_sources_component },
configurations_component,
lambda { framework_detection_exclusion_component }
]
end
def framework_detection_exclusion_component
create_component('FrameworkDetectionExcludesConfiguration') do |xml|
xml.file :url => file_path(buildr_project._(:artifacts))
end
end
def initial_components
[
lambda { project_root_manager_component },
lambda { project_details_component }
]
end
def project_root_manager_component
attribs = {}
attribs["version"] = "2"
attribs["languageLevel"] = "JDK_#{self.jdk_version.gsub('.', '_')}"
attribs["assert-keyword"] = "true"
attribs["jdk-15"] = (jdk_version >= "1.5").to_s
attribs["project-jdk-name"] = self.jdk_version
attribs["project-jdk-type"] = "JavaSDK"
create_component("ProjectRootManager", attribs) do |xml|
xml.output("url" => file_path(buildr_project._(:target, :idea, :project_out)))
end
end
def project_details_component
create_component("ProjectDetails") do |xml|
xml.option("name" => "projectName", "value" => self.name)
end
end
def modules_component
create_component("ProjectModuleManager") do |xml|
xml.modules do
buildr_project.projects.select { |subp| subp.iml? }.each do |subproject|
module_path = subproject.base_dir.gsub(/^#{buildr_project.base_dir}\//, '')
path = "#{module_path}/#{subproject.iml.name}.iml"
attribs = {:fileurl => "file://$PROJECT_DIR$/#{path}", :filepath => "$PROJECT_DIR$/#{path}"}
if subproject.iml.group == true
attribs[:group] = subproject.parent.name.gsub(':', '/')
elsif !subproject.iml.group.nil?
attribs[:group] = subproject.iml.group.to_s
end
xml.module attribs
end
self.extra_modules.each do |iml_file|
xml.module :fileurl => "file://$PROJECT_DIR$/#{iml_file}",
:filepath => "$PROJECT_DIR$/#{iml_file}"
end
if buildr_project.iml?
xml.module :fileurl => "file://$PROJECT_DIR$/#{buildr_project.iml.name}.iml",
:filepath => "$PROJECT_DIR$/#{buildr_project.iml.name}.iml"
end
end
end
end
def vcs_component
project_directories = buildr_project.projects.select { |p| p.iml? }.collect { |p| p.base_dir }
project_directories << buildr_project.base_dir
# Guess the iml file is in the same dir as base dir
project_directories += self.extra_modules.collect { |p| File.dirname(p) }
project_directories = project_directories.sort.uniq
mappings = {}
project_directories.each do |dir|
if File.directory?("#{dir}/.git")
mappings[dir] = "Git"
elsif File.directory?("#{dir}/.svn")
mappings[dir] = "svn"
end
end
if mappings.size > 1
create_component("VcsDirectoryMappings") do |xml|
mappings.each_pair do |dir, vcs_type|
resolved_dir = resolve_path(dir)
mapped_dir = resolved_dir == '$PROJECT_DIR$/.' ? buildr_project.base_dir : resolved_dir
xml.mapping :directory => mapped_dir, :vcs => vcs_type
end
end
end
end
def data_sources_component
create_composite_component("DataSourceManagerImpl", {:format => "xml", :hash => "3208837817"}, self.data_sources)
end
def artifacts_component
create_composite_component("ArtifactManager", {}, self.artifacts)
end
def configurations_component
create_composite_component("ProjectRunConfigurationManager", {}, self.configurations)
end
def resolve_path(path)
resolve_path_from_base(path, "$PROJECT_DIR$")
end
private
def to_artifact_name(project, options)
options[:name] || project.iml.id
end
def build_on_make(options)
options[:build_on_make].nil? ? false : options[:build_on_make]
end
def emit_jar_artifacts(xml, artifacts)
artifacts.each do |p|
xml.element :id => "artifact", 'artifact-name' => "#{p}.jar"
end
end
def emit_libraries(xml, libraries)
libraries.each(&:invoke).map(&:to_s).each do |dependency_path|
xml.element :id => "file-copy", :path => resolve_path(dependency_path)
end
end
def emit_module_output(xml, projects)
projects.each do |p|
xml.element :id => "module-output", :name => p.iml.id
end
end
def emit_output_path(xml, artifact_name, options)
## The content here can not be indented
output_dir = options[:output_dir] || buildr_project._(:artifacts, artifact_name)
xml.tag!('output-path', resolve_path(output_dir))
end
def emit_ejb_descriptors(xml, project, options)
if options[:enable_ejb] || (options[:ejb_module_names] && options[:ejb_module_names].size > 0)
module_names = options[:ejb_module_names] || [project.iml.id]
module_names.each do |module_name|
facet_name = options[:ejb_facet_name] || "EJB"
xml.element :id => "javaee-facet-resources", :facet => "#{module_name}/ejb/#{facet_name}"
end
end
end
def emit_jpa_descriptors(xml, project, options)
if options[:enable_jpa] || (options[:jpa_module_names] && options[:jpa_module_names].size > 0)
module_names = options[:jpa_module_names] || [project.iml.id]
module_names.each do |module_name|
facet_name = options[:jpa_facet_name] || "JPA"
xml.element :id => "jpa-descriptors", :facet => "#{module_name}/jpa/#{facet_name}"
end
end
end
def encrypt(password)
password.bytes.inject("") { |x, y| x + (y ^ 0xdfaa).to_s(16) }
end
def partition_dependencies(dependencies)
libraries = []
projects = []
dependencies.each do |dependency|
artifacts = Buildr.artifacts(dependency)
artifacts_as_strings = artifacts.map(&:to_s)
all_projects = Buildr::Project.instance_variable_get("@projects").keys
project = Buildr.projects(all_projects).detect do |project|
[project.packages, project.compile.target, project.resources.target, project.test.compile.target, project.test.resources.target].flatten.
detect { |component| artifacts_as_strings.include?(component.to_s) }
end
if project
projects << project
else
libraries += artifacts
end
end
return libraries.uniq, projects.uniq
end
end
module ProjectExtension
include Extension
first_time do
desc "Generate Intellij IDEA artifacts for all projects"
Project.local_task "idea" => "artifacts"
desc "Delete the generated Intellij IDEA artifacts"
Project.local_task "idea:clean"
end
before_define do |project|
project.recursive_task("idea")
project.recursive_task("idea:clean")
end
after_define do |project|
idea = project.task("idea")
files = [
(project.iml if project.iml?),
(project.ipr if project.ipr?)
].compact
files.each do |ideafile|
module_dir = File.dirname(ideafile.filename)
idea.enhance do |task|
mkdir_p module_dir
info "Writing #{ideafile.filename}"
t = Tempfile.open("buildr-idea")
temp_filename = t.path
t.close!
File.open(temp_filename, "w") do |f|
ideafile.write f
end
mv temp_filename, ideafile.filename
end
end
project.task("idea:clean") do
files.each do |f|
info "Removing #{f.filename}" if File.exist?(f.filename)
rm_rf f.filename
end
end
end
def ipr
if ipr?
@ipr ||= IdeaProject.new(self)
else
raise "Only the root project has an IPR"
end
end
def ipr?
!@no_ipr && self.parent.nil?
end
def iml
if iml?
unless @iml
inheritable_iml_source = self.parent
while inheritable_iml_source && !inheritable_iml_source.iml?
inheritable_iml_source = inheritable_iml_source.parent;
end
@iml = inheritable_iml_source ? inheritable_iml_source.iml.clone : IdeaModule.new
@iml.buildr_project = self
end
return @iml
else
raise "IML generation is disabled for #{self.name}"
end
end
def no_ipr
@no_ipr = true
end
def no_iml
@has_iml = false
end
def iml?
@has_iml = @has_iml.nil? ? true : @has_iml
end
end
end
end
class Buildr::Project
include Buildr::IntellijIdea::ProjectExtension
end