diff --git a/README.md b/README.md index 0122e7e46c..82cacdc3ce 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ To learn how to configure various properties of the buildpack, follow the "Confi * [Spring Boot](docs/container-spring_boot.md) * [Spring Boot CLI](docs/container-spring_boot_cli.md) ([Configuration](docs/container-spring_boot_cli.md#configuration)) * [Tomcat](docs/container-tomcat.md) ([Configuration](docs/container-tomcat.md#configuration)) + * [Vertx](docs/container-vertx.md) ([Configuration](docs/container-vertx.md#configuration)) * Standard Frameworks * [AppDynamics Agent](docs/framework-app_dynamics_agent.md) ([Configuration](docs/framework-app_dynamics_agent.md#configuration)) * [Introscope Agent](docs/framework-introscope_agent.md) ([Configuration](docs/framework-introscope_agent.md#configuration)) diff --git a/config/components.yml b/config/components.yml index 4b30dc02b2..03f77486cc 100644 --- a/config/components.yml +++ b/config/components.yml @@ -24,6 +24,7 @@ containers: - "JavaBuildpack::Container::SpringBoot" - "JavaBuildpack::Container::SpringBootCLI" - "JavaBuildpack::Container::Tomcat" + - "JavaBuildpack::Container::Vertx" # In order to use Oracle JREs instead of OpenJDK, you must comment out the OpenJDK line and uncomment the Oracle line. # Please see the documentation for more detail. diff --git a/config/open_jdk_jre.yml.orig b/config/open_jdk_jre.yml.orig new file mode 100644 index 0000000000..e625419d71 --- /dev/null +++ b/config/open_jdk_jre.yml.orig @@ -0,0 +1,52 @@ +# Cloud Foundry Java Buildpack +# Copyright 2013-2015 the original author or authors. +# +# Licensed 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. + +# Configuration for JRE repositories keyed by vendor +<<<<<<< HEAD +# If Java 7 is required, permgen will be used instead of metaspace. Please see the documentation for more detail. +--- +jre: + version: 1.8.0_+ + repository_root: ! '{default.repository.root}/openjdk/{platform}/{architecture}' +memory_calculator: + version: 1.+ + repository_root: ! '{default.repository.root}/memory-calculator/{platform}/{architecture}' + memory_sizes: + heap: + metaspace: 64m.. + native: + permgen: 64m.. + stack: + memory_heuristics: + heap: 75 + metaspace: 10 + native: 10 + permgen: 10 + stack: 5 +======= +# From Java 1.8 onwards, metaspace should be used instead of permgen. Please see the documentation for more detail. +--- +repository_root: "{default.repository.root}/openjdk/{platform}/{architecture}" +version: 1.7.0_+ +memory_sizes: + #metaspace: 64m.. + permgen: 64m.. +memory_heuristics: + heap: 75 + #metaspace: 10 + permgen: 10 + stack: 5 + native: 10 +>>>>>>> efcca67500c28a685cb647259ea3eafb53345db0 diff --git a/config/oracle_jre.yml.orig b/config/oracle_jre.yml.orig new file mode 100644 index 0000000000..53ba2197d8 --- /dev/null +++ b/config/oracle_jre.yml.orig @@ -0,0 +1,58 @@ +# Cloud Foundry Java Buildpack +# Copyright 2013-2015 the original author or authors. +# +# Licensed 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. + +# Configuration for JRE repositories keyed by vendor +<<<<<<< HEAD +# Pre Java 1.8, permgen was used instead of metaspace. Please see the documentation for more detail. + +# You must specify a the repository root of an Oracle JRE repository. Please see the documentation for more detail. +# e.g. repository_root: "http://example.com/oracle-jre/{platform}/{architecture}" +--- +jre: + version: 1.8.0_+ + repository_root: "" +memory_calculator: + version: 1.+ + repository_root: ! '{default.repository.root}/memory-calculator/{platform}/{architecture}' + memory_sizes: + heap: + metaspace: 64m.. + native: + permgen: 64m.. + stack: + memory_heuristics: + heap: 75 + metaspace: 10 + native: 10 + permgen: 10 + stack: 5 +======= +# From Java 1.8 onwards, metaspace should be used instead of permgen. Please see the documentation for more detail. +--- +# You must specify a the repository root of an Oracle JRE repository. Please see the documentation for more detail. +# e.g. repository_root: "http://example.com/oracle-jre/{platform}/{architecture}" + +repository_root: "" +version: 1.7.0_+ +memory_sizes: + # metaspace: 64m.. + permgen: 64m.. +memory_heuristics: + heap: 75 + # metaspace: 10 + permgen: 10 + stack: 5 + native: 10 +>>>>>>> efcca67500c28a685cb647259ea3eafb53345db0 diff --git a/config/tomcat.yml.orig b/config/tomcat.yml.orig new file mode 100644 index 0000000000..5aa6c11d88 --- /dev/null +++ b/config/tomcat.yml.orig @@ -0,0 +1,60 @@ +# Cloud Foundry Java Buildpack +# Copyright 2013-2015 the original author or authors. +# +# Licensed 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. + +# Configuration for the Tomcat container +--- +tomcat: +<<<<<<< HEAD + version: 8.0.+ + repository_root: ! '{default.repository.root}/tomcat' +======= + version: 7.0.55 + repository_root: "{default.repository.root}/tomcat" +>>>>>>> efcca67500c28a685cb647259ea3eafb53345db0 +lifecycle_support: + version: 2.+ + repository_root: ! '{default.repository.root}/tomcat-lifecycle-support' +logging_support: + version: 2.+ + repository_root: ! '{default.repository.root}/tomcat-logging-support' +access_logging_support: + version: 2.+ + repository_root: ! '{default.repository.root}/tomcat-access-logging-support' + access_logging: disabled +redis_store: + version: 1.+ + repository_root: ! '{default.repository.root}/redis-store' + database: 0 + timeout: 2000 + connection_pool_size: 2 +gemfire_store: + gemfire: + version: 8.0.+ + repository_root: ! '{default.repository.root}/gem-fire' + gemfire_modules: + version: 8.0.+ + repository_root: ! '{default.repository.root}/gem-fire-modules' + gemfire_modules_tomcat7: + version: 8.0.+ + repository_root: ! '{default.repository.root}/gem-fire-modules-tomcat7' + gemfire_security: + version: 8.0.+ + repository_root: ! '{default.repository.root}/gem-fire-security' + gemfire_logging: + version: 1.5.8 + repository_root: ! '{default.repository.root}/slf4j-jdk14' + gemfire_logging_api: + version: 1.5.8 + repository_root: ! '{default.repository.root}/slf4j-api' diff --git a/config/vertx.yml b/config/vertx.yml new file mode 100644 index 0000000000..0c7fc32cc9 --- /dev/null +++ b/config/vertx.yml @@ -0,0 +1,3 @@ +--- +version: 3.0.0 +repository_root: "https://dl.bintray.com/ringgi/vertxcf" diff --git a/docs/container-dist_zip.md b/docs/container-dist_zip.md index 41fe602150..fde41f52b4 100644 --- a/docs/container-dist_zip.md +++ b/docs/container-dist_zip.md @@ -16,11 +16,8 @@ The Dist Zip Container allows applications packaged in [`distZip`-style][] to be Tags are printed to standard output by the buildpack detect script -If the application uses Spring, [Spring profiles][] can be specified by setting the [`SPRING_PROFILES_ACTIVE`][] environment variable. This is automatically detected and used by Spring. The Spring Auto-reconfiguration Framework will specify the `cloud` profile in addition to any others. - ## Configuration The Dist Zip Container cannot be configured. + [`distZip`-style]: http://www.gradle.org/docs/current/userguide/application_plugin.html -[Spring profiles]:http://blog.springsource.com/2011/02/14/spring-3-1-m1-introducing-profile/ -[`SPRING_PROFILES_ACTIVE`]: http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/core/env/AbstractEnvironment.html#ACTIVE_PROFILES_PROPERTY_NAME diff --git a/docs/container-java_main.md b/docs/container-java_main.md index d311e85a2d..a1750512b8 100644 --- a/docs/container-java_main.md +++ b/docs/container-java_main.md @@ -18,8 +18,6 @@ Command line arguments may optionally be configured. Tags are printed to standard output by the buildpack detect script -If the application uses Spring, [Spring profiles][] can be specified by setting the [`SPRING_PROFILES_ACTIVE`][] environment variable. This is automatically detected and used by Spring. The Spring Auto-reconfiguration Framework will specify the `cloud` profile in addition to any others. - ## Spring Boot If the main class is Spring Boot's `JarLauncher`, `PropertiesLauncher` or `WarLauncher`, the Java Main Container adds a `--server.port` argument to the command so that the application uses the correct port. @@ -34,5 +32,3 @@ The container can be configured by creating or modifying the `config/java_main.y | `java_main_class` | The Java class name to run. Values containing whitespace are rejected with an error, but all others values appear without modification on the Java command line. If not specified, the Java Manifest value of `Main-Class` is used. [Configuration and Extension]: ../README.md#configuration-and-extension -[Spring profiles]:http://blog.springsource.com/2011/02/14/spring-3-1-m1-introducing-profile/ -[`SPRING_PROFILES_ACTIVE`]: http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/core/env/AbstractEnvironment.html#ACTIVE_PROFILES_PROPERTY_NAME diff --git a/docs/container-spring_boot.md b/docs/container-spring_boot.md index 7e7f030fb8..df7e082c3e 100644 --- a/docs/container-spring_boot.md +++ b/docs/container-spring_boot.md @@ -15,12 +15,8 @@ Tags are printed to standard output by the buildpack detect script The container expects to run the application creating by running [`gradle distZip`][d] in an application built with the Spring Boot Gradle plugin. -If the application uses Spring, [Spring profiles][] can be specified by setting the [`SPRING_PROFILES_ACTIVE`][] environment variable. This is automatically detected and used by Spring. The Spring Auto-reconfiguration Framework will specify the `cloud` profile in addition to any others. - ## Configuration The Spring Boot Container cannot be configured. [d]: http://docs.spring.io/spring-boot/docs/1.0.1.RELEASE/reference/htmlsingle/#using-boot-gradle [s]: http://projects.spring.io/spring-boot/ -[Spring profiles]:http://blog.springsource.com/2011/02/14/spring-3-1-m1-introducing-profile/ -[`SPRING_PROFILES_ACTIVE`]: http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/core/env/AbstractEnvironment.html#ACTIVE_PROFILES_PROPERTY_NAME diff --git a/docs/container-spring_boot_cli.md b/docs/container-spring_boot_cli.md index 4c0d82ac8f..0288b4e2d8 100644 --- a/docs/container-spring_boot_cli.md +++ b/docs/container-spring_boot_cli.md @@ -19,7 +19,7 @@ The Spring Boot CLI Container runs one or more Groovy (i.e. `*.groovy`) files us Tags are printed to standard output by the buildpack detect script. -If the application uses Spring, [Spring profiles][] can be specified by setting the [`SPRING_PROFILES_ACTIVE`][] environment variable. This is automatically detected and used by Spring. The Spring Auto-reconfiguration Framework will specify the `cloud` profile in addition to any others. +In order to specify [Spring profiles][], set the [`SPRING_PROFILES_ACTIVE`][] environment variable. This is automatically detected and used by Spring. ## Configuration For general information on configuring the buildpack, refer to [Configuration and Extension][]. diff --git a/docs/container-tomcat.md b/docs/container-tomcat.md index 1b08a8932f..f7788765cd 100644 --- a/docs/container-tomcat.md +++ b/docs/container-tomcat.md @@ -12,7 +12,7 @@ The Tomcat Container allows servlet 2 and 3 web applications to be run. These a Tags are printed to standard output by the buildpack detect script -If the application uses Spring, [Spring profiles][] can be specified by setting the [`SPRING_PROFILES_ACTIVE`][] environment variable. This is automatically detected and used by Spring. The Spring Auto-reconfiguration Framework will specify the `cloud` profile in addition to any others. +In order to specify [Spring profiles][], set the [`SPRING_PROFILES_ACTIVE`][] environment variable. This is automatically detected and used by Spring. ## Configuration For general information on configuring the buildpack, refer to [Configuration and Extension][]. diff --git a/docs/container-vertx.md b/docs/container-vertx.md new file mode 100644 index 0000000000..760375db46 --- /dev/null +++ b/docs/container-vertx.md @@ -0,0 +1,24 @@ +# Vertx Container +The Vertx Container allows [Vertx][r] modules to be deployed. You will need to setup a module with a mod.json file and push its contents using this buildpack. + + + + + + + + + + +
Detection CriteriaA valid mod.json file located on your directory
Tagsvertx=<version>
+Tags are printed to standard output by the buildpack detect script + +There's no support for HA or distributed EventBus at the moment. Since [Hazelcast][h] uses multicast for its P2P discovery, its going to be tricky to get this working. + +The buildpack expect either a zipfile with the mod.json or an exploded directory. Internally the buildpack will deploy it as a zip and use vertx runzip . The generated ZIPFILE is named after -1.0.0.zip. + +## Configuration +The Vertx Container cannot be configured. + +[r]: http://www.vertx.io +[h]: http://www.hazelcast.org diff --git a/docs/extending-repositories.md b/docs/extending-repositories.md index 82e5ea9434..5e626289f3 100644 --- a/docs/extending-repositories.md +++ b/docs/extending-repositories.md @@ -67,13 +67,6 @@ Repositories can be configured by modifying the [`config/repository.yml`][] file | ---- | ----------- | `default_repository_root` | This property can take a URI that is used as a common root for all of the repositories used by the buildpack. The value is substituted for the `{default.repository.root}` variable in `repository_root` declarations. -## Proxies -Access to repositories may be affected by the existence of network proxies. In order to configure the buildpack to use a proxy, set the `http_proxy`, `HTTP_PROXY`, `https_proxy`, or `HTTPS_PROXY` environment variables with the property proxy URI. Proxy authentication crendentials can be embedded in the URI if needed. - -```bash -cf set-env http_proxy http://username:password@host:port -``` - ## Version Syntax and Ordering Versions are composed of major, minor, micro, and optional qualifier parts (`..[_]`). The major, minor, and micro parts must be numeric. The qualifier part is composed of letters, digits, and hyphens. The lexical ordering of the qualifier is: diff --git a/docs/framework-spring_auto_reconfiguration.md b/docs/framework-spring_auto_reconfiguration.md index 86b0708e65..515693c216 100644 --- a/docs/framework-spring_auto_reconfiguration.md +++ b/docs/framework-spring_auto_reconfiguration.md @@ -13,7 +13,7 @@ The Spring Auto-reconfiguration Framework causes an application to be automatica Tags are printed to standard output by the buildpack detect script -If a `/WEB-INF/web.xml` file exists, the framework will modify it in addition to making the auto-reconfiguration JAR available on the classpath. This modification consists of adding `org.cloudfoundry.reconfiguration.spring.CloudProfileApplicationContextInitializer`, `org.cloudfoundry.reconfiguration.spring.CloudPropertySourceApplicationContextInitializer`, and `org.cloudfoundry.reconfiguration.spring.CloudAutoReconfigurationApplicationContextInitializer` to the collection of `contextInitializerClasses`. The Spring Auto-reconfiguration Framework also adds the `cloud` profile to any existing Spring profiles such as those defined in the [`SPRING_PROFILES_ACTIVE`][] environment variable. +If a `/WEB-INF/web.xml` file exists, the framework will modify it in addition to making the auto-reconfiguration JAR available on the classpath. This modification consists of adding `org.cloudfoundry.reconfiguration.spring.CloudProfileApplicationContextInitializer`, `org.cloudfoundry.reconfiguration.spring.CloudPropertySourceApplicationContextInitializer`, and `org.cloudfoundry.reconfiguration.spring.CloudAutoReconfigurationApplicationContextInitializer` to the collection of `contextInitializerClasses`. ## Configuration For general information on configuring the buildpack, refer to [Configuration and Extension][]. @@ -31,4 +31,3 @@ The framework can be configured by modifying the [`config/spring_auto_reconfigur [repositories]: extending-repositories.md [this listing]: http://download.pivotal.io.s3.amazonaws.com/auto-reconfiguration/index.yml [version syntax]: extending-repositories.md#version-syntax-and-ordering -[`SPRING_PROFILES_ACTIVE`]: http://docs.spring.io/spring/docs/4.0.0.RELEASE/javadoc-api/org/springframework/core/env/AbstractEnvironment.html#ACTIVE_PROFILES_PROPERTY_NAME diff --git a/lib/java_buildpack/container/dist_zip.rb b/lib/java_buildpack/container/dist_zip.rb index 8d11898a9b..2e304bbc8d 100644 --- a/lib/java_buildpack/container/dist_zip.rb +++ b/lib/java_buildpack/container/dist_zip.rb @@ -48,6 +48,7 @@ def supports? start_script(root) && start_script(root).exist? && jars? && + !verticle? && !@ratpack_utils.is?(@application) && !@spring_boot_utils.is?(@application) && !JavaBuildpack::Util::Play::Factory.create(@droplet) @@ -63,6 +64,12 @@ def lib_dir root + 'lib' end + def verticle? + (@application.root + 'mod.json').exist? + end + + + end end diff --git a/lib/java_buildpack/container/vertx.rb b/lib/java_buildpack/container/vertx.rb new file mode 100644 index 0000000000..acf83b1e86 --- /dev/null +++ b/lib/java_buildpack/container/vertx.rb @@ -0,0 +1,53 @@ +require 'java_buildpack/component/versioned_dependency_component' +require 'java_buildpack/container' + +module JavaBuildpack + module Container + class Vertx < JavaBuildpack::Component::VersionedDependencyComponent + + def initialize(context) + super(context) + end + + def supports? + verticle? + end + + def compile + download(@version,@uri) {|file| expand file} + FileUtils.mkdir_p apps + shell "zip -j #{zip_name} #{@droplet.root}/*" + end + + def release + [ + @droplet.java_home.as_env_var, + @droplet.java_opts.as_env_var, + "$PWD/#{(@droplet.sandbox + 'bin/vertx').relative_path_from(@droplet.root)}", + 'runzip', + "$PWD/#{(@droplet.sandbox+'apps').relative_path_from(@droplet.root)}/#{@application.details['application_name']}-1.0.0.zip" + + ].flatten.compact.join(' ') + end + + def zip_name + "#{apps}/#{@application.details['application_name']}-1.0.0.zip" + end + + def apps + @droplet.sandbox + "apps" + end + + def verticle? + (@application.root + 'mod.json').exist? + end + + def expand(file) + with_timing "Expanding Vertx to #{@droplet.sandbox.relative_path_from(@droplet.root)}" do + FileUtils.mkdir_p @droplet.sandbox + shell "tar xzf #{file.path} -C #{@droplet.sandbox} --strip 1 2>&1" + end + end + end + end +end diff --git a/lib/java_buildpack/repository/repository_index.rb.orig b/lib/java_buildpack/repository/repository_index.rb.orig new file mode 100644 index 0000000000..d9cf31fab3 --- /dev/null +++ b/lib/java_buildpack/repository/repository_index.rb.orig @@ -0,0 +1,108 @@ +# Encoding: utf-8 +# Cloud Foundry Java Buildpack +# Copyright 2013-2015 the original author or authors. +# +# Licensed 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. + +require 'java_buildpack/logging/logger_factory' +require 'java_buildpack/repository' +require 'java_buildpack/repository/version_resolver' +require 'java_buildpack/util/cache' +require 'java_buildpack/util/cache/download_cache' +require 'java_buildpack/util/configuration_utils' +require 'rbconfig' +require 'yaml' + +module JavaBuildpack + module Repository + + # A repository index represents the index of repository containing various versions of a file. + class RepositoryIndex + + # Creates a new repository index, populating it with values from an index file. + # + # @param [String] repository_root the root of the repository to create the index for + def initialize(repository_root) + @logger = JavaBuildpack::Logging::LoggerFactory.instance.get_logger RepositoryIndex + + @default_repository_root = JavaBuildpack::Util::ConfigurationUtils.load('repository')['default_repository_root'] + .chomp('/') + + cache.get("#{canonical repository_root}#{INDEX_PATH}") do |file| + @index = YAML.load_file(file) + @logger.debug { @index } + end + end + + # Finds a version of the file matching the given, possibly wildcarded, version. + # + # @param [String] version the possibly wildcarded version to find + # @return [TokenizedVersion] the version of the file found + # @return [String] the URI of the file found + def find_item(version) +<<<<<<< HEAD + found_version = VersionResolver.resolve(version, @index.keys) + fail "No version resolvable for '#{version}' in #{@index.keys.join(', ')}" if found_version.nil? + uri = @index[found_version.to_s] + [found_version, uri] +======= + version = VersionResolver.resolve(version, @index.keys) + uri = @index[version.to_s] + [version, uri] +>>>>>>> efcca67500c28a685cb647259ea3eafb53345db0 + end + + private + + INDEX_PATH = '/index.yml'.freeze + + private_constant :INDEX_PATH + + def architecture + `uname -m`.strip + end + + def cache + JavaBuildpack::Util::Cache::DownloadCache.new(Pathname.new(Dir.tmpdir), + JavaBuildpack::Util::Cache::CACHED_RESOURCES_DIRECTORY) + end + + def canonical(raw) + cooked = raw + .gsub(/\{default.repository.root\}/, @default_repository_root) + .gsub(/\{platform\}/, platform) + .gsub(/\{architecture\}/, architecture) + .chomp('/') + @logger.debug { "#{raw} expanded to #{cooked}" } + cooked + end + + def platform + redhat_release = Pathname.new('/etc/redhat-release') + + if redhat_release.exist? + tokens = redhat_release.read.match(/(\w+) (?:Linux )?release (\d+)/) + "#{tokens[1].downcase}#{tokens[2]}" + elsif `uname -s` =~ /Darwin/ + 'mountainlion' + elsif !`which lsb_release 2> /dev/null`.empty? + `lsb_release -cs`.strip + else + fail 'Unable to determine platform' + end + end + + end + + end +end diff --git a/lib/java_buildpack/repository/version_resolver.rb b/lib/java_buildpack/repository/version_resolver.rb index 4a72cf642b..6fb865e395 100644 --- a/lib/java_buildpack/repository/version_resolver.rb +++ b/lib/java_buildpack/repository/version_resolver.rb @@ -35,7 +35,8 @@ class << self # @param [TokenizedVersion] candidate_version the version, possibly containing a wildcard, to resolve. If # +nil+, substituted with +. # @param [Array] versions the collection of versions to resolve against - # @return [TokenizedVersion] the resolved version or nil if no matching version is found + # @return [TokenizedVersion] the resolved version + # @raise if no version can be resolved def resolve(candidate_version, versions) tokenized_candidate_version = safe_candidate_version candidate_version tokenized_versions = versions.map do |version| @@ -46,6 +47,7 @@ def resolve(candidate_version, versions) .select { |tokenized_version| matches? tokenized_candidate_version, tokenized_version } .max { |a, b| a <=> b } + fail "No version resolvable for '#{candidate_version}' in #{versions.join(', ')}" if version.nil? version end diff --git a/rakelib/dependency_cache_task.rb b/rakelib/dependency_cache_task.rb index 26d160fcf3..9e0b1f1301 100644 --- a/rakelib/dependency_cache_task.rb +++ b/rakelib/dependency_cache_task.rb @@ -55,44 +55,35 @@ def initialize private_constant :ARCHITECTURE_PATTERN, :DEFAULT_REPOSITORY_ROOT_PATTERN, :PLATFORM_PATTERN - def augment(raw, key, pattern, candidates, &block) - if raw.respond_to? :at + def augment(raw, pattern, candidates, &block) + if raw.respond_to? :map raw.map(&block) else - if raw[:uri] =~ pattern - candidates.map do |candidate| - dup = raw.clone - dup[key] = candidate - dup[:uri] = raw[:uri].gsub pattern, candidate - - dup - end - else - raw - end + raw =~ pattern ? candidates.map { |p| raw.gsub pattern, p } : raw end end def augment_architecture(raw) - augment(raw, :architecture, ARCHITECTURE_PATTERN, ARCHITECTURES) { |r| augment_architecture r } + augment(raw, ARCHITECTURE_PATTERN, ARCHITECTURES) { |r| augment_architecture r } end def augment_path(raw) - if raw.respond_to? :at + if raw.respond_to? :map raw.map { |r| augment_path r } else - raw[:uri] = "#{raw[:uri].chomp('/')}/index.yml" - raw + "#{raw.chomp('/')}/index.yml" end end def augment_platform(raw) - augment(raw, :platform, PLATFORM_PATTERN, PLATFORMS) { |r| augment_platform r } + augment(raw, PLATFORM_PATTERN, PLATFORMS) { |r| augment_platform r } end def augment_repository_root(raw) - augment(raw, :repository_root, DEFAULT_REPOSITORY_ROOT_PATTERN, [@default_repository_root]) do |r| - augment_repository_root r + if raw.respond_to? :map + raw.map { |r| augment_repository_root r } + else + raw.gsub DEFAULT_REPOSITORY_ROOT_PATTERN, @default_repository_root end end @@ -139,13 +130,12 @@ def default_repository_root configuration('repository')['default_repository_root'].chomp('/') end - def index_configuration(configuration) + def index_uris(configuration) [configuration['repository_root']] - .map { |r| { uri: r } } - .map { |r| augment_repository_root r } - .map { |r| augment_platform r } - .map { |r| augment_architecture r } - .map { |r| augment_path r }.flatten + .map { |r| augment_repository_root r } + .map { |r| augment_platform r } + .map { |r| augment_architecture r } + .map { |r| augment_path r }.flatten end def repository_configuration?(configuration) @@ -156,9 +146,13 @@ def uris(configurations) uris = [] configurations.each do |configuration| - index_configuration(configuration).each do |index_configuration| - multitask PACKAGE_NAME => [cache_task(index_configuration[:uri])] - get_from_cache(configuration, index_configuration, uris) + index_uris(configuration).each do |index_uri| + multitask PACKAGE_NAME => [cache_task(index_uri)] + + @cache.get(index_uri) do |f| + index = YAML.load f + uris << index[version(configuration, index).to_s] + end end end diff --git a/rakelib/dependency_cache_task.rb.orig b/rakelib/dependency_cache_task.rb.orig new file mode 100644 index 0000000000..86ace8e935 --- /dev/null +++ b/rakelib/dependency_cache_task.rb.orig @@ -0,0 +1,222 @@ +# Encoding: utf-8 +# Cloud Foundry Java Buildpack +# Copyright (c) 2014 the original author or authors. +# +# Licensed 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. + +$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) + +require 'java_buildpack/logging/logger_factory' +require 'java_buildpack/repository/version_resolver' +require 'java_buildpack/util/configuration_utils' +require 'java_buildpack/util/cache/download_cache' +require 'java_buildpack/util/snake_case' +require 'monitor' +require 'rake/tasklib' +require 'rakelib/package' +require 'pathname' +require 'yaml' + +module Package + + class DependencyCacheTask < Rake::TaskLib + include Package + + def initialize + return unless BUILDPACK_VERSION.offline + + JavaBuildpack::Logging::LoggerFactory.instance.setup "#{BUILD_DIR}/" + + @default_repository_root = default_repository_root + @cache = cache + @monitor = Monitor.new + + configurations = component_ids.map { |component_id| component_configuration(component_id) }.flatten + uris(configurations).each { |uri| multitask PACKAGE_NAME => [cache_task(uri)] } + end + + private + + ARCHITECTURE_PATTERN = /\{architecture\}/.freeze + + DEFAULT_REPOSITORY_ROOT_PATTERN = /\{default.repository.root\}/.freeze + + PLATFORM_PATTERN = /\{platform\}/.freeze + + private_constant :ARCHITECTURE_PATTERN, :DEFAULT_REPOSITORY_ROOT_PATTERN, :PLATFORM_PATTERN + + def augment(raw, pattern, candidates, &block) + if raw.respond_to? :map + raw.map(&block) + else + raw =~ pattern ? candidates.map { |p| raw.gsub pattern, p } : raw + end + end + + def augment_architecture(raw) + augment(raw, ARCHITECTURE_PATTERN, ARCHITECTURES) { |r| augment_architecture r } + end + + def augment_path(raw) + if raw.respond_to? :map + raw.map { |r| augment_path r } + else + "#{raw.chomp('/')}/index.yml" + end + end + + def augment_platform(raw) + augment(raw, PLATFORM_PATTERN, PLATFORMS) { |r| augment_platform r } + end + + def augment_repository_root(raw) +<<<<<<< HEAD + augment(raw, :repository_root, DEFAULT_REPOSITORY_ROOT_PATTERN, [@default_repository_root]) do |r| + augment_repository_root r +======= + if raw.respond_to? :map + raw.map { |r| augment_repository_root r } + else + raw.gsub DEFAULT_REPOSITORY_ROOT_PATTERN, @default_repository_root +>>>>>>> efcca67500c28a685cb647259ea3eafb53345db0 + end + end + + def cache + JavaBuildpack::Util::Cache::DownloadCache.new(Pathname.new("#{STAGING_DIR}/resources/cache")).freeze + end + + def cache_task(uri) + task uri do |t| + @monitor.synchronize { rake_output_message "Caching #{t.name}" } + cache.get(t.name) {} + end + + uri + end + + def component_ids + configuration('components').values.flatten.map { |component| component.split('::').last.snake_case } + end + + def configuration(id) + JavaBuildpack::Util::ConfigurationUtils.load(id, false, false) + end + + def configurations(component_id, configuration, sub_component_id = nil) + configurations = [] + + if repository_configuration?(configuration) + configuration['component_id'] = component_id + configuration['sub_component_id'] = sub_component_id if sub_component_id + configurations << configuration + else + configuration.each { |k, v| configurations << configurations(component_id, v, k) if v.is_a? Hash } + end + + configurations + end + + def component_configuration(component_id) + configurations(component_id, configuration(component_id)) + end + + def default_repository_root + configuration('repository')['default_repository_root'].chomp('/') + end + + def index_uris(configuration) + [configuration['repository_root']] +<<<<<<< HEAD + .map { |r| { uri: r } } + .map { |r| augment_repository_root r } + .map { |r| augment_platform r } + .map { |r| augment_architecture r } + .map { |r| augment_path r }.flatten +======= + .map { |r| augment_repository_root r } + .map { |r| augment_platform r } + .map { |r| augment_architecture r } + .map { |r| augment_path r }.flatten +>>>>>>> efcca67500c28a685cb647259ea3eafb53345db0 + end + + def repository_configuration?(configuration) + configuration['version'] && configuration['repository_root'] + end + + def uris(configurations) + uris = [] + + configurations.each do |configuration| +<<<<<<< HEAD + index_configuration(configuration).each do |index_configuration| + multitask PACKAGE_NAME => [cache_task(index_configuration[:uri])] + get_from_cache(configuration, index_configuration, uris) +======= + index_uris(configuration).each do |index_uri| + multitask PACKAGE_NAME => [cache_task(index_uri)] + + @cache.get(index_uri) do |f| + index = YAML.load f + uris << index[version(configuration, index).to_s] + end +>>>>>>> efcca67500c28a685cb647259ea3eafb53345db0 + end + end + + uris + end + + def get_from_cache(configuration, index_configuration, uris) + @cache.get(index_configuration[:uri]) do |f| + index = YAML.load f + found_version = version(configuration, index) + pin_version(configuration, found_version.to_s) if ENV['PINNED'].to_b + + if found_version.nil? + rake_output_message "Unable to resolve version '#{configuration['version']}' for platform " \ + "'#{index_configuration[:platform]}'" + end + + uris << index[found_version.to_s] unless found_version.nil? + end + end + + def pin_version(old_configuration, version) + component_id = old_configuration['component_id'] + sub_component_id = old_configuration['sub_component_id'] + rake_output_message "Pinning #{sub_component_id ? sub_component_id : component_id} version to #{version}" + configuration_to_update = JavaBuildpack::Util::ConfigurationUtils.load(component_id, false, true) + update_configuration(configuration_to_update, version, sub_component_id) + JavaBuildpack::Util::ConfigurationUtils.write(component_id, configuration_to_update) + end + + def update_configuration(config, version, sub_component) + if sub_component.nil? + config['version'] = version + elsif config.key?(sub_component) + config[sub_component]['version'] = version + else + config.values.each { |v| update_configuration(v, version, sub_component) if v.is_a? Hash } + end + end + + def version(configuration, index) + JavaBuildpack::Repository::VersionResolver.resolve( + JavaBuildpack::Util::TokenizedVersion.new(configuration['version']), index.keys) + end + + end + +end diff --git a/resources/vertx/index.yml b/resources/vertx/index.yml new file mode 100644 index 0000000000..8bf5d9773b --- /dev/null +++ b/resources/vertx/index.yml @@ -0,0 +1 @@ +3.0.0 : http://dl.bintray.com/vertx/downloads/vert.x-3.0.0-full.tar.gz \ No newline at end of file diff --git a/spec/java_buildpack/repository/version_resolver_spec.rb.orig b/spec/java_buildpack/repository/version_resolver_spec.rb.orig new file mode 100644 index 0000000000..2f173dd4ed --- /dev/null +++ b/spec/java_buildpack/repository/version_resolver_spec.rb.orig @@ -0,0 +1,72 @@ +# Encoding: utf-8 +# Cloud Foundry Java Buildpack +# Copyright 2013-2015 the original author or authors. +# +# Licensed 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. + +require 'spec_helper' +require 'java_buildpack/repository/version_resolver' +require 'java_buildpack/util/tokenized_version' + +describe JavaBuildpack::Repository::VersionResolver do + + let(:versions) { %w(1.6.0_26 1.6.0_27 1.6.1_14 1.7.0_19 1.7.0_21 1.8.0_M-7 1.8.0_05 2.0.0) } + + it 'resolves the default version if no candidate is supplied' do + expect(described_class.resolve(nil, versions)).to eq(tokenized_version('2.0.0')) + end + + it 'resolves a wildcard major version' do + expect(described_class.resolve(tokenized_version('+'), versions)).to eq(tokenized_version('2.0.0')) + end + + it 'resolves a wildcard minor version' do + expect(described_class.resolve(tokenized_version('1.+'), versions)).to eq(tokenized_version('1.8.0_05')) + end + + it 'resolves a wildcard micro version' do + expect(described_class.resolve(tokenized_version('1.6.+'), versions)).to eq(tokenized_version('1.6.1_14')) + end + + it 'resolves a wildcard qualifier' do + expect(described_class.resolve(tokenized_version('1.6.0_+'), versions)).to eq(tokenized_version('1.6.0_27')) + expect(described_class.resolve(tokenized_version('1.8.0_+'), versions)).to eq(tokenized_version('1.8.0_05')) + end + + it 'resolves a non-wildcard version' do + expect(described_class.resolve(tokenized_version('1.6.0_26'), versions)).to eq(tokenized_version('1.6.0_26')) + expect(described_class.resolve(tokenized_version('2.0.0'), versions)).to eq(tokenized_version('2.0.0')) + end + + it 'resolves a non-digit qualifier' do + expect(described_class.resolve(tokenized_version('1.8.0_M-7'), versions)).to eq(tokenized_version('1.8.0_M-7')) + end + +<<<<<<< HEAD + it 'raises an exception if no version can be resolved' do + expect(described_class.resolve(tokenized_version('2.1.0'), versions)).to be_nil +======= + it 'should raise an exception if no version can be resolved' do + expect { described_class.resolve(tokenized_version('2.1.0'), versions) }.to raise_error +>>>>>>> efcca67500c28a685cb647259ea3eafb53345db0 + end + + it 'raises an exception when a wildcard is specified in the [] collection' do + expect { described_class.resolve(tokenized_version('1.6.0_25'), %w(+)) }.to raise_error(/Invalid/) + end + + def tokenized_version(s) + JavaBuildpack::Util::TokenizedVersion.new(s) + end + +end