|
| 1 | +# Cloud Foundry Java Buildpack |
| 2 | +# Copyright 2013-2017 the original author or authors. |
| 3 | +# |
| 4 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | +# you may not use this file except in compliance with the License. |
| 6 | +# You may obtain a copy of the License at |
| 7 | +# |
| 8 | +# http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | +# |
| 10 | +# Unless required by applicable law or agreed to in writing, software |
| 11 | +# distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | +# See the License for the specific language governing permissions and |
| 14 | +# limitations under the License. |
| 15 | + |
| 16 | +require 'fileutils' |
| 17 | +require 'pathname' |
| 18 | +require 'java_buildpack/component/base_component' |
| 19 | +require 'java_buildpack/framework' |
| 20 | +require 'java_buildpack/logging/logger_factory' |
| 21 | +require 'java_buildpack/util/qualify_path' |
| 22 | +require 'yaml' |
| 23 | + |
| 24 | +module JavaBuildpack |
| 25 | + module Framework |
| 26 | + |
| 27 | + # Encapsulates the functionality for multi buildpack support. |
| 28 | + class MultiBuildpack < JavaBuildpack::Component::BaseComponent |
| 29 | + include JavaBuildpack::Util |
| 30 | + |
| 31 | + # (see JavaBuildpack::Component::BaseComponent#initialize) |
| 32 | + def initialize(context) |
| 33 | + super(context) |
| 34 | + |
| 35 | + @logger = JavaBuildpack::Logging::LoggerFactory.instance.get_logger MultiBuildpack |
| 36 | + @logger.debug { "Dependencies Directory: #{ARGV[3]}" } |
| 37 | + end |
| 38 | + |
| 39 | + # (see JavaBuildpack::Component::BaseComponent#detect) |
| 40 | + def detect |
| 41 | + !dep_directories.empty? ? "multi-buildpack=#{names(dep_directories).join(',')}" : nil |
| 42 | + end |
| 43 | + |
| 44 | + # (see JavaBuildpack::Component::BaseComponent#compile) |
| 45 | + def compile |
| 46 | + puts "#{'----->'.red.bold} #{'Multiple Buildpacks'.blue.bold} detected" |
| 47 | + |
| 48 | + dep_directories.each do |dep_directory| |
| 49 | + config = config(config_file(dep_directory)) |
| 50 | + name = name(config) |
| 51 | + |
| 52 | + log_configuration config |
| 53 | + log_dep_contents dep_directory |
| 54 | + |
| 55 | + contributions = [ |
| 56 | + add_bin(dep_directory), |
| 57 | + add_lib(dep_directory), |
| 58 | + add_additional_libraries(config), |
| 59 | + add_environment_variables(config), |
| 60 | + add_extension_directories(config), |
| 61 | + add_java_opts(config), |
| 62 | + add_security_providers(config) |
| 63 | + ] |
| 64 | + |
| 65 | + puts " #{name}#{contributions_message(contributions)}" |
| 66 | + end |
| 67 | + end |
| 68 | + |
| 69 | + # (see JavaBuildpack::Component::BaseComponent#release) |
| 70 | + def release |
| 71 | + dep_directories.each do |dep_directory| |
| 72 | + config = config(config_file(dep_directory)) |
| 73 | + |
| 74 | + add_bin(dep_directory) |
| 75 | + add_lib(dep_directory) |
| 76 | + add_additional_libraries(config) |
| 77 | + add_environment_variables(config) |
| 78 | + add_extension_directories(config) |
| 79 | + add_java_opts(config) |
| 80 | + add_security_providers(config) |
| 81 | + end |
| 82 | + end |
| 83 | + |
| 84 | + private |
| 85 | + |
| 86 | + def add_additional_libraries(config) |
| 87 | + additional_libraries = config['config']['additional_libraries'] |
| 88 | + return unless additional_libraries |
| 89 | + |
| 90 | + additional_libraries.each do |additional_library| |
| 91 | + @droplet.additional_libraries << Pathname.new(additional_library) |
| 92 | + end |
| 93 | + |
| 94 | + 'Additional Libraries' |
| 95 | + end |
| 96 | + |
| 97 | + def add_agentpaths(java_opts) |
| 98 | + agentpaths = java_opts['agentpaths'] |
| 99 | + return unless agentpaths |
| 100 | + |
| 101 | + agentpaths.each do |agentpath| |
| 102 | + @droplet.java_opts.add_agentpath Pathname.new(agentpath) |
| 103 | + end |
| 104 | + |
| 105 | + 'Agents' |
| 106 | + end |
| 107 | + |
| 108 | + def add_agentpaths_with_props(java_opts) |
| 109 | + agentpaths = java_opts['agentpaths_with_props'] |
| 110 | + return unless agentpaths |
| 111 | + |
| 112 | + agentpaths.each do |agentpath, props| |
| 113 | + @droplet.java_opts.add_agentpath_with_props Pathname.new(agentpath), props |
| 114 | + end |
| 115 | + |
| 116 | + 'Agent with Properties' |
| 117 | + end |
| 118 | + |
| 119 | + def add_bin(dep_directory) |
| 120 | + bin_directory = dep_directory + 'bin' |
| 121 | + return unless bin_directory.exist? |
| 122 | + |
| 123 | + @droplet.environment_variables |
| 124 | + .add_environment_variable('PATH', "$PATH:#{qualify_path(bin_directory, @droplet.root)}") |
| 125 | + |
| 126 | + '$PATH' |
| 127 | + end |
| 128 | + |
| 129 | + def add_bootclasspath_ps(java_opts) |
| 130 | + bootclasspath_ps = java_opts['bootclasspath_ps'] |
| 131 | + return unless bootclasspath_ps |
| 132 | + |
| 133 | + bootclasspath_ps.each do |bootclasspath_p| |
| 134 | + @droplet.java_opts.add_bootclasspath_p Pathname.new(bootclasspath_p) |
| 135 | + end |
| 136 | + |
| 137 | + 'Boot Classpaths' |
| 138 | + end |
| 139 | + |
| 140 | + def add_environment_variables(config) |
| 141 | + environment_variables = config['config']['environment_variables'] |
| 142 | + return unless environment_variables |
| 143 | + |
| 144 | + environment_variables.each do |key, value| |
| 145 | + path = Pathname.new(value) |
| 146 | + |
| 147 | + if path.exist? |
| 148 | + @droplet.environment_variables.add_environment_variable key, path |
| 149 | + else |
| 150 | + @droplet.environment_variables.add_environment_variable key, value |
| 151 | + end |
| 152 | + end |
| 153 | + |
| 154 | + 'Environment Variables' |
| 155 | + end |
| 156 | + |
| 157 | + def add_extension_directories(config) |
| 158 | + extension_directories = config['config']['extension_directories'] |
| 159 | + return unless extension_directories |
| 160 | + |
| 161 | + extension_directories.each do |extension_directory| |
| 162 | + @droplet.extension_directories << Pathname.new(extension_directory) |
| 163 | + end |
| 164 | + |
| 165 | + 'Extension Directories' |
| 166 | + end |
| 167 | + |
| 168 | + def add_javaagent(java_opts) |
| 169 | + javaagents = java_opts['javaagents'] |
| 170 | + return unless javaagents |
| 171 | + |
| 172 | + javaagents.each do |javaagent| |
| 173 | + @droplet.java_opts.add_javaagent Pathname.new(javaagent) |
| 174 | + end |
| 175 | + |
| 176 | + 'Java Agents' |
| 177 | + end |
| 178 | + |
| 179 | + def add_java_opts(config) |
| 180 | + java_opts = config['config']['java_opts'] |
| 181 | + return unless java_opts |
| 182 | + |
| 183 | + [ |
| 184 | + add_agentpaths(java_opts), |
| 185 | + add_agentpaths_with_props(java_opts), |
| 186 | + add_bootclasspath_ps(java_opts), |
| 187 | + add_javaagent(java_opts), |
| 188 | + add_options(java_opts), |
| 189 | + add_preformatted_options(java_opts), |
| 190 | + add_system_properties(java_opts) |
| 191 | + ] |
| 192 | + end |
| 193 | + |
| 194 | + def add_lib(dep_directory) |
| 195 | + lib_directory = dep_directory + 'lib' |
| 196 | + return unless lib_directory.exist? |
| 197 | + |
| 198 | + @droplet.environment_variables |
| 199 | + .add_environment_variable('LD_LIBRARY_PATH', |
| 200 | + "$LD_LIBRARY_PATH:#{qualify_path(lib_directory, @droplet.root)}") |
| 201 | + |
| 202 | + '$LD_LIBRARY_PATH' |
| 203 | + end |
| 204 | + |
| 205 | + def add_options(java_opts) |
| 206 | + options = java_opts['options'] |
| 207 | + return unless options |
| 208 | + |
| 209 | + options.each do |key, value| |
| 210 | + path = Pathname.new(value) |
| 211 | + |
| 212 | + if path.exist? |
| 213 | + @droplet.java_opts.add_option key, path |
| 214 | + else |
| 215 | + @droplet.java_opts.add_option key, value |
| 216 | + end |
| 217 | + end |
| 218 | + |
| 219 | + 'Options' |
| 220 | + end |
| 221 | + |
| 222 | + def add_preformatted_options(java_opts) |
| 223 | + preformatted_options = java_opts['preformatted_options'] |
| 224 | + return unless preformatted_options |
| 225 | + |
| 226 | + preformatted_options.each do |preformatted_option| |
| 227 | + @droplet.java_opts.add_preformatted_options preformatted_option |
| 228 | + end |
| 229 | + |
| 230 | + 'Preformatted Options' |
| 231 | + end |
| 232 | + |
| 233 | + def add_security_providers(config) |
| 234 | + security_providers = config['config']['security_providers'] |
| 235 | + return unless security_providers |
| 236 | + |
| 237 | + security_providers.each do |security_provider| |
| 238 | + @droplet.security_providers << security_provider |
| 239 | + end |
| 240 | + |
| 241 | + 'Security Providers' |
| 242 | + end |
| 243 | + |
| 244 | + def add_system_properties(java_opts) |
| 245 | + system_properties = java_opts['system_properties'] |
| 246 | + return unless system_properties |
| 247 | + |
| 248 | + system_properties.each do |key, value| |
| 249 | + path = Pathname.new(value) |
| 250 | + |
| 251 | + if path.exist? |
| 252 | + @droplet.java_opts.add_system_property key, path |
| 253 | + else |
| 254 | + @droplet.java_opts.add_system_property key, value |
| 255 | + end |
| 256 | + end |
| 257 | + |
| 258 | + 'System Properties' |
| 259 | + end |
| 260 | + |
| 261 | + def config(config_file) |
| 262 | + YAML.load_file(config_file) |
| 263 | + end |
| 264 | + |
| 265 | + def config_file(dep_directory) |
| 266 | + dep_directory + 'config.yml' |
| 267 | + end |
| 268 | + |
| 269 | + def contributions_message(contributions) |
| 270 | + return if contributions.compact.empty? |
| 271 | + " contributed to: #{contributions.flatten.compact.sort.join(', ')}" |
| 272 | + end |
| 273 | + |
| 274 | + def dep_directories |
| 275 | + deps = Pathname.glob('/tmp/*/deps').first |
| 276 | + return [] unless deps |
| 277 | + |
| 278 | + deps |
| 279 | + .children |
| 280 | + .select { |dep_directory| config_file(dep_directory).exist? } |
| 281 | + .sort_by(&:basename) |
| 282 | + end |
| 283 | + |
| 284 | + def log_configuration(config) |
| 285 | + @logger.debug { "Configuration: #{config}" } |
| 286 | + end |
| 287 | + |
| 288 | + def log_dep_contents(dep_directory) |
| 289 | + @logger.debug do |
| 290 | + paths = [] |
| 291 | + dep_directory.find { |f| paths << f.relative_path_from(dep_directory).to_s } |
| 292 | + |
| 293 | + "Application Contents (#{dep_directory}): #{paths}" |
| 294 | + end |
| 295 | + end |
| 296 | + |
| 297 | + def name(config) |
| 298 | + config['name'] |
| 299 | + end |
| 300 | + |
| 301 | + def names(dep_directories) |
| 302 | + dep_directories.map { |dep_directory| name(config(config_file(dep_directory))) } |
| 303 | + end |
| 304 | + |
| 305 | + end |
| 306 | + |
| 307 | + end |
| 308 | +end |
0 commit comments