├── .github └── workflows │ └── check.yaml ├── .gitignore ├── .gitmodules ├── DESCRIPTION ├── NAMESPACE ├── NEWS ├── R ├── 0classes.R ├── J.R ├── arrays.R ├── call.R ├── comparison.R ├── completion.R ├── converter.R ├── exceptions.R ├── gc.R ├── import.R ├── instanceof.R ├── jfirst.R ├── jinit.R ├── jri.R ├── loader.R ├── memprof.R ├── methods.R ├── options.R ├── reflection.R ├── rep.R ├── serialize.R ├── tools.R ├── windows │ └── FirstLib.R ├── with.R └── zzz.R.in ├── README.md ├── configure ├── configure.ac ├── configure.win ├── jri ├── LGPL.txt ├── LICENSE ├── Makefile.all ├── Makefile.in ├── Makefile.win ├── Makevars.win ├── Mutex.java ├── NEWS ├── RBool.java ├── RConsoleOutputStream.java ├── README ├── REXP.java ├── RFactor.java ├── RList.java ├── RMainLoopCallbacks.java ├── RVector.java ├── Rengine.java ├── bootstrap │ ├── Boot.java │ ├── DelegatedClassLoader.java │ ├── DelegatedURLClassLoader.java │ ├── JRIBootstrap.c │ ├── JRIBootstrap.h │ ├── JRIBootstrap.java │ ├── JRIClassLoader.java │ ├── Makefile │ └── mft ├── configure ├── configure.ac ├── configure.win ├── examples │ ├── rtest.java │ └── rtest2.java ├── mkdist ├── package-info.java ├── run.in ├── src │ ├── Makefile.all │ ├── Makefile.in │ ├── Makefile.win │ ├── Rcallbacks.c │ ├── Rcallbacks.h │ ├── Rdecl.h │ ├── Rengine.c │ ├── Rinit.c │ ├── Rinit.h │ ├── config.h.in │ ├── globals.c │ ├── globals.h │ ├── h2ic │ ├── jri.c │ ├── jri.h │ ├── rjava.c │ ├── rjava.h │ ├── rjstring.c │ ├── rjstring.h │ └── win32 │ │ ├── Makefile │ │ ├── findjava.c │ │ ├── jvm.def │ │ └── jvm64.def ├── tools │ ├── config.guess │ ├── config.sub │ ├── getsp.class │ ├── getsp.java │ ├── install-sh │ └── mkinstalldirs └── version ├── man ├── Exceptions.Rd ├── J.Rd ├── accessOp.Rd ├── aslist.Rd ├── clone.Rd ├── instanceof.Rd ├── jarray.Rd ├── jarrayRef-class.Rd ├── java-tools.Rd ├── javaImport.Rd ├── jcall.Rd ├── jcast.Rd ├── jcastToArray.Rd ├── jcheck.Rd ├── jclassName.Rd ├── jengine.Rd ├── jequals.Rd ├── jfield.Rd ├── jfloat-class.Rd ├── jfloat.Rd ├── jgc.Rd ├── jinit.Rd ├── jmemprof.Rd ├── jnew.Rd ├── jnull.Rd ├── jobjRef-class.Rd ├── jpackage.Rd ├── jrectRef-class.Rd ├── jreflection.Rd ├── jserialize.Rd ├── jsimplify.Rd ├── loader.Rd ├── new.Rd ├── rJava-internal.Rd ├── rep.Rd ├── show.Rd ├── toJava.Rd └── with.Rd ├── mkdist ├── src ├── Makevars.in ├── Makevars.win ├── Rglue.c ├── arrayc.c ├── callJNI.c ├── callback.c ├── callback.h ├── config.h.in ├── fields.c ├── init.c ├── install.libs.R ├── java │ ├── ArrayDimensionException.java │ ├── ArrayWrapper.java │ ├── ArrayWrapper_Test.java │ ├── DummyPoint.java │ ├── FlatException.java │ ├── Makefile │ ├── NotAnArrayException.java │ ├── NotComparableException.java │ ├── ObjectArrayException.java │ ├── PrimitiveArrayException.java │ ├── RJavaArrayIterator.java │ ├── RJavaArrayTools.java │ ├── RJavaArrayTools_Test.java │ ├── RJavaClassLoader.java │ ├── RJavaComparator.java │ ├── RJavaImport.java │ ├── RJavaTools.java │ ├── RJavaTools_Test.java │ ├── RectangularArrayBuilder.java │ ├── RectangularArrayBuilder_Test.java │ ├── RectangularArrayExamples.java │ ├── RectangularArraySummary.java │ └── TestException.java ├── jri_glue.c ├── jvm-w32 │ ├── Makefile │ ├── WinRegistry.c │ ├── config.h │ ├── findjava.c │ ├── jvm.def │ └── jvm64.def ├── loader.c ├── otables.c ├── rJava.c ├── rJava.h ├── registration.c ├── rjstring.c ├── rjstring.h └── tools.c ├── tests ├── README └── old │ ├── Leaks.class │ ├── Leaks.java │ ├── Makefile │ ├── Types.class │ ├── Types.java │ ├── leaks.R │ └── types.R ├── tools ├── getsp.class ├── getsp.java └── install-sh └── version /.github/workflows/check.yaml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | 3 | name: check 4 | 5 | jobs: 6 | check: 7 | runs-on: ${{ matrix.os }} 8 | env: 9 | NOAWT: 1 10 | 11 | name: ${{ matrix.os }}, R ${{ matrix.r }}, Java ${{ matrix.java }} 12 | 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | os: [ 'windows-2022', 'macOS-13', 'macOS-14', 'ubuntu-22.04' ] 17 | r: [ 'release' ] 18 | java: [ 8, 11 ] 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | 23 | - name: Install R 24 | uses: s-u/R-actions/install@v2 25 | with: 26 | r-version: ${{ matrix.r }} 27 | tools: base 28 | 29 | - uses: actions/setup-java@v4 30 | with: 31 | distribution: 'zulu' 32 | java-version: ${{ matrix.java }} 33 | 34 | - name: Setup R Java support 35 | if: runner.os != 'Windows' 36 | run: | 37 | echo export PATH=$PATH > reconf.sh 38 | echo export JAVA_HOME=$JAVA_HOME >> reconf.sh 39 | echo R CMD javareconf >> reconf.sh 40 | sudo bash reconf.sh 41 | shell: bash 42 | 43 | - uses: s-u/R-actions/pkg-check@v2 44 | with: 45 | build-script: sh mkdist 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "jri/REngine"] 2 | path = jri/REngine 3 | url = https://github.com/s-u/REngine.git 4 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: rJava 2 | Version: (populated by mkdist!) 3 | Title: Low-Level R to Java Interface 4 | Author: Simon Urbanek 5 | Maintainer: Simon Urbanek 6 | Depends: R (>= 3.6.0), methods 7 | Description: Low-level interface to Java VM very much like .C/.Call and friends. Allows creation of objects, calling methods and accessing fields. 8 | License: LGPL-2.1 9 | URL: http://www.rforge.net/rJava/ 10 | SystemRequirements: Java JDK 1.2 or higher (for JRI/REngine JDK 1.4 or higher), GNU make 11 | BugReports: https://github.com/s-u/rJava/issues 12 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | exportPattern("^\\.j") 2 | export( "J" ) 3 | export( "%instanceof%" ) 4 | 5 | export( clone ) 6 | S3method( clone, default ) 7 | export(is.jnull, .r2j, .rJava.base.path, toJava) 8 | exportClasses(jobjRef, jarrayRef, jrectRef, jfloat, jlong, jbyte, jchar, jclassName) 9 | exportMethods(show, "$", "$<-", 10 | "==", "!=", "<", ">", "<=", ">=", 11 | names, new, as.character, length, head, tail, 12 | "[", "[[", "[[<-", str, "dim<-", 13 | unique, duplicated, anyDuplicated, 14 | sort, rev, 15 | min, max, range, 16 | rep, 17 | clone ) 18 | import(methods) 19 | importFrom(utils,head) 20 | importFrom(utils,tail) 21 | importFrom(utils,str) 22 | importFrom(utils, assignInNamespace) 23 | 24 | S3method(with, jobjRef) 25 | S3method(with, jarrayRef) 26 | S3method(with, jclassName) 27 | 28 | S3method(within, jobjRef) 29 | S3method(within, jarrayRef) 30 | S3method(within, jclassName) 31 | 32 | # within requires that with.jobjRef is visible outside 33 | export(with.jobjRef) 34 | 35 | if( exists( ".DollarNames", asNamespace("utils") ) ) importFrom( utils, .DollarNames ) 36 | S3method(.DollarNames, jobjRef) 37 | S3method(.DollarNames, jarrayRef) 38 | S3method(.DollarNames, jrectRef) 39 | S3method(.DollarNames, jclassName) 40 | 41 | S3method( as.list, jobjRef ) 42 | S3method( as.list, jarrayRef ) 43 | S3method( as.list, jrectRef ) 44 | 45 | S3method( "$", "Throwable" ) 46 | S3method( "$<-", "Throwable" ) 47 | 48 | export( javaImport ) 49 | 50 | -------------------------------------------------------------------------------- /R/0classes.R: -------------------------------------------------------------------------------- 1 | ## S4 classes (jobjRef is re-defined in .First.lib to contain valid jobj) 2 | #' java object reference 3 | setClass("jobjRef", representation(jobj="externalptr", jclass="character"), 4 | prototype=list(jobj=NULL, jclass="java/lang/Object")) 5 | 6 | #' rugged arrays 7 | setClass("jarrayRef", representation("jobjRef", jsig="character")) 8 | 9 | #' rectangular java arrays double[][] d = new double[m][n] 10 | setClass("jrectRef", 11 | representation("jarrayRef", dimension="integer" ) ) 12 | 13 | 14 | 15 | # we extend array here so that we can keep dimensions 16 | # in the helper functions below, the storage mode is 17 | # set when the objects are built 18 | # TODO: maybe an initialize method is needed here 19 | # TODO: maybe a validate method is needed here as well 20 | setClass("jfloat", representation("array" ) ) 21 | setClass("jlong", representation("array" ) ) 22 | setClass("jbyte", representation("array" ) ) 23 | setClass("jshort", representation("array" ) ) 24 | setClass("jchar", representation("array" ) ) 25 | 26 | # there is no way to distinguish between double and float in R, so we need to mark floats specifically 27 | .jfloat <- function(x) { 28 | storage.mode( x ) <- "double" 29 | new("jfloat", x ) 30 | } 31 | # the same applies to long 32 | .jlong <- function(x) { 33 | storage.mode( x ) <- "double" 34 | new("jlong", x) 35 | } 36 | # and byte 37 | .jbyte <- function(x) { 38 | storage.mode( x ) <- "integer" 39 | new("jbyte", x) 40 | } 41 | # and short 42 | .jshort <- function(x){ 43 | storage.mode( x ) <- "integer" 44 | new("jshort", x) 45 | } 46 | # and char (experimental) 47 | .jchar <- function(x){ 48 | if (is.character(x)) { 49 | if (length(x) != 1L || is.na(x)) 50 | stop(".jchar() supports only (non-NA) character vectors of length one (aka strings)") 51 | ## use Java to actually do the conversion 52 | x <- .jcall(.jnew("java.lang.String", x), "[C", "toCharArray") 53 | } 54 | storage.mode( x ) <- "integer" 55 | new("jchar", x) 56 | } 57 | -------------------------------------------------------------------------------- /R/J.R: -------------------------------------------------------------------------------- 1 | setClass("jclassName", representation(name="character", jobj="jobjRef")) 2 | 3 | jclassName <- function(class, class.loader=.rJava.class.loader) { 4 | if (.need.init()) .jinit() 5 | if( is( class, "jobjRef" ) && .jinherits(class, "java/lang/Class" ) ){ 6 | jobj <- class 7 | name <- .jcall( class, "Ljava/lang/String;", "getName", evalString = TRUE ) 8 | } else{ 9 | name <- gsub("/",".",as.character(class)) 10 | jobj <- .jfindClass(as.character(class), class.loader=class.loader) 11 | } 12 | new("jclassName", name=name, jobj=jobj) 13 | } 14 | 15 | setGeneric("new") 16 | setMethod("new", signature(Class="jclassName"), function(Class, ...) .J(Class, ...)) 17 | 18 | ## FIXME: this is not quite right - it looks at static method/fields only, 19 | ## but that prevents things like x = J("foo"); x$equals(x) from working 20 | ## while x$class$equals(x) works. 21 | setMethod("$", c(x="jclassName"), function(x, name) { 22 | if( name == "class" ){ 23 | x@jobj 24 | } else if (classHasField(x@jobj, name, TRUE)){ 25 | .jfield(x, , name) 26 | } else if (classHasMethod(x@jobj, name, TRUE)){ 27 | function(...) .jrcall(x, name, ...) 28 | } else if( classHasClass(x@jobj, name, FALSE) ){ 29 | inner.cl <- .jcall( "RJavaTools", "Ljava/lang/Class;", "getClass", x@jobj, name, FALSE ) 30 | new("jclassName", name=.jcall(inner.cl, "S", "getName"), jobj=inner.cl) 31 | } else { 32 | stop("no static field, method or inner class called `", name, "' in `", x@name, "'") 33 | } 34 | }) 35 | setMethod("$<-", c(x="jclassName"), function(x, name, value) .jfield(x, name) <- value) 36 | setMethod("show", c(object="jclassName"), function(object) invisible(show(paste("Java-Class-Name:",object@name)))) 37 | setMethod("as.character", c(x="jclassName"), function(x, ...) x@name) 38 | 39 | ## the magic `J' 40 | J<-function(class, method, ..., class.loader=.rJava.class.loader) if (nargs() <= 2L && missing(method)) jclassName(class, class.loader=class.loader) else .jrcall(class, method, ..., class.loader=class.loader) 41 | -------------------------------------------------------------------------------- /R/comparison.R: -------------------------------------------------------------------------------- 1 | 2 | #' if a and b are compatable, 3 | #' in the sense of the java.util.Comparable interface 4 | #' then the result of the compareTo method is returned 5 | #' otherwise an error message is generated 6 | .jcompare <- function(a, b) { 7 | if (is.null(a)) a <- new("jobjRef") 8 | if (is.null(b)) b <- new("jobjRef") 9 | 10 | if( isJavaArray(a) || isJavaArray(b) ){ 11 | stop( "comparison (<,>,<=,>=) is not implemented for java arrays yet" ) 12 | } 13 | 14 | if( !is(a, "jobjRef" ) ) a <- ._java_valid_object( a ) 15 | if( !is(b, "jobjRef" ) ) b <- ._java_valid_object( b ) 16 | 17 | .jcall( "RJavaComparator", "I", "compare", .jcast(a), .jcast(b) ) 18 | 19 | } 20 | ._lower <- function(e1, e2){ 21 | .jcompare( e1, e2 ) <= 0L 22 | } 23 | ._greater <- function(e1, e2 ){ 24 | .jcompare( e1, e2 ) >= 0L 25 | } 26 | ._strictly_lower <- function(e1, e2 ){ 27 | .jcompare( e1, e2 ) < 0L 28 | } 29 | ._strictly_greater <- function(e1, e2 ){ 30 | .jcompare( e1, e2 ) > 0L 31 | } 32 | 33 | setMethod("<" , c(e1="jobjRef",e2="jobjRef"), ._strictly_lower ) 34 | setMethod("<" , c(e1="jobjRef") , ._strictly_lower ) 35 | setMethod("<" , c(e2="jobjRef") , ._strictly_lower ) 36 | 37 | setMethod(">" , c(e1="jobjRef",e2="jobjRef"), ._strictly_greater ) 38 | setMethod(">" , c(e1="jobjRef") , ._strictly_greater ) 39 | setMethod(">" , c(e2="jobjRef") , ._strictly_greater ) 40 | 41 | setMethod("<=", c(e1="jobjRef",e2="jobjRef"), ._lower ) 42 | setMethod("<=", c(e1="jobjRef") , ._lower ) 43 | setMethod("<=", c(e2="jobjRef") , ._lower ) 44 | 45 | setMethod(">=", c(e1="jobjRef",e2="jobjRef"), ._greater ) 46 | setMethod(">=", c(e1="jobjRef") , ._greater ) 47 | setMethod(">=", c(e2="jobjRef") , ._greater ) 48 | 49 | 50 | -------------------------------------------------------------------------------- /R/completion.R: -------------------------------------------------------------------------------- 1 | # :tabSize=4:indentSize=4:noTabs=false:folding=explicit:collapseFolds=1: 2 | 3 | # S4 dispatch does not work for .DollarNames, so we'll use S3 4 | # {{{ bring .DollarNames from the future if necessary 5 | if( !exists( ".DollarNames", envir = asNamespace("utils") ) ){ 6 | .DollarNames <- function(x, pattern) 7 | UseMethod(".DollarNames") 8 | } 9 | # }}} 10 | 11 | # {{{ support function to retrieve completion names from RJavaTools 12 | ### get completion names from RJavaTools 13 | classNamesMethod <- function (cl, static.only = TRUE ) { 14 | # TODO: return both from java instead of two java calls 15 | fieldnames <- .jcall( "RJavaTools", "[Ljava/lang/String;", 16 | "getFieldNames", cl, static.only ) 17 | methodnames <- .jcall( "RJavaTools", "[Ljava/lang/String;", 18 | "getMethodNames", cl, static.only ) 19 | c(fieldnames, methodnames) 20 | } 21 | # }}} 22 | 23 | # {{{ jclassName 24 | ._names_jclassName <- function(x){ 25 | c( "class", classNamesMethod(x@jobj, static.only = TRUE ) ) 26 | } 27 | .DollarNames.jclassName <- function(x, pattern = "" ){ 28 | grep( pattern, ._names_jclassName(x), value = TRUE ) 29 | } 30 | 31 | setMethod("names", c(x="jclassName"), ._names_jclassName ) 32 | # }}} 33 | 34 | # {{{ jobjRef 35 | ._names_jobjRef <- function(x){ 36 | classNamesMethod(.jcall(x, "Ljava/lang/Class;", "getClass"), static.only = FALSE ) 37 | } 38 | .DollarNames.jobjRef <- function(x, pattern = "" ){ 39 | grep( pattern, ._names_jobjRef(x), value = TRUE ) 40 | } 41 | setMethod("names", c(x="jobjRef"), ._names_jobjRef ) 42 | # }}} 43 | 44 | # {{{ jarrayRef and jrectRef 45 | ._names_jarrayRef <- function(x ){ 46 | c("length", classNamesMethod(.jcall(x, "Ljava/lang/Class;", "getClass"), static.only = FALSE ) ) 47 | } 48 | .DollarNames.jarrayRef <- .DollarNames.jrectRef <- function(x, pattern = ""){ 49 | grep( pattern, ._names_jarrayRef(x), value = TRUE ) 50 | } 51 | 52 | setMethod("names", c(x="jarrayRef"), ._names_jarrayRef ) 53 | setMethod("names", c(x="jrectRef"), ._names_jarrayRef ) 54 | 55 | 56 | # }}} 57 | -------------------------------------------------------------------------------- /R/converter.R: -------------------------------------------------------------------------------- 1 | # in: Java -> R 2 | .conv.in <- new.env(parent=emptyenv()) 3 | .conv.in$. <- FALSE 4 | # out: R -> Java 5 | .conv.out <- new.env(parent=emptyenv()) 6 | .conv.out$. <- FALSE 7 | 8 | # --- internal fns 9 | .convert.in <- function(jobj, verify.class=TRUE) { 10 | jcl <- if (verify.class) .jclass(jobj) else gsub("/",".",jobj@jclass) 11 | cv <- .conv.in[[jcl]] 12 | if (!is.null(cv)) jobj else cv$fn(jobj) 13 | } 14 | 15 | .convert.out <- function(robj) { 16 | for (cl in class(robj)) { 17 | cv <- .conv.out[[cl]] 18 | if (!is.null(cv)) return(cv$fn(robj)) 19 | } 20 | robj 21 | } 22 | 23 | # external fns 24 | .jsetJConvertor <- function(java.class, fn) { 25 | if (is.null(fn)) { 26 | rm(list=java.class, envir=.conv.in) 27 | if (!length(ls(.conv.in))) .conv.in$. <- FALSE 28 | } else { 29 | .conv.in$. <- TRUE 30 | .conv.in[[java.class]] <- list(fn=fn) 31 | } 32 | } 33 | 34 | .jsetRConvertor <- function(r.class, fn) { 35 | if (is.null(fn)) { 36 | rm(list=r.class, envir=.conv.out) 37 | if (!length(ls(.conv.out))) .conv.out$. <- FALSE 38 | } else { 39 | .conv.out$. <- TRUE 40 | .conv.out[[r.class]] <- list(fn=fn) 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /R/exceptions.R: -------------------------------------------------------------------------------- 1 | ## functions for some basic exception handling 2 | 3 | # FIXME: should all these actually be deprecated or defunct 4 | 5 | ## poll for an exception 6 | .jgetEx <- function(clear=FALSE) { 7 | exo <- .Call(RpollException) 8 | if (is.null(exo)) return(NULL) 9 | x <- new("jobjRef", jobj=exo, jclass="java/lang/Throwable") 10 | if (clear) .jclear() 11 | x 12 | } 13 | 14 | ## explicitly clear any pending exceptions 15 | .jclear <- function() { 16 | .C(RclearException) 17 | invisible(NULL) 18 | } 19 | 20 | ## throw an exception 21 | .jthrow <- function(exception, message=NULL) { 22 | if (is.character(exception)) 23 | exception <- .jnew(exception, as.character(message)) 24 | if (is(exception, "jobjRef")) 25 | .Call(RthrowException, exception) 26 | else 27 | stop("Invalid exception.") 28 | } 29 | 30 | 31 | "$.Throwable" <- function( x, name ){ 32 | if( name %in% names(c(x)) ){ 33 | c(x)[[ name ]] 34 | } else{ 35 | ._jobjRef_dollar( x[["jobj"]], name ) 36 | } 37 | } 38 | 39 | "$<-.Throwable" <- function( x, name, value ){ 40 | if( name %in% names(x) ){ 41 | x[[ name ]] <- value 42 | } else{ 43 | ._jobjRef_dollargets( x[["jobj"]], name, value ) 44 | } 45 | x 46 | 47 | } 48 | 49 | -------------------------------------------------------------------------------- /R/gc.R: -------------------------------------------------------------------------------- 1 | .jgc <- function(R.gc=TRUE, ...) { 2 | if (R.gc) gc(...) 3 | .jcall(.jcall("java.lang.Runtime","Ljava/lang/Runtime;","getRuntime"), "V", "gc") 4 | } 5 | -------------------------------------------------------------------------------- /R/import.R: -------------------------------------------------------------------------------- 1 | 2 | IMPORTER <- ".__rjava__import" 3 | 4 | java_class_importers <- new.env() 5 | assign( ".namespaces", NULL, envir = java_class_importers ) 6 | 7 | getImporterFromNamespace <- function( nm, create = TRUE ){ 8 | .namespaces <- get(".namespaces", envir = java_class_importers ) 9 | if( !is.null( .namespaces ) ){ 10 | for( item in .namespaces ){ 11 | if( identical( item$nm, nm ) ){ 12 | return( item$importer ) 13 | } 14 | } 15 | } 16 | if( create ){ 17 | addImporterNamespace(nm) 18 | } 19 | 20 | } 21 | addImporterNamespace <- function( nm ){ 22 | importer <- .jnew( "RJavaImport", .jcast( .rJava.class.loader, "java/lang/ClassLoader" ) ) 23 | assign( ".namespaces", 24 | append( list( list( nm = nm, importer = importer ) ), get(".namespaces", envir = java_class_importers ) ), 25 | envir = java_class_importers ) 26 | importer 27 | } 28 | 29 | getImporterFromEnvironment <- function(env, create = TRUE){ 30 | if( isNamespace( env ) ){ 31 | getImporterFromNamespace( env ) 32 | } else if( exists(IMPORTER, envir = env ) ){ 33 | get( IMPORTER, envir = env ) 34 | } else if( create ){ 35 | addImporterNamespace(env) 36 | } 37 | } 38 | 39 | getImporterFromGlobalEnv <- function( ){ 40 | if( exists( "global", envir = java_class_importers ) ){ 41 | get( "global", envir = java_class_importers ) 42 | } else{ 43 | initGlobalEnvImporter() 44 | } 45 | } 46 | initGlobalEnvImporter <- function(){ 47 | importer <- .jnew( "RJavaImport", .jcast( .rJava.class.loader, "java/lang/ClassLoader" ) ) 48 | assign( "global", importer , envir = java_class_importers ) 49 | importer 50 | } 51 | 52 | import <- function( package = "java.util", env = sys.frame(sys.parent()) ){ 53 | 54 | if( missing(env) ){ 55 | caller <- sys.function(-1) 56 | env <- environment( caller ) 57 | if( isNamespace( env ) ){ 58 | importer <- getImporterFromNamespace( env ) 59 | } 60 | } else{ 61 | force(env) 62 | 63 | if( !is.environment( env ) ){ 64 | stop( "env is not an environment" ) 65 | } 66 | 67 | if( ! exists( IMPORTER, env ) || is.jnull( get( IMPORTER, envir = env ) ) ){ 68 | importer <- .jnew( "RJavaImport", .jcast( .rJava.class.loader, "java/lang/ClassLoader" ) ) 69 | if( isNamespace(env) ){ 70 | unlockBinding( IMPORTER, env = env ) 71 | assignInNamespace( IMPORTER, importer, envir = env ) 72 | } 73 | assign( IMPORTER, importer, envir = env ) 74 | } else{ 75 | importer <- get( IMPORTER, envir = env ) 76 | } 77 | } 78 | mustbe.importer( importer ) 79 | .jcall( importer, "V", "importPackage", package ) 80 | 81 | } 82 | 83 | is.importer <- function(x){ 84 | is( x, "jobjRef" ) && .jinherits( x, "RJavaImport" ) 85 | } 86 | mustbe.importer <- function(x){ 87 | if( !is.importer(x) ){ 88 | stop( "object not a suitable java package importer" ) 89 | } 90 | } 91 | 92 | #' collect importers 93 | getAvailableImporters <- function( frames = TRUE, namespace = TRUE, 94 | global = TRUE, caller = sys.function(-1L) ){ 95 | 96 | importers <- .jnew( "java/util/HashSet" ) 97 | 98 | addImporter <- function( importer ){ 99 | if( is.importer( importer ) ){ 100 | .jcall( importers, "Z", "add", .jcast(importer) ) 101 | } 102 | } 103 | if( isTRUE( global ) ){ 104 | addImporter( getImporterFromGlobalEnv() ) 105 | } 106 | 107 | if( isTRUE( frames ) ){ 108 | frames <- sys.frames() 109 | if( length(frames) > 1L ){ 110 | sapply( head( frames, -1L ), function(env) { 111 | if( !identical( env, .GlobalEnv ) ){ 112 | addImporter( getImporterFromEnvironment( env ) ) 113 | } 114 | } ) 115 | } 116 | } 117 | 118 | if( isTRUE( namespace ) ){ 119 | force(caller) 120 | env <- environment( caller ) 121 | if( isNamespace( env ) ){ 122 | addImporter( getImporterFromNamespace( env ) ) 123 | } 124 | } 125 | 126 | importers 127 | } 128 | 129 | #' lookup for a class name in the available importers 130 | lookup <- function( name = "Object", ..., caller = sys.function(-1L) ){ 131 | force(caller) 132 | importers <- getAvailableImporters(..., caller = caller) 133 | .jcall( "RJavaImport", "Ljava/lang/Class;", "lookup", 134 | name, .jcast( importers, "java/util/Set" ) ) 135 | } 136 | 137 | 138 | javaImport <- function( packages = "java.lang" ){ 139 | importer <- .jnew( "RJavaImport", .jcast( .rJava.class.loader, "java/lang/ClassLoader" ) ) 140 | .jcall( importer, "V", "importPackage", packages ) 141 | .Call( newRJavaLookupTable , importer ) 142 | } 143 | -------------------------------------------------------------------------------- /R/instanceof.R: -------------------------------------------------------------------------------- 1 | `%instanceof%` <- .jinstanceof <- function( o, cl ){ 2 | 3 | if( !inherits( o, "jobjRef" ) ){ 4 | stop( "o is not a java object" ) 5 | } 6 | 7 | # first get the class object that represents cl 8 | if( inherits( cl, "jobjRef" ) ){ 9 | if( .jclass( cl ) == "java.lang.Class" ){ 10 | clazz <- cl 11 | } else { 12 | clazz <- .jcall( cl, "Ljava/lang/Class;", "getClass" ) 13 | } 14 | } else if( inherits( cl, "jclassName" ) ) { 15 | clazz <- cl@jobj 16 | } else if( inherits( cl, "character" ) ){ 17 | clazz <- .jfindClass(cl) 18 | } else { 19 | return(FALSE) 20 | } 21 | 22 | # then find out if o is an instance of the class 23 | .jcall( clazz , "Z", "isInstance", .jcast(o, "java/lang/Object" ) ) 24 | } 25 | 26 | -------------------------------------------------------------------------------- /R/jfirst.R: -------------------------------------------------------------------------------- 1 | # this part is common to all platforms and must be invoked 2 | # from .First.lib after library.dynam 3 | 4 | # actual namespace environment of this package 5 | .env <- environment() 6 | 7 | # variables in the rJava environment that will be initialized *after* the package is loaded 8 | # they need to be pre-created at load time and populated later by .jinit 9 | .delayed.export.variables <- c(".jniInitialized", ".jclassObject", ".jclassString", ".jclassClass", 10 | ".jclass.int", ".jclass.double", ".jclass.float", ".jclass.boolean", 11 | ".jclass.void", ".jinit.merge.error") 12 | # variables that are delayed but not exported are added here 13 | .delayed.variables <- c(.delayed.export.variables, ".rJava.class.loader") 14 | 15 | # C entry points to register 16 | .register.addr <- c( # .Call 17 | "PushToREXP", "RJava_checkJVM", "RJava_needs_init", "RJava_new_class_loader", 18 | "RJava_primary_class_loader", "RJava_set_class_loader", "RJava_set_memprof", "RJavaCheckExceptions", 19 | "RcreateArray", "RgetBoolArrayCont", "RgetByteArrayCont", "RgetCharArrayCont", 20 | "RgetDoubleArrayCont", "RgetField", "RgetFloatArrayCont", "RgetIntArrayCont", 21 | "RgetLongArrayCont", "RgetNullReference", "RgetObjectArrayCont", 22 | "RgetShortArrayCont", "RgetStringArrayCont", "RidenticalRef", "RgetSimpleClassNames", 23 | "RisAssignableFrom", "RpollException", "RsetField", "RthrowException", 24 | "javaObjectCache", "initRJavaTools", "newRJavaLookupTable", "useDynamicSymbols", 25 | "RgetJVMstate", 26 | # .External 27 | "RcreateObject", "RgetStringValue", "RinitJVM", "RtoString", "RcallMethod", 28 | # .C 29 | "RclearException", "RuseJNICache" 30 | ) 31 | 32 | .jfirst <- function(libname, pkgname) { 33 | # register all C entry points 34 | addr <- getNativeSymbolInfo(.register.addr, pkgname) 35 | for (name in .register.addr) 36 | .env[[name]] <- addr[[name]]$address 37 | 38 | # disable symbol lookup from now on - if there is an error 39 | # in native calls from now on, it means a symbol has not 40 | # been added to the list above 41 | .Call(useDynamicSymbols, FALSE) 42 | 43 | assign(".rJava.base.path", paste(libname, pkgname, sep=.Platform$file.sep), .env) 44 | assign(".jzeroRef", .Call(RgetNullReference), .env) 45 | 46 | for (x in .delayed.variables) assign(x, NULL, .env) 47 | assign(".jniInitialized", FALSE, .env) 48 | 49 | ## S4 classes update - all classes are created earlier in classes.R, but jobjRef's prototype is only valid after the dylib is loaded 50 | setClass("jobjRef", representation(jobj="externalptr", jclass="character"), prototype=list(jobj=.jzeroRef, jclass="java/lang/Object"), where=.env) 51 | } 52 | -------------------------------------------------------------------------------- /R/jri.R: -------------------------------------------------------------------------------- 1 | ## bindings into JRI 2 | 3 | ## warning: JRI REXP class has currently no finalizers! (RReleaseREXP must be used manually for now) 4 | ## warning: this produces JRI-API pbjects - that should go away! use toJava below 5 | .r2j <- function(x, engine = NULL, convert = TRUE) { 6 | if (is.null(engine)) engine <- .jcall("org/rosuda/JRI/Rengine","Lorg/rosuda/JRI/Rengine;","getMainEngine") 7 | if (!is(engine, "jobjRef")) stop("invalid or non-existent engine") 8 | new("jobjRef",jobj=.Call(PushToREXP,"org/rosuda/JRI/REXP",engine@jobj,engine@jclass,x,convert),jclass="org/rosuda/JRI/REXP") 9 | } 10 | 11 | toJava <- function(x, engine = NULL) { 12 | ## this is really the wrong place for all this REngine checking stuff, but so far .jengine uses JRI API only and legacy code may rely on that 13 | ## so this is the only place that assumes REngine API and thus will load it ... 14 | ec <- .jfindClass("org.rosuda.JRI.Rengine", silent=TRUE) 15 | if (is.jnull(ec)) { 16 | .jcheck(TRUE) 17 | stop("JRI is not loaded. Please start JRI first - see ?.jengine") 18 | } 19 | ec <- .jfindClass("org.rosuda.REngine.REngine", silent=TRUE) 20 | if (is.jnull(ec)) { 21 | .jcheck(TRUE) 22 | fn <- system.file("jri","REngine.jar",package="rJava") 23 | if (nzchar(fn)) .jaddClassPath(fn) 24 | fn <- system.file("jri","JRIEngine.jar",package="rJava") 25 | if (nzchar(fn)) .jaddClassPath(fn) 26 | ec <- .jfindClass("org.rosuda.REngine.REngine", silent=TRUE) 27 | if (is.jnull(ec)) { 28 | .jcheck(TRUE) 29 | stop("Cannot find REngine API classes. Please make sure you have installed and loaded the REngine API") 30 | } 31 | } 32 | if (is.null(engine)) engine <- .jcall("org/rosuda/REngine/REngine","Lorg/rosuda/REngine/REngine;","getLastEngine") 33 | if (is.jnull(engine)) { # no last engine, but there may be JRI engine already running ... 34 | me <- .jcall("org/rosuda/JRI/Rengine","Lorg/rosuda/JRI/Rengine;","getMainEngine", check=FALSE) 35 | .jcheck(TRUE) 36 | if (is.jnull(me)) stop("JRI is not running. Please start JRI first - see ?.jengine") 37 | engine <- .jnew("org/rosuda/REngine/JRI/JRIEngine", me) 38 | .jcheck(TRUE) 39 | } 40 | .jcheck(TRUE) 41 | if (!is(engine, "jobjRef")) stop("invalid or non-existent engine") 42 | new("jobjRef",jobj=.Call(PushToREXP,"org/rosuda/REngine/REXPReference",engine@jobj,"org/rosuda/REngine/REngine",x,NULL),jclass="org/rosuda/REngine/REXPReference") 43 | } 44 | 45 | .setupJRI <- function(new=TRUE) { 46 | ec <- .jfindClass("org.rosuda.JRI.Rengine", silent=TRUE) 47 | if (is.jnull(ec)) { 48 | .jcheck(TRUE) 49 | .jaddClassPath(system.file("jri","JRI.jar",package="rJava")) 50 | ec <- .jfindClass("org.rosuda.JRI.Rengine", silent=TRUE) 51 | .jcheck(TRUE) 52 | if (is.jnull(ec)) 53 | stop("Cannot find JRI classes") 54 | } 55 | me <- .jcall("org/rosuda/JRI/Rengine","Lorg/rosuda/JRI/Rengine;","getMainEngine", check=FALSE) 56 | .jcheck(TRUE) 57 | if (!is.jnull(me)) { 58 | if (!new) return(TRUE) 59 | warning("JRI engine is already running.") 60 | return(FALSE) 61 | } 62 | e <- .jnew("org/rosuda/JRI/Rengine") 63 | !is.jnull(e) 64 | } 65 | 66 | .jengine <- function(start=FALSE, silent=FALSE) { 67 | me <- NULL 68 | ec <- .jfindClass("org.rosuda.JRI.Rengine", silent=TRUE) 69 | .jcheck(TRUE) 70 | if (!is.jnull(ec)) { 71 | me <- .jcall("org/rosuda/JRI/Rengine","Lorg/rosuda/JRI/Rengine;","getMainEngine", check=FALSE) 72 | .jcheck(TRUE) 73 | } 74 | if (is.jnull(me)) { 75 | if (!start) { 76 | if (silent) return(NULL) 77 | stop("JRI engine is not running.") 78 | } 79 | .setupJRI(FALSE) 80 | me <- .jcall("org/rosuda/JRI/Rengine","Lorg/rosuda/JRI/Rengine;","getMainEngine", check=FALSE) 81 | .jcheck(TRUE) 82 | } 83 | if (is.jnull(me) && !silent) 84 | stop("JRI engine is not running.") 85 | me 86 | } 87 | -------------------------------------------------------------------------------- /R/loader.R: -------------------------------------------------------------------------------- 1 | .jaddClassPath <- function(path, class.loader=.rJava.class.loader) { 2 | if (!length(path)) return(invisible(NULL)) 3 | if (!is.jnull(class.loader)) 4 | invisible(.jcall(class.loader, "V", "addClassPath", as.character(path))) 5 | else { 6 | cpr <- try(.jmergeClassPath(paste(path, collapse=.Platform$path.sep)), silent=TRUE) 7 | invisible(!inherits(cpr, "try-error")) 8 | } 9 | } 10 | 11 | .jclassPath <- function(class.loader=.rJava.class.loader) { 12 | if (is.jnull(class.loader)) { 13 | cp <- .jcall("java/lang/System", "S", "getProperty", "java.class.path") 14 | unlist(strsplit(cp, .Platform$path.sep)) 15 | } else { 16 | .jcall(class.loader,"[Ljava/lang/String;","getClassPath") 17 | } 18 | } 19 | 20 | .jaddLibrary <- function(name, path, class.loader=.rJava.class.loader) { 21 | if (!is.jnull(class.loader)) 22 | invisible(.jcall(class.loader, "V", "addRLibrary", as.character(name)[1], as.character(path)[1])) 23 | } 24 | 25 | .jrmLibrary <- function(name) { 26 | ## FIXME: unimplemented 27 | } 28 | 29 | .jclassLoader <- function(package=NULL) { 30 | if (!is.null(package)) { 31 | loader <- asNamespace(package)$.rJava.class.loader 32 | if (!is.jnull(loader)) return(loader) 33 | } 34 | .rJava.class.loader 35 | } 36 | 37 | .jpackage <- function(name, jars='*', morePaths='', nativeLibrary=FALSE, lib.loc=NULL, 38 | parameters=getOption("java.parameters"), own.loader=FALSE) { 39 | if (!.jniInitialized) 40 | .jinit(parameters=parameters) 41 | loader <- .rJava.class.loader 42 | if (isTRUE(own.loader)) { 43 | lib <- "libs" 44 | if (nchar(.Platform$r_arch)) 45 | lib <- file.path("libs", .Platform$r_arch) 46 | ns <- asNamespace(name) 47 | loader <- ns$.rJava.class.loader <- 48 | .jnew("RJavaClassLoader", .rJava.base.path, 49 | file.path(.rJava.base.path, lib), .rJava.class.loader, check = FALSE) 50 | } 51 | 52 | classes <- system.file("java", package=name, lib.loc=lib.loc) 53 | if (nchar(classes)) { 54 | .jaddClassPath(classes, class.loader=loader) 55 | if (length(jars)) { 56 | if (length(jars) == 1 && jars == '*') { 57 | jars <- grep(".*\\.jar", list.files(classes, full.names=TRUE), TRUE, value=TRUE) 58 | if (length(jars)) .jaddClassPath(jars, class.loader=loader) 59 | } else .jaddClassPath(paste(classes, jars, sep=.Platform$file.sep), class.loader=loader) 60 | } 61 | } 62 | if (any(nchar(morePaths))) { 63 | cl <- as.character(morePaths) 64 | cl <- cl[nchar(cl)>0] 65 | .jaddClassPath(cl, class.loader=loader) 66 | } 67 | if (is.logical(nativeLibrary)) { 68 | if (nativeLibrary) { 69 | libs <- "libs" 70 | if (nchar(.Platform$r_arch)) lib <- file.path("libs", .Platform$r_arch) 71 | lib <- system.file(libs, paste(name, .Platform$dynlib.ext, sep=''), package=name, lib.loc=lib.loc) 72 | if (nchar(lib)) 73 | .jaddLibrary(name, lib, class.loader=loader) 74 | else 75 | warning("Native library for `",name,"' could not be found.") 76 | } 77 | } else { 78 | .jaddLibrary(name, nativeLibrary, class.loader=loader) 79 | } 80 | invisible(TRUE) 81 | } 82 | -------------------------------------------------------------------------------- /R/memprof.R: -------------------------------------------------------------------------------- 1 | .jmemprof <- function(file = "-") { 2 | if (is.null(file)) file <- "" 3 | invisible(.Call(RJava_set_memprof, as.character(file))) 4 | } 5 | -------------------------------------------------------------------------------- /R/methods.R: -------------------------------------------------------------------------------- 1 | ## methods for jobjRef class 2 | ## 3 | ## additional methods ($ and $<-) are defined in reflection.R 4 | 5 | # show method 6 | # FIXME: this should show the class of the object instead of Java-Object 7 | setMethod("show", c(object="jobjRef"), function(object) { 8 | if (is.jnull(object)) show("Java-Object") else show(paste("Java-Object{", .jstrVal(object), "}", sep='')) 9 | invisible(NULL) 10 | }) 11 | 12 | setMethod("show", c(object="jarrayRef"), function(object) { 13 | show(paste("Java-Array-Object",object@jsig,":", .jstrVal(object), sep='')) 14 | invisible(NULL) 15 | }) 16 | 17 | # map R comparison operators to .jequals 18 | setMethod("==", c(e1="jobjRef",e2="jobjRef"), function(e1,e2) .jequals(e1,e2)) 19 | setMethod("==", c(e1="jobjRef"), function(e1,e2) .jequals(e1,e2)) 20 | setMethod("==", c(e2="jobjRef"), function(e1,e2) .jequals(e1,e2)) 21 | 22 | setMethod("!=", c(e1="jobjRef",e2="jobjRef"), function(e1,e2) !.jequals(e1,e2)) 23 | setMethod("!=", c(e1="jobjRef"), function(e1,e2) !.jequals(e1,e2)) 24 | setMethod("!=", c(e2="jobjRef"), function(e1,e2) !.jequals(e1,e2)) 25 | 26 | # other operators such as <,> are defined in comparison.R 27 | 28 | -------------------------------------------------------------------------------- /R/options.R: -------------------------------------------------------------------------------- 1 | .joptions <- function(...) { 2 | l <- list(...) 3 | if (length(l)==0) return(list()) 4 | if ("jni.cache" %in% names(l)) { 5 | v <- l[["jni.cache"]] 6 | if (!is.logical(v) || length(v)!=1) 7 | stop("jni.cache must be a logical vector of length 1") 8 | .C(RuseJNICache,v) 9 | invisible(NULL) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /R/rep.R: -------------------------------------------------------------------------------- 1 | # :tabSize=4:indentSize=4:noTabs=false:folding=explicit:collapseFolds=1: 2 | 3 | # {{{ rep 4 | setGeneric("rep") 5 | setMethod( "rep", "jobjRef", function( x, times = 1L, ... ){ 6 | .jcall( "RJavaArrayTools", "[Ljava/lang/Object;", "rep", 7 | .jcast(x), as.integer(times), evalArray = FALSE ) 8 | } ) 9 | setMethod( "rep", "jarrayRef", function(x, times = 1L, ...){ 10 | .NotYetImplemented() 11 | } ) 12 | setMethod( "rep", "jrectRef", function(x, times = 1L, ...){ 13 | .NotYetImplemented() 14 | } ) 15 | # }}} 16 | 17 | # {{{ clone 18 | clone <- function( x, ... ){ 19 | UseMethod( "clone" ) 20 | } 21 | clone.default <- function( x, ... ){ 22 | .NotYetImplemented() 23 | } 24 | setGeneric( "clone" ) 25 | setMethod( "clone", "jobjRef", function(x, ...){ 26 | .jcall( "RJavaArrayTools", "Ljava/lang/Object;", "cloneObject", .jcast( x ) ) 27 | } ) 28 | setMethod( "clone", "jarrayRef", function(x, ...){ .NotYetImplemented( ) } ) 29 | setMethod( "clone", "jrectRef", function(x, ...){ .NotYetImplemented( ) } ) 30 | # }}} 31 | -------------------------------------------------------------------------------- /R/serialize.R: -------------------------------------------------------------------------------- 1 | ## Java serialization/unserialization 2 | 3 | .jserialize <- function(o) { 4 | if (!is(o, "jobjRef")) 5 | stop("can serialize Java objects only") 6 | .jcall("RJavaClassLoader","[B","toByte",.jcast(o, "java.lang.Object")) 7 | } 8 | 9 | .junserialize <- function(data) { 10 | if (!is.raw(data)) 11 | stop("can de-serialize raw vectors only") 12 | o <- .jcall("RJavaClassLoader","Ljava/lang/Object;","toObjectPL",.jarray(data, dispatch = FALSE)) 13 | if (!is.jnull(o)) { 14 | cl<-try(.jclass(o), silent=TRUE) 15 | if (all(class(cl) == "character")) 16 | o@jclass <- gsub("\\.","/",cl) 17 | } 18 | o 19 | } 20 | 21 | .jcache <- function(o, update=TRUE) { 22 | if (!is(o, "jobjRef")) 23 | stop("o must be a Java object") 24 | if (!is.null(update) && (!is.logical(update) || length(update) != 1)) 25 | stop("update must be TRUE, FALSE of NULL") 26 | what <- update 27 | if (isTRUE(what)) what <- .jserialize(o) 28 | invisible(.Call(javaObjectCache, o@jobj, what)) 29 | } 30 | -------------------------------------------------------------------------------- /R/tools.R: -------------------------------------------------------------------------------- 1 | #' converts a java class name to jni notation 2 | tojni <- function( cl = "java.lang.Object" ){ 3 | gsub( "[.]", "/", cl ) 4 | } 5 | 6 | tojniSignature <- function( cl ){ 7 | sig <- tojni( cl ) 8 | 9 | if( isPrimitiveTypeName(sig) || isPrimitiveArraySignature(sig) ){ 10 | return( sig ) 11 | } 12 | 13 | n <- nchar( sig ) 14 | last <- substr( sig, n, n ) 15 | add.semi <- last != ";" 16 | 17 | first <- substr( sig, 1, 1 ) 18 | add.L <- ! first %in% c("L", "[" ) 19 | 20 | sig <- if( !add.L && !add.semi) sig else sprintf( "%s%s%s", if( add.L ) "L" else "", sig, if( add.semi ) ";" else "" ) 21 | sig 22 | } 23 | 24 | #' converts jni notation to java notation 25 | tojava <- function( cl = "java/lang/Object" ){ 26 | gsub( "/", ".", cl ) 27 | } 28 | 29 | -------------------------------------------------------------------------------- /R/windows/FirstLib.R: -------------------------------------------------------------------------------- 1 | .msg <- message 2 | 3 | .onLoad <- 4 | function(libname, pkgname) { 5 | OPATH <- Sys.getenv("PATH") 6 | javahome <- if (!is.null(getOption("java.home"))) getOption("java.home") else Sys.getenv("JAVA_HOME") 7 | if (nzchar(javahome) && !dir.exists(javahome)) { 8 | .msg("java.home option: ", getOption("java.home")) 9 | .msg("JAVA_HOME environment variable: ", Sys.getenv("JAVA_HOME")) 10 | warning("Java home setting is INVALID, it will be ignored.\nPlease do NOT set it unless you want to override system settings.") 11 | javahome <- "" 12 | } 13 | if(!nzchar(javahome)) { ## JAVA_HOME was not set explicitly 14 | find.java <- function() { 15 | for (root in c("HLM", "HCU")) 16 | for(key in c( 17 | "Software\\JavaSoft\\JRE", 18 | "Software\\JavaSoft\\JDK", 19 | "Software\\JavaSoft\\Java Runtime Environment", 20 | "Software\\JavaSoft\\Java Development Kit" 21 | )) { 22 | hive <- try(utils::readRegistry(key, root, 2), silent=TRUE) 23 | if (!inherits(hive, "try-error")) return(hive) 24 | } 25 | hive 26 | } 27 | hive <- find.java() 28 | if (inherits(hive, "try-error")) 29 | stop("JAVA_HOME cannot be determined from the Registry") 30 | if (!length(hive$CurrentVersion)) 31 | stop("No CurrentVersion entry in Software/JavaSoft registry! Try re-installing Java and make sure R and Java have matching architectures.") 32 | this <- hive[[hive$CurrentVersion]] 33 | javahome <- this$JavaHome 34 | paths <- if (is.character(this$RuntimeLib)) dirname(this$RuntimeLib) else character() # wrong on 64-bit 35 | } else paths <- character() 36 | if(is.null(javahome) || !length(javahome) || !nchar(javahome)) 37 | stop("JAVA_HOME is not set and could not be determined from the registry") 38 | #else cat("using JAVA_HOME =", javahome, "\n") 39 | 40 | ## we need to add Java-related library paths to PATH 41 | curPath <- OPATH 42 | paths <- c(paths, 43 | file.path(javahome, "bin", "client"), # 32-bit 44 | file.path(javahome, "bin", "server"), # 64-bit 45 | file.path(javahome, "bin"), # base (now needed for MSVCRT in recent Sun Java) 46 | file.path(javahome, "jre", "bin", "server"), # old 64-bit (or manual JAVA_HOME setting to JDK) 47 | file.path(javahome, "jre", "bin", "client")) # old 32-bit (or manual JAVA_HOME setting to JDK) 48 | cpc <- strsplit(curPath, ";", fixed=TRUE)[[1]] ## split it up so we can check presence/absence of a path 49 | 50 | ## add paths only if they are not in already and they exist 51 | for (path in unique(paths)) 52 | if (!path %in% cpc && file.exists(path)) curPath <- paste(path, curPath, sep=";") 53 | 54 | ## set PATH only if it's not correct already (cannot use identical/isTRUE because of PATH name attribute) 55 | if (curPath != OPATH) { 56 | Sys.setenv(PATH = curPath) 57 | # check the resulting PATH - if they don't match then Windows has truncated it 58 | if (curPath != Sys.getenv("PATH")) 59 | warning("*** WARNING: your Windows system seems to suffer from truncated PATH bug which will likely prevent rJava from loading.\n Either reduce your PATH or read http://support.microsoft.com/kb/906469 on how to fix your system.") 60 | } 61 | 62 | library.dynam("rJava", pkgname, libname) 63 | Sys.setenv(PATH = OPATH) 64 | .jfirst(libname, pkgname) 65 | } 66 | -------------------------------------------------------------------------------- /R/zzz.R.in: -------------------------------------------------------------------------------- 1 | .onLoad <- function(libname, pkgname) { 2 | ## we can skip all the detection logic if forced - assuming the user has loaded JVM already 3 | if (!nzchar(Sys.getenv("RJAVA_FORCE_LOAD"))) { 4 | ## On OS X with Oracle Java we may need to work around Oracle bug: 5 | ## https://bugs.openjdk.java.net/browse/JDK-7131356 6 | use.dynload <- FALSE 7 | @USE_DYNLOAD_TRUE@use.dynload <- TRUE 8 | if (length(grep("^darwin", R.version$os))) { 9 | jh <- Sys.getenv("JAVA_HOME") 10 | if (nzchar(jh) && !dir.exists(jh)) { 11 | warning("JAVA_HOME is set incorrectly! Ingoring.") 12 | jh <- "" 13 | } 14 | if (!nzchar(jh) && file.exists("/usr/libexec/java_home")) 15 | jh <- system("/usr/libexec/java_home", intern=TRUE)[1L] 16 | if (!nzchar(jh)) { 17 | if (use.dynload) 18 | stop("Cannot find Java. Install Java run-time and use R CMD javareconf.\nAs a last resort you can set JAVA_HOME appropriately.") 19 | warning("Cannot find Java. Install Java run-time and use R CMD javareconf.\nAs a last resort you can set JAVA_HOME if you know the correct value.") 20 | } 21 | if (file.exists(file.path(jh, "jre/lib"))) jh <- file.path(jh, "jre") 22 | dlp <- Sys.getenv("DYLD_LIBRARY_PATH") 23 | if (nzchar(dlp)) dlp <- paste0(":", dlp) 24 | ## pre-load JLI due to Oracle bug 25 | if (file.exists(jli <- file.path(jh, "lib/jli/libjli.dylib"))) 26 | dyn.load(jli, FALSE) 27 | ## this is mandatory - we need the JVM 28 | if (file.exists(jvm <- file.path(jh, "lib/server/libjvm.dylib"))) { 29 | dyn.load(jvm, FALSE) 30 | Sys.setenv(DYLD_LIBRARY_PATH=paste0(file.path(jh, "lib/server"), dlp)) 31 | } else { 32 | warning("Cannot find JVM library '", jvm, "'\nInstall Java and/or check JAVA_HOME (if in doubt, do NOT set it, it will be detected)") 33 | if (use.dynload) stop("JVM could not be found") 34 | } 35 | } else if (use.dynload) { 36 | jh <- Sys.getenv("JAVA_HOME") 37 | if (nzchar(jh) && !dir.exists(jh)) { 38 | warning("JAVA_HOME is set incorrectly! Ingoring.") 39 | jh <- "" 40 | } 41 | if (!nzchar(jh)) 42 | stop("JAVA_HOME is requied for dynamically loaded JVM, but is not set.\nRe-run R CMD javareconf or set JAVA_HOME correctly.") 43 | if (file.exists(file.path(jh, "jre/lib"))) jh <- file.path(jh, "jre") 44 | if (!file.exists(jvm <- file.path(jh, "lib/server/libjvm.so"))) 45 | stop("Cannot find ", jvm,", re-configure R or use valid JAVA_HOME") 46 | dyn.load(jvm, FALSE) 47 | } 48 | } ## RJAVA_FORCE_LOAD 49 | 50 | library.dynam("rJava", pkgname, libname) 51 | # pass on to the system-independent part 52 | .jfirst(libname, pkgname) 53 | } 54 | -------------------------------------------------------------------------------- /configure.win: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Generate Windows-specific files (src/jvm-w32) ..." 4 | make -C src/jvm-w32 5 | 6 | if [ $? != 0 ]; then 7 | exit 1 8 | fi 9 | 10 | echo "Find Java..." 11 | # findjava honors JAVA_HOME environment variable, so we can safely overwite it 12 | if [ -e src/jvm-w32/findjava.exe ]; then 13 | JAVA_HOME=`src/jvm-w32/findjava -s -f` 14 | fi 15 | if [ x$JAVA_HOME = x ]; then 16 | echo "ERROR: cannot find Java Development Kit." >&2 17 | echo " Please set JAVA_HOME to specify its location manually" >&2 18 | exit 1 19 | fi 20 | 21 | echo " JAVA_HOME=$JAVA_HOME" 22 | 23 | echo "JAVA_HOME:=$JAVA_HOME" > src/Makevars.java 24 | 25 | if [ -e jri/configure.win ]; then 26 | echo "=== Building JRI ===" 27 | CONFIGURED=1 28 | export CONFIGURED 29 | if [ -z "${RHOME}" ]; then 30 | RHOME="${R_HOME}" 31 | fi 32 | R_HOME=${RHOME} 33 | export R_HOME 34 | export RHOME 35 | export JAVA_HOME 36 | cd jri 37 | sh configure.win 38 | make 39 | BR=$? 40 | cd .. 41 | if [ $BR = 0 ]; then 42 | echo "=== JRI built ===" 43 | mkdir -p inst/jri 44 | # also copy into R_ARCH is present to avoid overwriting different archs 45 | if [ -n "${R_ARCH}" ]; then 46 | mkdir -p inst/jri${R_ARCH} 47 | cp jri/src/jri.dll inst/jri${R_ARCH}/ 48 | fi 49 | # yet still install into JRI in case users get confused 50 | cp -r jri/run.bat jri/src/jri.dll jri/src/JRI.jar jri/examples inst/jri/ 51 | else 52 | echo "**** WARNING: JRI could NOT be built" >&2 53 | if [ -z "$IGNORE" ]; then 54 | echo "Set IGNORE=1 if you want to build rJava anyway." 55 | exit 1 56 | fi 57 | fi 58 | fi 59 | 60 | echo "Configuration done." 61 | 62 | -------------------------------------------------------------------------------- /jri/LICENSE: -------------------------------------------------------------------------------- 1 | JRI - Java/R Interface 2 | Copyright (C) 2004-2007 Simon Urbanek 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; 7 | version 2.1 of the License. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library (LGPL.txt); if not, write to the 16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 | Boston, MA 02110-1301 USA 18 | -------------------------------------------------------------------------------- /jri/Makefile.all: -------------------------------------------------------------------------------- 1 | # JRI 0.2 (C) Simon Urbanek 2 | # This is the actual Makefile - all autconf'ed values should 3 | # be passed as vars, because we also want to use this for 4 | # the Windows build that has no autoconf 5 | # 6 | # Note: the dependencies are often across directories mainly 7 | # for historical reasons. The Java sources are actually compiled 8 | # by the Makefile in the src directory, although they are here, 9 | # because they originally belonged to src. 10 | 11 | EX_JAVA=$(wildcard examples/*.java) 12 | EX_CLASS=$(EX_JAVA:%.java=%.class) 13 | 14 | TARGETS=src/JRI.jar $(JRILIB) $(EX_CLASS) 15 | 16 | all: $(TARGETS) 17 | 18 | src/JRI.jar: 19 | $(MAKE) -C src JRI.jar 20 | 21 | src/${JRILIB}: 22 | $(MAKE) -C src $(JRILIB) 23 | 24 | $(JRILIB): src/$(JRILIB) 25 | rm -f $@ 26 | cp $< $@ 27 | 28 | examples/%.class: examples/%.java src/JRI.jar 29 | $(JAVAC) $(JFLAGS) -classpath src/JRI.jar -d examples $< 30 | 31 | clean: 32 | $(MAKE) -C src clean 33 | rm -rf $(TARGETS) *~ examples/*.class 34 | 35 | examples: $(EX_CLASS) 36 | 37 | JRI_JDOCSRC=$(wildcard *.java) 38 | 39 | doc: $(JRI_JDOCSRC) 40 | rm -rf JavaDoc 41 | mkdir JavaDoc 42 | $(JAVA)doc -d JavaDoc -author -version -breakiterator -link http://java.sun.com/j2se/1.4.2/docs/api $^ 43 | 44 | .PHONY: clean all examples doc 45 | 46 | .NOTPARALLEL: 47 | -------------------------------------------------------------------------------- /jri/Makefile.in: -------------------------------------------------------------------------------- 1 | # JRI - Java/R Interface experimental! 2 | #-------------------------------------------------------------------------- 3 | # See Makefile.all for the actual building process 4 | 5 | # The values are all auto-configured 6 | RHOME=@R_HOME@ 7 | JAVAC=@JAVAC@ 8 | JAVAH=@JAVAH@ 9 | JAVA=@JAVA_PROG@ 10 | JFLAGS=@JFLAGS@ 11 | 12 | JRILIB=@JNIPREFIX@jri@JNISO@ 13 | 14 | include Makefile.all 15 | -------------------------------------------------------------------------------- /jri/Makefile.win: -------------------------------------------------------------------------------- 1 | # Windows-specific part of the Makefile 2 | 3 | include src/Makefile.wconf 4 | include Makevars.win 5 | 6 | windows.all: all run.bat 7 | 8 | $(RHOME)/src/gnuwin32/libR.a: 9 | make -C $(RHOME)/src/gnuwin32 libR.a 10 | 11 | run.bat: jri.dll 12 | echo "set PATH=%PATH%;$(RHOME)\\bin;$(RHOME)\\lib" > run.bat 13 | echo "$(JAVA_PROG) -cp .;examples;JRI.jar;src/JRI.jar rtest \$$*" >> run.bat 14 | 15 | include Makefile.all 16 | -------------------------------------------------------------------------------- /jri/Makevars.win: -------------------------------------------------------------------------------- 1 | R_HOME=$(RHOME) 2 | JAVA_HOME=$(JAVAHOME) 3 | JAVAINC=-I$(JAVAHOME)/include -I$(JAVAHOME)/include/win32 4 | RINC=-I$(R_HOME)/include 5 | JNISO=.dll 6 | JAVA_LIBS=-Lwin32 -ljvm 7 | JNILD=-shared $(JAVA_LIBS) -L$(RHOME)/src/gnuwin32 -L$(RHOME)/bin$(R_ARCH) -lR -Wl,--kill-at 8 | CFLAGS+=-DWin32 -D_JNI_IMPLEMENTATION_ 9 | JAVA_PROG=$(JAVAHOME)/bin/java 10 | JAVA=$(JAVAHOME)/bin/java 11 | JAVAC=$(JAVAHOME)/bin/javac 12 | JAR=$(JAVAHOME)/bin/jar 13 | JRIDEPS=win32/libjvm.dll.a 14 | JNIPREFIX= 15 | PLATFORMT=run.bat 16 | JRILIB=jri.dll 17 | -------------------------------------------------------------------------------- /jri/RBool.java: -------------------------------------------------------------------------------- 1 | package org.rosuda.JRI; 2 | 3 | // JRclient library - client interface to Rserve, see http://www.rosuda.org/Rserve/ 4 | // Copyright (C) 2004 Simon Urbanek 5 | // --- for licensing information see LICENSE file in the original JRclient distribution --- 6 | 7 | /** Implementation of tri-state logical data type in R. 8 | The three states are TRUE, FALSE and NA. To obtain truly boolean 9 | value, you'll need to use {@link #isTRUE} or {@link #isFALSE} since there is 10 | no canonical representation of RBool in boolean 11 | 12 | @version $Id: RBool.java 2720 2007-03-15 17:35:42Z urbanek $ 13 | */ 14 | public class RBool extends Object { 15 | int val; 16 | 17 | public RBool(boolean b) { 18 | val=(b)?1:0; 19 | }; 20 | public RBool(RBool r) { 21 | val=r.val; 22 | }; 23 | public RBool(int i) { /* 0=FALSE, 2=NA, anything else = TRUE */ 24 | val=(i==0||i==2)?i:1; 25 | }; 26 | 27 | public boolean isNA() { return (val==2); }; 28 | public boolean isTRUE() { return (val==1); }; 29 | public boolean isFALSE() { return (val==0); }; 30 | 31 | public String toString() { return (val==0)?"FALSE":((val==2)?"NA":"TRUE"); }; 32 | } 33 | -------------------------------------------------------------------------------- /jri/RConsoleOutputStream.java: -------------------------------------------------------------------------------- 1 | // RConsoleOutputStream, part of Java/R Interface 2 | // 3 | // (C)Copyright 2007 Simon Urbanek 4 | // 5 | // For licensing terms see LICENSE in the root if the JRI distribution 6 | 7 | package org.rosuda.JRI; 8 | 9 | import java.io.OutputStream; 10 | import java.io.IOException; 11 | 12 | /** RConsoleOutputStream provides an OutputStream which causes its output to be written to the R console. It is a pseudo-stream as there is no real descriptor connected to the R console and thusly it is legal to have multiple console streams open. The synchonization happens at the RNI level.

