| # 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 |