| # 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. |
| |
| if RbConfig::CONFIG['host_os'] =~ /darwin/i |
| # On OS X we attempt to guess where JAVA_HOME is, if not set |
| # We set JAVA_HOME early so we can use it without calling Java.load first. |
| ENV['JAVA_HOME'] ||= '/System/Library/Frameworks/JavaVM.framework/Home' |
| end |
| |
| require 'rjb' |
| |
| |
| # Equivalent to Java system properties. For example: |
| # ENV_JAVA['java.version'] |
| # ENV_JAVA['java.class.version'] |
| ENV_JAVA = {} |
| |
| |
| # Buildr runs along side a JVM, using either RJB or JRuby. The Java module allows |
| # you to access Java classes and create Java objects. |
| # |
| # Java classes are accessed as static methods on the Java module, for example: |
| # str = Java.java.lang.String.new('hai!') |
| # str.toUpperCase |
| # => 'HAI!' |
| # Java.java.lang.String.isInstance(str) |
| # => true |
| # Java.com.sun.tools.javac.Main.compile(args) |
| # |
| # The classpath attribute allows Buildr to add JARs and directories to the classpath, |
| # for example, we use it to load Ant and various Ant tasks, code generators, test |
| # frameworks, and so forth. |
| # |
| # When using an artifact specification, Buildr will automatically download and |
| # install the artifact before adding it to the classpath. |
| # |
| # For example, Ant is loaded as follows: |
| # Java.classpath << 'org.apache.ant:ant:jar:1.7.0' |
| # |
| # Artifacts can only be downloaded after the Buildfile has loaded, giving it |
| # a chance to specify which remote repositories to use, so adding to classpath |
| # does not by itself load any libraries. You must call Java.load before accessing |
| # any Java classes to give Buildr a chance to load the libraries specified in the |
| # classpath. |
| # |
| # When building an extension, make sure to follow these rules: |
| # 1. Add to the classpath when the extension is loaded (i.e. in module or class |
| # definition), so the first call to Java.load anywhere in the code will include |
| # the libraries you specify. |
| # 2. Call Java.load once before accessing any Java classes, allowing Buildr to |
| # set up the classpath. |
| # 3. Only call Java.load when invoked, otherwise you may end up loading the JVM |
| # with a partial classpath, or before all remote repositories are listed. |
| # 4. Check on a clean build with empty local repository. |
| module Java |
| |
| module Package #:nodoc: |
| |
| def method_missing(sym, *args, &block) |
| raise ArgumentError, 'No arguments expected' unless args.empty? |
| name = "#{@name}.#{sym}" |
| return ::Rjb.import(name) if sym.to_s =~ /^[[:upper:]]/ |
| ::Java.send :__package__, name |
| end |
| |
| end |
| |
| class << self |
| |
| # Returns the classpath, an array listing directories, JAR files and |
| # artifacts. Use when loading the extension to add any additional |
| # libraries used by that extension. |
| # |
| # For example, Ant is loaded as follows: |
| # Java.classpath << 'org.apache.ant:ant:jar:1.7.0' |
| def classpath |
| @classpath ||= begin |
| classpath = [] |
| class << classpath |
| |
| def new_add(*args) |
| warn 'Java is already loaded' if Java.loaded? |
| send(:old_add, *args) |
| end |
| |
| alias_method :old_add, :<< |
| alias_method :<<, :new_add |
| end |
| classpath |
| end |
| end |
| |
| # Returns true if the JVM is loaded with all the libraries loaded on the classpath. |
| def loaded? |
| @loaded |
| end |
| |
| # Most platforms requires tools.jar to be on the classpath, tools.jar contains the |
| # Java compiler (OS X and AIX are two exceptions we know about, may be more). |
| # Guess where tools.jar is from JAVA_HOME, which hopefully points to the JDK, |
| # but maybe the JRE. Return nil if not found. |
| def tools_jar #:nodoc: |
| @tools_jar ||= begin |
| home = ENV['JAVA_HOME'] or fail 'Are we forgetting something? JAVA_HOME not set.' |
| ['lib/tools.jar', '../lib/tools.jar'].map { |path| File.expand_path(path, home) }. |
| find { |path| File.exist?(path) } |
| end |
| end |
| |
| # Loads the JVM and all the libraries listed on the classpath. Call this |
| # method before accessing any Java class, but only call it from methods |
| # used in the build, giving the Buildfile a chance to load all extensions |
| # that append to the classpath and specify which remote repositories to use. |
| def load |
| return self if @loaded |
| classpath << tools_jar if tools_jar |
| |
| classpath.map! { |path| Proc === path ? path.call : path } |
| cp = Buildr.artifacts(classpath).map(&:to_s).each { |path| file(path).invoke } |
| java_opts = (ENV['JAVA_OPTS'] || ENV['JAVA_OPTIONS']).to_s.split |
| |
| # Prepend the JDK bin directory to the path under windows as RJB can have issues if it picks |
| # up jvm dependencies from other products installed on the system |
| if Buildr::Util.win_os? |
| ENV["PATH"] = "#{ENV['JAVA_HOME']}#{File::SEPARATOR}bin#{File::PATH_SEPARATOR}#{ENV["PATH"]}" |
| end |
| ::Rjb.load cp.join(File::PATH_SEPARATOR), java_opts |
| |
| props = ::Rjb.import('java.lang.System').getProperties |
| enum = props.propertyNames |
| while enum.hasMoreElements |
| name = enum.nextElement.toString |
| ENV_JAVA[name] = props.getProperty(name) |
| end |
| @loaded = true |
| self |
| end |
| |
| def method_missing(sym, *args, &block) #:nodoc: |
| raise ArgumentError, 'No arguments expected' unless args.empty? |
| Java.load # need to load RJB's classpath now! |
| name = sym.to_s |
| return ::Rjb.import(name) if name =~ /^[[:upper:]]/ |
| __package__ name |
| end |
| |
| private |
| |
| def __package__(name) #:nodoc: |
| Module.new.tap do |m| |
| m.extend Package |
| m.instance_variable_set :@name, name |
| end |
| end |
| |
| end |
| |
| end |
| |
| class Array #:nodoc: |
| # Converts a Ruby array into a typed Java array, argument specifies the element type. |
| # This is necessary for JRuby and causes no harm on RJB. |
| def to_java(cls) |
| map { |item| cls.new(item) } |
| end |
| end |