Note that stdout/stderr are not connected to the R console by default, so one way of using this stream is to re-route Java output to R console:

13 | System.setOut(new PrintStream(new RConsoleOutputStream(engine, 0)));
14 | System.setErr(new PrintStream(new RConsoleOutputStream(engine, 1)));
15 | 
16 | 17 | @since JRI 0.4-0 18 | */ 19 | public class RConsoleOutputStream extends OutputStream { 20 | Rengine eng; 21 | int oType; 22 | boolean isOpen; 23 | 24 | /** opens a new output stream to R console 25 | @param eng R engine 26 | @param oType output type (0=regular, 1=error/warning) */ 27 | public RConsoleOutputStream(Rengine eng, int oType) { 28 | this.eng = eng; 29 | this.oType = oType; 30 | isOpen = true; 31 | } 32 | 33 | public void write(byte[] b, int off, int len) throws IOException { 34 | if (!isOpen) throw new IOException("cannot write to a closed stream"); 35 | if (eng == null) throw new IOException("missing R engine"); 36 | String s = new String(b, off, len); 37 | eng.rniPrint(s, oType); 38 | } 39 | 40 | public void write(byte[] b) throws IOException { write(b, 0, b.length); } 41 | public void write(int b) throws IOException { write(new byte[] { (byte)(b&255) }); } 42 | public void close() throws IOException { isOpen=false; eng=null; } 43 | } 44 | -------------------------------------------------------------------------------- /jri/README: -------------------------------------------------------------------------------- 1 | JRI - Java/R Interface 2 | ------------------------ 3 | 4 | Copyright (C) 2006 Simon Urbanek 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; 9 | version 2.1 of the License. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details (LGPL.txt). 15 | 16 | 17 | This package contains code that is necessary to run 18 | R as a single thread of a Java application. It provides 19 | callback that make it possible to run R in REPL mode 20 | thus giving the Java application full access to the 21 | console. 22 | 23 | Currently the API is very, very low-level, comparable 24 | to the C level interface to R. Convenience methods for 25 | mid to high-level are planned, but not implemented yet. 26 | 27 | For R-to-Java interface, use rJava package which 28 | integrates fine with JRI. rJava hooks into the same 29 | JVM, so both are opertaing in the same environment. 30 | 31 | Java to R: JRI 32 | R to Java: rJava 33 | 34 | How to compile 35 | ---------------- 36 | 37 | As of JRI 0.2 everything is 'autoconf'igured. 38 | 39 | 1) Make sure JDK 1.4 or higher is installed (on Linux 40 | 1.5 or later must be installed) and all java 41 | commands are ont the PATH. Alternatively you can 42 | set JAVA_HOME instead. 43 | 2) ./configure 44 | 3) make 45 | 46 | On Windows run "sh configure.win" instead of configure 47 | 48 | Note for Windows users: you will need the same tools 49 | that are necessary to build R, i.e. the /bin tools 50 | and MinGW. See R for details. 51 | 52 | How to use JRI 53 | ---------------- 54 | 55 | There are two Java examples in the JRI directory: 56 | 57 | rtest.java - demonstrates the use of the low-level 58 | interface to construct and retrieve 59 | complex R objects. It also demonstrates 60 | how to setup callbacks for handling of 61 | the console. 62 | rtest2.java - a very simple console using stdin as input 63 | and a TextField for output. 64 | 65 | The examples can be run with 66 | ./run rtest 67 | ./run rtest2 68 | 69 | On Windows use run.bat instead 70 | 71 | --- 72 | 04/2006 Simon Urbanek 73 | 74 | -------------------------------------------------------------------------------- /jri/RFactor.java: -------------------------------------------------------------------------------- 1 | package org.rosuda.JRI; 2 | 3 | // JRclient library - client interface to Rserve, see http://www.rosuda.org/Rserve/ 4 | // Copyright (C) 2004 Simon Urbanek 5 | // --- for licensing information see LICENSE file in the original JRclient distribution --- 6 | 7 | import java.util.*; 8 | 9 | /** representation of a factor variable. In R there is no actual xpression 10 | type called "factor", instead it is coded as an int vector with a list 11 | attribute. The parser code of REXP converts such constructs directly into 12 | the RFactor objects and defines an own XT_FACTOR type 13 | 14 | @version $Id: RFactor.java 2909 2008-07-15 15:06:49Z urbanek $ 15 | */ 16 | public class RFactor extends Object { 17 | /** IDs (content: Integer) each entry corresponds to a case, ID specifies the category */ 18 | Vector id; 19 | /** values (content: String), ergo category names */ 20 | Vector val; 21 | 22 | /** create a new, empty factor var */ 23 | public RFactor() { id=new Vector(); val=new Vector(); } 24 | 25 | /** create a new factor variable, based on the supplied arrays. 26 | @param i array of IDs (0..v.length-1) 27 | @param v values - category names */ 28 | public RFactor(int[] i, String[] v) { 29 | this(i, v, 0); 30 | } 31 | 32 | /** create a new factor variable, based on the supplied arrays. 33 | @param i array of IDs (base .. v.length-1+base) 34 | @param v values - cotegory names 35 | @param base of the indexing 36 | */ 37 | RFactor(int[] i, String[] v, int base) { 38 | id=new Vector(); val=new Vector(); 39 | int j; 40 | if (i!=null && i.length>0) 41 | for(j=0;j0) 44 | for(j=0;j= id.size()) return null; 64 | int j = ((Integer)id.elementAt(i)).intValue(); 65 | /* due to the index shift NA (INT_MIN) will turn into INT_MAX if base is 1 */ 66 | return (j < 0 || j > 2147483640) ? null : ((String)val.elementAt(j)); 67 | } 68 | 69 | /** returns the number of caes */ 70 | public int size() { return id.size(); } 71 | 72 | /** displayable representation of the factor variable */ 73 | public String toString() { 74 | //return "{"+((val==null)?";":("levels="+val.size()+";"))+((id==null)?"":("cases="+id.size()))+"}"; 75 | StringBuffer sb=new StringBuffer("{levels=("); 76 | if (val==null) 77 | sb.append("null"); 78 | else 79 | for (int i=0;i0)?",\"":"\""); 81 | sb.append((String)val.elementAt(i)); 82 | sb.append("\""); 83 | }; 84 | sb.append("),ids=("); 85 | if (id==null) 86 | sb.append("null"); 87 | else 88 | for (int i=0;i0) sb.append(","); 90 | sb.append((Integer)id.elementAt(i)); 91 | }; 92 | sb.append(")}"); 93 | return sb.toString(); 94 | } 95 | } 96 | 97 | -------------------------------------------------------------------------------- /jri/RMainLoopCallbacks.java: -------------------------------------------------------------------------------- 1 | package org.rosuda.JRI; 2 | 3 | /** Interface which must be implmented by any class that wants to pose as the call-back handler for R event loop callbacks. It is legal to return immediately except when user interaction is required: {@link #rReadConsole} and {@link #rChooseFile} are expected to block until the user performs the desired action. */ 4 | public interface RMainLoopCallbacks { 5 | /** called when R prints output to the console 6 | @param re calling engine 7 | @param text text to display in the console 8 | @param oType output type (0=regular, 1=error/warning) 9 | */ 10 | public void rWriteConsole (Rengine re, String text, int oType); 11 | /** called when R enters or exits a longer evaluation. It is usually a good idea to signal this state to the user, e.g. by changing the cursor to a "hourglass" and back. 12 | @param re calling engine 13 | @param which identifies whether R enters (1) or exits (0) the busy state */ 14 | public void rBusy (Rengine re, int which); 15 | /** called when R waits for user input. During the duration of this callback it is safe to re-enter R, and very often it is also the only time. The implementation is free to block on this call until the user hits Enter, but in JRI it is a good idea to call {@link Rengine.rniIdle()} occasionally to allow other event handlers (e.g graphics device UIs) to run. Implementations should NEVER return immediately even if there is no input - such behavior will result in a fast cycling event loop which makes the use of R pretty much impossible. 16 | @param re calling engine 17 | @param prompt prompt to be displayed at the console prior to user's input 18 | @param addToHistory flag telling the handler whether the input should be considered for adding to history (!=0) or not (0) 19 | @return user's input to be passed to R for evaluation */ 20 | public String rReadConsole (Rengine re, String prompt, int addToHistory); 21 | /** called when R want to show a warning/error message (not to be confused with messages displayed in the console output) 22 | @param re calling engine 23 | @param message message to display */ 24 | public void rShowMessage (Rengine re, String message); 25 | /** called when R expects the user to choose a file 26 | @param re calling engine 27 | @param newFile flag determining whether an existing or new file is to be selecteed 28 | @return path/name of the selected file */ 29 | public String rChooseFile (Rengine re, int newFile); 30 | /** called when R requests the console to flush any buffered output 31 | @param re calling engine */ 32 | public void rFlushConsole (Rengine re); 33 | /** called to save the contents of the history (the implementation is responsible of keeping track of the history) 34 | @param re calling engine 35 | @param filename name of the history file */ 36 | public void rSaveHistory (Rengine re, String filename); 37 | /** called to load the contents of the history 38 | @param re calling engine 39 | @param filename name of the history file */ 40 | public void rLoadHistory (Rengine re, String filename); 41 | } 42 | -------------------------------------------------------------------------------- /jri/RVector.java: -------------------------------------------------------------------------------- 1 | package org.rosuda.JRI; 2 | 3 | import java.util.Vector; 4 | import java.util.Enumeration; 5 | 6 | /** class encapsulating named generic vectors in R - do NOT use add/remove directly as names are not synchronized with the contents. The reason for this implementation is for historical compatibility and it may change in the future. 7 |

