├── test
├── .exitcode
├── ci.boxr
├── test.sh
├── tests
│ ├── TestAPIServers.cfc
│ ├── TestSHA256.cfc
│ ├── TestBinary.cfc
│ ├── TestOptions.cfc
│ ├── TestFormPost.cfc
│ ├── TestFailureConditions.cfc
│ ├── TestSNI.cfc
│ ├── TestCompression.cfc
│ ├── TestCookies.cfc
│ └── TestCFHttpCompatability.cfc
├── util
│ └── cfhttp.cfc
├── Application.cfc
├── info.cfm
├── test-data.json
├── run.cfm
├── tls-tests.cfm
└── http.cfm
├── .gitignore
├── lib
├── httpcore-4.4.5.jar
├── httpclient-4.5.2.jar
├── commons-codec-1.10.jar
├── commons-logging-1.2.jar
└── httpasyncclient-4.1.2.jar
├── server.json
├── javaloader
├── lib
│ └── classloader-20120103162851.jar
├── licence.txt
├── JavaProxy.cfc
└── JavaLoader.cfc
├── ModuleConfig.cfc
├── .travis.yml
├── .github
└── workflows
│ └── ci.yml
├── box.json
├── README.md
├── bolthttp.cfc
└── LICENSE
/test/.exitcode:
--------------------------------------------------------------------------------
1 | 0
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | testbox/
2 | .DS_Store
--------------------------------------------------------------------------------
/test/ci.boxr:
--------------------------------------------------------------------------------
1 | install
2 | server start cfengine=$CFENGINE
--------------------------------------------------------------------------------
/lib/httpcore-4.4.5.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foundeo/bolthttp/HEAD/lib/httpcore-4.4.5.jar
--------------------------------------------------------------------------------
/lib/httpclient-4.5.2.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foundeo/bolthttp/HEAD/lib/httpclient-4.5.2.jar
--------------------------------------------------------------------------------
/lib/commons-codec-1.10.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foundeo/bolthttp/HEAD/lib/commons-codec-1.10.jar
--------------------------------------------------------------------------------
/lib/commons-logging-1.2.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foundeo/bolthttp/HEAD/lib/commons-logging-1.2.jar
--------------------------------------------------------------------------------
/lib/httpasyncclient-4.1.2.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foundeo/bolthttp/HEAD/lib/httpasyncclient-4.1.2.jar
--------------------------------------------------------------------------------
/server.json:
--------------------------------------------------------------------------------
1 | {
2 | "name":"bolthttp",
3 | "web":{
4 | "http":{
5 | "port":8484
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/javaloader/lib/classloader-20120103162851.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foundeo/bolthttp/HEAD/javaloader/lib/classloader-20120103162851.jar
--------------------------------------------------------------------------------
/test/test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cd `dirname $0`
4 | CWD="`pwd`"
5 |
6 | curl "http://127.0.0.1:8484/test/run.cfm?reporter=text"
7 |
8 | exitcode=$(<.exitcode)
9 | rm -f .exitcode
10 |
11 | exit $exitcode
--------------------------------------------------------------------------------
/ModuleConfig.cfc:
--------------------------------------------------------------------------------
1 | component {
2 |
3 | this.name = "bolthttp";
4 | this.author = "";
5 | this.webUrl = "https://github.com/foundeo/bolthttp";
6 | this.autoMapModels = false;
7 | this.cfmapping = "bolthttp";
8 |
9 | function configure() {
10 | binder.map( "bolthttp@bolthttp" )
11 | .to( "#moduleMapping#.bolthttp" )
12 |
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/test/tests/TestAPIServers.cfc:
--------------------------------------------------------------------------------
1 | component extends="testbox.system.BaseSpec" {
2 |
3 | //
4 |
5 | function run(testResults, testBox) {
6 |
7 | describe("Test maps.google.com", function() {
8 | it("Should connect to https://maps.googleapis.com/robots.txt", function() {
9 | var bolt = new bolthttp.bolthttp();
10 | var result = bolt.request("https://maps.googleapis.com/robots.txt");
11 | expect(result.fileContent).toInclude("Disallow:");
12 |
13 | });
14 |
15 |
16 |
17 | });
18 | }
19 | }
--------------------------------------------------------------------------------
/test/tests/TestSHA256.cfc:
--------------------------------------------------------------------------------
1 | component extends="testbox.system.BaseSpec" {
2 |
3 | //
4 |
5 | function run(testResults, testBox) {
6 |
7 | describe("Test SHA-256 Certificate", function() {
8 | it("Should connect to https://www.sandbox.paypal.com/robots.txt", function() {
9 | var bolt = new bolthttp.bolthttp();
10 | var result = bolt.request("https://www.sandbox.paypal.com/robots.txt");
11 | expect(result.fileContent).toInclude("Disallow:");
12 |
13 | });
14 |
15 |
16 |
17 | });
18 | }
19 | }
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | sudo: false
3 | jdk:
4 | - oraclejdk8
5 | env:
6 | global:
7 | - TEST_RUNNER_URI=/test/run.cfm
8 | matrix:
9 | - CFENGINE=lucee@4.5
10 | - CFENGINE=lucee@5
11 | - CFENGINE=adobe@10
12 | - CFENGINE=adobe@11
13 | - CFENGINE=adobe@2016
14 | - CFENGINE=adobe@9
15 | before_install:
16 | - git clone https://github.com/foundeo/cfmatrix.git cfmatrix
17 | install:
18 | - cfmatrix/bin/box recipe recipeFile=cfmatrix/ci.boxr CFENGINE=$CFENGINE
19 | before_script:
20 | - chmod +x cfmatrix/run.sh
21 | script:
22 | - "./cfmatrix/run.sh"
--------------------------------------------------------------------------------
/test/util/cfhttp.cfc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/test/tests/TestBinary.cfc:
--------------------------------------------------------------------------------
1 | component extends="testbox.system.BaseSpec" {
2 |
3 |
4 |
5 | function run(testResults, testBox) {
6 |
7 |
8 | describe("Test Binary Responses", function() {
9 | it("should work for a png", function() {
10 | var bolt = new bolthttp.bolthttp();
11 | var result = bolt.request(url="http://httpbin.org/image/png", method="GET");
12 | expect(result.text).toBeFalse();
13 | expect(result.mimetype).toBe("image/png");
14 | expect(isBinary(result.fileContent)).toBeTrue("Should be binary");
15 | });
16 |
17 |
18 |
19 | });
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/test/tests/TestOptions.cfc:
--------------------------------------------------------------------------------
1 | component extends="testbox.system.BaseSpec" {
2 |
3 | //http://httpbin.org/
4 |
5 | function run(testResults, testBox) {
6 |
7 |
8 | describe("Test User Agent", function() {
9 | it("It should allow you to set the user agent.", function() {
10 | var bolt = new bolthttp.bolthttp({userAgent="TestUserAgent"});
11 | var result = bolt.request(url="http://httpbin.org/user-agent", method="GET");
12 | var rObj = deserializeJSON(result.fileContent);
13 | expect(rObj["user-agent"]).toBe("TestUserAgent");
14 | });
15 |
16 |
17 | });
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/test/tests/TestFormPost.cfc:
--------------------------------------------------------------------------------
1 | component extends="testbox.system.BaseSpec" {
2 |
3 | //http://httpbin.org/post
4 |
5 | function run(testResults, testBox) {
6 |
7 |
8 | describe("Test formfield POST", function() {
9 | it("It should post data", function() {
10 | var bolt = new bolthttp.bolthttp();
11 | var result = bolt.request(url="http://httpbin.org/post", method="POST", params=[{type="formfield",name="foo",value="moo"}]);
12 | var rObj = deserializeJSON(result.fileContent);
13 | expect(rObj.form.foo).toBe("moo");
14 |
15 | });
16 |
17 |
18 |
19 | });
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/test/tests/TestFailureConditions.cfc:
--------------------------------------------------------------------------------
1 | component extends="testbox.system.BaseSpec" {
2 |
3 | function run(testResults, testBox) {
4 |
5 | describe("Throw exceptions", function() {
6 | it("Should throw exception when connecting to an invalid scheme", function() {
7 | expect(function() {
8 | var bolt = new bolthttp.bolthttp();
9 | var result = bolt.request("htp://foo/moo");
10 |
11 | }).toThrow();
12 |
13 | });
14 |
15 | it("Should throw exception when connecting to an invalid host", function() {
16 | expect(function() {
17 | var bolt = new bolthttp.bolthttp();
18 | var result = bolt.request("http://192.168");
19 |
20 | }).toThrow();
21 |
22 | });
23 |
24 | });
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/test/Application.cfc:
--------------------------------------------------------------------------------
1 | component {
2 | this.name="bolt_tests";
3 | this.projectRoot = Replace(getDirectoryFromPath(getCurrentTemplatePath()), "/test/", "/");
4 | this.mappings["/testbox"] = this.projectRoot & "testbox";
5 | this.mappings["/bolthttp"] = this.projectRoot;
6 | this.mappings["/util"] = this.projectRoot & "test/util";
7 | this.mappings["/tests"] = this.projectRoot & "test/tests";
8 |
9 | //this.javaSettings.loadPaths = [this.projectRoot & "lib"];
10 | //this.javaSettings.reloadOnChange = true;
11 |
12 | public boolean function onRequestStart(targetPage) {
13 | if (!isLocalHost(cgi.remote_addr)) {
14 | writeOutput("Sorry localhost only...");
15 | abort;
16 | return false;
17 | }
18 | return true;
19 | }
20 |
21 | }
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | workflow_dispatch:
10 |
11 | env:
12 | TEST_RUNNER_URI: /test/run.cfm
13 |
14 | jobs:
15 |
16 | cfmatrix:
17 | runs-on: ubuntu-latest
18 | permissions:
19 | contents: read
20 |
21 | #setup the matrix of CF Engines
22 | strategy:
23 | matrix:
24 | cfengine: ["lucee@5.3", "adobe@2018"]
25 | env:
26 | CFENGINE: ${{ matrix.cfengine }}
27 | steps:
28 | - uses: actions/checkout@v2
29 |
30 | - name: Clone cfmatrix
31 | run: git clone --depth 1 https://github.com/foundeo/cfmatrix.git cfmatrix
32 |
33 | - name: Install cfmatrix
34 | run: bash ./cfmatrix/install.sh
35 |
36 | - name: Run Tests
37 | run: bash ./cfmatrix/run.sh
38 |
39 |
--------------------------------------------------------------------------------
/test/info.cfm:
--------------------------------------------------------------------------------
1 |
Bolt Info
2 |
3 | Bolt Version: #bolt.getVersion()# HttpClient Version: #bolt.getHttpClientVersion()#
4 |
5 |
6 | File Exists:#fileExists(j)# #j#
7 |
8 |
9 |
10 | Java System Properties
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | #htmlEditFormat(propName)# = #htmlEditFormat(system.getProperty(propName))#
20 |
21 |
--------------------------------------------------------------------------------
/test/test-data.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "url":"https://www.google.com/robots.txt",
4 | "title":"Google",
5 | "expect":"200"
6 | },
7 | {
8 | "url":"https://www.sandbox.paypal.com/robots.txt",
9 | "title":"PayPal: SHA-256 Cert",
10 | "expect":"200"
11 | },
12 | {
13 | "url":"https://mozilla-modern.badssl.com/",
14 | "title":"TLS 1.2 / Mozilla Modern Configuration",
15 | "expect":"200"
16 | },
17 | {
18 | "url":"https://mozilla-intermediate.badssl.com/",
19 | "title":"Mozilla Intermediate Configuration",
20 | "expect":"200"
21 | },
22 | {
23 | "url":"https://mozilla-old.badssl.com/",
24 | "title":"Mozilla Old Browser Configuration",
25 | "expect":"200"
26 | },
27 | {
28 | "url":"https://self-signed.badssl.com/",
29 | "title":"Self Signed Certificate",
30 | "expect":"exception"
31 | },
32 | {
33 | "url":"https://expired.badssl.com/",
34 | "title":"Expired Certificate",
35 | "expect":"exception"
36 | },
37 | {
38 | "url":"https://1000-sans.badssl.com/",
39 | "title":"Subject Alt Names - 1000 SAN Certificate",
40 | "expect":"200"
41 | }
42 |
43 | ]
44 |
--------------------------------------------------------------------------------
/test/tests/TestSNI.cfc:
--------------------------------------------------------------------------------
1 | component extends="testbox.system.BaseSpec" {
2 | function beforeAll(){
3 |
4 | }
5 |
6 | function run(testResults, testBox) {
7 |
8 | /* THESE servers do not seam to be working
9 | cfHttp = new util.cfhttp();
10 | describe("SNI Tests", function() {
11 | var sniHosts = ["mallory.sni.velox.ch", "dave.sni.velox.ch", "alice.sni.velox.ch"];
12 | var results = {};
13 | for (var s in sniHosts) {
14 | var bolt = new bolthttp.bolthttp();
15 | results[s] = bolt.request("https://#s#/");
16 | }
17 | it("should have sent the SNI extension ", function() {
18 | for (var s in sniHosts) {
19 | var boltResult = results[s];
20 | expect(boltResult.fileContent).toInclude("#s#", "No strong tag with host: #s#");
21 | }
22 |
23 |
24 | });
25 |
26 | it("should have Host: header", function() {
27 | for (var s in sniHosts) {
28 | var boltResult = results[s];
29 | expect(boltResult.fileContent).toInclude("Host: #s#", "No Host: #s#");
30 | }
31 |
32 | });
33 |
34 |
35 |
36 |
37 | });
38 | */
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/box.json:
--------------------------------------------------------------------------------
1 | {
2 | "name":"bolthttp",
3 | "version":"1.0.1",
4 | "slug":"bolthttp",
5 | "devDependencies":{
6 | "testbox":"^2.3.0"
7 | },
8 | "installPaths":{
9 | "testbox":"testbox"
10 | },
11 | "ignore":[
12 | "**/.*",
13 | "test",
14 | "testbox"
15 | ],
16 | "location":"foundeo/bolthttp#v1.0.1",
17 | "homepage":"https://github.com/foundeo/bolthttp",
18 | "documentation":"https://github.com/foundeo/bolthttp",
19 | "repository":{
20 | "type":"git",
21 | "URL":"https://github.com/foundeo/bolthttp"
22 | },
23 | "bugs":"https://github.com/foundeo/bolthttp/issues",
24 | "shortDescription":"A CFML HTTP Client",
25 | "description":"BoltHTTP is a HTTP client for CFML, it is a CFC that wraps the Apache HttpComponents java library. You can use the bolthttp CFC instead of CFHTTP when making HTTP requests within CFML.",
26 | "type":"modules",
27 | "scripts":{
28 | "postVersion":"package set location='foundeo/bolthttp#v`package version`'",
29 | "onRelease":"publish",
30 | "postPublish":"!git push && !git push --tags"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/test/tests/TestCompression.cfc:
--------------------------------------------------------------------------------
1 | component extends="testbox.system.BaseSpec" {
2 |
3 | //http://httpbin.org/
4 |
5 | function run(testResults, testBox) {
6 |
7 |
8 | describe("Test Compression", function() {
9 | it("It should support gzip", function() {
10 | var bolt = new bolthttp.bolthttp();
11 | var result = bolt.request(url="http://httpbin.org/gzip", method="GET");
12 | var rObj = deserializeJSON(result.fileContent);
13 | expect(rObj.gzipped).toBeTrue();
14 | });
15 |
16 | it("It should support deflate", function() {
17 | var bolt = new bolthttp.bolthttp();
18 | var result = bolt.request(url="http://httpbin.org/deflate", method="GET");
19 | var rObj = deserializeJSON(result.fileContent);
20 | expect(rObj.deflated).toBeTrue();
21 | });
22 |
23 | /*
24 | it("It should allow compression to be turned off", function() {
25 | var bolt = new bolthttp.bolthttp();
26 | var result = bolt.request(url="http://httpbin.org/gzip", method="GET", options={compression=false});
27 | var rObj = "";
28 | debug(result);
29 | var rObj = deserializeJSON(result.fileContent);
30 | expect(rObj.gzipped).toBeFalse();
31 | });*/
32 |
33 |
34 | });
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/test/run.cfm:
--------------------------------------------------------------------------------
1 |
2 |
3 | if (!structKeyExists(url, "reporter")) {
4 | if (cgi.http_user_agent contains "curl") {
5 | reporter = "text";
6 | } else {
7 | reporter = cgi.server_protocol == "CLI/1.0" ? "text" : "simple";
8 | }
9 | }
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | ", Chr(10), "ALL")>
20 | ", "#Chr(10)#==============================#Chr(10)#")>
21 | ", "#Chr(10)##Chr(10)#", "ALL")>
22 | ]+>", "", "ALL")>
23 | #test#
24 |
25 | #test#
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | BoltHTTP Tests
BoltHttp Tests
34 | Lucee #server.lucee.version#ColdFusion #server.coldfusion.productversion#
35 |
36 | try {
37 |
38 | testbox = new testbox.system.TestBox( options={}, reporter=reporter, directory="tests");
39 | writeOutput( testbox.run() );
40 | resultObject = testbox.getResult();
41 | errors = resultObject.getTotalFail() + resultObject.getTotalError();
42 | exitCode( errors ? 1 : 0 );
43 | } catch ( any e ) {
44 | writeOutput( "An error occurred running the tests. Message: [#e.message#], Detail: [#e.detail#]" );
45 | exitCode( 1 );
46 | }
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/test/tls-tests.cfm:
--------------------------------------------------------------------------------
1 |
2 | Bolt HTTP Tests
3 |
4 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | ColdFusion #server.coldfusion.productlevel# Edition #server.coldfusion.productversion#
15 |
16 | Lucee #server.lucee.version#
17 |
18 |
19 |
20 |
21 | Java: #htmlEditFormat(system.getProperty("java.version"))#
22 |
23 |
24 |
25 |
26 |
27 |
28 | #htmlEditFormat(test.title)#
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | OK:
54 |
55 | FAIL:
56 |
57 |
58 | Expected #test.expect#
59 |
60 | got exception: #htmlEditFormat(exception.message)#
61 |
62 |
63 | #htmlEditFormat(result.status)#
64 |
65 |
66 | got result: #htmlEditFormat(result.statuscode)#
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BoltHTTP
2 |
3 | [](https://github.com/foundeo/bolthttp/actions/workflows/ci.yml)
4 |
5 | BoltHTTP is a HTTP client for CFML, it is a CFC that wraps the Apache HttpComponents java library. You can use the `bolthttp` CFC instead of CFHTTP when making HTTP requests within CFML.
6 |
7 | ## How do I use it?
8 |
9 | Here's a simple example:
10 |
11 | bolt = new bolthttp();
12 | response = bolt.request(url="http://httpbin.org/robots.txt", method="GET");
13 | writeOutput(response.fileContent);
14 |
15 | The return value of `request` value is a `struct` that contains keys _mostly_ compatibale with what the `cfhttp` tag would return.
16 |
17 | The request method has the following signature:
18 |
19 | request(string url, string method="GET", array params=[], boolean close=true, struct options={})
20 |
21 | `url` the url to request, the only required argument.
22 |
23 | `method` the HTTP request method
24 |
25 | `params` similar to the `cfhttpparam` tag, an array of structs for headers, formfields, etc. For example passing a header you would use `[{type="header", name="X-MyHeader", value="My Value"}]`
26 |
27 | `close` when `true` it closes the internal HTTP Client for you once the request is complete, this means that you need to create another instance of `bolthttp` if you want to make a subsequent request, or set it to `false` and call `getHttpClient().close()` when you are done with the instance.
28 |
29 | `options` a struct of request level options. Currently supported options are: `maxredirects` `redirect` `sockettimeout` `connecttimeout` and `connectrequesttimeout`
30 |
31 | ## Advanced Usage
32 |
33 | The response struct also contains a key `httpResponse` which is an instance of a [org.apache.http.HttpResponse](http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/HttpResponse.html) object. You should be able to get any part of the HTTP response you need from this object.
34 |
35 | If you want to only work with the `HttpResponse` object instead of using the `request()` method of bolthttp you can use the `rawRequest()` method which only returns the `HttpResponse` object. Using `rawRequest` instead of `request().httpResponse` will offer better performance becauase it does not need to parse the response object to build the struct.
36 |
37 | ## System Requirements
38 |
39 | It requires Java 1.7 and ColdFusion 9 or greater or Lucee 4.5+
40 |
41 | _The requirement of ColdFusion 9+ is mainly due to it being written as a script based CFC, if you convert it to a tag based CFC it would probably run on CF8 or below as well._
42 |
43 | ## Why use it?
44 |
45 | * Consistent implementation of CFHTTP across various CFML engine versions.
46 | * Ability to use TLS 1.2 on ColdFusion 9
47 | * Friendly for script based code
48 |
--------------------------------------------------------------------------------
/test/tests/TestCookies.cfc:
--------------------------------------------------------------------------------
1 | component extends="testbox.system.BaseSpec" {
2 |
3 | //http://httpbin.org/
4 |
5 | function run(testResults, testBox) {
6 |
7 | describe("Test Response Cookies", function() {
8 | it("It should put multiple response cookies in a struct", function() {
9 | var bolt = new bolthttp.bolthttp();
10 | var result = bolt.request(url="http://httpbin.org/cookies/set?k2=v2&k1=v1", method="GET",options={redirect=false});
11 | expect(result.responseheader).toHaveKey("Set-Cookie");
12 | expect(result.responseHeader["Set-Cookie"]).toBeStruct("Set-Cookie in responseheader should be a struct");
13 | expect(result.responseheader["Set-Cookie"]).toHaveKey("1");
14 | expect(result.responseheader["Set-Cookie"]).toHaveKey("2");
15 | //not sure about ordering but make sure both values are there
16 | if (result.responseheader["Set-Cookie"]["1"] contains "k2") {
17 | expect(result.responseheader["Set-Cookie"]["1"]).toMatch("v2");
18 | expect(result.responseheader["Set-Cookie"]["2"]).toMatch("v1");
19 | } else {
20 | expect(result.responseheader["Set-Cookie"]["2"]).toMatch("v2");
21 | expect(result.responseheader["Set-Cookie"]["1"]).toMatch("v1");
22 | }
23 | });
24 |
25 | it("It should put single response cookies in a string", function() {
26 | var bolt = new bolthttp.bolthttp();
27 | var result = bolt.request(url="http://httpbin.org/cookies/set?k1=v1", method="GET", options={redirect=false});
28 | expect(result.responseheader).toHaveKey("Set-Cookie");
29 | expect(result.responseHeader["Set-Cookie"]).notToBeStruct("Set-Cookie in responseheader should not be a struct");
30 | expect(isSimpleValue(result.responseHeader["Set-Cookie"])).toBeTrue("Should be a simple value");
31 | expect(result.responseheader["Set-Cookie"]).toMatch("v1");
32 | });
33 | });
34 |
35 |
36 | describe("Test Request Cookies", function() {
37 | it("should send a cookie", function() {
38 | var bolt = new bolthttp.bolthttp();
39 | var result = bolt.request(url="http://httpbin.org/cookies", method="GET", params=[{type="cookie",name="myCookie",value="myValue"}]);
40 | var rObj = deserializeJSON(result.fileContent);
41 | expect(rObj.cookies).toHaveKey("myCookie");
42 | expect(rObj.cookies.myCookie).toBe("myValue");
43 | });
44 |
45 | it("should send multiple cookies", function() {
46 | var bolt = new bolthttp.bolthttp();
47 | var result = bolt.request(url="http://httpbin.org/cookies", method="GET", params=[{type="cookie",name="myCookie",value="myValue"}, {type="cookie",name="myOtherCookie",value="myOther/Value"}]);
48 | var rObj = deserializeJSON(result.fileContent);
49 | expect(rObj.cookies).toHaveKey("myCookie");
50 | expect(rObj.cookies).toHaveKey("myOtherCookie");
51 | expect(rObj.cookies.myCookie).toBe("myValue");
52 | expect(rObj.cookies.myOtherCookie).toBe("myOther/Value");
53 | });
54 |
55 | });
56 |
57 |
58 |
59 | }
60 | }
61 |
62 |
--------------------------------------------------------------------------------
/test/tests/TestCFHttpCompatability.cfc:
--------------------------------------------------------------------------------
1 | component extends="testbox.system.BaseSpec" {
2 | function beforeAll(){
3 |
4 | }
5 |
6 | function run(testResults, testBox) {
7 |
8 | cfHttp = new util.cfhttp();
9 | describe("CFHTTP Compatibility Tests", function() {
10 | var bolt = new bolthttp.bolthttp();
11 | var data = {};
12 | data.boltResult = bolt.request("http://httpbin.org/response-headers?X-Men=y&Server=httpbin&Content-Type=text%2Fplain%3B+charset%3DUTF-8");
13 | data.cfResult = cfHttp.run({url="http://httpbin.org/response-headers?X-Men=y&Server=httpbin&Content-Type=text%2Fplain%3B+charset%3DUTF-8", method="get"});
14 |
15 |
16 | if (structKeyExists(server, "lucee") && structKeyExists(data.boltResult.responseheader, "Http_Version")) {
17 | //lucee does not have the Http_Version header that CF has
18 | structDelete(data.boltResult.responseheader, "Http_Version");
19 | }
20 |
21 |
22 | it(title="should have the same file content", body=function(data) {
23 | expect(data.boltResult.fileContent).toBe(data.cfResult.fileContent);
24 | },data=data);
25 |
26 | it(title="should have the same charset", body=function(data) {
27 | expect(data.boltResult.charset).toBe(data.cfResult.charset);
28 | },data=data);
29 |
30 | it(title="should have the same mimetype", body=function(data) {
31 | expect(data.boltResult.mimetype).toBe(data.cfResult.mimetype);
32 | },data=data);
33 |
34 | it(title="should have the same text", body=function(data) {
35 | expect(data.boltResult.text).toBe(data.cfResult.text);
36 | },data=data);
37 |
38 | it(title="should have the same statuscode", body=function(data) {
39 | expect(data.boltResult.statuscode).toBe(data.cfResult.statuscode);
40 | },data=data);
41 |
42 | it(title="should have the same number of response headers", body=function(data) {
43 | expect(StructCount(data.boltResult.responseheader)).toBe(StructCount(data.cfResult.responseheader));
44 | },data=data);
45 |
46 | it(title="should have the same list of response headers", body=function(data) {
47 | expect(listSort(lcase(StructKeyList(data.cfResult.responseheader)), "text")).toBe(listSort(lcase(StructKeyList(data.boltResult.responseheader)), "text"));
48 | },data=data);
49 |
50 | //test headers
51 | for (h in StructKeyArray(data.cfResult.responseheader)) {
52 | data.h = h;
53 | it(title="bolt should have the response header: #h#", body=function(data) {
54 | expect(data.boltResult.responseheader).toHaveKey(data.h);
55 | }, data=data);
56 | if (StructKeyExists(data.boltResult.responseheader, h)) {
57 | if (isArray(data.cfResult.responseheader[h])) {
58 | it(title="the response header #h# should be an array", body=function(data) {
59 | expect(data.boltResult.responseheader[data.h]).toBeArray();
60 | },data=data);
61 | } else if (IsStruct(data.cfResult.responseheader[h])) {
62 | it(title="the response header #h# should be a struct", body=function(data) {
63 | expect(data.boltResult.responseheader[data.h]).toBeStruct();
64 | }, data=data);
65 | } else {
66 | it(title="the response header #h# should be a simple/string value", body=function(data) {
67 | expect(data.boltResult.responseheader[data.h]).toBeString();
68 | }, data=data);
69 | }
70 | it(title="the response header #h# values should be equal", body=function(data) {
71 | expect(data.boltResult.responseheader[data.h]).toBe(data.cfResult.responseheader[data.h]);
72 |
73 | }, data=data);
74 | }
75 |
76 | }
77 |
78 |
79 |
80 | });
81 | }
82 | }
--------------------------------------------------------------------------------
/test/http.cfm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | Request Execution Time: #NumberFormat(tock-tick)#ms
63 |
64 |
65 |
66 |
67 | #cfhttp.fileContent#
68 |
69 |
70 |
71 |
72 |
73 |
74 | #cfhttp.ResponseHeader["Set-Cookie"][header]#
75 |
76 | NOT HTTP ONLY!
77 |
78 |
79 |
80 |
81 |
82 |
83 | NOT HTTP ONLY! #header#
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/bolthttp.cfc:
--------------------------------------------------------------------------------
1 | component {
2 | variables.config = {charset="utf-8", userAgent="BoltHTTP"};
3 |
4 | variables.useJavaLoader = true;
5 |
6 | public function init(struct config={}) {
7 | initJavaLoader();
8 | if (!structIsEmpty(arguments.config)) {
9 | structAppend(variables.config, arguments.config, true);
10 | }
11 | variables.charset = create("java.nio.charset.Charset").forName(variables.config.charset);
12 | variables.entityUtils = create("org.apache.http.util.EntityUtils");
13 | local.clientBuilder = create("org.apache.http.impl.client.HttpClientBuilder").create();
14 | local.clientBuilder = local.clientBuilder.setUserAgent(variables.config.userAgent);
15 | variables.httpClient = local.clientBuilder.build();
16 |
17 | return this;
18 | }
19 |
20 | public function rawRequest(string url, string method="GET", array params=[], struct options={}) {
21 | var requestBuilder = create("org.apache.http.client.methods.RequestBuilder");
22 | var cookieHeader = "";
23 | switch (uCase(arguments.method)) {
24 | case "GET":
25 | requestBuilder = requestBuilder.get(arguments.url);
26 | break;
27 | case "POST":
28 | requestBuilder = requestBuilder.post(arguments.url);
29 | break;
30 | default:
31 | requestBuilder = requestBuilder.create(uCase(arguments.method)).setUri(arguments.url);
32 | break;
33 | }
34 | requestBuilder = requestBuilder.setCharset(variables.charset);
35 | for (local.p in arguments.params) {
36 | switch (LCase(local.p.type)) {
37 | case "header":
38 | case "cgi":
39 | if (structKeyExists(local.p, "encoded") && local.p.encoded) {
40 | requestBuilder.addHeader(javaCast("string", local.p.name), urlEncodedFormat(local.p.value));
41 | } else {
42 | requestBuilder.addHeader(javaCast("string", local.p.name), javaCast("string", local.p.value));
43 | }
44 | break;
45 | case "body":
46 | requestBuilder = requestBuilder.setEntity(create("org.apache.http.entity.StringEntity").init(javaCast("string", local.p.value)));
47 | break;
48 | case "formfield":
49 | requestBuilder = requestBuilder.addParameter(javaCast("string", local.p.name), javaCast("string", local.p.value));
50 | break;
51 | case "cookie":
52 | //todo cookies
53 | if (len(cookieHeader)) {
54 | cookieHeader = cookieHeader & "; ";
55 | }
56 | cookieHeader = cookieHeader & local.p.name & "=";
57 | if (structKeyExists(local.p, "encoded") && local.p.encoded) {
58 | cookieHeader = cookieHeader & urlEncodedFormat(local.p.value);
59 | } else {
60 | cookieHeader = cookieHeader & local.p.value;
61 | }
62 | break;
63 | default:
64 | throw(message="Unsupported param type:" & XmlFormat(local.p.type));
65 | break;
66 | }
67 | }
68 | if (len(cookieHeader)) {
69 | requestBuilder.addHeader("Cookie", cookieHeader);
70 | }
71 | if (!structIsEmpty(arguments.options)) {
72 | local.requestConfig = create("org.apache.http.client.config.RequestConfig").custom();
73 | for (local.key in arguments.options) {
74 | switch(lCase(local.key)) {
75 | case "maxredirects":
76 | local.requestConfig = local.requestConfig.setMaxRedirects(arguments.options.maxRedirects);
77 | break;
78 | case "redirect":
79 | local.requestConfig = local.requestConfig.setRedirectsEnabled(arguments.options.redirect);
80 | break;
81 | case "sockettimeout":
82 | local.requestConfig = local.requestConfig.setSocketTimeout(arguments.options.socketTimeout);
83 | break;
84 | case "connecttimeout":
85 | local.requestConfig = local.requestConfig.setConnectTimeout(arguments.options.connectTimeout);
86 | break;
87 | case "connectrequesttimeout":
88 | local.requestConfig = local.requestConfig.setConnectRequestTimeout(arguments.options.connectRequestTimeout);
89 | break;
90 | case "compression":
91 | local.requestConfig = local.requestConfig.setContentCompressionEnabled(arguments.options.compression);
92 | break;
93 | }
94 | }
95 | requestBuilder.setConfig(local.requestConfig.build());
96 | }
97 |
98 | try {
99 | return variables.httpClient.execute(requestBuilder.build());
100 | } catch (any e) {
101 | //auto close client on exception
102 | variables.httpClient.close();
103 | rethrow;
104 | }
105 | }
106 |
107 | public function request(string url, string method="GET", array params=[], boolean close=true, struct options={}) {
108 | var httpResponse = rawRequest(url=arguments.url, method=arguments.method, params=arguments.params, options=arguments.options);
109 |
110 | var result = StructNew();
111 | result["ErrorDetail"] = "";
112 | result.text = false;
113 | result.status = httpResponse.getStatusLine().getStatusCode();
114 | result.statuscode = httpResponse.getStatusLine().getStatusCode() & " " & httpResponse.getStatusLine().getReasonPhrase();
115 | result.responseHeader = StructNew();
116 | result.httpResponse = httpResponse;
117 |
118 | result.header = httpResponse.toString();
119 | local.headers = httpResponse.getAllHeaders();
120 | result.responseHeader["Explanation"] = httpResponse.getStatusLine().getReasonPhrase();
121 | result.responseHeader["Http_Version"] = httpResponse.getStatusLine().getProtocolVersion().toString();
122 | result.responseHeader["Status_Code"] = result.status;
123 | for (local.i=1;local.i<=ArrayLen(local.headers);local.i++) {
124 | local.h = local.headers[local.i];
125 | if (StructKeyExists(result.responseHeader, local.h.getName())) {
126 | //if multiple headers with the same name convert to a struct
127 | //this is odd, but it matches how cfhttp works
128 | if (isStruct(result.responseHeader[local.h.getName()])) {
129 | //append to existing struct
130 | local.i = structCount(result.responseHeader[local.h.getName()]) + 1;
131 | result.responseHeader[local.h.getName()][local.i] = local.h.getValue();
132 | } else {
133 | //convert to struct
134 | result.responseHeader[local.h.getName()] = {1=result.responseHeader[local.h.getName()], 2=local.h.getValue()};
135 | }
136 | } else {
137 | result.responseHeader[local.h.getName()] = local.h.getValue();
138 | }
139 | }
140 |
141 | if (StructKeyExists(result.responseHeader, "Content-Type")) {
142 | result.mimetype = Trim(ListFirst(result.responseHeader["Content-Type"], ";"));
143 | if (ListLen(result.responseHeader["Content-Type"], ";") EQ 2) {
144 | result.charset = Trim(ListGetAt(result.responseHeader["Content-Type"], 2, ";"));
145 | result.charset = ReplaceNoCase(result.charset, "charset=", "");
146 | }
147 | if (result.mimetype.startsWith("text/") OR result.mimetype.startsWith("message/")) {
148 | result.text = true;
149 | } else if (result.mimetype.startsWith("application/")) {
150 | if (ListFindNoCase("application/octet-stream,application/json", result.mimetype)) {
151 | result.text = true;
152 | }
153 | }
154 | } else if (ListFindNoCase("png,jpg,jpeg,gif,pdf", ListFirst(ListLast(url, "."), "?"))) {
155 | result.text = false;
156 | } else {
157 | result.text = true;
158 | }
159 | if (result.text) {
160 | result.filecontent = variables.entityUtils.toString(httpResponse.getEntity());
161 | } else {
162 | result.filecontent = variables.entityUtils.toByteArray(httpResponse.getEntity());
163 | }
164 |
165 | httpResponse.close();
166 |
167 | if (arguments.close) {
168 | httpClient.close();
169 | }
170 | return result;
171 | }
172 |
173 |
174 |
175 | /**
176 | * Create an instance of a java class
177 | */
178 | public function create(className) {
179 | if (variables.useJavaLoader) {
180 | return server[getLoaderKey()].create(arguments.className);
181 | } else {
182 | return createObject("java", arguments.className);
183 | }
184 | }
185 |
186 | public function getHttpClient() {
187 | return variables.httpClient;
188 | }
189 |
190 | public function getHttpClientVersion() {
191 | var versionInfo = create("org.apache.http.util.VersionInfo").loadVersionInfo("org.apache.http.client", getHttpClient().getClass().getClassLoader());
192 | return versionInfo.toString();
193 | }
194 |
195 | public function getVersion() {
196 | return "1.0.0";
197 | }
198 |
199 | private function getLoaderKey() {
200 | return "bolt_javaloader_" & replace(getVersion(), ".","","ALL");
201 | }
202 |
203 | private function initJavaLoader() {
204 | if (variables.useJavaLoader) {
205 | local.key = getLoaderKey();
206 | if (!structKeyExists(server, local.key)) {
207 | server[local.key] = new javaloader.JavaLoader(getJarArray(), false);
208 | }
209 | }
210 | }
211 |
212 | /**
213 | * @returns an array of java jar files used by this tool
214 | */
215 | public function getJarArray() {
216 | var lib = getDirectoryFromPath(getCurrentTemplatePath()) & "lib/";
217 | return [
218 | lib & "commons-logging-1.2.jar",
219 | lib & "commons-codec-1.10.jar",
220 | lib & "httpcore-4.4.5.jar",
221 | lib & "httpclient-4.5.2.jar",
222 | lib & "httpasyncclient-4.1.2.jar"
223 | ];
224 | }
225 |
226 | }
227 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/javaloader/licence.txt:
--------------------------------------------------------------------------------
1 | Common Public License Version 1.0
2 |
3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC
4 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
5 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
6 |
7 | 1. DEFINITIONS
8 |
9 | "Contribution" means:
10 |
11 | a) in the case of the initial Contributor, the initial code and
12 | documentation distributed under this Agreement, and
13 |
14 | b) in the case of each subsequent Contributor:
15 |
16 | i) changes to the Program, and
17 |
18 | ii) additions to the Program;
19 |
20 | where such changes and/or additions to the Program originate from and are
21 | distributed by that particular Contributor. A Contribution 'originates' from a
22 | Contributor if it was added to the Program by such Contributor itself or anyone
23 | acting on such Contributor's behalf. Contributions do not include additions to
24 | the Program which: (i) are separate modules of software distributed in
25 | conjunction with the Program under their own license agreement, and (ii) are not
26 | derivative works of the Program.
27 |
28 | "Contributor" means any person or entity that distributes the Program.
29 |
30 | "Licensed Patents " mean patent claims licensable by a Contributor which are
31 | necessarily infringed by the use or sale of its Contribution alone or when
32 | combined with the Program.
33 |
34 | "Program" means the Contributions distributed in accordance with this Agreement.
35 |
36 | "Recipient" means anyone who receives the Program under this Agreement,
37 | including all Contributors.
38 |
39 | 2. GRANT OF RIGHTS
40 |
41 | a) Subject to the terms of this Agreement, each Contributor hereby grants
42 | Recipient a non-exclusive, worldwide, royalty-free copyright license to
43 | reproduce, prepare derivative works of, publicly display, publicly perform,
44 | distribute and sublicense the Contribution of such Contributor, if any, and such
45 | derivative works, in source code and object code form.
46 |
47 | b) Subject to the terms of this Agreement, each Contributor hereby grants
48 | Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed
49 | Patents to make, use, sell, offer to sell, import and otherwise transfer the
50 | Contribution of such Contributor, if any, in source code and object code form.
51 | This patent license shall apply to the combination of the Contribution and the
52 | Program if, at the time the Contribution is added by the Contributor, such
53 | addition of the Contribution causes such combination to be covered by the
54 | Licensed Patents. The patent license shall not apply to any other combinations
55 | which include the Contribution. No hardware per se is licensed hereunder.
56 |
57 | c) Recipient understands that although each Contributor grants the licenses
58 | to its Contributions set forth herein, no assurances are provided by any
59 | Contributor that the Program does not infringe the patent or other intellectual
60 | property rights of any other entity. Each Contributor disclaims any liability to
61 | Recipient for claims brought by any other entity based on infringement of
62 | intellectual property rights or otherwise. As a condition to exercising the
63 | rights and licenses granted hereunder, each Recipient hereby assumes sole
64 | responsibility to secure any other intellectual property rights needed, if any.
65 | For example, if a third party patent license is required to allow Recipient to
66 | distribute the Program, it is Recipient's responsibility to acquire that license
67 | before distributing the Program.
68 |
69 | d) Each Contributor represents that to its knowledge it has sufficient
70 | copyright rights in its Contribution, if any, to grant the copyright license set
71 | forth in this Agreement.
72 |
73 | 3. REQUIREMENTS
74 |
75 | A Contributor may choose to distribute the Program in object code form under its
76 | own license agreement, provided that:
77 |
78 | a) it complies with the terms and conditions of this Agreement; and
79 |
80 | b) its license agreement:
81 |
82 | i) effectively disclaims on behalf of all Contributors all warranties and
83 | conditions, express and implied, including warranties or conditions of title and
84 | non-infringement, and implied warranties or conditions of merchantability and
85 | fitness for a particular purpose;
86 |
87 | ii) effectively excludes on behalf of all Contributors all liability for
88 | damages, including direct, indirect, special, incidental and consequential
89 | damages, such as lost profits;
90 |
91 | iii) states that any provisions which differ from this Agreement are offered
92 | by that Contributor alone and not by any other party; and
93 |
94 | iv) states that source code for the Program is available from such
95 | Contributor, and informs licensees how to obtain it in a reasonable manner on or
96 | through a medium customarily used for software exchange.
97 |
98 | When the Program is made available in source code form:
99 |
100 | a) it must be made available under this Agreement; and
101 |
102 | b) a copy of this Agreement must be included with each copy of the Program.
103 |
104 | Contributors may not remove or alter any copyright notices contained within the
105 | Program.
106 |
107 | Each Contributor must identify itself as the originator of its Contribution, if
108 | any, in a manner that reasonably allows subsequent Recipients to identify the
109 | originator of the Contribution.
110 |
111 | 4. COMMERCIAL DISTRIBUTION
112 |
113 | Commercial distributors of software may accept certain responsibilities with
114 | respect to end users, business partners and the like. While this license is
115 | intended to facilitate the commercial use of the Program, the Contributor who
116 | includes the Program in a commercial product offering should do so in a manner
117 | which does not create potential liability for other Contributors. Therefore, if
118 | a Contributor includes the Program in a commercial product offering, such
119 | Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
120 | every other Contributor ("Indemnified Contributor") against any losses, damages
121 | and costs (collectively "Losses") arising from claims, lawsuits and other legal
122 | actions brought by a third party against the Indemnified Contributor to the
123 | extent caused by the acts or omissions of such Commercial Contributor in
124 | connection with its distribution of the Program in a commercial product
125 | offering. The obligations in this section do not apply to any claims or Losses
126 | relating to any actual or alleged intellectual property infringement. In order
127 | to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
128 | Contributor in writing of such claim, and b) allow the Commercial Contributor to
129 | control, and cooperate with the Commercial Contributor in, the defense and any
130 | related settlement negotiations. The Indemnified Contributor may participate in
131 | any such claim at its own expense.
132 |
133 | For example, a Contributor might include the Program in a commercial product
134 | offering, Product X. That Contributor is then a Commercial Contributor. If that
135 | Commercial Contributor then makes performance claims, or offers warranties
136 | related to Product X, those performance claims and warranties are such
137 | Commercial Contributor's responsibility alone. Under this section, the
138 | Commercial Contributor would have to defend claims against the other
139 | Contributors related to those performance claims and warranties, and if a court
140 | requires any other Contributor to pay any damages as a result, the Commercial
141 | Contributor must pay those damages.
142 |
143 | 5. NO WARRANTY
144 |
145 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
146 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
147 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
148 | NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
149 | Recipient is solely responsible for determining the appropriateness of using and
150 | distributing the Program and assumes all risks associated with its exercise of
151 | rights under this Agreement, including but not limited to the risks and costs of
152 | program errors, compliance with applicable laws, damage to or loss of data,
153 | programs or equipment, and unavailability or interruption of operations.
154 |
155 | 6. DISCLAIMER OF LIABILITY
156 |
157 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
158 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
159 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
160 | PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
161 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
162 | OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
163 | GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
164 |
165 | 7. GENERAL
166 |
167 | If any provision of this Agreement is invalid or unenforceable under applicable
168 | law, it shall not affect the validity or enforceability of the remainder of the
169 | terms of this Agreement, and without further action by the parties hereto, such
170 | provision shall be reformed to the minimum extent necessary to make such
171 | provision valid and enforceable.
172 |
173 | If Recipient institutes patent litigation against a Contributor with respect to
174 | a patent applicable to software (including a cross-claim or counterclaim in a
175 | lawsuit), then any patent licenses granted by that Contributor to such Recipient
176 | under this Agreement shall terminate as of the date such litigation is filed. In
177 | addition, if Recipient institutes patent litigation against any entity
178 | (including a cross-claim or counterclaim in a lawsuit) alleging that the Program
179 | itself (excluding combinations of the Program with other software or hardware)
180 | infringes such Recipient's patent(s), then such Recipient's rights granted under
181 | Section 2(b) shall terminate as of the date such litigation is filed.
182 |
183 | All Recipient's rights under this Agreement shall terminate if it fails to
184 | comply with any of the material terms or conditions of this Agreement and does
185 | not cure such failure in a reasonable period of time after becoming aware of
186 | such noncompliance. If all Recipient's rights under this Agreement terminate,
187 | Recipient agrees to cease use and distribution of the Program as soon as
188 | reasonably practicable. However, Recipient's obligations under this Agreement
189 | and any licenses granted by Recipient relating to the Program shall continue and
190 | survive.
191 |
192 | Everyone is permitted to copy and distribute copies of this Agreement, but in
193 | order to avoid inconsistency the Agreement is copyrighted and may only be
194 | modified in the following manner. The Agreement Steward reserves the right to
195 | publish new versions (including revisions) of this Agreement from time to time.
196 | No one other than the Agreement Steward has the right to modify this Agreement.
197 | IBM is the initial Agreement Steward. IBM may assign the responsibility to serve
198 | as the Agreement Steward to a suitable separate entity. Each new version of the
199 | Agreement will be given a distinguishing version number. The Program (including
200 | Contributions) may always be distributed subject to the version of the Agreement
201 | under which it was received. In addition, after a new version of the Agreement
202 | is published, Contributor may elect to distribute the Program (including its
203 | Contributions) under the new version. Except as expressly stated in Sections
204 | 2(a) and 2(b) above, Recipient receives no rights or licenses to the
205 | intellectual property of any Contributor under this Agreement, whether
206 | expressly, by implication, estoppel or otherwise. All rights in the Program not
207 | expressly granted under this Agreement are reserved.
208 |
209 | This Agreement is governed by the laws of the State of New York and the
210 | intellectual property laws of the United States of America. No party to this
211 | Agreement will bring a legal action under this Agreement more than one year
212 | after the cause of action arose. Each party waives its rights to a jury trial in
213 | any resulting litigation.
214 |
--------------------------------------------------------------------------------
/javaloader/JavaProxy.cfc:
--------------------------------------------------------------------------------
1 |
22 |
23 |
24 |
25 |
29 |
30 |
31 |
32 |
33 | var classLoader = createObject("java", "java.lang.ClassLoader").getSystemClassLoader();
34 | var objectClass = classLoader.loadClass("java.lang.Object");
35 |
36 | _setArray(createObject("java", "java.lang.reflect.Array"));
37 |
38 | _setClassMethod(objectClass.getMethod("getClass", JavaCast("null", 0)));
39 |
40 | _setObjectClass(objectClass);
41 |
42 | _setClass(arguments.class);
43 |
44 | _setModifier(createObject("java", "java.lang.reflect.Modifier"));
45 |
46 | _setStaticFields();
47 |
48 | _initMethodCollection();
49 |
50 | return this;
51 |
52 |
53 |
54 |
55 |
56 | var constructor = 0;
57 | var instance = 0;
58 |
59 | //make sure we only ever have one instance
60 | if(_hasClassInstance())
61 | {
62 | return _getClassInstance();
63 | }
64 |
65 | constructor = _resolveMethodByParams("Constructor", _getClass().getConstructors(), arguments);
66 |
67 | instance = constructor.newInstance(_buildArgumentArray(arguments));
68 |
69 | _setClassInstance(instance);
70 |
71 | return _getClassInstance();
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | var method = _findMethod(arguments.missingMethodName, arguments.missingMethodArguments);
81 |
82 | if(_getModifier().isStatic(method.getModifiers()))
83 | {
84 | return method.invoke(JavaCast("null", 0), _buildArgumentArray(arguments.missingMethodArguments));
85 | }
86 | else
87 | {
88 | if(NOT _hasClassInstance())
89 | {
90 | //run the default constructor, just like in normal CF, if there is no instance
91 | init();
92 | }
93 |
94 | return method.invoke(_getClassInstance(), _buildArgumentArray(arguments.missingMethodArguments));
95 | }
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | var fields = _getClass().getFields();
108 | var counter = 1;
109 | var len = ArrayLen(fields);
110 | var field = 0;
111 |
112 | for(; counter <= len; counter++)
113 | {
114 | field = fields[counter];
115 | if(_getModifier().isStatic(field.getModifiers()))
116 | {
117 | this[field.getName()] = field.get(JavaCast("null", 0));
118 | }
119 | }
120 |
121 |
122 |
123 |
124 |
125 |
126 | var len = StructCount(arguments);
127 | var objArray = _getArray().newInstance(_getObjectClass(), len);
128 | var counter = 1;
129 | var obj = 0;
130 |
131 | for(; counter <= len; counter++)
132 | {
133 | obj = arguments[counter];
134 | _getArray().set(objArray, counter - 1, obj);
135 | }
136 |
137 | return objArray;
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 | var decision = 0;
146 |
147 | if(StructKeyExists(_getMethodCollection(), arguments.methodName))
148 | {
149 | decision = StructFind(_getMethodCollection(), arguments.methodName);
150 |
151 | //if there is only one option, try it, it's only going to throw a runtime exception if it doesn't work.
152 | if(ArrayLen(decision) == 1)
153 | {
154 | return decision[1];
155 | }
156 | else
157 | {
158 | return _resolveMethodByParams(arguments.methodName, decision, arguments.methodArgs);
159 | }
160 | }
161 |
162 | throwException("JavaProxy.MethodNotFoundException", "Could not find the designated method", "Could not find the method '#arguments.methodName#' in the class #_getClass().getName()#");
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 | var decisionLen = ArrayLen(arguments.decision);
172 | var method = 0;
173 | var counter = 1;
174 | var argLen = ArrayLen(arguments.methodArgs);
175 | var parameters = 0;
176 | var paramLen = 0;
177 | var pCounter = 0;
178 | var param = 0;
179 | var class = 0;
180 | var found = true;
181 |
182 | for(; counter <= decisionLen; counter++)
183 | {
184 | method = arguments.decision[counter];
185 | parameters = method.getParameterTypes();
186 | paramLen = ArrayLen(parameters);
187 |
188 | found = true;
189 |
190 | if(argLen eq paramLen)
191 | {
192 | for(pCounter = 1; pCounter <= paramLen AND found; pCounter++)
193 | {
194 | param = parameters[pCounter];
195 | class = _getClassMethod().invoke(arguments.methodArgs[pCounter], JavaCast("null", 0));
196 |
197 | if(param.isAssignableFrom(class))
198 | {
199 | found = true;
200 | }
201 | else if(param.isPrimitive()) //if it's a primitive, it can be mapped to object primtive classes
202 | {
203 | if(param.getName() eq "boolean" AND class.getName() eq "java.lang.Boolean")
204 | {
205 | found = true;
206 | }
207 | else if(param.getName() eq "int" AND class.getName() eq "java.lang.Integer")
208 | {
209 | found = true;
210 | }
211 | else if(param.getName() eq "long" AND class.getName() eq "java.lang.Long")
212 | {
213 | found = true;
214 | }
215 | else if(param.getName() eq "float" AND class.getName() eq "java.lang.Float")
216 | {
217 | found = true;
218 | }
219 | else if(param.getName() eq "double" AND class.getName() eq "java.lang.Double")
220 | {
221 | found = true;
222 | }
223 | else if(param.getName() eq "char" AND class.getName() eq "java.lang.Character")
224 | {
225 | found = true;
226 | }
227 | else if(param.getName() eq "byte" AND class.getName() eq "java.lang.Byte")
228 | {
229 | found = true;
230 | }
231 | else if(param.getName() eq "short" AND class.getName() eq "java.lang.Short")
232 | {
233 | found = true;
234 | }
235 | else
236 | {
237 | found = false;
238 | }
239 | }
240 | else
241 | {
242 | found = false;
243 | }
244 | }
245 |
246 | if(found)
247 | {
248 | return method;
249 | }
250 | }
251 | }
252 |
253 | throwException("JavaProxy.MethodNotFoundException", "Could not find the designated method", "Could not find the method '#arguments.methodName#' in the class #_getClass().getName()#");
254 |
255 |
256 |
257 |
258 |
259 | var methods = _getClass().getMethods();
260 | var len = ArrayLen(methods);
261 | var counter = 1;
262 | var method = 0;
263 |
264 | _setMethodCollection(StructNew());
265 |
266 | for(; counter <= len; counter++)
267 | {
268 | method = methods[counter];
269 |
270 | if(NOT StructKeyExists(_getMethodCollection(), method.getName()))
271 | {
272 | StructInsert(_getMethodCollection(), method.getName(), ArrayNew(1));
273 | }
274 |
275 | ArrayAppend(StructFind(_getMethodCollection(), method.getName()), method);
276 | }
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
--------------------------------------------------------------------------------
/javaloader/JavaLoader.cfc:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 | instance = StructNew();
17 | instance.static.uuid = "A0608BEC-0AEB-B46A-0E1E1EC5F3CE7C9C";
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | initUseJavaProxyCFC();
33 |
34 | if(arguments.loadColdFusionClassPath)
35 | {
36 | //arguments.parentClassLoader = createObject("java", "java.lang.Thread").currentThread().getContextClassLoader();
37 | //can't use above, as doesn't work in some... things
38 |
39 | arguments.parentClassLoader = getPageContext().getClass().getClassLoader();
40 |
41 | //arguments.parentClassLoader = createObject("java", "java.lang.ClassLoader").getSystemClassLoader();
42 | //can't use the above, it doesn't have the CF stuff in it.
43 | }
44 |
45 | setClassLoadPaths(arguments.loadPaths);
46 | setParentClassLoader(arguments.parentClassLoader);
47 |
48 | ensureNetworkClassLoaderOnServerScope();
49 |
50 | loadClasses();
51 |
52 | if(structKeyExists(arguments, "sourceDirectories") AND ArrayLen(arguments.sourceDirectories))
53 | {
54 | setJavaCompiler(createObject("component", "JavaCompiler").init(arguments.compileDirectory));
55 | setSourceDirectories(arguments.sourceDirectories);
56 | setCompileDirectory(arguments.compileDirectory);
57 |
58 | setTrustedSource(arguments.trustedSource);
59 |
60 | compileSource();
61 |
62 | setSourceLastModified(calculateSourceLastModified());
63 |
64 | //do the method switching for non-trusted source
65 | if(NOT arguments.trustedSource)
66 | {
67 | variables.createWithoutCheck = variables.create;
68 |
69 | StructDelete(this, "create");
70 | StructDelete(variables, "create");
71 |
72 | this.create = variables.createWithSourceCheck;
73 | }
74 | }
75 |
76 | return this;
77 |
78 |
79 |
80 |
81 |
82 |
83 | try
84 | {
85 | //do this in one line just for speed.
86 | return createJavaProxy(getURLClassLoader().loadClass(arguments.className));
87 | }
88 | catch(java.lang.ClassNotFoundException exc)
89 | {
90 | throwException("javaloader.ClassNotFoundException", "The requested class could not be found.", "The requested class '#arguments.className#' could not be found in the loaded jars/directories.");
91 | }
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
116 |
117 | var local = {};
118 | var func = 0; //need this as cf8 doesn't like the structure with functions.
119 | var System = createObject("java", "java.lang.System");
120 | var Thread = createObject("java", "java.lang.Thread");
121 | var currentClassloader = Thread.currentThread().getContextClassLoader();
122 | var classLoader = "";
123 |
124 | if (structCount(arguments) == 4)
125 | {
126 | // the last 2 arguments are the function arguments and class loader
127 | classLoader = arguments[4];
128 | local.funcArgs = arguments[3];
129 | }
130 | else if (structCount(arguments) == 3)
131 | {
132 | // 2nd argument could be classloader or function arguments
133 | if (isInstanceOf(arguments[2],"java.lang.ClassLoader"))
134 | {
135 | classLoader = arguments[2];
136 | }
137 | else if (isStruct(arguments[2]))
138 | {
139 | local.funcArgs = arguments[2];
140 | }
141 |
142 | // 3rd argument could be classloader or function arguments
143 | if (isInstanceOf(arguments[3],"java.lang.ClassLoader"))
144 | {
145 | classLoader = arguments[3];
146 | }
147 | else if (isStruct(arguments[3]))
148 | {
149 | local.funcArgs = arguments[3];
150 | }
151 | }
152 | else if (structCount(arguments) == 2)
153 | {
154 | // the 2nd argument could be a class loader or function arguments
155 | if (isInstanceOf(arguments[2],"java.lang.ClassLoader"))
156 | {
157 | classLoader = arguments[2];
158 | }
159 | else if (isStruct(arguments[2]))
160 | {
161 | local.funcArgs = arguments[2];
162 | }
163 | }
164 |
165 | if (!structKeyExists(local,"funcArgs"))
166 | {
167 | local.funcArgs = {};
168 | }
169 |
170 | if (isSimpleValue(classLoader))
171 | {
172 | classLoader = getURLClassLoader();
173 | }
174 |
175 |
176 |
177 |
178 | Thread.currentThread().setContextClassLoader(classloader);
179 |
180 |
181 |
182 |
183 |
184 |
185 | func = arguments[1];
186 | local.return = func(argumentCollection = local.funcArgs);
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 | Thread.currentThread().setContextClassLoader(currentClassloader);
197 |
198 |
199 |
200 |
201 |
202 |
203 | //need to do this twice, as cf8 has no finally.
204 | Thread.currentThread().setContextClassLoader(currentClassloader);
205 |
206 | if(structKeyExists(local, "return"))
207 | {
208 | return local.return;
209 | }
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 | var dateLastModified = calculateSourceLastModified();
225 |
226 | /*
227 | If the source has changed in any way, recompile and load
228 | */
229 | if(dateCompare(dateLastModified, getSourceLastModified()) eq 1)
230 | {
231 | loadClasses();
232 | compileSource();
233 | }
234 |
235 | //if all the comilation goes according to plan, set the date last modified
236 | setSourceLastModified(dateLastModified);
237 |
238 | return createWithoutCheck(argumentCollection=arguments);
239 |
240 |
241 |
242 |
243 |
244 | var iterator = getClassLoadPaths().iterator();
245 | var file = 0;
246 | var classLoader = 0;
247 | var networkClassLoaderClass = 0;
248 | var networkClassLoaderProxy = 0;
249 |
250 | networkClassLoaderClass = getServerURLClassLoader().loadClass("com.compoundtheory.classloader.NetworkClassLoader");
251 |
252 | networkClassLoaderProxy = createJavaProxy(networkClassLoaderClass);
253 |
254 | if(isObject(getParentClassLoader()))
255 | {
256 | classLoader = networkClassLoaderProxy.init(getParentClassLoader());
257 | }
258 | else
259 | {
260 | classLoader = networkClassLoaderProxy.init();
261 | }
262 |
263 | while(iterator.hasNext())
264 | {
265 | file = createObject("java", "java.io.File").init(iterator.next());
266 | if(NOT file.exists())
267 | {
268 | throwException("javaloader.PathNotFoundException", "The path you have specified could not be found", file.getAbsolutePath() & " does not exist");
269 | }
270 |
271 | classLoader.addUrl(file.toURL());
272 | }
273 |
274 | setURLClassLoader(classLoader);
275 |
276 |
277 |
278 |
279 |
280 | var dir = 0;
281 | var path = 0;
282 |
283 | var paths = 0;
284 | var file = 0;
285 | var counter = 1;
286 | var len = 0;
287 | var directories = 0;
288 |
289 | //do check to see if the compiled jar is already there
290 | var jarName = calculateJarName(getSourceDirectories());
291 | var jar = getCompileDirectory() & "/" & jarName;
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 | //first we copy the source to our tmp dir
312 | directories = getSourceDirectories();
313 | len = arraylen(directories);
314 | for(; counter lte len; counter = counter + 1)
315 | {
316 | dir = directories[counter];
317 | $directoryCopy(dir, path);
318 | }
319 |
320 | //then we compile it, and grab that jar
321 |
322 | paths = ArrayNew(1); //have to write it this way so CF7 compiles
323 | ArrayAppend(paths, path);
324 |
325 | jar = getJavaCompiler().compile(paths, getURLClassLoader(), jarName);
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 | var file = hash(arrayToList(arguments.directoryArray)) & ".jar";
357 |
358 | return file;
359 |
360 |
361 |
362 |
363 |
364 | var lastModified = createDate(1900, 1, 1);
365 | var dir = 0;
366 | var qLastModified = 0;
367 | var directories = getSourceDirectories();
368 | var len = arraylen(directories);
369 | var counter = 0;
370 |
371 |
372 |
373 |
374 |
375 |
379 |
380 | //it's possible there are no source files.
381 | if(qLastModified.recordCount)
382 | {
383 | //get the latest date modified
384 | if(dateCompare(lastModified, qlastModified.dateLastModified) eq -1)
385 | {
386 | /*
387 | This is here, because cfdirectory only ever gives you minute accurate modified
388 | date, which is not good enough.
389 | */
390 | lastModified = createObject("java", "java.util.Date").init(createObject("java", "java.io.File").init(qLastModified.directory & "/" & qLastModified.name).lastModified());
391 | }
392 | }
393 | else
394 | {
395 | lastModified = Now();
396 | }
397 |
398 |
399 |
400 |
401 |
402 |
403 |
406 |
407 | var Class = createObject("java", "java.lang.Class");
408 | var Array = createObject("java", "java.lang.reflect.Array");
409 | var jars = queryJars();
410 | var iterator = jars.iterator();
411 | var file = 0;
412 | var urls = Array.newInstance(Class.forName("java.net.URL"), ArrayLen(jars));
413 | var counter = 0;
414 | var urlClassLoader = 0;
415 | var key = instance.static.uuid & "." & getVersion();
416 |
417 |
418 |
419 |
420 |
421 | if(NOT StructKeyExists(server, key))
422 | {
423 | while(iterator.hasNext())
424 | {
425 | Array.set(urls, counter, createObject("java", "java.io.File").init(iterator.next()).toURL());
426 | counter = counter + 1;
427 | }
428 |
429 | urlClassLoader = createObject("java", "java.net.URLClassLoader").init(urls);
430 |
431 | //put it on the server scope
432 | server[key] = urlClassLoader;
433 | }
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 | return createObject("java", "coldfusion.runtime.java.JavaProxy").init(arguments.class);
443 |
444 |
445 |
446 |
447 |
448 |
449 | return createObject("component", "JavaProxy")._init(arguments.class);
450 |
451 |
452 |
453 |
454 |
455 | try
456 | {
457 | createObject("java", "coldfusion.runtime.java.JavaProxy");
458 | }
459 | catch(Object exc)
460 | {
461 | //do method replacement, as it will be much faster long term
462 | variables.createJavaProxy = variables.createJavaProxyCFC;
463 | }
464 |
465 |
466 |
467 |
468 |
469 | var qJars = 0;
470 | //the path to my jar library
471 | var path = getDirectoryFromPath(getMetaData(this).path) & "lib/";
472 | var jarList = "";
473 | var aJars = ArrayNew(1);
474 | var libName = 0;
475 |
476 |
477 |
478 |
479 |
480 | libName = ListGetAt(qJars.name, 1, "-");
481 | //let's not use the lib's that have the same name, but a lower datestamp
482 | if(NOT ListFind(jarList, libName))
483 | {
484 | ArrayAppend(aJars, path & "/" & qJars.name);
485 | jarList = ListAppend(jarList, libName);
486 | }
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
--------------------------------------------------------------------------------