8 | It is now used in REXP where Vector type was used previously for contents storage. 9 | @since JRI 0.3 10 | */ 11 | public class RVector extends java.util.Vector { 12 | Vector names = null; 13 | public RVector() { super(); } 14 | 15 | /** replace the names vector - do NOT use directly! 16 | @param nam list of names */ 17 | public void setNames(String[] nam) { 18 | names=new Vector(nam.length); 19 | int i=0; 20 | while (inull if not found 31 | @param name key (name) 32 | @return contents or null if not found 33 | */ 34 | public REXP at(String name) { 35 | if (names==null) return null; 36 | int i=0; 37 | for (Enumeration e = names.elements() ; e.hasMoreElements() ;) { 38 | String n = (String)e.nextElement(); 39 | if (n.equals(name)) return (REXP) elementAt(i); 40 | i++; 41 | } 42 | return null; 43 | } 44 | 45 | public REXP at(int i) { 46 | return (REXP)elementAt(i); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /jri/bootstrap/Boot.java: -------------------------------------------------------------------------------- 1 | import java.io.File; 2 | import java.io.InputStream; 3 | import java.io.FileOutputStream; 4 | import java.util.StringTokenizer; 5 | import java.util.zip.ZipFile; 6 | import java.util.zip.ZipEntry; 7 | import java.lang.reflect.Method; 8 | 9 | public class Boot { 10 | public static String bootFile = null; 11 | 12 | public static String findInPath(String path, String fn) { 13 | StringTokenizer st = new StringTokenizer(path, File.pathSeparator); 14 | while (st.hasMoreTokens()) { 15 | String dirname=st.nextToken(); 16 | try { 17 | File f = new File(dirname+File.separator+fn); 18 | if (f.isFile()) return f.getPath(); 19 | } catch (Exception fex) {} 20 | } 21 | return null; 22 | } 23 | 24 | public static String findNativeLibrary(String basename, boolean internalFirst) { 25 | String libName = "lib"+basename; 26 | String ext = ".so"; 27 | String os = System.getProperty("os.name"); 28 | if (os.startsWith("Win")) { 29 | os = "Win"; 30 | ext= ".dll"; 31 | libName=basename; 32 | } 33 | if (os.startsWith("Mac")) { 34 | os = "Mac"; 35 | ext= ".jnilib"; 36 | } 37 | String fullName = libName+ext; 38 | 39 | // first, try the system path unless instructed otherwise 40 | if (!internalFirst) { 41 | try { 42 | String r = findInPath("."+File.pathSeparator+System.getProperty("java.library.path"), 43 | fullName); 44 | if (r != null) return r; 45 | } catch (Exception ex1) {} 46 | } 47 | 48 | // second, try to locate in on the class path (in the JAR file or in one of the directories) 49 | String cp = System.getProperty("java.class.path"); 50 | StringTokenizer st = new StringTokenizer(cp, File.pathSeparator); 51 | while (st.hasMoreTokens()) { 52 | String dirname=st.nextToken(); 53 | try { 54 | File f = new File(dirname); 55 | if (f.isFile()) { 56 | // look in a JAR file and extract it if necessary 57 | ZipFile jf = new ZipFile(f); 58 | ZipEntry ze = jf.getEntry(fullName); 59 | if (ze != null) { // found it inside a JAR file 60 | try { 61 | bootFile = f.toString(); 62 | File tf = File.createTempFile(basename,ext); 63 | System.out.println("Boot.findNativeLibrary: found in a JAR ("+jf+"), extracting into "+tf); 64 | InputStream zis = jf.getInputStream(ze); 65 | FileOutputStream fos = new FileOutputStream(tf); 66 | byte b[] = new byte[65536]; 67 | while (zis.available()>0) { 68 | int n = zis.read(b); 69 | if (n>0) fos.write(b, 0, n); 70 | } 71 | zis.close(); 72 | fos.close(); 73 | tf.deleteOnExit(); 74 | return tf.getPath(); 75 | } catch (Exception foo) { 76 | } 77 | } 78 | } else if (f.isDirectory()) { 79 | File ff = new File(dirname+File.separator+fullName); 80 | if (ff.isFile()) return ff.getPath(); 81 | } 82 | } catch(Exception ex2) {} 83 | } 84 | 85 | // third, try the system path if we didn't look there before 86 | if (internalFirst) { 87 | try { 88 | String r = findInPath("."+File.pathSeparator+System.getProperty("java.library.path"), 89 | fullName); 90 | if (r != null) return r; 91 | } catch (Exception ex3) {} 92 | } 93 | return null; 94 | } 95 | 96 | public static void main(String[] args) { 97 | // 1) instantiate master class loader 98 | JRIClassLoader mcl = JRIClassLoader.getMainLoader(); 99 | 100 | // 2) locate boot JNI library 101 | String nl = findNativeLibrary("boot", false); 102 | 103 | if (nl == null) { 104 | System.err.println("ERROR: Unable to locate native bootstrap library."); 105 | System.exit(1); 106 | } 107 | 108 | // register boot library with MCL 109 | mcl.registerLibrary("boot", new File(nl)); 110 | 111 | // add path necessary for loading JRIBootstrap to MCL 112 | String cp = System.getProperty("java.class.path"); 113 | StringTokenizer st = new StringTokenizer(cp, File.pathSeparator); 114 | while (st.hasMoreTokens()) { 115 | String p = st.nextToken(); 116 | mcl.addClassPath(p); 117 | // we assume that the first file on the CP is us (FIXME: verify this!) 118 | if (bootFile==null && (new File(p)).isFile()) bootFile=p; 119 | } 120 | 121 | // call static bootstrap method 122 | try { 123 | // force the use of the MCL even if the system loader could find it 124 | Class stage2class = mcl.findAndLinkClass("JRIBootstrap"); 125 | Method m = stage2class.getMethod("bootstrap", new Class[] { String[].class }); 126 | m.invoke(null, new Object[] { args }); 127 | } catch (Exception rtx) { 128 | System.err.println("ERROR: Unable to invoke bootstrap method in JRIBootstrap! ("+rtx+")"); 129 | rtx.printStackTrace(); 130 | System.exit(2); 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /jri/bootstrap/DelegatedClassLoader.java: -------------------------------------------------------------------------------- 1 | import java.net.URL; 2 | 3 | public interface DelegatedClassLoader { 4 | public String delegatedFindLibrary(String name); 5 | public Class delegatedFindClass(String name) throws ClassNotFoundException; 6 | public URL delegatedFindResource(String name); 7 | } 8 | -------------------------------------------------------------------------------- /jri/bootstrap/DelegatedURLClassLoader.java: -------------------------------------------------------------------------------- 1 | /* An extension of URLClassLoader that implements DelegatedClassLoader */ 2 | 3 | import java.net.URL; 4 | import java.net.URLClassLoader; 5 | 6 | public class DelegatedURLClassLoader extends URLClassLoader implements DelegatedClassLoader { 7 | public DelegatedURLClassLoader() { 8 | super(new URL[]{}); 9 | } 10 | public DelegatedURLClassLoader(URL[] urls) { 11 | super(urls); 12 | } 13 | public String delegatedFindLibrary(String name) { 14 | return super.findLibrary(name); 15 | } 16 | public Class delegatedFindClass(String name) throws ClassNotFoundException { 17 | return super.findClass(name); 18 | } 19 | public URL delegatedFindResource(String name) { 20 | return super.findResource(name); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /jri/bootstrap/JRIBootstrap.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class JRIBootstrap */ 4 | 5 | #ifndef _Included_JRIBootstrap 6 | #define _Included_JRIBootstrap 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | #undef JRIBootstrap_HKLM 11 | #define JRIBootstrap_HKLM 0L 12 | #undef JRIBootstrap_HKCU 13 | #define JRIBootstrap_HKCU 1L 14 | /* 15 | * Class: JRIBootstrap 16 | * Method: getenv 17 | * Signature: (Ljava/lang/String;)Ljava/lang/String; 18 | */ 19 | JNIEXPORT jstring JNICALL Java_JRIBootstrap_getenv 20 | (JNIEnv *, jclass, jstring); 21 | 22 | /* 23 | * Class: JRIBootstrap 24 | * Method: setenv 25 | * Signature: (Ljava/lang/String;Ljava/lang/String;)V 26 | */ 27 | JNIEXPORT void JNICALL Java_JRIBootstrap_setenv 28 | (JNIEnv *, jclass, jstring, jstring); 29 | 30 | /* 31 | * Class: JRIBootstrap 32 | * Method: regvalue 33 | * Signature: (ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String; 34 | */ 35 | JNIEXPORT jstring JNICALL Java_JRIBootstrap_regvalue 36 | (JNIEnv *, jclass, jint, jstring, jstring); 37 | 38 | /* 39 | * Class: JRIBootstrap 40 | * Method: regsubkeys 41 | * Signature: (ILjava/lang/String;)[Ljava/lang/String; 42 | */ 43 | JNIEXPORT jobjectArray JNICALL Java_JRIBootstrap_regsubkeys 44 | (JNIEnv *, jclass, jint, jstring); 45 | 46 | /* 47 | * Class: JRIBootstrap 48 | * Method: expand 49 | * Signature: (Ljava/lang/String;)Ljava/lang/String; 50 | */ 51 | JNIEXPORT jstring JNICALL Java_JRIBootstrap_expand 52 | (JNIEnv *, jclass, jstring); 53 | 54 | #ifdef __cplusplus 55 | } 56 | #endif 57 | #endif 58 | -------------------------------------------------------------------------------- /jri/bootstrap/JRIClassLoader.java: -------------------------------------------------------------------------------- 1 | import java.net.URLClassLoader; 2 | import java.net.URL; 3 | import java.util.HashMap; 4 | import java.util.Vector; 5 | import java.util.Enumeration; 6 | import java.io.File; 7 | 8 | public class JRIClassLoader extends URLClassLoader { 9 | HashMap libMap; 10 | 11 | Vector children; 12 | 13 | static JRIClassLoader mainLoader; 14 | 15 | public static JRIClassLoader getMainLoader() { 16 | if (mainLoader == null) mainLoader = new JRIClassLoader(); 17 | return mainLoader; 18 | } 19 | 20 | public JRIClassLoader() { 21 | super(new URL[]{}); 22 | children = new Vector(); 23 | libMap = new HashMap(); 24 | System.out.println("JRIClassLoader: new loader "+this); 25 | } 26 | 27 | public void registerLoader(DelegatedClassLoader cl) { 28 | if (!children.contains(cl)) 29 | children.add(cl); 30 | } 31 | 32 | public void unregisterLoader(DelegatedClassLoader cl) { 33 | children.removeElement(cl); 34 | } 35 | 36 | public void registerLibrary(String name, File f) { 37 | libMap.put(name, f); 38 | } 39 | 40 | /** add path to the class path list 41 | @param path string denoting the path to the file or directory */ 42 | public void addClassPath(String path) { 43 | try { 44 | File f = new File(path); 45 | if (f.exists()) addURL(f.toURL()); 46 | } catch (Exception x) {} 47 | } 48 | 49 | /** add path to the class path list 50 | @param f file/directory to add to the list */ 51 | public void addClassPath(File f) { 52 | try { 53 | if (f.exists()) addURL(f.toURL()); 54 | } catch (Exception x) {} 55 | } 56 | 57 | protected String findLibrary(String name) { 58 | String s = null; 59 | System.out.println("boot findLibrary(\""+name+"\")"); 60 | try { 61 | for (Enumeration e = children.elements() ; e.hasMoreElements() ;) { 62 | DelegatedClassLoader cl = (DelegatedClassLoader)e.nextElement(); 63 | if (cl != null) { 64 | s = cl.delegatedFindLibrary(name); 65 | if (s != null) { 66 | System.out.println(" - found delegated answer "+s+" from "+cl); 67 | return s; 68 | } 69 | } 70 | } 71 | } catch (Exception ex) {} 72 | 73 | File u = (File) libMap.get(name); 74 | if (u!=null && u.exists()) s=u.getAbsolutePath(); 75 | System.out.println(" - mapping to "+((s==null)?"":s)); 76 | 77 | return s; 78 | } 79 | 80 | public Class findAndLinkClass(String name) throws ClassNotFoundException { 81 | Class c = findClass(name); 82 | resolveClass(c); 83 | return c; 84 | } 85 | 86 | protected Class findClass(String name) throws ClassNotFoundException { 87 | Class cl = null; 88 | System.out.println("boot findClass(\""+name+"\")"); 89 | for (Enumeration e = children.elements() ; e.hasMoreElements() ;) { 90 | DelegatedClassLoader ldr = (DelegatedClassLoader)e.nextElement(); 91 | if (ldr != null) { 92 | try { 93 | cl = ldr.delegatedFindClass(name); 94 | if (cl != null) { 95 | System.out.println(" - found delegated answer "+cl+" from "+ldr); 96 | return cl; 97 | } 98 | } catch (Exception ex) {} 99 | } 100 | } 101 | return super.findClass(name); 102 | } 103 | 104 | public URL findResource(String name) { 105 | URL u = null; 106 | System.out.println("boot findResource(\""+name+"\")"); 107 | for (Enumeration e = children.elements() ; e.hasMoreElements() ;) { 108 | DelegatedClassLoader ldr = (DelegatedClassLoader)e.nextElement(); 109 | if (ldr != null) { 110 | try { 111 | u = ldr.delegatedFindResource(name); 112 | if (u != null) { 113 | System.out.println(" - found delegated answer "+u+" from "+ldr); 114 | return u; 115 | } 116 | } catch (Exception ex) {} 117 | } 118 | } 119 | return super.findResource(name); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /jri/bootstrap/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for JRI bootstrap 2 | # Win/OSX should be ok, Linux will need some tweaking 3 | 4 | all: boot.jar 5 | 6 | OSKIND=$(shell if echo "${OS}"|grep -i windows >/dev/null 2>&1; then echo win32; else uname -s; fi) 7 | 8 | ifeq ($(OSKIND),win32) 9 | ifeq ($(JAVA_HOME),) 10 | JAVA_HOME=N:/java/jdk1.5.0 11 | endif 12 | JSO_PREFIX= 13 | JSO_SUFFIX=.dll 14 | JCPPFLAGS=-DWIN32 -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/win32 15 | JLDFLAGS=-shared -Wl,--add-stdcall-alias -mno-cygwin 16 | JLIBS=-L$(JAVA_HOME)/jre/bin/client -L$(JAVA_HOME)/jre/bin -ljvm 17 | PATHSEP=\; 18 | KNOWNOS=yes 19 | OSNAME=Windows 20 | JAVA=$(JAVA_HOME)/bin/java 21 | JAVAC=$(JAVA_HOME)/bin/javac 22 | JAR=$(JAVA_HOME)/bin/jar 23 | endif 24 | ifeq ($(OSKIND),Darwin) 25 | JSO_PREFIX=lib 26 | JSO_SUFFIX=.jnilib 27 | JLDFLAGS=-dynamiclib 28 | JLIBS=-framework JavaVM 29 | JCPPFLAGS=-I/System/Library/Frameworks/JavaVM.framework/Headers 30 | PATHSEP=: 31 | KNOWNOS=yes 32 | OSNAME=MacOSX 33 | JAVA=java 34 | JAVAC=javac 35 | JAR=jar 36 | endif 37 | ifneq ($(KNOWNOS),yes) 38 | ifeq ($(JAVA_HOME),) 39 | JAVA_HOME=/usr/lib/java 40 | endif 41 | JSO_PREFIX=lib 42 | JSO_SUFFIX=.so 43 | JCPPFLAGS=-I$(JAVA_HOME)/include -I$(shell dirname `find $(JAVA_HOME)/include -name jni_md.h|sed -n -e 1p`) 44 | JLDFLAGS=-shared 45 | JLIBS=-L$(JAVA_HOME)/lib -ljvm 46 | PATHSEP=: 47 | OSNAME="generic unix" 48 | JAVA=java 49 | JAVAC=javac 50 | JAR=jar 51 | endif 52 | 53 | $(JSO_PREFIX)boot$(JSO_SUFFIX): JRIBootstrap.o 54 | $(CC) $(JLDFLAGS) -o $@ $^ #$(JLIBS) 55 | 56 | JRIBootstrap.o: JRIBootstrap.c JRIBootstrap.h 57 | $(CC) -c -o $@ $< $(JCPPFLAGS) 58 | 59 | run: boot.jar 60 | $(JAVA) -jar $< 61 | 62 | clean: 63 | rm -f JRIBootstrap.o $(JSO_PREFIX)boot$(JSO_SUFFIX) *.class *~ 64 | 65 | boot.jar: $(JSO_PREFIX)boot$(JSO_SUFFIX) 66 | $(JAVAC) -source 1.2 -target 1.2 *.java 67 | $(JAR) fcm $@ mft *.class $^ 68 | 69 | .PHONY: clean run all 70 | -------------------------------------------------------------------------------- /jri/bootstrap/mft: -------------------------------------------------------------------------------- 1 | Main-Class: Boot 2 | -------------------------------------------------------------------------------- /jri/configure.win: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # if CONFIGURED is set, then we don't attempt to run findjava 4 | # (useful when building inside rJava) 5 | if [ -z "$CONFIGURED" ]; then 6 | echo "Generate Windows-specific files (src/jvm-w32) ..." 7 | make -C src/win32 8 | 9 | if [ $? != 0 ]; then 10 | exit 1 11 | fi 12 | 13 | echo "Find Java..." 14 | # findjava honors JAVA_HOME environment variable, so we can safely overwite it 15 | if [ -e src/win32/findjava.exe ]; then 16 | JAVA_HOME=`src/win32/findjava -s -f` 17 | R_HOME=`src/win32/findjava -R -s -f` 18 | fi 19 | fi 20 | 21 | if [ x$JAVA_HOME = x ]; then 22 | echo "ERROR: cannot find Java Development Kit." >&2 23 | echo " Please set JAVA_HOME to specify its location manually" >&2 24 | exit 1 25 | fi 26 | 27 | if [ x$R_HOME = x ]; then 28 | echo "ERROR: cannot find R. Please set R_HOME correspondingly." >&2 29 | exit 1 30 | fi 31 | 32 | echo " JAVA_HOME=$JAVA_HOME" 33 | echo " R_HOME=$R_HOME" 34 | 35 | echo "JAVAHOME:=$JAVA_HOME" > src/Makefile.wconf 36 | echo "RHOME:=$R_HOME" >> src/Makefile.wconf 37 | 38 | if [ -e "$JAVA_HOME/bin/javah.exe" ]; then ## does the JDK have javah? 39 | echo 'JDK includes javah.exe' 40 | echo 'JAVAH=$(JAVAHOME)/bin/javah' >> src/Makefile.wconf 41 | else ## else we have to create headers during the compilation 42 | echo 'JDK has no javah.exe - using javac -h . instead' 43 | ## if this is at least 1.8 we can set source/target 44 | ## it is mandatory for 14 (and may be earlier) due to yield 45 | tgt=`"${JAVA_HOME}/bin/java" -cp tools getsp -minver 8` 46 | echo "Is the Java version at least 1.8 ... $tgt" 47 | if [ x$tgt = xyes ]; then 48 | echo 'JFLAGS=-source 1.8 -target 1.8 -h .' >> src/Makefile.wconf 49 | else 50 | echo 'JFLAGS=-h .' >> src/Makefile.wconf 51 | fi 52 | fi 53 | 54 | echo "Creating Makefiles ..." 55 | cp Makefile.win Makefile 56 | cp src/Makefile.win src/Makefile 57 | 58 | echo "Configuration done." 59 | 60 | -------------------------------------------------------------------------------- /jri/examples/rtest2.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | 3 | import java.awt.*; 4 | import javax.swing.*; 5 | 6 | import org.rosuda.JRI.Rengine; 7 | import org.rosuda.JRI.REXP; 8 | import org.rosuda.JRI.RMainLoopCallbacks; 9 | import org.rosuda.JRI.RConsoleOutputStream; 10 | 11 | class TextConsole2 implements RMainLoopCallbacks 12 | { 13 | JFrame f; 14 | 15 | public JTextArea textarea = new JTextArea(); 16 | 17 | public TextConsole2() { 18 | f = new JFrame(); 19 | f.getContentPane().add(new JScrollPane(textarea)); 20 | f.setSize(new Dimension(800,600)); 21 | f.show(); 22 | } 23 | 24 | public void rWriteConsole(Rengine re, String text, int oType) { 25 | textarea.append(text); 26 | } 27 | 28 | public void rBusy(Rengine re, int which) { 29 | System.out.println("rBusy("+which+")"); 30 | } 31 | 32 | public String rReadConsole(Rengine re, String prompt, int addToHistory) { 33 | System.out.print(prompt); 34 | try { 35 | BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 36 | String s=br.readLine(); 37 | return (s==null||s.length()==0)?s:s+"\n"; 38 | } catch (Exception e) { 39 | System.out.println("jriReadConsole exception: "+e.getMessage()); 40 | } 41 | return null; 42 | } 43 | 44 | public void rShowMessage(Rengine re, String message) { 45 | System.out.println("rShowMessage \""+message+"\""); 46 | } 47 | 48 | public String rChooseFile(Rengine re, int newFile) { 49 | FileDialog fd = new FileDialog(f, (newFile==0)?"Select a file":"Select a new file", (newFile==0)?FileDialog.LOAD:FileDialog.SAVE); 50 | fd.show(); 51 | String res=null; 52 | if (fd.getDirectory()!=null) res=fd.getDirectory(); 53 | if (fd.getFile()!=null) res=(res==null)?fd.getFile():(res+fd.getFile()); 54 | return res; 55 | } 56 | 57 | public void rFlushConsole (Rengine re) { 58 | } 59 | 60 | public void rLoadHistory (Rengine re, String filename) { 61 | } 62 | 63 | public void rSaveHistory (Rengine re, String filename) { 64 | } 65 | } 66 | 67 | public class rtest2 { 68 | public static void main(String[] args) { 69 | System.out.println("Press to continue (time to attach the debugger if necessary)"); 70 | try { System.in.read(); } catch(Exception e) {}; 71 | System.out.println("Creating Rengine (with arguments)"); 72 | Rengine re=new Rengine(args, true, new TextConsole2()); 73 | System.out.println("Rengine created, waiting for R"); 74 | if (!re.waitForR()) { 75 | System.out.println("Cannot load R"); 76 | return; 77 | } 78 | System.out.println("re-routing stdout/err into R console"); 79 | System.setOut(new PrintStream(new RConsoleOutputStream(re, 0))); 80 | System.setErr(new PrintStream(new RConsoleOutputStream(re, 1))); 81 | 82 | System.out.println("Letting go; use main loop from now on"); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /jri/mkdist: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | PNAME=JRI 4 | SWD=`pwd` 5 | echo "Removing previous dist ..." 6 | rm -rf /tmp/${PNAME} 7 | echo "Copying package base ..." 8 | mkdir /tmp/${PNAME} 9 | cp -r . /tmp/${PNAME} 10 | 11 | rm -f /tmp/${PNAME}/mkdist 12 | 13 | cd /tmp/${PNAME} 14 | 15 | if [ -e configure ]; then 16 | echo "*skipping* autoconf (configure already present)" 17 | else 18 | echo "Running autoconf ..." 19 | rm -rf autom4te* acloc* 20 | autoreconf 21 | #autoheader 22 | #autoconf 23 | fi 24 | rm -rf autom4te* acloc* 25 | 26 | echo "Compiling getsp ..." 27 | if [ ! -e tools/getsp.class ]; then 28 | cd tools 29 | javac -target 1.2 -source 1.2 getsp.java 30 | cd .. 31 | fi 32 | 33 | echo "Removing CVS/SVN and backup stuff ..." 34 | rm -rf `find . -name CVS -or -name .svn -or -name \*~` 35 | 36 | echo "Updating version ..." 37 | VER=`sed -n -e 's/.*JRI v\([0-9.-]\{1,\}\).*/\1/p' src/jri.h` 38 | echo "$PNAME version ${VER}" 39 | # cat DESCRIPTION| sed "s/Version:.*/Version: ${VER}/" > d 40 | # mv d DESCRIPTION 41 | echo "Creating package ..." 42 | cd .. 43 | tar fcz ${PNAME}_${VER}.tar.gz ${PNAME} 44 | cd ${SWD} 45 | cp /tmp/${PNAME}_${VER}.tar.gz .. 46 | rm -rf /tmp/${PNAME} 47 | echo "Done." 48 | ls -l ../${PNAME}_${VER}.tar.gz 49 | -------------------------------------------------------------------------------- /jri/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * low level Java/R Interface 3 | */ 4 | package org.rosuda.JRI ; 5 | 6 | -------------------------------------------------------------------------------- /jri/run.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | R_HOME=@R_HOME@ 4 | 5 | R_SHARE_DIR=@R_SHARE_DIR@ 6 | export R_SHARE_DIR 7 | R_INCLUDE_DIR=@R_INCLUDE_DIR@ 8 | export R_INCLUDE_DIR 9 | R_DOC_DIR=@R_DOC_DIR@ 10 | export R_DOC_DIR 11 | 12 | JRI_LD_PATH=${R_HOME}/lib:${R_HOME}/bin:@JAVA_LD_PATH@ 13 | if test -z "$LD_LIBRARY_PATH"; then 14 | LD_LIBRARY_PATH=$JRI_LD_PATH 15 | else 16 | LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$JRI_LD_PATH 17 | fi 18 | JAVA=@JAVA_PROG@ 19 | 20 | : ${CLASSPATH=.:examples} 21 | 22 | export R_HOME 23 | export LD_LIBRARY_PATH 24 | 25 | if [ -z "$1" ]; then 26 | echo "" 27 | echo " Usage: run [...]" 28 | echo "" 29 | echo " For example: ./run rtest" 30 | echo " Set CLASSPATH variable if other than .:examples is desired" 31 | echo "" 32 | else 33 | ${JAVA} -Djava.library.path=.:@JAVA_LD_PATH@ -cp ${CLASSPATH}:src/JRI.jar:JRI.jar $* 34 | fi 35 | -------------------------------------------------------------------------------- /jri/src/Makefile.all: -------------------------------------------------------------------------------- 1 | # JRI - Java/R Interface experimental! 2 | #-------------------------------------------------------------------------- 3 | # JRI_CPPFLAGS and JRI_LIBS are additional overrides that can be supplied 4 | # by the user 5 | 6 | JRI_JSRC=$(wildcard ../*.java) 7 | TARGETS=$(JNIPREFIX)jri$(JNISO) JRI.jar 8 | 9 | all: $(TARGETS) 10 | 11 | JRI.jar: $(JRI_JSRC) $(JNIPREFIX)jri$(JNISO) 12 | $(JAVAC) $(JFLAGS) $(JRI_JFLAGS) -d . $(JRI_JSRC) 13 | $(JAR) fc $@ org $(JNIPREFIX)jri$(JNISO) 14 | 15 | org_rosuda_JRI_Rengine.h: org/rosuda/JRI/Rengine.class 16 | if [ -n "$(JAVAH)" ]; then $(JAVAH) -d . -classpath . org.rosuda.JRI.Rengine; fi 17 | 18 | Rcallbacks.o: Rcallbacks.c Rcallbacks.h globals.h rjstring.h org_rosuda_JRI_Rengine.h 19 | $(CC) -c -o $@ $< $(CFLAGS) $(CPICF) $(JAVAINC) $(RINC) $(JRI_CPPFLAGS) 20 | 21 | rjstring.o: rjstring.c rjstring.h 22 | $(CC) -c -o $@ $< $(CFLAGS) $(CPICF) $(JAVAINC) $(RINC) $(JRI_CPPFLAGS) 23 | 24 | Rinit.o: Rinit.c Rinit.h Rcallbacks.h 25 | $(CC) -c -o $@ $< $(CFLAGS) $(CPICF) $(RINC) $(JRI_CPPFLAGS) 26 | 27 | globals.o: globals.c globals.h 28 | $(CC) -c -o $@ $< $(CFLAGS) $(CPICF) $(JAVAINC) $(JRI_CPPFLAGS) 29 | 30 | rjava.o: rjava.c rjava.h 31 | $(CC) -c -o $@ $< $(CFLAGS) $(CPICF) $(JAVAINC) $(JRI_CPPFLAGS) 32 | 33 | Rengine.o: Rengine.c org_rosuda_JRI_Rengine.h globals.h Rcallbacks.h Rinit.h 34 | $(CC) -c -o $@ Rengine.c $(CFLAGS) $(CPICF) $(JAVAINC) $(RINC) $(JRI_CPPFLAGS) 35 | 36 | jri.o: jri.c 37 | $(CC) -c -o $@ jri.c $(CFLAGS) $(CPICF) $(JAVAINC) $(RINC) $(JRI_CPPFLAGS) 38 | 39 | $(JNIPREFIX)jri$(JNISO): Rengine.o jri.o Rcallbacks.o Rinit.o globals.o rjava.o rjstring.o $(JRIDEPS) 40 | $(CC) -o $@ $^ $(LDFLAGS) $(JNILD) $(RLD) $(JRI_LIBS) 41 | 42 | win32/libjvm.dll.a: 43 | make -C win32 libjvm.dll.a 44 | 45 | org/rosuda/JRI/Rengine.class org/rosuda/JRI/REXP.class org/rosuda/JRI/Mutex.class: $(JRI_JSRC) 46 | $(JAVAC) $(JFLAGS) $(JRI_JFLAGS) -d . $^ 47 | 48 | clean: 49 | rm -rf $(TARGETS) org *.o *~ org_rosuda_JRI_Rengine.h *$(JNISO) *.class *~ 50 | 51 | .PHONY: clean all 52 | 53 | .NOTPARALLEL: 54 | -------------------------------------------------------------------------------- /jri/src/Makefile.in: -------------------------------------------------------------------------------- 1 | # JRI - Java/R Interface experimental! 2 | #-------------------------------------------------------------------------- 3 | 4 | #--- comment out the following for non-debug version 5 | CFLAGS+=-g 6 | 7 | CC=@CC@ 8 | CFLAGS+=-Iinclude @DEFFLAGS@ -DHAVE_CONFIG_H @CFLAGS@ @JAVA_CFLAGS@ 9 | LDFLAGS+=@LDFLAGS@ 10 | 11 | CC=@CC@ 12 | RHOME=@R_HOME@ 13 | JAVAC=@JAVAC@ 14 | JAVAH=@JAVAH@ 15 | JAVAINC=@JAVA_INC@ 16 | JAR=@JAR@ 17 | JFLAGS=@JFLAGS@ 18 | 19 | RINC=@RINC@ -I@R_INCLUDE_DIR@ 20 | RLD=@RLD@ 21 | JNILD=@JNILD@ 22 | JNISO=@JNISO@ 23 | JNIPREFIX=@JNIPREFIX@ 24 | CPICF=@CPICF@ 25 | 26 | include Makefile.all 27 | -------------------------------------------------------------------------------- /jri/src/Makefile.win: -------------------------------------------------------------------------------- 1 | # Windows-specific part of the Makefile 2 | 3 | include $(R_HOME)/etc$(R_ARCH)/Makeconf 4 | include Makefile.wconf 5 | include ../Makevars.win 6 | include Makefile.all 7 | -------------------------------------------------------------------------------- /jri/src/Rcallbacks.h: -------------------------------------------------------------------------------- 1 | #ifndef __R_CALLBACKS__H__ 2 | #define __R_CALLBACKS__H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | /* functions provided as R callbacks */ 9 | 10 | #if R_VERSION < R_Version(2,7,0) 11 | #define RCCONST 12 | #else 13 | #define RCCONST const 14 | #endif 15 | /* ReadConsole API has been changed (unannounced and undocumented!) for Windows in r81626 */ 16 | #if defined (WIN32) && (R_VERSION < R_Version(4,2,0)) 17 | #define RCSIGN 18 | #else 19 | #define RCSIGN unsigned 20 | #endif 21 | 22 | int Re_ReadConsole(RCCONST char *prompt, RCSIGN char *buf, int len, int addtohistory); 23 | void Re_Busy(int which); 24 | void Re_WriteConsole(RCCONST char *buf, int len); 25 | void Re_WriteConsoleEx(RCCONST char *buf, int len, int oType); 26 | void Re_ResetConsole(void); 27 | void Re_FlushConsole(void); 28 | void Re_ClearerrConsole(void); 29 | int Re_ChooseFile(int new, char *buf, int len); 30 | void Re_ShowMessage(RCCONST char *buf); 31 | void Re_read_history(char *buf); 32 | void Re_loadhistory(SEXP call, SEXP op, SEXP args, SEXP env); 33 | void Re_savehistory(SEXP call, SEXP op, SEXP args, SEXP env); 34 | int Re_ShowFiles(int nfile, RCCONST char **file, RCCONST char **headers, RCCONST char *wtitle, Rboolean del, RCCONST char *pager); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /jri/src/Rdecl.h: -------------------------------------------------------------------------------- 1 | #ifndef __RDECL_H__ 2 | #define __RDECL_H__ 3 | 4 | /* declarations from R internals or other include files */ 5 | /* last update: R 2.4.0 */ 6 | 7 | void run_Rmainloop(void); /* main/main.c */ 8 | int R_ReadConsole(char*, unsigned char*, int, int); /* include/Defn.h */ 9 | void Rf_checkArity(SEXP, SEXP); /* include/Defn.h */ 10 | int Rf_initialize_R(int ac, char **av); /* include/Rembedded.h */ 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /jri/src/Rinit.h: -------------------------------------------------------------------------------- 1 | #ifndef __R_INIT__H__ 2 | #define __R_INIT__H__ 3 | 4 | int initR(int argc, char **argv); 5 | void initRinside(void); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /jri/src/config.h.in: -------------------------------------------------------------------------------- 1 | /* src/config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Define to 1 if you have the header file. */ 4 | #undef HAVE_INTTYPES_H 5 | 6 | /* Define to 1 if you have the header file. */ 7 | #undef HAVE_STDINT_H 8 | 9 | /* Define to 1 if you have the header file. */ 10 | #undef HAVE_STDIO_H 11 | 12 | /* Define to 1 if you have the header file. */ 13 | #undef HAVE_STDLIB_H 14 | 15 | /* Define to 1 if you have the header file. */ 16 | #undef HAVE_STRINGS_H 17 | 18 | /* Define to 1 if you have the header file. */ 19 | #undef HAVE_STRING_H 20 | 21 | /* Define to 1 if you have the header file. */ 22 | #undef HAVE_SYS_SELECT_H 23 | 24 | /* Define to 1 if you have the header file. */ 25 | #undef HAVE_SYS_STAT_H 26 | 27 | /* Define to 1 if you have the header file. */ 28 | #undef HAVE_SYS_TIME_H 29 | 30 | /* Define to 1 if you have the header file. */ 31 | #undef HAVE_SYS_TYPES_H 32 | 33 | /* Define to 1 if you have the header file. */ 34 | #undef HAVE_UNISTD_H 35 | 36 | /* Define to the address where bug reports for this package should be sent. */ 37 | #undef PACKAGE_BUGREPORT 38 | 39 | /* Define to the full name of this package. */ 40 | #undef PACKAGE_NAME 41 | 42 | /* Define to the full name and version of this package. */ 43 | #undef PACKAGE_STRING 44 | 45 | /* Define to the one symbol short name of this package. */ 46 | #undef PACKAGE_TARNAME 47 | 48 | /* Define to the home page for this package. */ 49 | #undef PACKAGE_URL 50 | 51 | /* Define to the version of this package. */ 52 | #undef PACKAGE_VERSION 53 | 54 | /* Define to 1 if all of the C90 standard headers exist (not just the ones 55 | required in a freestanding environment). This macro is provided for 56 | backward compatibility; new code need not use it. */ 57 | #undef STDC_HEADERS 58 | -------------------------------------------------------------------------------- /jri/src/globals.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | jobject engineObj; 4 | jclass engineClass; 5 | JNIEnv *eenv; 6 | -------------------------------------------------------------------------------- /jri/src/globals.h: -------------------------------------------------------------------------------- 1 | #ifndef __GLOBALS__H__ 2 | #define __GLOBALS__H__ 3 | 4 | #include 5 | 6 | extern jobject engineObj; 7 | extern jclass engineClass; 8 | extern JNIEnv *eenv; 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /jri/src/h2ic: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | $fn=shift; 4 | 5 | print "#include \"$fn\"\n#include \n\n"; 6 | 7 | open IN, $fn; 8 | $fn=~s/\..*?$//; 9 | $fn=$1 if ($fn=~/\/([^\/]+)$/); 10 | $pre=$fn; 11 | while () { 12 | if (/^JNIEXPORT ([a-z]+) JNICALL ([a-zA-Z0-9_]+)/) { 13 | $ret=$1; $fn=$2; 14 | $a=; 15 | if ($a=~/\((JNIEnv.*)\)/) { 16 | $par=$1; 17 | @p=split /,/,$par; $i=0; undef @pc; 18 | foreach (@p) { $_.=" par$i"; push @pc, "par$i"; $i++; } 19 | $parn=join ',',@p; 20 | $parc=join ', ',@pc; 21 | $rc = ($ret eq 'void')?'':'return '; 22 | print "typedef $ret(*c_${fn}_t)($par);\nc_${fn}_t Call_$fn;\n"; 23 | print "JNIEXPORT $ret JNICALL $fn\n ($parn) {\n $rc Call_$fn($parc);\n }\n\n"; 24 | push @fnl, $fn; 25 | } 26 | } 27 | } 28 | 29 | print "void Setup_$pre(void **ptrs) {\n"; 30 | $i=0; 31 | foreach (@fnl) { print "Call_$_ = (c_${_}_t) ptrs[$i];\n"; $i++; } 32 | print "}\n\n"; 33 | 34 | $i=0; 35 | print "void **GetRef_$pre() { 36 | void **ptrs = (void**) malloc(sizeof(void*) * ( $#fnl + 2 ) ); 37 | "; 38 | foreach (@fnl) { print "ptrs[$i] = (void*) Call_$_;\n"; $i++; } 39 | print "ptrs[$i] = (void*) 0;\nreturn ptrs;\n}\n"; 40 | 41 | -------------------------------------------------------------------------------- /jri/src/jri.h: -------------------------------------------------------------------------------- 1 | #ifndef __JRI_H__ 2 | #define __JRI_H__ 3 | 4 | #include 5 | #ifdef HAVE_CONFIG_H 6 | #include "config.h" 7 | #endif 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | /* the viewpoint is from R, i.e. "get" means "Java->R" whereas "put" means "R->Java" */ 14 | 15 | #define JRI_VERSION 0x0507 /* JRI v0.5-7 */ 16 | #define JRI_API 0x010a /* API-version 1.10 */ 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | /* jlong can always hold a pointer 23 | to avoid warnings we go ptr->size_t->jlong */ 24 | #define SEXP2L(s) ((jlong)((size_t)(s))) 25 | #define L2SEXP(s) ((SEXP)((jlong)((size_t)(s)))) 26 | 27 | jstring jri_callToString(JNIEnv *env, jobject o); 28 | 29 | SEXP jri_getDoubleArray(JNIEnv *env, jarray o); 30 | SEXP jri_getIntArray(JNIEnv *env, jarray o); 31 | SEXP jri_getByteArray(JNIEnv *env, jarray o); 32 | SEXP jri_getBoolArrayI(JNIEnv *env, jarray o); 33 | SEXP jri_getBoolArray(JNIEnv *env, jarray o); 34 | SEXP jri_getObjectArray(JNIEnv *env, jarray o); 35 | SEXP jri_getString(JNIEnv *env, jstring s); 36 | SEXP jri_getStringArray(JNIEnv *env, jarray o); 37 | SEXP jri_getSEXPLArray(JNIEnv *env, jarray o); 38 | 39 | SEXP jri_installString(JNIEnv *env, jstring s); /* as Rf_install, just for Java strings */ 40 | 41 | jarray jri_putDoubleArray(JNIEnv *env, SEXP e); 42 | jarray jri_putIntArray(JNIEnv *env, SEXP e); 43 | jarray jri_putBoolArrayI(JNIEnv *env, SEXP e); 44 | jarray jri_putByteArray(JNIEnv *env, SEXP e); 45 | jstring jri_putString(JNIEnv *env, SEXP e, int ix); /* ix=index, 0=1st */ 46 | jarray jri_putStringArray(JNIEnv *env, SEXP e); 47 | jarray jri_putSEXPLArray(JNIEnv *env, SEXP e); /* SEXPs are strored as "long"s */ 48 | 49 | jstring jri_putSymbolName(JNIEnv *env, SEXP e); 50 | 51 | void jri_checkExceptions(JNIEnv *env, int describe); 52 | 53 | void jri_error(char *fmt, ...); 54 | 55 | /* define mkCharUTF8 in a compatible fashion */ 56 | #if R_VERSION < R_Version(2,7,0) 57 | #define mkCharUTF8(X) mkChar(X) 58 | #define CHAR_UTF8(X) CHAR(X) 59 | #else 60 | #define mkCharUTF8(X) mkCharCE(X, CE_UTF8) 61 | #define CHAR_UTF8(X) jri_char_utf8(X) 62 | const char *jri_char_utf8(SEXP); 63 | #endif 64 | 65 | #ifdef __cplusplus 66 | } 67 | #endif 68 | 69 | #endif 70 | 71 | /* 72 | API version changes: 73 | ----------------------- 74 | 1.3 (initial public API version) 75 | [ 1.4 never publicly released - added put/getenv but was abandoned ] 76 | 1.5 JRI 0.3-0 77 | + rniGetTAG 78 | + rniInherits 79 | + rniGetSymbolName 80 | + rniInstallSymbol 81 | + rniJavaToXref, rniXrefToJava 82 | 1.6 JRI 0.3-2 83 | + rniPutBoolArray, rniPutBoolArrayI, rniGetBoolArrayI 84 | 1.7 JRI 0.3-7 85 | + rniCons(+2 args) 86 | 1.8 JRI 0.4-0 87 | + rniPrint 88 | 1.9 JRI 0.4-3 89 | + rniPreserve, rniRelease 90 | + rniParentEnv, rniFindVar, rniListEnv 91 | + rniSpecialObject(0-7) 92 | + rniPrintValue 93 | 1.10 JRI 0.5-1 94 | * rniAssign returns jboolean instead of void 95 | */ 96 | -------------------------------------------------------------------------------- /jri/src/rjava.c: -------------------------------------------------------------------------------- 1 | #include "rjava.h" 2 | #include 3 | 4 | #ifdef _WIN64 5 | typedef long long ptrlong; 6 | #else 7 | typedef long ptrlong; 8 | #endif 9 | 10 | int ipcout; 11 | int resin; 12 | int *rjctrl = 0; 13 | 14 | typedef void(callbackfn)(void *); 15 | 16 | int RJava_request_lock(void) { 17 | ptrlong buf[4]; 18 | int n; 19 | if (rjctrl && *rjctrl) return 2; 20 | 21 | buf[0] = IPCC_LOCK_REQUEST; 22 | if (write(ipcout, buf, sizeof(ptrlong)) < sizeof(ptrlong)) return 0; 23 | n = read(resin, buf, sizeof(ptrlong)); 24 | return (n == sizeof(ptrlong) && buf[0] == IPCC_LOCK_GRANTED) ? 1 : 0; 25 | } 26 | 27 | int RJava_clear_lock(void) { 28 | ptrlong buf[4]; 29 | buf[0] = IPCC_CLEAR_LOCK; 30 | return (write(ipcout, buf, sizeof(ptrlong)) == sizeof(ptrlong)) ? 1 : 0; 31 | } 32 | 33 | int RJava_request_callback(callbackfn *fn, void *data) { 34 | ptrlong buf[4]; 35 | buf[0] = IPCC_CALL_REQUEST; 36 | buf[1] = (ptrlong) fn; 37 | buf[2] = (ptrlong) data; 38 | return (write(ipcout, buf, sizeof(ptrlong) * 3) == sizeof(ptrlong) * 3) ? 1 : 0; 39 | } 40 | 41 | void RJava_setup(int _in, int _out) { 42 | /* ptrlong buf[4]; */ 43 | ipcout = _out; 44 | resin = _in; 45 | } 46 | 47 | void RJava_init_ctrl(void) { 48 | ptrlong buf[4]; 49 | buf[0] = IPCC_CONTROL_ADDR; 50 | if (write(ipcout, buf, sizeof(ptrlong)) == sizeof(ptrlong) && 51 | read(resin, buf, sizeof(ptrlong) * 2) == sizeof(ptrlong) * 2 && 52 | buf[0] == IPCC_CONTROL_ADDR) { 53 | rjctrl= (int*) buf[1]; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /jri/src/rjava.h: -------------------------------------------------------------------------------- 1 | #ifndef __CALLBACK_H__ 2 | #define __CALLBACK_H__ 3 | 4 | #define RJavaActivity 16 5 | 6 | /* all IPC messages are long-alligned */ 7 | #define IPCC_LOCK_REQUEST 1 8 | #define IPCC_LOCK_GRANTED 2 /* reponse on IPCC_LOCK_REQUEST */ 9 | #define IPCC_CLEAR_LOCK 3 10 | #define IPCC_CALL_REQUEST 4 /* pars: */ 11 | #define IPCC_CONTROL_ADDR 5 /* ipc: request, res: */ 12 | 13 | int RJava_request_lock(void); 14 | int RJava_clear_lock(void); 15 | /* int RJava_request_callback(callbackfn *fn, void *data); */ 16 | void RJava_setup(int _in, int _out); 17 | void RJava_init_ctrl(void); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /jri/src/rjstring.h: -------------------------------------------------------------------------------- 1 | #ifndef RJ_STRING_H__ 2 | #define RJ_STRING_H__ 3 | 4 | #include /* for jchar */ 5 | #include /* for SEXP */ 6 | 7 | /* --- API --- */ 8 | 9 | /* Returns static content for short strings so don't re-use. 10 | For dynamic strings uses R_alloc */ 11 | int rj_char_utf16(const char *c, int len, jchar **buf, const char *ifrom, int can_error); 12 | 13 | /* wrappers for above to use with CHARSXP to detect proper ifrom */ 14 | int rj_rchar_utf16(SEXP s, jchar **buf); 15 | int rj_rchar_utf16_noerr(SEXP s, jchar **buf); 16 | 17 | /* return jstring, but do NOT check exceptions */ 18 | jstring rj_newJavaString(JNIEnv *env, SEXP sChar); 19 | jstring rj_newNativeJavaString(JNIEnv *env, const char *str, int len); 20 | 21 | /* takes modified UTF-8 from Java, creates CHARSXP with valid UTF8 */ 22 | SEXP rj_mkCharUTF8(const char *src); 23 | SEXP rj_mkCharUTF8_noerr(const char *src); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /jri/src/win32/Makefile: -------------------------------------------------------------------------------- 1 | # helper tools and libs for building and running rJava for Windows 2 | # Author: Simon Urbanek 3 | 4 | include $(R_HOME)/etc$(R_ARCH)/Makeconf 5 | 6 | TARGETS=libjvm.dll.a findjava.exe 7 | 8 | # libjvm.dll.a - wrapper lib for jvm.dll from Java 9 | # findjava.exe - helper tool to find the current JDK from the registry 10 | 11 | all: $(TARGETS) 12 | 13 | ifeq ($(strip $(shell $(R_HOME)/bin/R --slave -e 'cat(.Machine$$sizeof.pointer)')),8) 14 | JVMDEF=jvm64.def 15 | else 16 | JVMDEF=jvm.def 17 | endif 18 | 19 | libjvm.dll.a: $(JVMDEF) 20 | $(DLLTOOL) --input-def $^ --kill-at --dllname jvm.dll --output-lib $@ 21 | 22 | # compile findjava.exe from source - no magic here, no special libs necessary 23 | findjava.o: findjava.c 24 | $(CC) -O2 -c -o $@ $^ 25 | 26 | findjava.exe: findjava.o 27 | $(CC) -s -o $@ $^ 28 | 29 | # just cleanup everything 30 | clean: 31 | rm -f *.o *~ $(TARGETS) 32 | 33 | .PHONY: all clean 34 | -------------------------------------------------------------------------------- /jri/src/win32/findjava.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static char RegStrBuf[32768], dbuf[32768]; 6 | 7 | int main(int argc, char **argv) { 8 | int i=0, doit=0; 9 | DWORD t,s=32767; 10 | HKEY k; 11 | HKEY root=HKEY_LOCAL_MACHINE; 12 | char *javakey="Software\\JavaSoft\\Java Runtime Environment"; 13 | 14 | if (argc>1 && argv[1][0]=='-' && argv[1][1]=='R') { 15 | if (getenv("R_HOME")) { 16 | strcpy(RegStrBuf,getenv("R_HOME")); 17 | } else { 18 | javakey="Software\\R-core\\R"; s=32767; 19 | if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,javakey,0,KEY_QUERY_VALUE,&k)!=ERROR_SUCCESS || 20 | RegQueryValueEx(k,"InstallPath",0,&t,RegStrBuf,&s)!=ERROR_SUCCESS) { 21 | if (RegOpenKeyEx(HKEY_CURRENT_USER,javakey,0,KEY_QUERY_VALUE,&k)!=ERROR_SUCCESS || 22 | RegQueryValueEx(k,"InstallPath",0,&t,RegStrBuf,&s)!=ERROR_SUCCESS) { 23 | fprintf(stderr, "ERROR*> R - can't open registry keys.\n"); 24 | return -1; 25 | } 26 | } 27 | } 28 | } else 29 | /* JAVA_HOME can override our detection - but we still post-process it */ 30 | if (getenv("JAVA_HOME")) { 31 | strcpy(RegStrBuf,getenv("JAVA_HOME")); 32 | } else { 33 | 34 | #ifdef FINDJRE 35 | if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,javakey,0,KEY_QUERY_VALUE,&k)!=ERROR_SUCCESS || 36 | RegQueryValueEx(k,"CurrentVersion",0,&t,RegStrBuf,&s)!=ERROR_SUCCESS) { 37 | javakey="Software\\JavaSoft\\JRE"; s=32767; 38 | if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,javakey,0,KEY_QUERY_VALUE,&k)!=ERROR_SUCCESS || 39 | RegQueryValueEx(k,"CurrentVersion",0,&t,RegStrBuf,&s)!=ERROR_SUCCESS) { 40 | #endif 41 | javakey="Software\\JavaSoft\\Java Development Kit"; s=32767; 42 | if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,javakey,0,KEY_QUERY_VALUE,&k)!=ERROR_SUCCESS || 43 | RegQueryValueEx(k,"CurrentVersion",0,&t,RegStrBuf,&s)!=ERROR_SUCCESS) { 44 | javakey="Software\\JavaSoft\\JDK"; s=32767; 45 | if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,javakey,0,KEY_QUERY_VALUE,&k)!=ERROR_SUCCESS || 46 | RegQueryValueEx(k,"CurrentVersion",0,&t,RegStrBuf,&s)!=ERROR_SUCCESS) { 47 | fprintf(stderr, "ERROR*> JavaSoft\\{JRE|JDK} can't open registry keys.\n"); 48 | /* MessageBox(wh, "Can't find Sun's Java runtime.\nPlease install Sun's J2SE JRE or JDK 1.4.2 or later (see http://java.sun.com/).","Can't find Sun's Java",MB_OK|MB_ICONERROR); */ 49 | return -1; 50 | } 51 | } 52 | #ifdef FINDJRE 53 | } 54 | } 55 | #endif 56 | RegCloseKey(k); s=32767; 57 | 58 | strcpy(dbuf,javakey); 59 | strcat(dbuf,"\\"); 60 | strcat(dbuf,RegStrBuf); 61 | javakey=(char*) malloc(strlen(dbuf)+1); 62 | strcpy(javakey, dbuf); 63 | 64 | if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,javakey,0,KEY_QUERY_VALUE,&k)!=ERROR_SUCCESS || 65 | RegQueryValueEx(k,"JavaHome",0,&t,RegStrBuf,&s)!=ERROR_SUCCESS) { 66 | fprintf(stderr, "There's no JavaHome value in the JDK/JRE registry key.\n"); 67 | /* MessageBox(wh, "Can't find Java home path. Maybe your JRE is too old.\nPlease install Sun's J2SE JRE or SDK 1.4.2 (see http://java.sun.com/).","Can't find Sun's Java",MB_OK|MB_ICONERROR); */ 68 | return -1; 69 | } 70 | RegCloseKey(k); 71 | } 72 | 73 | /*--- post-processing according to supplied flags --*/ 74 | 75 | /* -a = automagic, i.e. use short name only if the name contains spaces */ 76 | i=1; 77 | while (i0) { 4 | if (args[0].compareTo("-test")==0) { 5 | System.out.println("Test1234OK"); 6 | } else 7 | if (args[0].compareTo("-libs")==0) { 8 | String prefix="-L"; 9 | if (args.length>1) prefix=args[1]; 10 | String lp=System.getProperty("java.library.path"); 11 | // we're not using StringTokenizer in case the JVM is very crude 12 | int i=0,j,k=0; 13 | String r=null; 14 | String pss=System.getProperty("path.separator"); 15 | char ps=':'; 16 | if (pss!=null && pss.length()>0) ps=pss.charAt(0); 17 | j=lp.length(); 18 | while (i<=j) { 19 | if (i==j || lp.charAt(i)==ps) { 20 | String lib=lp.substring(k,i); 21 | k=i+1; 22 | if (lib.compareTo(".")!=0) 23 | r=(r==null)?(prefix+lib):(r+" "+prefix+lib); 24 | } 25 | i++; 26 | } 27 | if (r!=null) System.out.println(r); 28 | } else 29 | if (args[0].equals("-minver")) { 30 | boolean meets = false; 31 | String jv = System.getProperty("java.version"); 32 | if (jv.startsWith("1.")) 33 | jv = jv.substring(2); 34 | try { 35 | int i = 0; 36 | while (i < jv.length() && jv.charAt(i) >= '0' && jv.charAt(i) < '9') 37 | i++; 38 | jv = jv.substring(0, i); 39 | if (args.length > 1) { 40 | int req = Integer.parseInt(args[1]); 41 | int cv = Integer.parseInt(jv); 42 | meets = cv >= req; 43 | } 44 | } catch (Exception e) { 45 | } 46 | System.out.println(meets ? "yes" : "no"); 47 | } else 48 | System.out.println(System.getProperty(args[0])); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /jri/tools/mkinstalldirs: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # mkinstalldirs --- make directory hierarchy 3 | 4 | scriptversion=2020-07-26.22; # UTC 5 | 6 | # Original author: Noah Friedman 7 | # Created: 1993-05-16 8 | # Public domain. 9 | # 10 | # This file is maintained in Automake, please report 11 | # bugs to or send patches to 12 | # . 13 | 14 | nl=' 15 | ' 16 | IFS=" "" $nl" 17 | errstatus=0 18 | dirmode= 19 | 20 | usage="\ 21 | Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... 22 | 23 | Create each directory DIR (with mode MODE, if specified), including all 24 | leading file name components. 25 | 26 | Report bugs to ." 27 | 28 | # process command line arguments 29 | while test $# -gt 0 ; do 30 | case $1 in 31 | -h | --help | --h*) # -h for help 32 | echo "$usage" 33 | exit $? 34 | ;; 35 | -m) # -m PERM arg 36 | shift 37 | test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } 38 | dirmode=$1 39 | shift 40 | ;; 41 | --version) 42 | echo "$0 $scriptversion" 43 | exit $? 44 | ;; 45 | --) # stop option processing 46 | shift 47 | break 48 | ;; 49 | -*) # unknown option 50 | echo "$usage" 1>&2 51 | exit 1 52 | ;; 53 | *) # first non-opt arg 54 | break 55 | ;; 56 | esac 57 | done 58 | 59 | for file 60 | do 61 | if test -d "$file"; then 62 | shift 63 | else 64 | break 65 | fi 66 | done 67 | 68 | case $# in 69 | 0) exit 0 ;; 70 | esac 71 | 72 | # Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and 73 | # mkdir -p a/c at the same time, both will detect that a is missing, 74 | # one will create a, then the other will try to create a and die with 75 | # a "File exists" error. This is a problem when calling mkinstalldirs 76 | # from a parallel make. We use --version in the probe to restrict 77 | # ourselves to GNU mkdir, which is thread-safe. 78 | case $dirmode in 79 | '') 80 | if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then 81 | echo "mkdir -p -- $*" 82 | exec mkdir -p -- "$@" 83 | else 84 | # On NextStep and OpenStep, the 'mkdir' command does not 85 | # recognize any option. It will interpret all options as 86 | # directories to create, and then abort because '.' already 87 | # exists. 88 | test -d ./-p && rmdir ./-p 89 | test -d ./--version && rmdir ./--version 90 | fi 91 | ;; 92 | *) 93 | if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && 94 | test ! -d ./--version; then 95 | echo "umask 22" 96 | umask 22 97 | echo "mkdir -m $dirmode -p -- $*" 98 | exec mkdir -m "$dirmode" -p -- "$@" 99 | else 100 | # Clean up after NextStep and OpenStep mkdir. 101 | for d in ./-m ./-p ./--version "./$dirmode"; 102 | do 103 | test -d $d && rmdir $d 104 | done 105 | fi 106 | ;; 107 | esac 108 | 109 | echo "umask 22" 110 | umask 22 111 | 112 | for file 113 | do 114 | case $file in 115 | /*) pathcomp=/ ;; 116 | *) pathcomp= ;; 117 | esac 118 | oIFS=$IFS 119 | IFS=/ 120 | set fnord $file 121 | shift 122 | IFS=$oIFS 123 | 124 | for d 125 | do 126 | test "x$d" = x && continue 127 | 128 | pathcomp=$pathcomp$d 129 | case $pathcomp in 130 | -*) pathcomp=./$pathcomp ;; 131 | esac 132 | 133 | if test ! -d "$pathcomp"; then 134 | echo "mkdir $pathcomp" 135 | 136 | mkdir "$pathcomp" || lasterr=$? 137 | 138 | if test ! -d "$pathcomp"; then 139 | errstatus=$lasterr 140 | fi 141 | fi 142 | 143 | pathcomp=$pathcomp/ 144 | done 145 | 146 | if test ! -z "$dirmode"; then 147 | echo "chmod $dirmode $file" 148 | chmod "$dirmode" "$file" || errstatus=$? 149 | fi 150 | done 151 | 152 | exit $errstatus 153 | 154 | # Local Variables: 155 | # mode: shell-script 156 | # sh-indentation: 2 157 | # eval: (add-hook 'before-save-hook 'time-stamp) 158 | # time-stamp-start: "scriptversion=" 159 | # time-stamp-format: "%:y-%02m-%02d.%02H" 160 | # time-stamp-time-zone: "UTC0" 161 | # time-stamp-end: "; # UTC" 162 | # End: 163 | -------------------------------------------------------------------------------- /jri/version: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | VER=`awk -v ORS= '/JRI v/ { print substr($6,2) }' src/jri.h` 4 | if test "$1" == "-f"; then 5 | echo "JRI_${VER}.tar.gz" 6 | else 7 | echo "${VER}" 8 | fi 9 | -------------------------------------------------------------------------------- /man/Exceptions.Rd: -------------------------------------------------------------------------------- 1 | \name{Exceptions} 2 | \alias{Exceptions} 3 | \alias{$.Throwable} 4 | \alias{$<-.Throwable} 5 | \title{Exception handling} 6 | \description{R handling of java exception} 7 | \usage{ 8 | \S3method{$}{Throwable}(x, name ) 9 | \S3method{$}{Throwable}(x, name ) <- value 10 | } 11 | \arguments{ 12 | \item{x}{condition} 13 | \item{name}{...} 14 | \item{value}{...} 15 | } 16 | \details{ 17 | Java exceptions are mapped to R conditions that are relayed by the 18 | \code{\link{stop}} function. 19 | 20 | The R condition contains the actual exception object as the 21 | \code{jobj} item. 22 | 23 | The class name of the R condition is made of a vector 24 | of simple java class names, the class names without their package 25 | path. This allows the R code to use direct handlers similar to 26 | direct exception handlers in java. See the example below. 27 | } 28 | \examples{ 29 | \dontshow{.jinit()} 30 | 31 | Integer <- J("java.lang.Integer") 32 | tryCatch( Integer$parseInt( "10.." ), NumberFormatException = function(e){ 33 | e$jobj$printStackTrace() 34 | } ) 35 | 36 | # the dollar method is also implemented for Throwable conditions, 37 | # so that syntactic sugar can be used on condition objects 38 | # however, in the example below e is __not__ a jobjRef object reference 39 | tryCatch( Integer$parseInt( "10.." ), NumberFormatException = function(e){ 40 | e$printStackTrace() 41 | } ) 42 | 43 | 44 | \dontshow{ 45 | tryCatch( Integer$parseInt( "10.." ), NumberFormatException = function(e){ 46 | classes <- class( e ) 47 | stopifnot( "NumberFormatException" \%in\% classes ) 48 | stopifnot( "Exception" \%in\% classes ) 49 | stopifnot( "Object" \%in\% classes ) 50 | stopifnot( "error" \%in\% classes ) 51 | stopifnot( "condition" \%in\% classes ) 52 | } ) 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /man/J.Rd: -------------------------------------------------------------------------------- 1 | \name{J} 2 | \alias{J} 3 | \title{ 4 | High level API for accessing Java 5 | } 6 | \description{ 7 | \code{J} creates a Java class reference or calls a Java method 8 | } 9 | \usage{ 10 | J(class, method, ..., class.loader=.rJava.class.loader) 11 | } 12 | \arguments{ 13 | \item{class}{ 14 | java object reference or fully qualified class name in JNI 15 | notation (e.g "java/lang/String" ) or standard java notation (e.g 16 | "java.lang.String") 17 | } 18 | \item{method}{ 19 | if present then \code{J} results in a method call, otherwise it 20 | just creates a class name reference. 21 | } 22 | \item{\dots}{ 23 | optional parameters that will be passed to the method (if the 24 | \code{method} argument is present) 25 | } 26 | \item{class.loader}{optional, custom loader to use if a class look-up 27 | is necessary (i.e., if \code{class} is a string)} 28 | } 29 | \details{ 30 | \code{J} is the high-level access to Java. 31 | 32 | If the \code{method} argument is missing then \code{code} must be a 33 | class name and \code{J} creates a class name reference that can be 34 | used either in a call to \code{new} to create a new Java object 35 | (e.g. \code{new(J("java.lang.String"), "foo")}) or with \code{$} 36 | operator to call a static method 37 | (e.g. \code{J("java.lang.Double")$parseDouble("10.2")}.) 38 | 39 | If the \code{method} argument is present then it must be a string 40 | vector of length one which defines the method to be called on the 41 | object. 42 | } 43 | \value{ 44 | If \code{method} is missing the the returned value is an object of 45 | the class \code{jclassName}. Otherwise the value is the result of 46 | the method invocation. In the latter case Java exceptions may be 47 | thrown and the function doesn't return. 48 | } 49 | \note{ 50 | \code{J} is a high-level API which is slower than \code{\link{.jnew}} 51 | or \code{\link{.jcall}} since it has to use reflection to find the 52 | most suitable method. 53 | } 54 | \seealso{ 55 | \code{\link{.jcall}}, \code{\link{.jnew}} 56 | } 57 | \examples{ 58 | \dontshow{.jinit()} 59 | 60 | if (!nzchar(Sys.getenv("NOAWT"))) { 61 | f <- new(J("java.awt.Frame"), "Hello") 62 | f$setVisible(TRUE) 63 | } 64 | 65 | J("java.lang.Double")$parseDouble("10.2") 66 | J("java.lang.Double", "parseDouble", "10.2" ) 67 | 68 | Double <- J("java.lang.Double") 69 | Double$parseDouble( "10.2") 70 | 71 | # String[] strings = new String[]{ "string", "array" } ; 72 | strings <- .jarray( c("string", "array") ) 73 | # this uses the JList( Object[] ) constructor 74 | # even though the "strings" parameter is a String[] 75 | l <- new( J("javax.swing.JList"), strings) 76 | 77 | } 78 | \keyword{interface} 79 | -------------------------------------------------------------------------------- /man/accessOp.Rd: -------------------------------------------------------------------------------- 1 | \name{JavaAccess} 2 | \alias{$,jobjRef-method} 3 | \alias{$,jclassName-method} 4 | \alias{$<-,jobjRef-method} 5 | \alias{$<-,jclassName-method} 6 | \alias{names,jobjRef-method} 7 | \alias{names,jclassName-method} 8 | \alias{names,jarrayRef-method} 9 | \alias{names,jrectRef-method} 10 | \alias{.DollarNames.jobjRef} 11 | \alias{.DollarNames.jclassName} 12 | \alias{.DollarNames.jarrayRef} 13 | \alias{.DollarNames.jrectRef} 14 | 15 | \title{ 16 | Field/method operator for Java objects 17 | } 18 | \description{ 19 | The \code{$} operator for \code{jobjRef} Java object references provides convenience access to object attributes and calling Java methods. 20 | } 21 | \usage{ 22 | \S3method{.DollarNames}{jobjRef} (x, pattern = "" ) 23 | \S3method{.DollarNames}{jarrayRef} (x, pattern = "" ) 24 | \S3method{.DollarNames}{jrectRef} (x, pattern = "" ) 25 | \S3method{.DollarNames}{jclassName}(x, pattern = "" ) 26 | } 27 | \arguments{ 28 | \item{x}{object to complete} 29 | \item{pattern}{pattern} 30 | } 31 | \section{Methods}{ 32 | \describe{ 33 | \item{\code{$}}{\code{signature(x = "jobjRef")}: ... } 34 | \item{\code{$}}{\code{signature(x = "jclassName")}: ... } 35 | \item{\code{$<-}}{\code{signature(x = "jobjRef")}: ... } 36 | \item{\code{$<-}}{\code{signature(x = "jclassName")}: ... } 37 | \item{\code{names}}{\code{signature(x = "jobjRef")}: ... } 38 | \item{\code{names}}{\code{signature(x = "jarrayRef")}: ... } 39 | \item{\code{names}}{\code{signature(x = "jrectRef")}: ... } 40 | \item{\code{names}}{\code{signature(x = "jclassName")}: ... } 41 | } 42 | } 43 | \details{ 44 | rJava provides two levels of API: low-level JNI-API in the form of \code{\link{.jcall}} function and high-level reflection API based on the \code{$} operator. The former is very fast, but inflexible. The latter is a convenient way to use Java-like programming at the cost of performance. The reflection API is build around the \code{$} operator on \code{\link{jobjRef-class}} objects that allows to access Java attributes and call object methods. 45 | 46 | \code{$} returns either the value of the attribute or calls a method, depending on which name matches first. 47 | 48 | \code{$<-} assigns a value to the corresponding Java attribute. 49 | 50 | \code{names} and \code{.DollarNames} returns all fields and methods associated with the object. 51 | Method names are followed by \code{(} or \code{()} depending on arity. 52 | This use of names is mainly useful for code completion, it is not intended to be used programmatically. 53 | 54 | This is just a convenience API. Internally all calls are mapped into \code{\link{.jcall}} calls, therefore the calling conventions and returning objects use the same rules. For time-critical Java calls \code{\link{.jcall}} should be used directly. 55 | } 56 | \seealso{ 57 | \code{\link{J}}, \code{\link{.jcall}}, \code{\link{.jnew}}, \code{\link{jobjRef-class}} 58 | } 59 | \examples{ 60 | \dontshow{.jinit()} 61 | 62 | v <- new(J("java.lang.String"), "Hello World!") 63 | v$length() 64 | v$indexOf("World") 65 | names(v) 66 | 67 | \dontshow{ 68 | stopifnot( v$length() == 12L ) 69 | stopifnot( v$indexOf("World") == 6L ) 70 | } 71 | 72 | J("java.lang.String")$valueOf(10) 73 | 74 | Double <- J("java.lang.Double") 75 | # the class pseudo field - instance of Class for the associated class 76 | # similar to java Double.class 77 | Double$class 78 | \dontshow{ 79 | stopifnot( Double$class$getName() == "java.lang.Double" ) 80 | } 81 | 82 | } 83 | \keyword{interface} 84 | -------------------------------------------------------------------------------- /man/aslist.Rd: -------------------------------------------------------------------------------- 1 | \name{aslist} 2 | \alias{as.list.jobjRef} 3 | \alias{as.list.jarrayRef} 4 | \alias{as.list.jrectRef} 5 | \title{ 6 | Converts java objects or arrays to R lists 7 | } 8 | \description{ 9 | \code{as.list} is implemented for java objects and java arrays 10 | to facilitate using \code{lapply} calls over elements of a java array 11 | or items of an Iterator associated with an Iterable object 12 | 13 | For java array references, \code{as.list} is mapped to 14 | \code{\link{.jevalArray}} 15 | 16 | For java objects that implement the Iterable interface, 17 | the list is created by iterating over the associated iterator 18 | } 19 | \usage{ 20 | \S3method{as.list}{jobjRef}(x, ...) 21 | \S3method{as.list}{jarrayRef}(x, ...) 22 | } 23 | \arguments{ 24 | \item{x}{java array or Iterable java object} 25 | \item{\dots}{ignored} 26 | } 27 | \value{ 28 | An R list, or vector. 29 | } 30 | \note{ 31 | The function is not intended to be called directly. It is implemented 32 | so that java arrays or Iterable java objects can be used as the first 33 | argument of \code{\link{lapply}} 34 | } 35 | \seealso{ 36 | \code{\link{.jevalArray}}, \code{\link{lapply}} 37 | } 38 | \examples{ 39 | \dontshow{.jinit()} 40 | # lapplying over a java array 41 | a <- .jarray( list( 42 | .jnew( "java/awt/Point", 10L, 10L ), 43 | .jnew( "java/awt/Point", 30L, 30L ) 44 | ) ) 45 | lapply( a, function(point){ 46 | with(point, { 47 | (x + y ) ^ 2 48 | } ) 49 | } ) 50 | 51 | # lapply over a Vector (implements Iterable) 52 | v <- .jnew("java/util/Vector") 53 | v$add( "foo" ) 54 | v$add( .jnew("java/lang/Double", 10.2 ) ) 55 | sapply( v, function(item) item$getClass()$getName() ) 56 | 57 | } 58 | \keyword{ programming } 59 | 60 | -------------------------------------------------------------------------------- /man/clone.Rd: -------------------------------------------------------------------------------- 1 | \name{clone} 2 | \alias{clone} 3 | \alias{clone,jobjRef-method} 4 | \alias{clone,jarrayRef-method} 5 | \alias{clone,jrectRef-method} 6 | 7 | \title{ 8 | Object cloner 9 | } 10 | \description{ 11 | Generic function to clone objects 12 | } 13 | \usage{ 14 | clone(x, ...) 15 | } 16 | \section{Methods}{ 17 | \describe{ 18 | \item{clone}{\code{signature(x = "jobjRef")}: clone a java object reference (must implement Cloneable) } 19 | \item{clone}{\code{signature(x = "jarrayRef")}: clone a java rugged array (not yet implemented) } 20 | \item{clone}{\code{signature(x = "jrectRef")}: clone a java rectangular array (not yet implemented) } 21 | } 22 | } 23 | 24 | \arguments{ 25 | \item{x}{An object to clone} 26 | \item{\dots}{Further arguments, ignored} 27 | } 28 | \value{ 29 | A clone of the object 30 | } 31 | \section{Warning}{ 32 | The implementation of clone for java object references uses 33 | the clone method of the Object class. The reading of its description 34 | in the java help page is \emph{strongly} recommended. 35 | } 36 | 37 | \examples{ 38 | \dontshow{.jinit()} 39 | 40 | p1 <- .jnew("java/awt/Point" ) 41 | p2 <- clone( p1 ) 42 | p2$move( 10L, 10L ) 43 | p1$getX() 44 | 45 | # check that p1 and p2 are not references to the same java object 46 | stopifnot( p1$getX() == 0 ) 47 | stopifnot( p2$getX() == 10 ) 48 | 49 | } 50 | \keyword{ programming } 51 | 52 | -------------------------------------------------------------------------------- /man/instanceof.Rd: -------------------------------------------------------------------------------- 1 | \name{.jinstanceof} 2 | \Rdversion{1.1} 3 | \alias{\%instanceof\%} 4 | \alias{.jinstanceof} 5 | \title{ 6 | Is a java object an instance of a given java class 7 | } 8 | \description{ 9 | Is a java object an instance of a given java class 10 | } 11 | \usage{ 12 | o \%instanceof\% cl 13 | .jinstanceof( o, cl ) 14 | } 15 | \arguments{ 16 | \item{o}{java object reference} 17 | \item{cl}{java class. This can be a character vector of length one 18 | giving the name of the class, or another java object, or an instance 19 | of the Class class, or a object of class \code{jclassName}.} 20 | } 21 | \value{ 22 | TRUE if o is an instance of cl 23 | } 24 | \author{ 25 | Romain Francois 26 | } 27 | \examples{ 28 | \dontshow{ 29 | .jinit() 30 | } 31 | Double <- J("java.lang.Double") 32 | d <- new( Double, "10.2" ) 33 | 34 | # character 35 | d \%instanceof\% "java.lang.Double" 36 | d \%instanceof\% "java.lang.Number" 37 | 38 | # jclassName 39 | d \%instanceof\% Double 40 | 41 | # instance of Class 42 | Double.class <- Double@jobj 43 | d \%instanceof\% Double.class 44 | 45 | # other object 46 | other.double <- new( Double, 10.2 ) 47 | d \%instanceof\% other.double 48 | 49 | \dontshow{ 50 | % simple unit tests 51 | stopifnot( d \%instanceof\% "java.lang.Double" ) 52 | stopifnot( d \%instanceof\% "java.lang.Number" ) 53 | stopifnot( d \%instanceof\% "java.lang.Object" ) 54 | stopifnot( d \%instanceof\% Double.class ) 55 | stopifnot( d \%instanceof\% other.double ) 56 | stopifnot( d \%instanceof\% Double ) 57 | } 58 | 59 | } 60 | \keyword{ interface } 61 | 62 | -------------------------------------------------------------------------------- /man/jarray.Rd: -------------------------------------------------------------------------------- 1 | \name{jarray} 2 | \alias{.jarray} 3 | \alias{.jevalArray} 4 | \title{ 5 | Java array handling functions 6 | } 7 | \description{ 8 | \code{.jarray} takes a vector (or a list of Java references) as its 9 | argument, creates a Java array containing the elements of the vector 10 | (or list) and returns a reference to such newly created array. 11 | 12 | \code{.jevalArray} takes a reference to a Java array and returns its 13 | contents (if possible). 14 | } 15 | \usage{ 16 | .jarray(x, contents.class = NULL, dispatch = FALSE) 17 | .jevalArray(obj, rawJNIRefSignature = NULL, silent = FALSE, simplify = FALSE) 18 | } 19 | \arguments{ 20 | \item{x}{vector or a list of Java references} 21 | \item{contents.class}{common class of the contained objects, see 22 | details} 23 | \item{obj}{Java object reference to an array that is to be evaluated} 24 | \item{rawJNIRefSignature}{JNI signature that would be used for 25 | conversion. If set to \code{NULL}, the signature is detected 26 | automatically.} 27 | \item{silent}{if set to true, warnings are suppressed} 28 | \item{dispatch}{logical. If \code{TRUE} the code attempts to dispatch 29 | to either a \code{jarrayRef} object for rugged arrays and 30 | \code{jrectRef} objects for rectangular arrays, creating possibly a 31 | multi-dimensional object in Java (e.g., when used with a matrix).} 32 | \item{simplify}{if set to \code{TRUE} more than two-dimensional arrays 33 | are converted to native objects (e.g., matrices) if their type and 34 | size matches (essentially the inverse for objects created with 35 | \code{dispatch=TRUE}).} 36 | } 37 | \value{ 38 | \code{.jarray} returns a Java array reference (\code{jarrayRef} or \code{jrectRef}) to an 39 | array created with the supplied contents. 40 | 41 | \code{.jevalArray} returns the contents of the array object. 42 | } 43 | \details{ 44 | \code{.jarray}: The input can be either a vector of some sort (such as 45 | numeric, integer, logical, ...) or a list of Java references. The 46 | contents is pushed to the Java side and a corresponding array is 47 | created. The type of the array depends on the input vector type. For 48 | example numeric vector creates \code{double[]} array, integer vector 49 | creates \code{int[]} array, character vector \code{String[]} array and 50 | so on. If \code{x} is a list, it must contain Java references only (or 51 | \code{NULL}s which will be treated as \code{NULL} references). 52 | 53 | The \code{contents.class} parameter is used only if \code{x} is a list 54 | of Java object references and it can specify the class that will be 55 | used for all objects in the array. If set to \code{NULL} no assumption 56 | is made and \code{java/lang/Object} will be used. Use with care and 57 | only if you know what you're doing - you can always use 58 | \code{\link{.jcast}} to cast the entire array to another type even if 59 | you use a more general object type. One typical use is to construct 60 | multi-dimensional arrays which mandates passing the array type as 61 | \code{contents.class}. 62 | 63 | The result is a reference to the newly created array. 64 | 65 | The inverse function which fetches the elements of an array reference 66 | is \code{.jevalArray}. 67 | 68 | \code{.jevalArray} currently supports only a subset of all possible 69 | array types. Recursive arrays are handled by returning a list of 70 | references which can then be evaluated separately. The only exception 71 | is \code{simplify=TRUE} in which case \code{.jevalArray} attempts to 72 | convert multi-dimensional arrays into native R type if there is a 73 | such. This only works for rectangular arrays of the same basic type 74 | (i.e. the length and type of each referenced array is the same - 75 | sometimes matrices are represented that way in Java). 76 | } 77 | \examples{ 78 | \dontshow{.jinit()} 79 | a <- .jarray(1:10) 80 | print(a) 81 | .jevalArray(a) 82 | b <- .jarray(c("hello","world")) 83 | print(b) 84 | c <- .jarray(list(a,b)) 85 | print(c) 86 | # simple .jevalArray will return a list of references 87 | print(l <- .jevalArray(c)) 88 | # to convert it back, use lapply 89 | lapply(l, .jevalArray) 90 | 91 | # two-dimensional array resulting in int[2][10] 92 | d <- .jarray(list(a,a),"[I") 93 | print(d) 94 | # use dispatch to convert a matrix to [[D 95 | e <- .jarray(matrix(1:12/2, 3), dispatch=TRUE) 96 | print(e) 97 | # simplify it back to a matrix 98 | .jevalArray(e, simplify=TRUE) 99 | } 100 | \keyword{interface} 101 | -------------------------------------------------------------------------------- /man/jarrayRef-class.Rd: -------------------------------------------------------------------------------- 1 | \name{jarrayRef-class} 2 | \docType{class} 3 | \alias{jarrayRef-class} 4 | \alias{[,jarrayRef-method} 5 | \alias{[[,jarrayRef-method} 6 | \alias{[[<-,jarrayRef-method} 7 | \alias{head,jarrayRef-method} 8 | \alias{tail,jarrayRef-method} 9 | \alias{length,jarrayRef-method} 10 | \alias{str,jarrayRef-method} 11 | \alias{unique,jarrayRef-method} 12 | \alias{duplicated,jarrayRef-method} 13 | \alias{anyDuplicated,jarrayRef-method} 14 | \alias{sort,jarrayRef-method} 15 | \alias{rev,jarrayRef-method} 16 | \alias{min,jarrayRef-method} 17 | \alias{max,jarrayRef-method} 18 | \alias{range,jarrayRef-method} 19 | 20 | \title{Class "jarrayRef" Reference to an array Java object } 21 | \description{ This class is a subclass of \link{jobjRef-class} 22 | and represents a reference to an array Java object. } 23 | \section{Objects from the Class}{ 24 | Objects cannot be created directly, but only as the return 25 | value of \code{\link{.jcall}} function. 26 | } 27 | \section{Slots}{ 28 | \describe{ 29 | \item{\code{jsig}:}{JNI signature of the array type} 30 | \item{\code{jobj}:}{Internal identifier of the object} 31 | \item{\code{jclass}:}{Inherited from \code{jobjRef}, but unspecified} 32 | } 33 | } 34 | \section{Methods}{ 35 | \describe{ 36 | \item{[}{\code{signature(x = "jarrayRef")}: \emph{not yet implemented} } 37 | \item{[[}{\code{signature(x = "jarrayRef")}: R indexing of java arrays } 38 | \item{[[<-}{\code{signature(x = "jarrayRef")}: replacement method } 39 | \item{\code{head}}{\code{signature(x = "jarrayRef")}: head of the java array } 40 | \item{\code{tail}}{\code{signature(x = "jarrayRef")}: tail of the java array } 41 | \item{length}{\code{signature(object = "jarrayRef")}: Number of java objects in the java array } 42 | \item{str}{\code{signature(object = "jarrayRef")}: ... } 43 | \item{unique}{\code{signature(x = "jarrayRef")}: \emph{not yet implemented} } 44 | \item{duplicated}{\code{signature(x = "jarrayRef")}: \emph{not yet implemented} } 45 | \item{anyDuplicated}{\code{signature(x = "jarrayRef")}: \emph{not yet implemented} } 46 | \item{sort}{\code{signature(x = "jarrayRef")}: \emph{not yet implemented} } 47 | \item{rev}{\code{signature(x = "jarrayRef")}: \emph{not yet implemented} } 48 | \item{min}{\code{signature(x = "jarrayRef")}: \emph{not yet implemented} } 49 | \item{max}{\code{signature(x = "jarrayRef")}: \emph{not yet implemented} } 50 | \item{range}{\code{signature(x = "jarrayRef")}: \emph{not yet implemented} } 51 | } 52 | } 53 | \section{Extends}{ 54 | Class \code{"\linkS4class{jobjRef}"}, directly. 55 | } 56 | \author{ Simon Urbanek } 57 | \seealso{ 58 | \code{\link{.jcall}} or \code{\linkS4class{jobjRef}} 59 | \code{\linkS4class{jrectRef}} for rectangular arrays 60 | } 61 | % need to find examples of rugged arrays 62 | % \examples{ 63 | % \dontshow{.jinit()} 64 | % } 65 | \keyword{classes} 66 | -------------------------------------------------------------------------------- /man/java-tools.Rd: -------------------------------------------------------------------------------- 1 | \name{java-tools} 2 | \alias{java-tools} 3 | \title{java tools used internally in rJava} 4 | \description{java tools used internally in rJava} 5 | \examples{ 6 | \dontshow{ 7 | # running the java unit tests from the R examples 8 | .jinit() 9 | J("RJavaTools_Test")$runtests() 10 | J("RJavaArrayTools_Test")$runtests() 11 | J("ArrayWrapper_Test")$runtests() 12 | J("RectangularArrayBuilder_Test")$runtests() 13 | 14 | 15 | p <- .jnew( "java/awt/Point" ) 16 | classes <- .Call( rJava:::RgetSimpleClassNames, p@jobj, TRUE ) 17 | stopifnot( all( c( "Point", "Point2D", "Object", "error", "condition" ) \%in\% classes ) ) 18 | classes <- .Call( rJava:::RgetSimpleClassNames, p@jobj, FALSE ) 19 | stopifnot( all( c( "Point", "Point2D", "Object" ) \%in\% classes ) ) 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /man/javaImport.Rd: -------------------------------------------------------------------------------- 1 | \name{javaImport} 2 | \alias{javaImport} 3 | \title{ 4 | Attach mechanism for java packages 5 | } 6 | \description{ 7 | The \code{javaImport} function creates an item on R's 8 | search that maps names to class names references found in 9 | one or several "imported" java packages. 10 | } 11 | \usage{ 12 | javaImport(packages = "java.lang") 13 | } 14 | \arguments{ 15 | \item{packages}{character vector containing java package paths} 16 | } 17 | \value{ 18 | An external pointer to a java specific \code{UserDefinedDatabase} object 19 | } 20 | \references{ 21 | \emph{User-Defined Tables in the R Search Path}. Duncan Temple Lang. December 4, 2001 22 | \url{https://www.omegahat.net/RObjectTables/} 23 | } 24 | \author{ 25 | Romain Francois 26 | } 27 | \note{ 28 | Currently the list of objects in the imported package is populated 29 | as new objects are found, \emph{not} at creation time. 30 | } 31 | \section{Warning}{ 32 | This feature is experimental. Use with caution, and don't forget to 33 | detach. 34 | } 35 | \seealso{ 36 | \code{\link{attach}} 37 | } 38 | \examples{ 39 | \dontrun{ 40 | attach( javaImport( "java.util" ), pos = 2 , name = "java:java.util" ) 41 | 42 | # now we can just do something like this 43 | v <- new( Vector ) 44 | v$add( "foobar" ) 45 | ls( pos = 2 ) 46 | 47 | # or this 48 | m <- new( HashMap ) 49 | m$put( "foo", "bar" ) 50 | ls( pos = 2 ) 51 | 52 | # or even this : 53 | Collections$EMPTY_MAP 54 | } 55 | } 56 | \keyword{ programming } 57 | -------------------------------------------------------------------------------- /man/jcast.Rd: -------------------------------------------------------------------------------- 1 | \name{jcast} 2 | \alias{.jcast} 3 | \title{ 4 | Cast a Java object to another class 5 | } 6 | \description{ 7 | \code{.jcast} returns a Java object reference cast to another Java class. 8 | } 9 | \usage{ 10 | .jcast(obj, new.class = "java/lang/Object", check = FALSE, convert.array = FALSE) 11 | } 12 | \arguments{ 13 | \item{obj}{a Java object reference} 14 | \item{new.class}{fully qualified class name in JNI notation 15 | (e.g. \code{"java/lang/String"}). } 16 | \item{check}{logical. If \code{TRUE}, it is checked that the object 17 | effectively is an instance of the new class. See \code{\link{\%instanceof\%}}. 18 | Using FALSE (the default) for this argument, rJava does not perform type check and this 19 | will cause an error on the first use if the cast is illegal.} 20 | \item{convert.array}{logical. If \code{TRUE} and the object is an array, 21 | it is converted into a \code{jarrayRef} reference. } 22 | } 23 | \value{ 24 | Returns a Java object reference (\code{jobjRef}) to the object 25 | \code{obj}, changing the object class. 26 | } 27 | \details{ 28 | This function is necessary if a argument of \code{\link{.jcall}} or 29 | \code{\link{.jnew}} is defined as the superclass of the object to be 30 | passed (see \code{\link{.jcall}}). The original object is not modified. 31 | 32 | The default values for the arguments \code{check} and \code{convert.array} 33 | is \code{FALSE} in order to guarantee backwards compatibility, 34 | but it is recommended to set the arguments to \code{TRUE} 35 | } 36 | \seealso{ 37 | \code{\link{.jcall}} 38 | } 39 | \examples{ 40 | \dontrun{ 41 | v <- .jnew("java/util/Vector") 42 | .jcall("java/lang/System","I","identityHashCode",.jcast(v, "java/lang/Object")) 43 | } 44 | } 45 | \keyword{interface} 46 | -------------------------------------------------------------------------------- /man/jcastToArray.Rd: -------------------------------------------------------------------------------- 1 | \name{jcastToArray} 2 | \alias{.jcastToArray} 3 | \title{ 4 | Ensures that a given object is an array reference 5 | } 6 | \description{ 7 | \code{.jcastToArray} takes a Java object reference of any kind and 8 | returns Java array reference if the given object is a reference to an 9 | array. 10 | } 11 | \usage{ 12 | .jcastToArray(obj, signature=NULL, class="", quiet=FALSE) 13 | } 14 | \arguments{ 15 | \item{obj}{Java object reference to cast or a scalar vector} 16 | \item{signature}{array signature in JNI notation (e.g. \code{"[I"} for 17 | an array of integers). If set to \code{NULL} (the default), 18 | the signature is automatically determined from the object's class.} 19 | \item{class}{force the result to pose as a particular Java 20 | class. This has the same effect as using \code{\link{.jcast}} on the 21 | result and is provided for convenience only.} 22 | \item{quiet}{if set to \code{TRUE}, no failures are reported and the 23 | original object is returned unmodified.} 24 | } 25 | \value{ 26 | Returns a Java array reference (\code{jarrayRef}) on success. If 27 | \code{quiet} is \code{TRUE} then the result can also be the original 28 | object in the case of failure. 29 | } 30 | \details{ 31 | Sometimes a result of a method is by definition of the class 32 | \code{java.lang.Object}, but the actual referenced object may be an 33 | array. In that case the method returns a Java object reference instead 34 | of an array reference. In order to obtain an array reference, it is 35 | necessary to cast such an object to an array reference - this is done 36 | using the above \code{.jcastToArray} function. 37 | 38 | The input is an object reference that points to an array. Usually the 39 | signature should be left at \code{NULL} such that it is determined 40 | from the object's class. This is also a check, because if the object's 41 | class is not an array, then the functions fails either with an error 42 | (when \code{quiet=FALSE}) or by returning the original object (when 43 | \code{quiet=TRUE}). If the signature is set to anything else, it is 44 | not verified and the array reference is always created, even if it may 45 | be invalid and unusable. 46 | 47 | For convenience \code{.jcastToArray} also accepts non-references in 48 | which case it simply calls \code{\link{.jarray}}, ignoring all other 49 | parameters. 50 | } 51 | \examples{ 52 | \dontrun{ 53 | a <- .jarray(1:10) 54 | print(a) 55 | # let's create an array containing the array 56 | aa <- .jarray(list(a)) 57 | print(aa) 58 | ba <- .jevalArray(aa)[[1]] 59 | # it is NOT the inverse, because .jarray works on a list of objects 60 | print(ba) 61 | # so we need to cast the object into an array 62 | b <- .jcastToArray(ba) 63 | # only now a and b are the same array reference 64 | print(b) 65 | # for convenience .jcastToArray behaves like .jarray for non-references 66 | print(.jcastToArray(1:10/2)) 67 | } 68 | } 69 | \keyword{interface} 70 | -------------------------------------------------------------------------------- /man/jcheck.Rd: -------------------------------------------------------------------------------- 1 | \name{jcheck} 2 | \alias{.jcheck} 3 | \alias{.jthrow} 4 | \alias{.jclear} 5 | \alias{.jgetEx} 6 | \title{ 7 | Java exception handling 8 | } 9 | \description{ 10 | \code{.jcheck} checks the Java VM for any pending exceptions and 11 | clears them. 12 | 13 | \code{.jthrow} throws a Java exception. 14 | 15 | \code{.jgetEx} polls for any pending exceptions and returns the exception object. 16 | 17 | \code{.jclear} clears a pending exception. 18 | } 19 | \usage{ 20 | .jcheck(silent = FALSE) 21 | 22 | .jthrow(exception, message = NULL) 23 | .jgetEx(clear = FALSE) 24 | .jclear() 25 | } 26 | \arguments{ 27 | \item{silent}{If set to \code{FALSE} then Java is instructed to print 28 | the exception on \code{stderr}. Note that Windows Rgui doesn't show 29 | \code{stderr} so it will not appear there (as of rJava 0.5-1 some 30 | errors that the JVM prints using the vfprintf callback are passed 31 | to R. However, some parts are printed using \code{System.err} in 32 | which case the usual redirection using the \code{System} class 33 | can be used by the user).} 34 | \item{exception}{is either a class name of an exception to create or a 35 | throwable object reference that is to be thrown.} 36 | \item{message}{if \code{exception} is a class name then this parameter 37 | specifies the string to be used as the message of the exception. This 38 | parameter is ignored if \code{exception} is a reference.} 39 | \item{clear}{if set to \code{TRUE} then the returned exception is also 40 | cleared, otherwise the throwable is returned without clearing the 41 | cause.} 42 | } 43 | \value{ 44 | \code{.jcheck} returns \code{TRUE} if an exception occurred or 45 | \code{FALSE} otherwise. 46 | 47 | \code{.jgetEx} returns \code{NULL} if there are no pending exceptions 48 | or an object of the class "java.lang.Throwable" representing the 49 | current exception. 50 | } 51 | \details{ 52 | Please note that some functions (such as \code{\link{.jnew}} or 53 | \code{\link{.jcall}}) call \code{.jcheck} implicitly unless 54 | instructed to not do so. If you want to handle Java exceptions, you 55 | should make sure that those function don't clear the exception you may 56 | want to catch. 57 | 58 | The exception handling is still as a very low-level and experimental, 59 | because it requires polling of exceptions. A more elaborate system 60 | using constructs similar to \code{try} ... \code{catch} is planned for 61 | next major version of \code{rJava}. 62 | 63 | \emph{Warning:} When requesting exceptions to not be cleared 64 | automatically, please note that the \code{show} method (which is 65 | called by \code{print}) has a side-effect of making a Java call to get 66 | the string representation of a Java object. This implies that it will 67 | be impeded by any pending exceptions. Therefore exceptions obtained 68 | through \code{.jgetEx} can be stored, but should not be printed 69 | (or otherwise used in Java calls) until after the exception is 70 | cleared. In general, all Java calls will fail (possibly silently) 71 | until the exception is cleared. 72 | } 73 | \seealso{ 74 | \code{\link{.jcall}}, \code{\link{.jnew}} 75 | } 76 | \examples{ 77 | \donttest{ 78 | # we try to create a bogus object and 79 | # instruct .jnew to not clear the exception 80 | # this will raise an exception 81 | v <- .jnew("foo/bar", check=FALSE) 82 | 83 | # you can poll for the exception, but don't try to print it 84 | # (see details above) 85 | if (!is.null(e<-.jgetEx())) print("Java exception was raised") 86 | 87 | # expect TRUE result here because the exception was still not cleared 88 | print(.jcheck(silent=TRUE)) 89 | # next invocation will be FALSE because the exception is now cleared 90 | print(.jcheck(silent=TRUE)) 91 | 92 | # now you can print the actual expection (even after it was cleared) 93 | print(e) 94 | } 95 | } 96 | \keyword{interface} 97 | -------------------------------------------------------------------------------- /man/jclassName.Rd: -------------------------------------------------------------------------------- 1 | \name{jclassName-class} 2 | \docType{class} 3 | \alias{jclassName-class} 4 | \alias{as.character,jclassName-method} 5 | 6 | \title{Class "jclassName" - a representation of a Java class name } 7 | \description{ This class holds a name of a class in Java. } 8 | \section{Objects from the Class}{ 9 | Objects of this class should *not* be created directly. Instead, the 10 | function \code{\link{J}} should be used to create new objects of this class. 11 | } 12 | \section{Slots}{ 13 | \describe{ 14 | \item{\code{name}:}{Name of the class (in source code notation)} 15 | \item{\code{jobj}:}{Object representing the class in Java} 16 | } 17 | } 18 | \section{Methods}{ 19 | The objects of class \code{jclassName} are used indirectly to be able 20 | to create new Java objects via \code{new} such as 21 | \code{new(J("java.lang.String"), "foo")} or to use the \code{$} 22 | convenience operator on static classes, such as 23 | \code{J("java.lang.Double")$parseDouble("10.2")}. 24 | 25 | \describe{ 26 | \item{\code{as.character}}{\code{signature(x = "jclassName")}: 27 | returns the class name as a string vector of length one. 28 | } 29 | } 30 | } 31 | %\references{ ~put references to the literature/web site here ~ } 32 | \author{ Simon Urbanek } 33 | %\note{ ~~further notes~~ } 34 | % ~Make other sections like Warning with \section{Warning }{....} ~ 35 | \seealso{ 36 | \code{\link{J}}, \code{\link{new}} 37 | } 38 | %\examples{ 39 | %##---- Should be DIRECTLY executable !! ---- 40 | %} 41 | \keyword{classes} 42 | -------------------------------------------------------------------------------- /man/jengine.Rd: -------------------------------------------------------------------------------- 1 | \name{jengine} 2 | \alias{.jengine} 3 | \title{ 4 | Java callback engineCast a Java object to another class 5 | } 6 | \description{ 7 | \code{.jengine} obtains the current callback engine or starts it. 8 | } 9 | \usage{ 10 | .jengine(start=FALSE, silent=FALSE) 11 | } 12 | \arguments{ 13 | \item{start}{if set to \code{TRUE} then the callback engine is started 14 | if it is not yet active} 15 | \item{silent}{if set to \code{TRUE} then NULL is returned if there is 16 | no engine available. Otherwise an error is raised} 17 | } 18 | \value{ 19 | Returns a Java object reference (\code{jobjRef}) to the current Java 20 | callback engine. 21 | } 22 | \details{ 23 | \code{.jengine} can be used to detect whether the engine was started 24 | or to start the engine. 25 | 26 | Before any callbacks from Java into R can be performed, the Java 27 | callback engine must be initialized, loading Java/R Interface 28 | (JRI). If JRI was not started and \code{start} is set to \code{TRUE} 29 | then \code{.jengine} will load necessary classes and start 30 | it. 31 | 32 | Note that JRI is an optional part of rJava and requires R shared 33 | library at the moment. By default rJava will continue with 34 | installation even if JRI cannot be built. 35 | } 36 | \seealso{ 37 | \code{\link{.jcall}} 38 | } 39 | \examples{ 40 | \dontrun{ 41 | .jengine(TRUE) 42 | } 43 | } 44 | \keyword{interface} 45 | -------------------------------------------------------------------------------- /man/jfield.Rd: -------------------------------------------------------------------------------- 1 | \name{jfield} 2 | \alias{.jfield} 3 | \alias{.jfield<-} 4 | \title{ 5 | Obtains the value of a field 6 | } 7 | \description{ 8 | \code{.jfield} returns the value of the specified field on an object. 9 | } 10 | \usage{ 11 | .jfield(o, sig = NULL, name, true.class = is.null(sig), convert = TRUE) 12 | `.jfield<-`(o, name, value) 13 | } 14 | \arguments{ 15 | \item{o}{Class name or object (Java reference) whose field is to be 16 | accessed. Static fields are supported both by specifying the class 17 | name or using an instance.} 18 | \item{sig}{signature (JNI type) of the field. If set to \code{NULL} 19 | rJava attempts to determine the signature using reflection. For 20 | efficiency it is recommended to specify the signature, because 21 | the reflection lookup is quite expensive.} 22 | \item{name}{name of the field to access} 23 | \item{true.class}{by default the class of the resulting object matches 24 | the signature of the field. Setting this flag to \code{TRUE} causes 25 | \code{.jfield} to use true class name of the resulting object 26 | instead. (this flag has no effect on scalar fields)} 27 | \item{convert}{when set to \code{TRUE} all references are converted to 28 | native types (where possible). Otherwise Java references are 29 | returned directly.} 30 | \item{value}{value to assign into the field. The field signature is 31 | determined from the value in the same way that parameter signatures 32 | are determined in \code{\link{.jcall}} - be sure to cast the value 33 | as necessary, no automatic conversion is done.} 34 | } 35 | \value{ 36 | \code{.jfield}: contents of the field, \code{.jfield<-}: modified object. 37 | } 38 | \details{ 39 | The detection of a field signature in \code{.jfield} using reflection 40 | is considerably expensive (more than 3 additional method calls have to 41 | be performed), therefore it is recommended for time-critical code to 42 | specify the field signature beforehand. 43 | 44 | NOTE: The sequence of arguments in \code{.jfield} has been changed 45 | since rJava 0.5 to be more consistent and match the sequence in 46 | \code{.jcall}. Also \code{.jsimplify} is no longer needed as primitive 47 | types are obtained directly. 48 | } 49 | \seealso{ 50 | \code{\link{.jcall}} 51 | } 52 | \examples{ 53 | \dontrun{ 54 | .jfield("java/lang/Boolean",, "TYPE") 55 | } 56 | } 57 | \keyword{interface} 58 | -------------------------------------------------------------------------------- /man/jfloat-class.Rd: -------------------------------------------------------------------------------- 1 | \name{jfloat-class} 2 | \docType{class} 3 | \alias{jfloat-class} 4 | \alias{jlong-class} 5 | \alias{jbyte-class} 6 | \alias{jchar-class} 7 | \title{Classes "jfloat", "jlong", "jbyte" and "jchar" specify Java 8 | native types that are not native in R} 9 | \description{ These classes wrap a numeric vector to be treated as 10 | \code{float} or \code{long} argument when passed to Java and an 11 | integer vector to be treated as \code{byte} or \code{char}. R doesn't 12 | distinguish between \code{double} and \code{float}, but Java 13 | does. In order to satisfy object types, numeric vectors that should be 14 | converted to floats or long on the Java side must be wrapped in this 15 | class. In addition \code{jbyte} must be used when passing scalar byte 16 | (but not byte arrays, those are mapped into RAW vectors). Finally 17 | \code{jchar} it used when mapping integer vectors into unicode Java 18 | character vectors.} 19 | \section{Objects from the Class}{ 20 | Objects can be created by calling \code{\link{.jfloat}}, 21 | \code{\link{.jlong}}, \code{\link{.jbyte}} or \code{\link{.jchar}} 22 | respectively. 23 | } 24 | \section{Slots}{ 25 | \describe{ 26 | \item{\code{.Data}:}{Payload} 27 | } 28 | } 29 | \section{Extends}{ 30 | "jfloat" and "jlong": 31 | Class \code{"numeric"}, from data part. 32 | Class \code{"vector"}, by class \code{"numeric"}. 33 | 34 | "jbyte" and "jchar": 35 | Class \code{"integer"}, from data part. 36 | Class \code{"vector"}, by class \code{"integer"}. 37 | } 38 | \section{Methods}{ 39 | "jfloat" and "jlong" have no methods other than those inherited from "numeric". 40 | "jbyte" and "jchar" have no methods other than those inherited from "integer". 41 | } 42 | %\references{ ~put references to the literature/web site here ~ } 43 | \author{ Simon Urbanek } 44 | %\note{ ~~further notes~~ } 45 | 46 | % ~Make other sections like Warning with \section{Warning }{....} ~ 47 | 48 | \seealso{ 49 | \code{\link{.jfloat}}, \code{\link{.jlong}}, \code{\link{.jbyte}}, \code{\link{.jchar}} and \code{\link{.jcall}} 50 | } 51 | %\examples{ 52 | %##---- Should be DIRECTLY executable !! ---- 53 | %} 54 | \keyword{classes} 55 | -------------------------------------------------------------------------------- /man/jfloat.Rd: -------------------------------------------------------------------------------- 1 | \name{jfloat} 2 | \alias{.jfloat} 3 | \alias{.jlong} 4 | \alias{.jbyte} 5 | \alias{.jchar} 6 | \alias{.jshort} 7 | \alias{jfloat} 8 | \alias{jlong} 9 | \alias{jbyte} 10 | \alias{jchar} 11 | \alias{jshort} 12 | \title{ 13 | Wrap numeric vector as flat Java parameter 14 | } 15 | \description{ 16 | \code{.jfloat} marks a numeric vector as an object that can be used 17 | as parameter to Java calls that require \code{float} parameters. 18 | Similarly, \code{.jlong} marks a numeric vector as \code{long} 19 | parameter, \code{.jshort} as \code{short} and \code{.jbyte} as 20 | \code{byte}. 21 | } 22 | \usage{ 23 | .jfloat(x) 24 | .jlong(x) 25 | .jbyte(x) 26 | .jchar(x) 27 | .jshort(x) 28 | } 29 | \arguments{ 30 | \item{x}{numeric vector} 31 | } 32 | \value{ 33 | Returns a numeric vector of the class \code{jfloat}, \code{jlong}, 34 | \code{jbyte}, \code{jshort} or \code{jchar} 35 | that can be used as parameter to Java calls that require 36 | \code{float}, \code{long}, \code{byte}, \code{short} or \code{char} 37 | parameters respectively. 38 | } 39 | \details{ 40 | R has no native \code{float} or \code{long} type. Numeric vectors are 41 | stored as \code{double}s, hence there is no native way to pass float 42 | numbers to Java methods. The \code{.jfloat} call marks a numeric 43 | vector as having the Java type \code{float} by wrapping it in the 44 | \code{jfloat} class. The class is still a subclass of \code{numeric}, 45 | therefore all regular R operations are unaffected by this. 46 | 47 | Similarly, \code{.jlong} is used to mark a numeric vector as a 48 | parameter of the \code{long} Java type. Please note that in general R 49 | has no native type that will hold a \code{long} value, so conversion 50 | between Java's \code{long} type and R's numeric is potentially lossy. 51 | 52 | \code{.jbyte} is used when a scalar byte is to be passed to Java. Note 53 | that byte arrays are natively passed as raw vectors, not as 54 | \code{.jbyte} arrays, although non-scalar \code{.jbyte} is equivalent 55 | except for using four-times as much memory. 56 | 57 | \code{.jchar} is strictly experimental and uses integer vector as 58 | storage class. The type \code{char} in Java 59 | represents 16-bit Unicode code points (not to be confused with 60 | \code{char} in C which is \code{byte} in Java!), see Java 61 | documentation for details. \code{x} can also be a non-\code{NA} string 62 | in which case \code{.jchar(x)} is just a shorthand for 63 | \code{.jnew("java.lang.String", x)$toCharArray()} and thus performs a 64 | Java call (unlike all other functions mentioned here). 65 | } 66 | \seealso{ 67 | \code{\link{.jcall}}, \code{\link{jfloat-class}} 68 | } 69 | %\examples{ 70 | %\dontrun{ 71 | %v <- .jnew("java/util/Vector") 72 | %.jcall("java/lang/System","I","identityHashCode",.jcast(v, "java/lang/Object")) 73 | %} 74 | %} 75 | \keyword{interface} 76 | -------------------------------------------------------------------------------- /man/jgc.Rd: -------------------------------------------------------------------------------- 1 | \name{.jgc} 2 | \alias{.jgc} 3 | \title{ 4 | Invoke Java Garbage Collection 5 | } 6 | \description{ 7 | \code{.jgc} invokes the R and Java garbage collectors. 8 | } 9 | \usage{ 10 | .jgc(R.gc = TRUE, ...) 11 | } 12 | \arguments{ 13 | \item{R.gc}{logical, if \code{TRUE} then \code{gc(\dots)} is called 14 | first, if \code{FALSE} only Java garbage collector is called} 15 | \item{\dots}{any additional parameters passed to \code{gc()}} 16 | } 17 | \details{ 18 | \code{.jgc} invokes the R garbage collector (unless 19 | \code{R.gc=FALSE}) which removes any unused Java references and then 20 | invokes the Java garbage collector to reclaim Java heap space. 21 | } 22 | \author{ 23 | Simon Urbanek 24 | } 25 | \keyword{interface} 26 | -------------------------------------------------------------------------------- /man/jmemprof.Rd: -------------------------------------------------------------------------------- 1 | \name{jmemprof} 2 | \alias{.jmemprof} 3 | \title{ 4 | rJava memory profiler 5 | } 6 | \description{ 7 | \code{.jmemprof} enables or disables rJava memory profiling. If rJava 8 | was compiled without memory profiling support, then a call to this 9 | function always causes an error. 10 | } 11 | \usage{ 12 | .jmemprof(file = "-") 13 | } 14 | \arguments{ 15 | \item{file}{file to write profiling information to or \code{NULL} to 16 | disable profiling} 17 | } 18 | \value{ 19 | Returns \code{NULL}. 20 | } 21 | \details{ 22 | The \code{file} parameter must be either a filename (which will be 23 | opened in append-mode) or "-" to use standard output or \code{NULL} to 24 | disable profiling. An empty string "" is equivalent to \code{NULL} in 25 | this context. 26 | 27 | Note that lots of finalizers are run only when R exists, so usually 28 | you want to enable profiling early and let R exit to get a sensible 29 | profile. Running gc may be helpful to get rid of references that can 30 | be collected in R. 31 | 32 | A simple perl script is provided to analyze the result of the 33 | profiler. Due to its simple text format, it is possible to capture 34 | entire stdout including the profiler information to have both the 35 | console context for the allocations and the profile. Memory profiling 36 | is also helpful if rJava debug is enabled. 37 | 38 | Note that memory profiling support must be compiled in rJava and it is 39 | by default compiled only if debug mode is enabled (which is not the 40 | case by default). 41 | } 42 | \examples{ 43 | ## memory profiling support is optional so only works when enabled 44 | tryCatch( 45 | .jmemprof("rJava.mem.profile.txt"), 46 | error=function(e) message(e)) 47 | } 48 | \keyword{interface} 49 | -------------------------------------------------------------------------------- /man/jnew.Rd: -------------------------------------------------------------------------------- 1 | \name{jnew} 2 | \alias{.jnew} 3 | \title{ 4 | Create a Java object 5 | } 6 | \description{ 7 | \code{.jnew} create a new Java object. 8 | } 9 | \usage{ 10 | .jnew(class, ..., check=TRUE, silent=!check, class.loader=NULL) 11 | } 12 | \arguments{ 13 | \item{class}{fully qualified class name in JNI notation (e.g. \code{"java/lang/String"}).} 14 | \item{...}{ 15 | Any parameters that will be passed to the corresponding 16 | constructor. The parameter types are determined automatically and/or 17 | taken from the \code{jobjRef} object. For details see 18 | \code{\link{.jcall}}. Note that all named parameters are discarded.} 19 | \item{check}{ 20 | If set to \code{TRUE} then \code{\link{.jcheck}} is invoked before 21 | and after the call to the constructor to clear any pending Java 22 | exceptions.} 23 | \item{silent}{ 24 | If set to \code{FALSE} then \code{.jnew} will fail with an error if 25 | the object cannot be created, otherwise a null-reference is returned 26 | instead. In addition, this flag is also passed to final 27 | \code{.jcheck} if \code{check} above is set to \code{TRUE}. Note 28 | that the error handling also clears exceptions, so 29 | \code{check=FALSE, silent=FALSE} is usually not a meaningful 30 | combination. 31 | } 32 | \item{class.loader}{optional class loader to force for loading the 33 | class. If not set, the rJava class loader is used first. The default 34 | Java class loader is always used as a last resort. Set to 35 | \code{.rJava.class.loader} inside a package if it uses its own class 36 | loader (see \code{\link{.jpackage}} for details).} 37 | } 38 | \value{ 39 | Returns the reference (\code{jobjRef}) to the newly created object or 40 | \code{null}-reference (see \code{\link{.jnull}}) if something went wrong. 41 | } 42 | \seealso{ 43 | \code{\link{.jcall}}, \code{\link{.jnull}} 44 | } 45 | \examples{ 46 | \dontrun{ 47 | f <- .jnew("java/awt/Frame","Hello") 48 | .jcall(f,,"setVisible",TRUE) 49 | } 50 | } 51 | \keyword{interface} 52 | -------------------------------------------------------------------------------- /man/jnull.Rd: -------------------------------------------------------------------------------- 1 | \name{jnull} 2 | \alias{.jnull} 3 | \alias{is.jnull} 4 | \title{ 5 | Java null object reference 6 | } 7 | \description{ 8 | \code{.jnull} returns a \code{null} reference of a specified class 9 | type. The resulting object is of the class \code{jobjRef}. 10 | 11 | \code{is.jnull} is an extension of \code{is.null} that also returns 12 | \code{TRUE} if the supplied object is a \code{null} Java reference. 13 | } 14 | \usage{ 15 | .jnull(class = "java/lang/Object") 16 | is.jnull(x) 17 | } 18 | \arguments{ 19 | \item{class}{fully qualified target class name in JNI notation 20 | (e.g. \code{"java/lang/String"}).} 21 | \item{x}{object to check} 22 | } 23 | \value{ 24 | \code{.jnull} returns a Java object reference (\code{jobjRef}) of a 25 | \code{null} object having the specified object class. 26 | 27 | \code{is.jnull} returns \code{TRUE} if \code{is.null(x)} is 28 | \code{TRUE} or if \code{x} is a Java \code{null} reference. 29 | } 30 | \details{ 31 | \code{.jnull} is necessary if \code{null} is to be passed as an 32 | argument of \code{\link{.jcall}} or \code{\link{.jnew}}, in order to be 33 | able to find the correct method/constructor. 34 | 35 | Example: given the following method definitions of the class \code{A}: 36 | \itemize{ 37 | \item \code{public static void run(String a);} 38 | \item \code{public static void run(Double n);} 39 | } 40 | Calling \code{.jcall("A",,"run",NULL)} is ambiguous, because it is 41 | unclear which method is to be used. Therefore rJava requires class 42 | information with each argument to \code{\link{.jcall}}. If we wanted 43 | to run the String-version, we could use 44 | \code{.jcall("A",,"run",.jnull("java/lang/String"))}. 45 | 46 | \code{is.jnull} is a test that should be used to determine whether a 47 | given Java reference is a \code{null} reference. 48 | } 49 | \seealso{ 50 | \code{\link{.jcall}}, \code{\link{.jcast}} 51 | } 52 | \examples{ 53 | \dontrun{ 54 | .jcall("java/lang/System","I","identityHashCode",.jnull()) 55 | } 56 | } 57 | \keyword{interface} 58 | -------------------------------------------------------------------------------- /man/jobjRef-class.Rd: -------------------------------------------------------------------------------- 1 | \name{jobjRef-class} 2 | \docType{class} 3 | \alias{jobjRef-class} 4 | 5 | \title{Class "jobjRef" - Reference to a Java object } 6 | \description{ This class describes a reference to an object held in a JavaVM. } 7 | \section{Objects from the Class}{ 8 | Objects of this class should *not* be created directly. Instead, the function \code{\link{.jnew}} should be use to create new Java objects. They can also be created as results of the \code{\link{.jcall}} function. 9 | } 10 | \section{Slots}{ 11 | \describe{ 12 | \item{\code{jobj}:}{Internal identifier of the object (external pointer to be precise)} 13 | \item{\code{jclass}:}{Java class name of the object (in JNI notation)} 14 | } 15 | Java-side attributes are not accessed via slots, but the \code{$} operator instead. 16 | } 17 | \section{Methods}{ 18 | This object's Java methods are not accessed directly. Instead, \code{\link{.jcall}} JNI-API should be used for invoking Java methods. For convenience the \code{$} operator can be used to call methods via reflection API. 19 | } 20 | \author{ Simon Urbanek } 21 | \seealso{ 22 | \code{\link{.jnew}}, \code{\link{.jcall}} or \code{\link{jarrayRef-class}} 23 | } 24 | \keyword{classes} 25 | -------------------------------------------------------------------------------- /man/jreflection.Rd: -------------------------------------------------------------------------------- 1 | \name{jreflection} 2 | \alias{.jmethods} 3 | \alias{.jfields} 4 | \alias{.jconstructors} 5 | \title{ 6 | Simple helper functions for Java reflection 7 | } 8 | \description{ 9 | \code{.jconstructors} returns a character vector with all constructors for 10 | a given class or object. 11 | \code{.jmethods} returns a character vector with all methods for 12 | a given class or object. 13 | \code{.jfields} returns a character vector with all fields (aka attributes) for a given class or object. 14 | } 15 | \usage{ 16 | .jconstructors(o, as.obj = FALSE, class.loader=.rJava.class.loader) 17 | .jmethods(o, name = NULL, as.obj = FALSE, class.loader=.rJava.class.loader) 18 | .jfields(o, name = NULL, as.obj = FALSE, class.loader=.rJava.class.loader) 19 | } 20 | \arguments{ 21 | \item{o}{Name of a class (either notation is fine) or an object whose 22 | class will be queried} 23 | \item{name}{string, regular expression of the method/field to look for} 24 | \item{as.obj}{if \code{TRUE} then a list of Java objects is 25 | returned, otherwise a character vector (obtained by calling 26 | \code{toString()} on each entry).} 27 | \item{class.loader}{optional, class loader to use for class look up if 28 | needed (i.e., if \code{o} is a string)} 29 | } 30 | \value{ 31 | Returns a character vector (if \code{as.obj} is \code{FALSE}) or a 32 | list of Java objects. Each entry corresponds to the 33 | \code{Constructor} resp. \code{Method} resp. \code{Field} 34 | object. The string result is constructed by calling 35 | \code{toString()} on the objects. 36 | } 37 | \details{ 38 | There first two functions are intended to help with finding correct 39 | signatures for methods and constructors. Since the low-level API in 40 | rJava doesn't use reflection automatically, it is necessary to 41 | provide a proper signature. That is somewhat easier using the above 42 | methods. 43 | } 44 | \seealso{ 45 | \code{\link{.jcall}}, \code{\link{.jnew}}, \code{\link{.jcast}} or \code{\link{$,jobjRef-method}} 46 | } 47 | \examples{ 48 | \dontrun{ 49 | .jconstructors("java.util.Vector") 50 | v <- .jnew("java.util.Vector") 51 | .jmethods(v, "add") 52 | } 53 | } 54 | \keyword{interface} 55 | -------------------------------------------------------------------------------- /man/jsimplify.Rd: -------------------------------------------------------------------------------- 1 | \name{jsimplify} 2 | \alias{.jsimplify} 3 | \title{ 4 | Converts Java object to a simple scalar if possible 5 | } 6 | \description{ 7 | \code{.jsimplify} attempts to convert Java objects that represent 8 | simple scalars into corresponding scalar representation in R. 9 | } 10 | \usage{ 11 | .jsimplify(o, promote=FALSE) 12 | } 13 | \arguments{ 14 | \item{o}{arbitrary object} 15 | \item{promote}{logical, if \code{TRUE} then an ambiguous conversion 16 | where the native type value would map to \code{NA} (e.g., Java 17 | \code{int} type with value -2147483648) will be taken 18 | to represent an actual value and will be promoted to a larger type 19 | that can represent the value (in case of \code{int} promoted to 20 | \code{double}). If \code{FALSE} then such values are assumed to 21 | represent \code{NA}s.} 22 | } 23 | \value{ 24 | Simple scalar or \code{o} unchanged. 25 | } 26 | \details{ 27 | If \code{o} is not a Java object reference, \code{o} is returned 28 | as-is. If \code{o} is a reference to a scalar object (such as single 29 | integer, number, string or boolean) then the value of that object is 30 | returned as R vector of the corresponding type and length one. 31 | 32 | This function is used by \code{\link{.jfield}} to simplify the results 33 | of field access if required. 34 | 35 | Currently there is no function inverse to this, the usual way to wrap 36 | scalar values in Java references is to use \code{\link{.jnew}} as the 37 | corresponding constructor. 38 | } 39 | \seealso{ 40 | \code{\link{.jfield}} 41 | } 42 | \examples{ 43 | \dontrun{ 44 | i <- .jnew("java/lang/Integer", as.integer(10)) 45 | print(i) 46 | print(.jsimplify(i)) 47 | } 48 | } 49 | \keyword{interface} 50 | -------------------------------------------------------------------------------- /man/loader.Rd: -------------------------------------------------------------------------------- 1 | \name{loader} 2 | \alias{.jaddClassPath} 3 | \alias{.jclassPath} 4 | \alias{.jclassLoader} 5 | \title{ 6 | Java Class Loader 7 | } 8 | \description{ 9 | \code{.jaddClassPath} adds directories or JAR files to the class 10 | path. 11 | 12 | \code{.jclassPath} returns a vector containing the current entries in 13 | the class path 14 | } 15 | \usage{ 16 | .jaddClassPath(path, class.loader=.rJava.class.loader) 17 | .jclassPath(class.loader=.rJava.class.loader) 18 | .jclassLoader(package=NULL) 19 | } 20 | \arguments{ 21 | \item{path}{character string vector listing the paths to add to the 22 | class path} 23 | \item{class.loader}{Java class loader to use for the query of 24 | madification. Defaults to global class loader.} 25 | \item{package}{string, name of a package or \code{NULL} for the global 26 | class loader} 27 | } 28 | \value{ 29 | \code{.jclassPath} returns a character vector listing the class path sequence. 30 | } 31 | \details{ 32 | Whenever a class needs to be instantiated in Java it is referred by 33 | name which is used to locate a file with the bytecode for the 34 | class. The mechanism to map a name to an actual bytecode to load ind 35 | instantiate is habdled by the Java class loader. It typically keeps a 36 | list of directories and JAR files to search for the class names. 37 | 38 | The \code{.jaddClassPath()} function allows the user to append new 39 | locations to the list of places which will be searched. The function 40 | \code{.jclassPath} retrieves the current sarch list from the loader. 41 | 42 | When rJava is initialized, it instantiates the global class loader 43 | which is responsible for finding classes in functions such as 44 | \code{.jnew()}. In addition to the global class loader, R packages can 45 | create their own class loaders to avoid conflicts between packages 46 | such that they can be sure to use their own files to look for 47 | classes. See \code{\link{.jpackage}} for details on how that works. 48 | If the \code{package} argument is supplied \code{.jclassLoader} will 49 | look in that package to see if it has a custom loader and will return 50 | it, otherwise it returns the global loader. Note that is will fail with 51 | an error when supplied a non-existing package name. 52 | 53 | If you want to trace issues related to missing classes, you can enable 54 | debugging in the class loader by using the \code{setDebug} method, for 55 | example: \code{.jclassLoader()$setDebug(1L)} 56 | } 57 | \seealso{ 58 | \code{\link{.jpackage}} 59 | } 60 | \examples{ 61 | \dontrun{ 62 | .jaddClassPath("/my/jars/foo.jar","/my/classes/") 63 | print(.jclassPath()) 64 | } 65 | } 66 | \keyword{interface} 67 | -------------------------------------------------------------------------------- /man/new.Rd: -------------------------------------------------------------------------------- 1 | \name{new} 2 | \alias{new,jclassName-method} 3 | \title{ 4 | Create a new Java object 5 | } 6 | \description{ 7 | Creates a new Java object and invokes the constructor with given arguments. 8 | } 9 | \section{Methods}{ 10 | \describe{ 11 | \item{\code{new}}{\code{signature(Class = "jclassName")}: ... } 12 | } 13 | } 14 | \details{ 15 | The \code{new} method is used as the high-level API to create new 16 | Java objects (for low-level access see \code{\link{.jnew}}). It 17 | returns the newly created Java object. 18 | 19 | \code{...} arguments are passed to the constructor of the class 20 | specified as \code{J("class.name")}. 21 | } 22 | \seealso{ 23 | \code{\link{.jnew}}, \code{\link{jclassName-class}} 24 | } 25 | \examples{ 26 | \dontrun{ 27 | v <- new(J("java.lang.String"), "Hello World!") 28 | v$length() 29 | v$indexOf("World") 30 | names(v) 31 | } 32 | } 33 | \keyword{interface} 34 | -------------------------------------------------------------------------------- /man/rJava-internal.Rd: -------------------------------------------------------------------------------- 1 | \name{rJava-internal} 2 | \alias{rJava-internal} 3 | \alias{.jaddLibrary} 4 | \alias{.jclass} 5 | \alias{.jclass.boolean} 6 | \alias{.jclass.double} 7 | \alias{.jclass.float} 8 | \alias{.jclass.int} 9 | \alias{.jclass.void} 10 | \alias{.jclassClass} 11 | \alias{.jclassObject} 12 | \alias{.jclassRef} 13 | \alias{.jclassString} 14 | \alias{.jfindClass} 15 | \alias{.jfirst} 16 | \alias{.jidenticalRef} 17 | \alias{.jinherits} 18 | \alias{.jinit.merge.error} 19 | \alias{.jmergeClassPath} 20 | \alias{.jmkref} 21 | \alias{.jniInitialized} 22 | \alias{.joptions} 23 | \alias{.jproperty} 24 | \alias{.jrcall} 25 | \alias{.jrmLibrary} 26 | \alias{.jsetJConvertor} 27 | \alias{.jsetRConvertor} 28 | \alias{.jstrVal} 29 | \alias{.jzeroRef} 30 | \alias{.r2j} 31 | \alias{.rJava.base.path} 32 | \title{ 33 | Internal functions and constants 34 | } 35 | \description{ 36 | The following functions are either internal or are not officially part 37 | of the API and therefore may changes in the future. 38 | } 39 | \usage{ 40 | .jaddLibrary(name, path, class.loader = .rJava.class.loader) 41 | .jclass(o, true = TRUE) 42 | .jclassRef(x, silent = FALSE) 43 | .jfindClass(cl, silent = FALSE, class.loader = .rJava.class.loader) 44 | .jfirst(libname, pkgname) 45 | .jidenticalRef(a, b) 46 | .jinherits(o, cl, class.loader = .rJava.class.loader) 47 | .jmergeClassPath(cp) 48 | .jmkref(jobj, jclass = "java/lang/Object") 49 | .joptions(...) 50 | .jproperty(key) 51 | .jrcall(o, method, ..., simplify = TRUE, class.loader = .rJava.class.loader) 52 | .jrmLibrary(name) 53 | .jsetJConvertor(java.class, fn) 54 | .jsetRConvertor(r.class, fn) 55 | .jstrVal(obj) 56 | .r2j(x, engine = NULL, convert = TRUE) 57 | } 58 | \arguments{ 59 | \item{name}{string, name of the library} 60 | \item{path}{string, path} 61 | \item{class.loader}{class loader object} 62 | \item{o}{Java object} 63 | \item{x}{Java object} 64 | \item{cl}{string, class name (or Java class name object)} 65 | \item{libname}{string, library location} 66 | \item{pkgname}{string, package name} 67 | \item{a}{Java object} 68 | \item{b}{Java object} 69 | \item{cp}{string, class path} 70 | \item{jobj}{Java object} 71 | \item{simplify}{logical} 72 | \item{java.class}{string, class name} 73 | \item{fn}{convertor function} 74 | \item{r.class}{string, R class} 75 | \item{obj}{Java object} 76 | \item{engine}{Java engine object, if \code{NULL} uses the main engine} 77 | \item{convert}{logical} 78 | \item{\dots}{additional parameters} 79 | } 80 | \keyword{internal} 81 | -------------------------------------------------------------------------------- /man/rep.Rd: -------------------------------------------------------------------------------- 1 | \name{rep} 2 | \alias{rep,jarrayRef-method} 3 | \alias{rep,jobjRef-method} 4 | \alias{rep,jrectRef-method} 5 | 6 | \title{Creates java arrays by cloning} 7 | \description{ 8 | Creates a java array by cloning a reference several times 9 | } 10 | \section{Methods}{ 11 | \describe{ 12 | \item{rep}{\code{signature(object = "jobjRef")}: ... } 13 | \item{rep}{\code{signature(object = "jarrayRef")}: ... } 14 | \item{rep}{\code{signature(object = "jrectRef")}: ... } 15 | } 16 | } 17 | 18 | \seealso{ 19 | \code{\link[base]{rep}} or \code{\link{.jarray}} 20 | } 21 | 22 | \examples{ 23 | \dontshow{.jinit()} 24 | if (!nzchar(Sys.getenv("NOAWT"))) { 25 | p <- .jnew( "java.awt.Point" ) 26 | a <- rep( p, 10 ) 27 | 28 | stopifnot( dim(a) == c(10L ) ) 29 | a[[1]]$move( 10L, 50L ) 30 | stopifnot( a[[2]]$getX() == 0.0 ) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /man/show.Rd: -------------------------------------------------------------------------------- 1 | \name{show} 2 | \alias{show,jobjRef-method} 3 | \alias{str,jobjRef-method} 4 | \alias{show,jarrayRef-method} 5 | \alias{show,jclassName-method} 6 | \title{Show a Java Object Reference} 7 | \description{ 8 | Display a Java object reference in a descriptive, textual form. The 9 | default implementation calls \code{toString} Java method to obtain 10 | object's printable value and uses calls \code{show} on the resulting 11 | string garnished with additional details. 12 | } 13 | \section{Methods}{ 14 | \describe{ 15 | \item{show}{\code{signature(object = "jobjRef")}: ... } 16 | \item{show}{\code{signature(object = "jarrayRef")}: ... } 17 | \item{show}{\code{signature(object = "jclassName")}: ... } 18 | \item{str}{\code{signature(object = "jobjRef")}: currently identical to show } 19 | } 20 | } 21 | \keyword{interface} 22 | -------------------------------------------------------------------------------- /man/toJava.Rd: -------------------------------------------------------------------------------- 1 | \name{toJava} 2 | \alias{toJava} 3 | \title{ 4 | Convert R objects to REXP references in Java 5 | } 6 | \description{ 7 | \code{toJava} takes an R object and creates a reference to that object 8 | in Java. This reference can then be passed to Java methods such that 9 | they can refer to it back in R. This is commonly used to pass functions 10 | to Java such that Java code can call those functions later. 11 | } 12 | \usage{ 13 | toJava(x, engine = NULL) 14 | } 15 | \arguments{ 16 | \item{x}{R object to reference. It can be any R object and it will be 17 | retained at least for the duration of the reference on the Java side.} 18 | \item{engine}{REngine in which the reference is to be created. If 19 | null then the last created engine is used. This must be 20 | a Java object and a subclass of org.rosuda.REngine (and NOT the old 21 | org.rosuda.JRI.Rengine!). 22 | } 23 | } 24 | %\details{ 25 | %} 26 | \value{ 27 | There result is a Java reference (\code{jobjRef}) of the Java class 28 | \code{REXPReference}. 29 | } 30 | \examples{ 31 | \dontrun{ 32 | .jinit() 33 | # requires JRI and REngine classes 34 | .jengine(TRUE) 35 | f <- function() { cat("Hello!\n"); 1 } 36 | fref <- toJava(f) 37 | # to use this in Java you would use something like: 38 | # public static REXP call(REXPReference fn) throws REngineException, REXPMismatchException { 39 | # return fn.getEngine().eval(new REXPLanguage(new RList(new REXP[] { fn })), null, false); 40 | # } 41 | # .jcall("Call","Lorg/rosuda/REngine/REXP;","call", fref) 42 | } 43 | } 44 | \keyword{interface} 45 | -------------------------------------------------------------------------------- /man/with.Rd: -------------------------------------------------------------------------------- 1 | \name{with.jobjRef} 2 | \alias{with.jobjRef} 3 | \alias{within.jobjRef} 4 | \alias{with.jarrayRef} 5 | \alias{within.jarrayRef} 6 | \alias{with.jclassName} 7 | \alias{within.jclassName} 8 | \title{ 9 | with and within methods for Java objects and class names 10 | } 11 | \description{ 12 | Convenience wrapper that allow calling methods of 13 | Java object and classes from within the object (or class). 14 | } 15 | \usage{ 16 | \S3method{with}{jobjRef}(data, expr, ...) 17 | \S3method{within}{jobjRef}(data, expr, ...) 18 | 19 | \S3method{with}{jarrayRef}(data, expr, ...) 20 | \S3method{within}{jarrayRef}(data, expr, ...) 21 | 22 | \S3method{with}{jclassName}(data, expr, ...) 23 | \S3method{within}{jclassName}(data, expr, ...) 24 | } 25 | \arguments{ 26 | \item{data}{ 27 | A Java object reference or a java class name. See \code{\link{J}} 28 | } 29 | \item{expr}{ 30 | R expression to evaluate 31 | } 32 | \item{\dots}{ 33 | ignored 34 | } 35 | } 36 | \details{ 37 | The expression is evaluated in an environment 38 | that contains a mapping between the public fields 39 | and methods of the object. 40 | 41 | The methods of the object are mapped to standard R functions 42 | in the environment. In case of classes, only static methods 43 | are used. 44 | 45 | The fields of the object are mapped to active bindings 46 | (see \link{makeActiveBinding}) so that they can be accessed 47 | and modified from within the environment. For classes, only 48 | static fields are used. 49 | } 50 | \value{ 51 | \code{with} returns the value of the expression and 52 | \code{within} returns the \code{data} argument 53 | } 54 | \author{ 55 | Romain Francois 56 | } 57 | \references{ 58 | the \code{java.lang.reflect} package: 59 | \url{https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/package-summary.html} 60 | } 61 | \examples{ 62 | \dontshow{.jinit()} 63 | 64 | if (!nzchar(Sys.getenv("NOAWT"))) { 65 | p <- .jnew( "java/awt/Point", 0L, 0L ) 66 | with( p, { 67 | # x and y and now 0 68 | move( 10L, 10L ) 69 | # x and y are now 10 70 | x <- x + y 71 | } ) 72 | 73 | f <- within( .jnew( "javax/swing/JFrame" ) , { 74 | layout <- .jnew( "java/awt/BorderLayout" ) 75 | setLayout( layout ) 76 | add( .jnew( "javax/swing/JLabel", "north" ), layout$NORTH ) 77 | add( .jnew( "javax/swing/JLabel", "south" ), layout$SOUTH ) 78 | add( .jnew( "javax/swing/JLabel", "west" ), layout$WEST ) 79 | add( .jnew( "javax/swing/JLabel", "east" ), layout$EAST ) 80 | setSize( .jnew( "java/awt/Dimension", 400L, 400L ) ) 81 | setVisible( TRUE ) 82 | } ) 83 | } 84 | 85 | Double <- J("java.lang.Double") 86 | with( Double, MIN_VALUE ) 87 | with( Double, parseDouble( "10.2" ) ) 88 | 89 | \dontrun{ 90 | # inner class example 91 | % TODO: find a better example 92 | HashMap <- J("java.util.HashMap") 93 | with( HashMap, new( SimpleEntry, "key", "value" ) ) 94 | with( HashMap, SimpleEntry ) 95 | } 96 | 97 | with( J("java.lang.System"), getProperty("java.home") ) 98 | 99 | \dontshow{ 100 | stopifnot( with( Double, parseDouble("10.0") ) == 10.0 ) 101 | d <- new( Double, "10.0") 102 | stopifnot( with( d, doubleValue() ) == 10.0 ) 103 | } 104 | 105 | } 106 | \keyword{ classes } 107 | -------------------------------------------------------------------------------- /src/Makevars.in: -------------------------------------------------------------------------------- 1 | # we need to add JNI specific stuff here 2 | PKG_CPPFLAGS=-I. @JAVA_CPPFLAGS@ 3 | @USE_DYNLOAD_FALSE@PKG_LIBS=@JAVA_LIBS@ 4 | JAVA_HOME=@JAVA_HOME@ 5 | # make SHLIB believe that we know better what the objects are 6 | #OBJECTS=Rglue.o callJNI.o initJNI.o rJava.o jri.o jri_glue.o 7 | 8 | all: $(SHLIB) @WANT_JRI_TRUE@ jri 9 | 10 | .PHONY: all 11 | 12 | # this is a hack to force SHLIB to run our sub-make 13 | jri: 14 | (cd ../jri && $(MAKE)) 15 | -@mkdir -p ../inst/jri 16 | @(cp -r ../jri/src/JRI.jar ../jri/*jri.* ../jri/run ../jri/examples ../inst/jri/) 17 | 18 | -------------------------------------------------------------------------------- /src/Makevars.win: -------------------------------------------------------------------------------- 1 | # To compile the Windows version, you need to: 2 | # - set JAVA_HOME to the JDK root (used for includes only) 3 | # in addition if the pre-compiled stuff is not present, then also: 4 | # - generate libjvm.dll.a from JDK's jvm.dll 5 | # (run `make' in `jvm-w32') 6 | # - copy WinRegistry.dll into inst/libs 7 | 8 | # You can modify the following line as the unlima ratio fallback. 9 | # Shouldn't be necessary, because JAVA_HOME and autodetection 10 | # have higher precedence. 11 | DEFAULT_JAVA_HOME=C:\\jdk1.4.2_04 12 | 13 | # this file is generated by configure.win and honors JAVA_HOME env.var 14 | -include Makevars.java 15 | 16 | ifeq ($(JAVA_HOME),) 17 | JAVA_HOME:=$(DEFAULT_JAVA_HOME) 18 | endif 19 | 20 | $(warning JAVA_HOME is $(JAVA_HOME)) 21 | 22 | # normally you don't have to touch this unless you want to add 23 | # debugging flags like -DRJ_DEBUG or -DRJ_PROFILE to PKG_CFLAGS 24 | JAVA_INCLUDES=$(JAVA_HOME)/include $(JAVA_HOME)/include/win32 25 | PKG_CPPFLAGS = -D_R_ -DWin32 -Ijvm-w32 -I$(RHOME)/src/include $(JAVA_INCLUDES:%=-I%) 26 | PKG_LIBS = -Ljvm-w32 -ljvm.dll 27 | 28 | $(warning PKG_CPPFLAGS are $(PKG_CPPFLAGS)) 29 | 30 | -------------------------------------------------------------------------------- /src/callback.c: -------------------------------------------------------------------------------- 1 | #include "rJava.h" 2 | 3 | #ifdef ENABLE_JRICB 4 | 5 | #include 6 | #include 7 | #include "callback.h" 8 | 9 | int RJava_has_control = 0; 10 | 11 | /* ipcin -> receives requests on R thread 12 | ipcout <- write to place requests to main R thread 13 | resout <- written by main thread to respond 14 | resin -> read to get info from main thread */ 15 | 16 | static int ipcin, ipcout, resin, resout; 17 | 18 | static struct rJavaInfoBlock_s { 19 | int ipcin, ipcout, resin, resout; 20 | int *has_control; 21 | } rJavaInfoBlock; 22 | 23 | struct rJavaInfoBlock_s *RJava_get_info_block() { 24 | return &rJavaInfoBlock; 25 | } 26 | 27 | typedef void(callbackfn)(void*); 28 | 29 | static void RJava_ProcessEvents(void *data) { 30 | long buf[4]; 31 | int n = read(ipcin, buf, sizeof(long)); 32 | if (buf[0] == IPCC_LOCK_REQUEST) { 33 | RJava_has_control = 1; 34 | buf[0] = IPCC_LOCK_GRANTED; 35 | write(resout, buf, sizeof(long)); 36 | n = read(ipcin, buf, sizeof(long)); 37 | } 38 | if (buf[0] == IPCC_CLEAR_LOCK) { 39 | RJava_has_control = 0; 40 | } 41 | if (buf[0] == IPCC_CONTROL_ADDR) { 42 | buf[1] = (long) (void*) &RJava_has_control; 43 | write(resout, buf, sizeof(long)*2); 44 | } 45 | if (buf[0] == IPCC_CALL_REQUEST) { 46 | callbackfn *fn; 47 | read(ipcin, buf+1, sizeof(long)*2); 48 | fn = (callbackfn*) buf[1]; 49 | RJava_has_control = 1; 50 | fn((void*) buf[2]); 51 | RJava_has_control = 0; 52 | } 53 | } 54 | 55 | int RJava_init_loop() { 56 | int pfd[2]; 57 | pipe(pfd); 58 | ipcin = pfd[0]; 59 | ipcout = pfd[1]; 60 | pipe(pfd); 61 | resin = pfd[0]; 62 | resout = pfd[1]; 63 | 64 | rJavaInfoBlock.ipcin = ipcin; 65 | rJavaInfoBlock.ipcout = ipcout; 66 | rJavaInfoBlock.resin = resin; 67 | rJavaInfoBlock.resout = resout; 68 | rJavaInfoBlock.has_control = &RJava_has_control; 69 | 70 | addInputHandler(R_InputHandlers, ipcin, RJava_ProcessEvents, RJavaActivity); 71 | return 0; 72 | } 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/callback.h: -------------------------------------------------------------------------------- 1 | #ifndef __CALLBACK_H__ 2 | #define __CALLBACK_H__ 3 | 4 | #ifdef ENABLE_JRICB 5 | extern int RJava_has_control; 6 | #endif 7 | 8 | #define RJavaActivity 16 9 | 10 | /* all IPC messages are long-alligned */ 11 | #define IPCC_LOCK_REQUEST 1 12 | #define IPCC_LOCK_GRANTED 2 /* reponse on IPCC_LOCK_REQUEST */ 13 | #define IPCC_CLEAR_LOCK 3 14 | #define IPCC_CALL_REQUEST 4 /* pars: */ 15 | #define IPCC_CONTROL_ADDR 5 /* ipc: request, res: */ 16 | 17 | #endif 18 | 19 | -------------------------------------------------------------------------------- /src/config.h.in: -------------------------------------------------------------------------------- 1 | /* src/config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* define if callbacks support is enabled. */ 4 | #undef ENABLE_JRICB 5 | 6 | /* Define to 1 if you have the declaration of `siglongjmp', and to 0 if you 7 | don't. */ 8 | #undef HAVE_DECL_SIGLONGJMP 9 | 10 | /* Define to 1 if you have the declaration of `sigsetjmp', and to 0 if you 11 | don't. */ 12 | #undef HAVE_DECL_SIGSETJMP 13 | 14 | /* Define to 1 if you have the header file. */ 15 | #undef HAVE_INTTYPES_H 16 | 17 | /* Define to 1 if you have the header file. */ 18 | #undef HAVE_MEMORY_H 19 | 20 | /* Define if you have POSIX.1 compatible sigsetjmp/siglongjmp. */ 21 | #undef HAVE_POSIX_SETJMP 22 | 23 | /* Define to 1 when static inline works */ 24 | #undef HAVE_STATIC_INLINE 25 | 26 | /* Define to 1 if you have the header file. */ 27 | #undef HAVE_STDINT_H 28 | 29 | /* Define to 1 if you have the header file. */ 30 | #undef HAVE_STDLIB_H 31 | 32 | /* Define to 1 if you have the header file. */ 33 | #undef HAVE_STRINGS_H 34 | 35 | /* Define to 1 if you have the header file. */ 36 | #undef HAVE_STRING_H 37 | 38 | /* Define to 1 if you have the header file. */ 39 | #undef HAVE_SYS_STAT_H 40 | 41 | /* Define to 1 if you have the header file. */ 42 | #undef HAVE_SYS_TIME_H 43 | 44 | /* Define to 1 if you have the header file. */ 45 | #undef HAVE_SYS_TYPES_H 46 | 47 | /* Define to 1 if you have that is POSIX.1 compatible. */ 48 | #undef HAVE_SYS_WAIT_H 49 | 50 | /* Define to 1 if you have the header file. */ 51 | #undef HAVE_UNISTD_H 52 | 53 | /* Set if the Java parameter -Xrs is supported */ 54 | #undef HAVE_XRS 55 | 56 | /* Set if caching JNI environment is enabled. */ 57 | #undef JNI_CACHE 58 | 59 | /* memory profiling is enabled when defined */ 60 | #undef MEMPROF 61 | 62 | /* Define to the address where bug reports for this package should be sent. */ 63 | #undef PACKAGE_BUGREPORT 64 | 65 | /* Define to the full name of this package. */ 66 | #undef PACKAGE_NAME 67 | 68 | /* Define to the full name and version of this package. */ 69 | #undef PACKAGE_STRING 70 | 71 | /* Define to the one symbol short name of this package. */ 72 | #undef PACKAGE_TARNAME 73 | 74 | /* Define to the home page for this package. */ 75 | #undef PACKAGE_URL 76 | 77 | /* Define to the version of this package. */ 78 | #undef PACKAGE_VERSION 79 | 80 | /* Define to 1 if you have the ANSI C header files. */ 81 | #undef STDC_HEADERS 82 | 83 | /* Set if threading support should be enabled. */ 84 | #undef THREADS 85 | 86 | /* Define to 1 if you can safely include both and . */ 87 | #undef TIME_WITH_SYS_TIME 88 | 89 | /* Set if headless mode is to be used when starting the JVM */ 90 | #undef USE_HEADLESS_INIT 91 | 92 | /* Define to empty if `const' does not conform to ANSI C. */ 93 | #undef const 94 | -------------------------------------------------------------------------------- /src/install.libs.R: -------------------------------------------------------------------------------- 1 | ## the first part just replicates the default installation of libs 2 | libarch <- if (nzchar(R_ARCH)) paste("libs", R_ARCH, sep='') else "libs" 3 | dest <- file.path(R_PACKAGE_DIR, libarch) 4 | files <- Sys.glob(paste("*", SHLIB_EXT, sep='')) 5 | if (length(files)) { 6 | dir.create(dest, recursive = TRUE, showWarnings = FALSE) 7 | file.copy(files, dest, overwrite = TRUE) 8 | if (nzchar(Sys.getenv("PKG_MAKE_DSYM")) && length(grep("^darwin", R.version$os))) { 9 | message('generating debug symbols (dSYM)') 10 | dylib <- Sys.glob(paste(dest, "/*", SHLIB_EXT, sep='')) 11 | if (length(dylib)) for (file in dylib) system(paste("dsymutil ", file, sep='')) 12 | } 13 | } 14 | 15 | # just a wrapper to system() that shows what we are doing ... 16 | sys <- function(x, ...) { 17 | message(x) 18 | s <- system(x, ...) 19 | # if (!isTRUE(s == 0L)) message("-> FAILED") 20 | s 21 | } 22 | 23 | ## the next part is about JRI 24 | ## on OS X we need to merge architectures into one fat file 25 | if (length(grep("^darwin", R.version$os))) { 26 | is.fat <- function(fn) { a <- 0L; try({f <- file(fn, "rb"); a <- readBin(f, 1L, 1L); close(f)}, silent=TRUE); isTRUE(a[1] == -1095041334L || a[1] == -889275714L) } ## fat magic is 0xCAFEBABE - either endianness 27 | jni <- "../jri/libjri.jnilib" 28 | if (isTRUE(file.exists(jni))) { ## continue only if JRI was actually compiled 29 | dir.create(file.path(R_PACKAGE_DIR, "jri"), recursive = TRUE, showWarnings = FALSE) 30 | dest <- file.path(R_PACKAGE_DIR, "jri", "libjri.jnilib") 31 | if (is.fat(jni) || !file.exists(dest)) { 32 | ## if the new file is fat we assume it has all archs so we copy; if there is no dest, copy as well 33 | file.copy(jni, dest, overwrite = TRUE) 34 | } else { ## new file is single arch, so merge 35 | ## we try lipo -create first and fall back to -replace if it doesn't work (becasue the arch exists already) 36 | if (sys(paste("/usr/bin/lipo -create", shQuote(dest), jni, "-o", shQuote(dest), ">/dev/null 2>&1")) != 0) { 37 | if (is.fat(dest)) { # if the file is fat, replace, otherwise it means we have the same arch so copy 38 | arch <- gsub("/", "", R_ARCH, fixed=TRUE) 39 | sys(paste("/usr/bin/lipo -replace", arch, jni, shQuote(dest), "-o", shQuote(dest), ">/dev/null 2>&1")) 40 | } else file.copy(jni, dest, overwrite = TRUE) 41 | } 42 | } 43 | } 44 | } else { ## on other platforms we simply install in jri$(R_ARCH) 45 | jri <- if (WINDOWS) "jri.dll" else "libjri.so" 46 | jni <- file.path("..", "jri", jri) 47 | if (isTRUE(file.exists(jni))) { ## continue only if JRI was actually compiled 48 | libarch <- if (nzchar(R_ARCH)) paste("jri", R_ARCH, sep='') else "jri" 49 | dir.create(file.path(R_PACKAGE_DIR, libarch), recursive = TRUE, showWarnings = FALSE) 50 | dest <- file.path(R_PACKAGE_DIR, libarch, jri) 51 | file.copy(jni, dest, overwrite = TRUE) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/java/ArrayDimensionException.java: -------------------------------------------------------------------------------- 1 | public class ArrayDimensionException extends Exception{ 2 | public ArrayDimensionException(String message){ 3 | super( message ) ; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/java/DummyPoint.java: -------------------------------------------------------------------------------- 1 | 2 | public class DummyPoint implements Cloneable { 3 | public int x; 4 | public int y ; 5 | public DummyPoint(){ 6 | this( 0, 0 ) ; 7 | } 8 | public DummyPoint( int x, int y){ 9 | this.x = x ; 10 | this.y = y ; 11 | } 12 | public double getX(){ 13 | return (double)x ; 14 | } 15 | public void move(int x, int y){ 16 | this.x += x ; 17 | this.y += y ; 18 | } 19 | public Object clone() { 20 | return new DummyPoint(x, y); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/java/FlatException.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Generated when one attemps to flatten an array that is not rectangular 4 | */ 5 | public class FlatException extends Exception{ 6 | public FlatException(){ 7 | super( "Can only flatten rectangular arrays" ); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/java/Makefile: -------------------------------------------------------------------------------- 1 | JAVA_SRC=$(wildcard *.java) 2 | JFLAGS=-source 1.6 -target 1.6 3 | JAVAC=javac 4 | JAVA=java 5 | JAVADOC=javadoc 6 | JAVADOCFLAGS=-author -version -breakiterator -link http://java.sun.com/j2se/1.4.2/docs/api 7 | 8 | all: compile test 9 | 10 | compile: $(JAVA_SRC) 11 | $(JAVAC) $(JFLAGS) $(JAVA_SRC) 12 | 13 | test_RJavaTools: compile 14 | $(JAVA) RJavaTools_Test 15 | 16 | test_RJavaArrayTools: compile 17 | $(JAVA) RJavaArrayTools_Test 18 | 19 | test_ArrayWrapper: 20 | $(JAVA) ArrayWrapper_Test 21 | 22 | test_RectangularArrayBuilder: 23 | $(JAVA) RectangularArrayBuilder_Test 24 | 25 | test: compile test_RJavaTools test_RJavaArrayTools test_ArrayWrapper test_RectangularArrayBuilder 26 | 27 | javadoc: 28 | $(JAVADOC) $(JAVADOCFLAGS) -d javadoc $(JAVA_SRC) 29 | 30 | clean: 31 | rm -rfv *.class *~ 32 | 33 | .PHONY: all clean 34 | 35 | -------------------------------------------------------------------------------- /src/java/NotAnArrayException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Exception indicating that an object is not a java array 3 | */ 4 | public class NotAnArrayException extends Exception{ 5 | public NotAnArrayException(Class clazz){ 6 | super( "not an array : " + clazz.getName() ) ; 7 | } 8 | public NotAnArrayException(String message){ 9 | super( message ) ; 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /src/java/NotComparableException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Exception generated when two objects cannot be compared 3 | * 4 | * Such cases happen when an object does not implement the Comparable 5 | * interface or when the comparison produces a ClassCastException 6 | */ 7 | public class NotComparableException extends Exception{ 8 | public NotComparableException(Object a, Object b){ 9 | super( "objects of class " + a.getClass().getName() + 10 | " and " + b.getClass().getName() + " are not comparable" ) ; 11 | } 12 | public NotComparableException( Object o){ 13 | this( o.getClass().getName() ) ; 14 | } 15 | 16 | public NotComparableException( Class cl){ 17 | this( cl.getName() ) ; 18 | } 19 | 20 | public NotComparableException( String type ){ 21 | super( "class " + type + " does not implement java.util.Comparable" ) ; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/java/ObjectArrayException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Generated when one tries to access an array of primitive 3 | * values as an array of Objects 4 | */ 5 | public class ObjectArrayException extends Exception{ 6 | public ObjectArrayException(String type){ 7 | super( "array is of primitive type : " + type ) ; 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/java/PrimitiveArrayException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Generated when one tries to convert an arrays into 3 | * a primitive array of the wrong type 4 | */ 5 | public class PrimitiveArrayException extends Exception{ 6 | public PrimitiveArrayException(String type){ 7 | super( "cannot convert to single dimension array of primitive type" + type ) ; 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/java/RJavaArrayIterator.java: -------------------------------------------------------------------------------- 1 | import java.lang.reflect.Array ; 2 | 3 | public abstract class RJavaArrayIterator { 4 | 5 | protected int[] dimensions; 6 | protected int nd ; 7 | protected int[] index ; 8 | protected int[] dimprod ; 9 | protected Object array ; 10 | protected int increment; 11 | protected int position ; 12 | protected int start ; 13 | 14 | public Object getArray(){ 15 | return array ; 16 | } 17 | 18 | /** 19 | * @return the class name of the array 20 | */ 21 | public String getArrayClassName(){ 22 | return array.getClass().getName(); 23 | } 24 | 25 | public int[] getDimensions(){ 26 | return dimensions; 27 | } 28 | 29 | public RJavaArrayIterator(){ 30 | dimensions = null; 31 | index = null ; 32 | dimprod = null ; 33 | array = null ; 34 | } 35 | 36 | public RJavaArrayIterator(int[] dimensions){ 37 | this.dimensions = dimensions ; 38 | nd = dimensions.length ; 39 | if( nd > 1){ 40 | index = new int[ nd-1 ] ; 41 | dimprod = new int[ nd-1 ] ; 42 | for( int i=0; i<(nd-1); i++){ 43 | index[i] = 0 ; 44 | dimprod[i] = (i==0) ? dimensions[i] : ( dimensions[i]*dimprod[i-1] ); 45 | increment = dimprod[i] ; 46 | } 47 | } 48 | position = 0 ; 49 | start = 0; 50 | } 51 | public RJavaArrayIterator(int d1){ 52 | this( new int[]{ d1} ) ; 53 | } 54 | 55 | protected Object next( ){ 56 | 57 | /* get the next array and the position of the first elemtn in the flat array */ 58 | Object o = array ; 59 | for( int i=0; i=0; i--){ 70 | if( (index[i] + 1) == dimensions[i] ){ 71 | index[i] = 0 ; 72 | } else{ 73 | index[i] = index[i] + 1 ; 74 | break; 75 | } 76 | } 77 | 78 | position++ ; 79 | return o; 80 | } 81 | 82 | protected boolean hasNext( ){ 83 | return position < increment ; 84 | } 85 | 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/java/RJavaComparator.java: -------------------------------------------------------------------------------- 1 | import java.lang.Comparable ; 2 | 3 | /** 4 | * Utility class to compare two objects in the sense 5 | * of the java.lang.Comparable interface 6 | * 7 | */ 8 | public class RJavaComparator { 9 | 10 | /** 11 | * compares a and b in the sense of the java.lang.Comparable if possible 12 | * 13 | *

instances of the Number interface are treated specially, in order to 14 | * allow comparing Numbers of different classes, for example it is allowed 15 | * to compare a Double with an Integer. if the Numbers have the same class, 16 | * they are compared normally, otherwise they are first converted to Doubles 17 | * and then compared

18 | * 19 | * @param a an object 20 | * @param b another object 21 | * 22 | * @return the result of a.compareTo(b) if this makes sense 23 | * @throws NotComparableException if the two objects are not comparable 24 | */ 25 | public static int compare( Object a, Object b ) throws NotComparableException{ 26 | int res ; 27 | if( a.equals( b ) ) return 0 ; 28 | 29 | // treat Number s separately 30 | if( a instanceof Number && b instanceof Number && !( a.getClass() == b.getClass() ) ){ 31 | Double _a = Double.valueOf( ((Number)a).doubleValue() ); 32 | Double _b = Double.valueOf( ((Number)b).doubleValue() ); 33 | return _a.compareTo( _b ); 34 | } 35 | 36 | if( ! ( a instanceof Comparable ) ) throw new NotComparableException( a ); 37 | if( ! ( b instanceof Comparable ) ) throw new NotComparableException( b ); 38 | 39 | try{ 40 | res = ( (Comparable)a ).compareTo( b ) ; 41 | } catch( ClassCastException e){ 42 | try{ 43 | res = - ((Comparable)b).compareTo( a ) ; 44 | } catch( ClassCastException f){ 45 | throw new NotComparableException( a, b ); 46 | } 47 | } 48 | return res ; 49 | } 50 | 51 | } 52 | 53 | -------------------------------------------------------------------------------- /src/java/TestException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Generated as part of testing rjava internal java tools 3 | */ 4 | public class TestException extends Exception{ 5 | public TestException(String message){super(message);} 6 | } 7 | 8 | -------------------------------------------------------------------------------- /src/jri_glue.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "rJava.h" 4 | 5 | /* creates a reference to an R object on the Java side 6 | 1) lock down the object in R 7 | 2) call new Rengine(eng,robj) {or any other class such as REXPReference for REngine API} 8 | */ 9 | REPC SEXP PushToREXP(SEXP clname, SEXP eng, SEXP engCl, SEXP robj, SEXP doConv) { 10 | char sig[128]; 11 | jvalue jpar[4]; 12 | jobject o; 13 | int convert = (doConv == R_NilValue) ? -1 : asInteger(doConv); 14 | JNIEnv *env=getJNIEnv(); 15 | const char *cName; 16 | 17 | if (!isString(clname) || LENGTH(clname)!=1) error("invalid class name"); 18 | if (!isString(engCl) || LENGTH(engCl)!=1) error("invalid engine class name"); 19 | if (TYPEOF(eng)!=EXTPTRSXP) error("invalid engine object"); 20 | R_PreserveObject(robj); 21 | sig[127]=0; 22 | cName = CHAR(STRING_ELT(clname,0)); 23 | jpar[0].l = (jobject)EXTPTR_PTR(eng); 24 | jpar[1].j = (jlong) (size_t) robj; 25 | if (convert == -1) 26 | snprintf(sig,127,"(L%s;J)V",CHAR(STRING_ELT(engCl,0))); 27 | else { 28 | snprintf(sig,127,"(L%s;JZ)V",CHAR(STRING_ELT(engCl,0))); 29 | jpar[2].z = (jboolean) convert; 30 | } 31 | o = createObject(env, cName, sig, jpar, 1, 0); 32 | if (!o) error("Unable to create Java object"); 33 | return j2SEXP(env, o, 1); 34 | /* ok, some thoughts on mem mgmt - j2SEXP registers a finalizer. But I believe that is ok, because the pushed reference is useless until it is passed as an argument to some Java method. And then, it will have another reference which will prevent the Java side from being collected. The R-side reference may be gone, but that's ok, because it's the Java finalizer that needs to clean up the pushed R object and for that it doesn't need the proxy object at all. This is the reason why RReleaseREXP uses EXTPTR - all the Java finalizer has to do is to call RReleaseREXP(self). For that it can create a fresh proxy object containing the REXP. But here comes he crux - this proxy cannot again create a reference - it must be plain pass-through, so this part needs to be verified. 35 | 36 | Note: as of REngine API the references assume protected objects and use rniRelease to clean up, so RReleaseREXP won't be called and is not needed. That is good, because RReleaseREXP assumes JRI objects whereas REngine will create REXPReference (no xp there). However, if we ever change that REXPReference assumption we will be in trouble. 37 | */ 38 | } 39 | 40 | /* this is pretty much hard-coded for now - it's picking "xp" attribute */ 41 | REPC SEXP RReleaseREXP(SEXP ptr) { 42 | jobject o; 43 | if (TYPEOF(ptr)==EXTPTRSXP) error("invalid object"); 44 | o = (jobject)EXTPTR_PTR(ptr); 45 | { 46 | JNIEnv *env = getJNIEnv(); 47 | jclass cls = (*env)->GetObjectClass(env, o); 48 | if (cls) { 49 | jfieldID fid=(*env)->GetFieldID(env,cls,"xp","J"); 50 | if (fid) { 51 | jlong r = (*env)->GetLongField(env, o, fid); 52 | SEXP x = (SEXP) r; 53 | if (x) R_ReleaseObject(x); 54 | } 55 | } 56 | } 57 | return R_NilValue; 58 | } 59 | -------------------------------------------------------------------------------- /src/jvm-w32/Makefile: -------------------------------------------------------------------------------- 1 | # helper tools and libs for building and running rJava for Windows 2 | # Author: Simon Urbanek 3 | # with contributions from Brian Ripley 4 | 5 | include $(R_HOME)/etc$(R_ARCH)/Makeconf 6 | 7 | TARGETS=libjvm.dll.a findjava.exe 8 | 9 | # libjvm.dll.a - wrapper lib for jvm.dll from Java 10 | # findjava.exe - helper tool to find the current JDK from the registry 11 | 12 | all: $(TARGETS) 13 | 14 | # detect 64-bit Windows 15 | ifeq ($(strip $(shell $(R_HOME)/bin/R --slave -e 'cat(.Machine$$sizeof.pointer)')),8) 16 | JVM64DEF=64 17 | endif 18 | 19 | libjvm.dll.a: jvm$(JVM64DEF).def 20 | $(DLLTOOL) --input-def $^ --kill-at --dllname jvm.dll --output-lib $@ 21 | 22 | # compile findjava.exe from source - no magic here, no special libs necessary 23 | findjava.o: findjava.c 24 | $(CC) -O2 -c -o $@ $^ 25 | 26 | findjava.exe: findjava.o 27 | $(CC) -s -o $@ $^ 28 | 29 | # just cleanup everything 30 | clean: 31 | rm -f *.o *~ $(TARGETS) 32 | 33 | .PHONY: all clean 34 | -------------------------------------------------------------------------------- /src/jvm-w32/WinRegistry.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef WIN32 4 | #include 5 | #include 6 | 7 | char RegStrBuf[32768]; 8 | 9 | SEXP RegGetStrValue(SEXP par) { 10 | SEXP res=R_NilValue; 11 | DWORD t,s=32767; 12 | HKEY k; 13 | char *key=CHAR(STRING_ELT(par, 0)); 14 | char *val=CHAR(STRING_ELT(par, 1)); 15 | 16 | RegStrBuf[32767]=*RegStrBuf=0; 17 | /* printf("RegGetStrValue(\"%s\",\"%s\")\n",key,val); */ 18 | 19 | if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,key,0,KEY_QUERY_VALUE,&k)!=ERROR_SUCCESS || 20 | RegQueryValueEx(k,val,0,&t,RegStrBuf,&s)!=ERROR_SUCCESS) 21 | return res; 22 | 23 | PROTECT(res = allocVector(STRSXP, 1)); 24 | SET_STRING_ELT(res, 0, mkChar(RegStrBuf)); 25 | UNPROTECT(1); 26 | 27 | return res; 28 | }; 29 | 30 | #else 31 | /* all functions return NULL since they are not supported on non-Win32 platforms */ 32 | SEXP RegGetStrValue(SEXP par) { return R_NilValue; }; 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/jvm-w32/config.h: -------------------------------------------------------------------------------- 1 | /* fall-back setting on Widnows */ 2 | 3 | /* assume Sun/Oracle JVM which supports -Xrs */ 4 | #define HAVE_XRS 1 5 | -------------------------------------------------------------------------------- /src/jvm-w32/findjava.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static char RegStrBuf[32768], dbuf[32768]; 6 | 7 | int main(int argc, char **argv) { 8 | int i=0, doit=0; 9 | DWORD t,s=32767; 10 | HKEY k; 11 | HKEY root=HKEY_LOCAL_MACHINE; 12 | char *javakey="Software\\JavaSoft\\Java Runtime Environment"; 13 | 14 | if (argc>1 && argv[1][0]=='-' && argv[1][1]=='R') { 15 | if (getenv("R_HOME")) { 16 | strcpy(RegStrBuf,getenv("R_HOME")); 17 | } else { 18 | javakey="Software\\R-core\\R"; s=32767; 19 | if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,javakey,0,KEY_QUERY_VALUE,&k)!=ERROR_SUCCESS || 20 | RegQueryValueEx(k,"InstallPath",0,&t,RegStrBuf,&s)!=ERROR_SUCCESS) { 21 | if (RegOpenKeyEx(HKEY_CURRENT_USER,javakey,0,KEY_QUERY_VALUE,&k)!=ERROR_SUCCESS || 22 | RegQueryValueEx(k,"InstallPath",0,&t,RegStrBuf,&s)!=ERROR_SUCCESS) { 23 | fprintf(stderr, "ERROR*> R - can't open registry keys.\n"); 24 | return -1; 25 | } 26 | } 27 | } 28 | } else 29 | /* JAVA_HOME can override our detection - but we still post-process it */ 30 | if (getenv("JAVA_HOME")) { 31 | strcpy(RegStrBuf,getenv("JAVA_HOME")); 32 | } else { 33 | 34 | #ifdef FINDJRE 35 | if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,javakey,0,KEY_QUERY_VALUE,&k)!=ERROR_SUCCESS || 36 | RegQueryValueEx(k,"CurrentVersion",0,&t,RegStrBuf,&s)!=ERROR_SUCCESS) { 37 | javakey="Software\\JavaSoft\\JRE"; s=32767; 38 | if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,javakey,0,KEY_QUERY_VALUE,&k)!=ERROR_SUCCESS || 39 | RegQueryValueEx(k,"CurrentVersion",0,&t,RegStrBuf,&s)!=ERROR_SUCCESS) { 40 | #endif 41 | javakey="Software\\JavaSoft\\Java Development Kit"; s=32767; 42 | if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,javakey,0,KEY_QUERY_VALUE,&k)!=ERROR_SUCCESS || 43 | RegQueryValueEx(k,"CurrentVersion",0,&t,RegStrBuf,&s)!=ERROR_SUCCESS) { 44 | javakey="Software\\JavaSoft\\JDK"; s=32767; 45 | if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,javakey,0,KEY_QUERY_VALUE,&k)!=ERROR_SUCCESS || 46 | RegQueryValueEx(k,"CurrentVersion",0,&t,RegStrBuf,&s)!=ERROR_SUCCESS) { 47 | fprintf(stderr, "ERROR*> JavaSoft\\{JRE|JDK} can't open registry keys.\n"); 48 | /* MessageBox(wh, "Can't find Sun's Java runtime.\nPlease install Sun's J2SE JRE or JDK 1.4.2 or later (see http://java.sun.com/).","Can't find Sun's Java",MB_OK|MB_ICONERROR); */ 49 | return -1; 50 | } 51 | } 52 | #ifdef FINDJRE 53 | } 54 | } 55 | #endif 56 | RegCloseKey(k); s=32767; 57 | 58 | strcpy(dbuf,javakey); 59 | strcat(dbuf,"\\"); 60 | strcat(dbuf,RegStrBuf); 61 | javakey=(char*) malloc(strlen(dbuf)+1); 62 | strcpy(javakey, dbuf); 63 | 64 | if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,javakey,0,KEY_QUERY_VALUE,&k)!=ERROR_SUCCESS || 65 | RegQueryValueEx(k,"JavaHome",0,&t,RegStrBuf,&s)!=ERROR_SUCCESS) { 66 | fprintf(stderr, "There's no JavaHome value in the JDK/JRE registry key.\n"); 67 | /* MessageBox(wh, "Can't find Java home path. Maybe your JRE is too old.\nPlease install Sun's J2SE JRE or SDK 1.4.2 (see http://java.sun.com/).","Can't find Sun's Java",MB_OK|MB_ICONERROR); */ 68 | return -1; 69 | } 70 | RegCloseKey(k); 71 | } 72 | 73 | /*--- post-processing according to supplied flags --*/ 74 | 75 | /* -a = automagic, i.e. use short name only if the name contains spaces */ 76 | i=1; 77 | while (iNewGlobalRef(env, (*env)->GetObjectClass(env, cl)); 14 | /* oClassLoader = (*env)->NewGlobalRef(env, cl); */ 15 | oClassLoader = cl; 16 | #ifdef DEBUG_CL 17 | printf("initClassLoader: cl=%x, clCl=%x, jcl=%x\n", oClassLoader, clClassLoader, javaClassClass); 18 | #endif 19 | return 0; 20 | } 21 | 22 | REPC SEXP RJava_set_class_loader(SEXP ldr) { 23 | JNIEnv *env=getJNIEnv(); 24 | if (TYPEOF(ldr) != EXTPTRSXP) 25 | error("invalid type"); 26 | if (!env) 27 | error("VM not initialized"); 28 | 29 | jverify(ldr); 30 | initClassLoader(env, (jobject)EXTPTR_PTR(ldr)); 31 | return R_NilValue; 32 | } 33 | 34 | REPC SEXP RJava_primary_class_loader(void) { 35 | JNIEnv *env=getJNIEnv(); 36 | jclass cl = (*env)->FindClass(env, "RJavaClassLoader"); 37 | _dbg(Rprintf("RJava_primary_class_loader, cl = %x\n", (int) cl)); 38 | if (cl) { 39 | jmethodID mid = (*env)->GetStaticMethodID(env, cl, "getPrimaryLoader", "()LRJavaClassLoader;"); 40 | _dbg(Rprintf(" - mid = %d\n", (int) mid)); 41 | if (mid) { 42 | jobject o = (*env)->CallStaticObjectMethod(env, cl, mid); 43 | _dbg(Rprintf(" - call result = %x\n", (int) o)); 44 | if (o) { 45 | return j2SEXP(env, o, 1); 46 | } 47 | } 48 | } 49 | checkExceptionsX(env, 1); 50 | 51 | #ifdef NEW123 52 | jclass cl = (*env)->FindClass(env, "JRIBootstrap"); 53 | Rprintf("RJava_primary_class_loader, cl = %x\n", (int) cl); 54 | if (cl) { 55 | jmethodID mid = (*env)->GetStaticMethodID(env, cl, "getBootRJavaLoader", "()Ljava/lang/Object;"); 56 | Rprintf(" - mid = %d\n", (int) mid); 57 | if (mid) { 58 | jobject o = (*env)->CallStaticObjectMethod(env, cl, mid); 59 | Rprintf(" - call result = %x\n", (int) o); 60 | if (o) { 61 | return j2SEXP(env, o, 1); 62 | } 63 | } 64 | } 65 | checkExceptionsX(env, 1); 66 | #endif 67 | return R_NilValue; 68 | } 69 | 70 | REPC SEXP RJava_new_class_loader(SEXP p1, SEXP p2) { 71 | JNIEnv *env=getJNIEnv(); 72 | 73 | const char *c1 = CHAR(STRING_ELT(p1, 0)); 74 | const char *c2 = CHAR(STRING_ELT(p2, 0)); 75 | jstring s1 = newString(env, c1); 76 | jstring s2 = newString(env, c2); 77 | 78 | jclass cl = (*env)->FindClass(env, "RJavaClassLoader"); 79 | _dbg(Rprintf("find rJavaClassLoader: %x\n", (int) cl)); 80 | jmethodID mid = (*env)->GetMethodID(env, cl, "", "(Ljava/lang/String;Ljava/lang/String;)V"); 81 | _dbg(Rprintf("constructor mid: %x\n", mid)); 82 | jobject o = (*env)->NewObject(env, cl, mid, s1, s2); 83 | _dbg(Rprintf("new object: %x\n", o)); 84 | o = makeGlobal(env, o); 85 | _dbg(Rprintf("calling initClassLoader\n")); 86 | initClassLoader(env, o); 87 | releaseObject(env, s1); 88 | releaseObject(env, s2); 89 | releaseObject(env, cl); 90 | return R_NilValue; 91 | } 92 | -------------------------------------------------------------------------------- /src/registration.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* only to avoid NOTEs from broken checks, 5 | never called */ 6 | int dummy__(void) { 7 | return R_registerRoutines(0, 0, 0, 0, 0); 8 | } 9 | 10 | static DllInfo *dll; 11 | 12 | /* registration is done in R code, so it has 13 | to have a way to disable dynamic symbols when done */ 14 | SEXP useDynamicSymbols(SEXP sDo) { 15 | if (dll) { 16 | R_useDynamicSymbols(dll, asInteger(sDo)); 17 | return ScalarLogical(1); 18 | } 19 | return ScalarLogical(0); 20 | } 21 | 22 | /* record our dll so we can call useDynamicSymbols() later */ 23 | void R_init_rJava(DllInfo *dll_) { 24 | dll = dll_; 25 | } 26 | -------------------------------------------------------------------------------- /src/rjstring.h: -------------------------------------------------------------------------------- 1 | #ifndef RJ_STRING_H__ 2 | #define RJ_STRING_H__ 3 | 4 | #include /* for jchar */ 5 | #include /* for SEXP */ 6 | 7 | /* --- API --- */ 8 | 9 | /* Returns static content for short strings so don't re-use. 10 | For dynamic strings uses R_alloc */ 11 | int rj_char_utf16(const char *c, int len, jchar **buf, const char *ifrom, int can_error); 12 | 13 | /* wrappers for above to use with CHARSXP to detect proper ifrom */ 14 | int rj_rchar_utf16(SEXP s, jchar **buf); 15 | int rj_rchar_utf16_noerr(SEXP s, jchar **buf); 16 | 17 | /* return jstring, but do NOT check exceptions */ 18 | jstring rj_newJavaString(JNIEnv *env, SEXP sChar); 19 | jstring rj_newNativeJavaString(JNIEnv *env, const char *str, int len); 20 | 21 | /* takes modified UTF-8 from Java, creates CHARSXP with valid UTF8 */ 22 | SEXP rj_mkCharUTF8(const char *src); 23 | SEXP rj_mkCharUTF8_noerr(const char *src); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /tests/README: -------------------------------------------------------------------------------- 1 | This directory contains off-line tests, i.e. they are not included 2 | in the package, but can be used to test the rJava functionality. 3 | At some point we will create a proper test suite that is included 4 | in the package, but we're not there yet ... 5 | 6 | Run via make (default is retest which does clean-tests + test) 7 | -------------------------------------------------------------------------------- /tests/old/Leaks.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-u/rJava/ef046ea7698ff0ae9a701fe48eceb4ee54befc3f/tests/old/Leaks.class -------------------------------------------------------------------------------- /tests/old/Leaks.java: -------------------------------------------------------------------------------- 1 | public class Leaks { 2 | public int[] i; 3 | public String[] s; 4 | 5 | public Leaks(int[] i, String[] s) { 6 | this.i = i; 7 | this.s = s; 8 | } 9 | 10 | public String[] getS() { return s; } 11 | public int[] getI() { return i; } 12 | 13 | public String[] replaceS(String[] s) { 14 | String[] a = this.s; 15 | this.s = s; 16 | return a; 17 | } 18 | 19 | public int[] replaceI(int[] i) { 20 | int[] a = this.i; 21 | this.i = i; 22 | return a; 23 | } 24 | 25 | public static String[] passS(String[] s) { return s; } 26 | public static Object[] passSO(String[] s) { return (Object[])s; } 27 | public static int[] passI(int[] i) { return i; } 28 | 29 | 30 | public static void runGC() { 31 | Runtime r = Runtime.getRuntime(); 32 | r.runFinalization(); 33 | r.gc(); 34 | } 35 | 36 | public static String reportMem() { 37 | Runtime r = Runtime.getRuntime(); 38 | r.gc(); 39 | return "used: "+((r.totalMemory()-r.freeMemory())/1024L)+"kB (free: "+r.freeMemory()+" of "+r.totalMemory()+")"; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/old/Makefile: -------------------------------------------------------------------------------- 1 | RBIN=R 2 | RARGS=--vanilla --slave 3 | JAVAC=javac 4 | JFLAGS=-source 1.2 -target 1.2 5 | 6 | TESTS=types.R leaks.R 7 | SOURCES=Types.java Leaks.java 8 | 9 | TEST_RES=$(TESTS:%.R=%.test) 10 | CLASSES=$(SOURCES:%.java=%.class) 11 | 12 | retest: clean-tests test 13 | 14 | test: $(CLASSES) $(TEST_RES) 15 | 16 | .R.test: 17 | $(RBIN) $(RARGS) < $^ > $@ 18 | 19 | .java.class: 20 | $(JAVAC) $(JFLAGS) $^ 21 | 22 | clean: clean-tests 23 | rm -f *~ $(CLASSES) 24 | 25 | clean-tests: 26 | rm -f $(TEST_RES) 27 | 28 | .PHONY: clean test clean-tests retest 29 | 30 | .SUFFIXES: .R .test .java .class 31 | -------------------------------------------------------------------------------- /tests/old/Types.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-u/rJava/ef046ea7698ff0ae9a701fe48eceb4ee54befc3f/tests/old/Types.class -------------------------------------------------------------------------------- /tests/old/Types.java: -------------------------------------------------------------------------------- 1 | public class Types { 2 | public static int sri() { return si; } 3 | public int ri() { return i; } 4 | public static byte srb() { return sb; } 5 | public byte rb() { return b; } 6 | public static boolean srz() { return sz; } 7 | public boolean rz() { return z; } 8 | public static char src() { return sc; } 9 | public char rc() { return c; } 10 | public static short srs() { return ss; } 11 | public short rs() { return s; } 12 | public static long srj() { return sj; } 13 | public long rj() { return j; } 14 | public static float srf() { return sf; } 15 | public float rf() { return f; } 16 | public static double srd() { return sd; } 17 | public double rd() { return d; } 18 | public static String srS() { return sS; } 19 | public String rS() { return S; } 20 | 21 | public void zbcsijfdS(boolean _z, byte _b, char _c, 22 | short _s, int _i, long _j, 23 | float _f, double _d, String _S) { 24 | z = _z; b = _b; c = _c; 25 | s = _s; i = _i; j = _j; 26 | f = _f; d = _d; S = _S; 27 | } 28 | public static void szbcsijfdS(boolean z, byte b, char c, 29 | short s, int i, long j, 30 | float f, double d, String S) { 31 | sz = z; sb = b; sc = c; 32 | ss = s; si = i; sj = j; 33 | sf = f; sd = d; sS = S; 34 | } 35 | 36 | public boolean z = true; 37 | public byte b = 123; 38 | public char c = 'c'; 39 | public short s = 1234; 40 | public int i = 1234; 41 | public long j = 1234567890; 42 | public double d = 1234.567; 43 | public float f = 1234.567f; 44 | public String S = "ok"; 45 | public static boolean sz = true; 46 | public static byte sb = 123; 47 | public static char sc = 'c'; 48 | public static short ss = 1234; 49 | public static int si = 1234; 50 | public static long sj = 1234567890; 51 | public static double sd = 1234.567; 52 | public static float sf = 1234.567f; 53 | public static String sS = "ok"; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /tests/old/leaks.R: -------------------------------------------------------------------------------- 1 | library(rJava) 2 | # restrict memory so we run out of it earlier 3 | .jinit(".","-Xmx128m") 4 | gc() 5 | .s <- as.character(1:10000) 6 | .i <- 1:10000 7 | ..s <- .s 8 | ..i <- .i 9 | cat("=== Initial state:\n", .jcall("Leaks","S","reportMem"), "\n") 10 | cat(" - create unassigned objects\n") 11 | for (i in 1:100) .jnew("Leaks", .i, .s) 12 | cat(.jcall("Leaks","S","reportMem"),"\n") 13 | cat(" running R gc\n") 14 | gc() 15 | cat(" running java GC\n") 16 | cat(.jcall("Leaks","S","reportMem"),"\n") 17 | cat(" - static pass thorugh parameters\n") 18 | for (i in 1:800) { 19 | if (i %% 160 == 0) { cat(' (forcing R gc)\n'); gc() } 20 | .i <- .jcall("Leaks", "[I", "passI", .i) 21 | .s <- .jcall("Leaks", "[S", "passS", .s) 22 | } 23 | cat(.jcall("Leaks","S","reportMem"),"\n") 24 | cat(" running R gc\n") 25 | gc() 26 | cat(" running java GC\n") 27 | .jcall("Leaks","V","runGC") 28 | cat(.jcall("Leaks","S","reportMem"),"\n") 29 | if (!isTRUE(all.equal(.s, ..s))) 30 | stop("FAILED - string array was modified") 31 | if (!isTRUE(all.equal(.i, ..i))) 32 | stop("FAILED - integer array was modified") 33 | cat(" - dynamic storage\n") 34 | l <- .jnew("Leaks", .i, .s) 35 | for (i in 1:800) { 36 | if (i %% 160 == 0) { cat(' (forcing R gc)\n'); gc() } 37 | .i <- .jcall(l, "[I", "replaceI", .i) 38 | .s <- .jcall(l, "[S", "replaceS", .s) 39 | } 40 | cat(.jcall("Leaks","S","reportMem"),"\n") 41 | rm(l) 42 | cat(" running R gc\n") 43 | gc() 44 | cat(.jcall("Leaks","S","reportMem"),"\n") 45 | cat(" running java GC\n") 46 | .jcall("Leaks","V","runGC") 47 | cat(.jcall("Leaks","S","reportMem"),"\n") 48 | if (!isTRUE(all.equal(.s, ..s))) 49 | stop("FAILED - string array was modified") 50 | if (!isTRUE(all.equal(.i, ..i))) 51 | stop("FAILED - integer array was modified") 52 | 53 | cat("OK\n") 54 | -------------------------------------------------------------------------------- /tests/old/types.R: -------------------------------------------------------------------------------- 1 | library(rJava) 2 | .jinit(".") 3 | cat(" - instantiate Types class\n") 4 | t=.jnew("Types") 5 | ts=c("Z","B","C","T","I","J","D","F","Ljava/lang/String;") 6 | tn=c("z","b","c","s","i","j","d","f","S") 7 | ty=c("boolean","byte","char","short","int","long","double","float","string") 8 | ev=list(TRUE, 123L, 99L, 1234L, 1234L, 1234567890, 1234.567, 1234.567, "ok") 9 | for (i in 1:length(ts)) { 10 | cat(" -",ty[i],"\n") 11 | # cat(" static call\n"); 12 | sr=.jcall("Types",ts[i],paste('sr',tn[i],sep='')) 13 | # cat(" call\n"); 14 | r=.jcall(t,ts[i],paste('r',tn[i],sep='')) 15 | # cat(" static+sig\n"); 16 | sfr=.jfield("Types",ts[i],paste('s',tn[i],sep='')) 17 | # cat(" sig\n"); 18 | fr=.jfield(t,ts[i],tn[i]) 19 | # cat(" static\n"); 20 | .sfr=.jfield("Types",,paste('s',tn[i],sep='')) 21 | if (.sfr != sfr) stop("static field test failed: different results with and without a signature") 22 | # cat(" no sig\n"); 23 | .fr=.jfield(t,,tn[i]) 24 | if (.fr != fr) stop("field test failed: different results with and without a signature") 25 | ..sfr=.jfield(t,,paste('s',tn[i],sep='')) 26 | if (..sfr != .sfr) stop("field test failed: different results fetching a static field from an instance and the class") 27 | if (tn[i] == 'f') { 28 | if ((sr-ev[[i]])^2>1e-8) stop("failed static return test for ",ts[i]) 29 | if ((r-ev[[i]])^2>1e-8) stop("failed return test for ",ts[i]) 30 | if ((sfr-ev[[i]])^2>1e-8) stop("failed static field test for ",ts[i]) 31 | if ((fr-ev[[i]])^2>1e-8) stop("failed field test for ",ts[i]) 32 | } else { 33 | if (sr != ev[[i]]) stop("failed static return test for ",ts[i]) 34 | if (r != ev[[i]]) stop("failed return test for ",ts[i]) 35 | if (sfr != ev[[i]]) stop("failed static field test for ",ts[i]) 36 | if (fr != ev[[i]]) stop("failed field test for ",ts[i]) 37 | } 38 | } 39 | cat(" - calling a static method with all types\n") 40 | .jcall("Types", "V", "szbcsijfdS", 41 | TRUE, .jbyte(-123), .jchar(66), .jshort(4321), 4321L, 42 | .jlong(9876543210), .jfloat(4321.12), 4321.1234, "foo") 43 | cat(" - calling a method with all types\n") 44 | .jcall(t, "V", "zbcsijfdS", 45 | TRUE, .jbyte(-123), .jchar(66), .jshort(4321), 4321L, 46 | .jlong(9876543210), .jfloat(4321.12), 4321.1234, "foo") 47 | -------------------------------------------------------------------------------- /tools/getsp.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-u/rJava/ef046ea7698ff0ae9a701fe48eceb4ee54befc3f/tools/getsp.class -------------------------------------------------------------------------------- /tools/getsp.java: -------------------------------------------------------------------------------- 1 | public class getsp { 2 | public static void main(String[] args) { 3 | if (args!=null && args.length>0) { 4 | if (args[0].compareTo("-libs")==0) { 5 | String prefix="-L"; 6 | if (args.length>1) prefix=args[1]; 7 | String lp=System.getProperty("java.library.path"); 8 | // we're not using StringTokenizer in case the JVM is very crude 9 | int i=0,j,k=0; 10 | String r=null; 11 | String pss=System.getProperty("path.separator"); 12 | char ps=':'; 13 | if (pss!=null && pss.length()>0) ps=pss.charAt(0); 14 | j=lp.length(); 15 | while (i<=j) { 16 | if (i==j || lp.charAt(i)==ps) { 17 | String lib=lp.substring(k,i); 18 | k=i+1; 19 | if (lib.compareTo(".")!=0) 20 | r=(r==null)?(prefix+lib):(r+" "+prefix+lib); 21 | } 22 | i++; 23 | } 24 | if (r!=null) System.out.println(r); 25 | } else 26 | System.out.println(System.getProperty(args[0])); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /version: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | VER=`awk -v ORS= '/rJava v/ { print substr($6,2) }' src/rJava.h` 4 | if test "$1" == "-f"; then 5 | echo "rJava_${VER}.tar.gz" 6 | else 7 | echo "${VER}" 8 | fi 9 | --------------------------------------------------------------------------------