diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
new file mode 100644
index 0000000..2581fba
--- /dev/null
+++ b/.github/workflows/maven.yml
@@ -0,0 +1,23 @@
+name: Java CI
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ java: [8, 11, 16, 17]
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+ - name: Set up JDK
+ uses: actions/setup-java@v2.4.0
+ with:
+ distribution: 'temurin'
+ java-version: ${{matrix.java}}
+ cache: 'maven'
+ - name: Build with Maven
+ run: mvn verify -B -e -V --file pom.xml -Dgpg.skip=true
diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
new file mode 100644
index 0000000..fb9fbe9
--- /dev/null
+++ b/.github/workflows/pages.yml
@@ -0,0 +1,23 @@
+name: Publish Pages
+on:
+ push:
+ branches:
+ - master
+jobs:
+ build-and-deploy:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: Build
+ run: |
+ sudo apt-get update && sudo apt-get install -y pandoc
+ mkdir ghpages
+ pandoc -o ghpages/index.html README.md
+
+ - name: Deploy
+ uses: JamesIves/github-pages-deploy-action@4.1.5
+ with:
+ branch: gh-pages
+ folder: ghpages
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 6a06ba8..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-language: java
-
-addons:
- apt:
- update: true
- packages:
- - pandoc
-
-jdk:
- - oraclejdk11
- - openjdk8
- - openjdk9
- - openjdk10
- - openjdk11
- - openjdk12
-
-install:
- - mvn install -DskipTests=true -Dmaven.javadoc.skip=true -Dgpg.skip=true
- - mkdir ghpages
- - pandoc -o ghpages/index.html README.md
- - openssl aes-256-cbc -K $encrypted_60afd10366bc_key -iv $encrypted_60afd10366bc_iv -in ghpages_secret.enc -out ghpages_secret -d
-
-deploy:
- provider: pages:git
- edge: true
- skip_cleanup: true
- local_dir: ghpages
- deploy_key: ghpages_secret
- keep_history: true
- on:
- branch: master
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..b8b5301
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,56 @@
+# Changelog
+
+Note that new releases update the API types and services and may change or remove classes, methods, and types without
+notice.
+
+## [Unreleased]
+
+## [0.3.4] - 2021-12-17
+
+### Changed
+* Add deprecation annotations to types, properties, and methods. Deprecations may be removed in future changes to the
+ API.
+
+### Changed
+* New service definitions.
+
+## [0.3.3] - 2021-09-15
+
+### Changed
+* Updated services and types.
+* Updated dependencies.
+
+## [0.3.2] - 2021-01-20
+
+### Added
+* Added support for Bearer Authentication Token Support.
+
+```java
+import com.softlayer.api.*;
+ApiClient client = new RestApiClient().withBearerToken("qqqqwwwweeeaaassddd....");
+```
+
+### Changed
+* Updated services and types.
+
+## [0.3.1] - 2020-11-09
+
+### Changed
+* Updated services and types.
+
+## [0.3.0] - 2020-03-25
+
+### Added
+* Added a new `RestApiClient.BASE_SERVICE_URL` constant to use the client with the classic infrastructure private
+ network.
+
+### Changed
+* A breaking change has been made. Coerce return types to whatever the API metadata says should be returned, even if
+ the type returned by the API does not match (#64).
+
+* Updated services and types.
+
+## [0.2.9] - 2020-01-21
+
+### Changed
+* Updated generated services and types.
diff --git a/LICENSE b/LICENSE
index d8f5d64..213959f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2020 The SoftLayer Developer Network
+Copyright (c) 2021 The SoftLayer Developer Network
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 6612f93..a771bf3 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,19 @@
# SoftLayer API Client for Java
-[](https://travis-ci.org/softlayer/softlayer-java)
+[](https://github.com/softlayer/softlayer-java/actions/workflows/maven.yml)
[](https://search.maven.org/artifact/com.softlayer.api/softlayer-api-client)
[](https://www.javadoc.io/doc/com.softlayer.api/softlayer-api-client)
## Introduction
-This library provides a JVM client for the [SoftLayer API](http://sldn.softlayer.com/article/SoftLayer-API-Overview). It
+This library provides a JVM client for the [SoftLayer API](https://sldn.softlayer.com/article/getting-started/). It
has code generated and compiled via Maven. The client can work with any Java 8+ runtime. It uses the code generation
project in `gen/` to generate the service and type related code. Although likely to work in resource-constrained
environments (i.e. Android, J2ME, etc), using this is not recommended; Use the
-[REST](http://sldn.softlayer.com/article/REST) API instead.
+[REST](https://sldn.softlayer.com/article/rest/) API instead.
By default the HTTP client is the Java `HttpUrlConnection` and the JSON marshalling is done by
-[Gson](https://code.google.com/p/google-gson/). Both of these pieces can be exchanged for alternative implementations
+[Gson](https://github.com/google/gson). Both of these pieces can be exchanged for alternative implementations
(see below).
The `examples/` project has sample uses of the API. It can be executed from Maven while inside the `examples/` folder
@@ -40,20 +40,20 @@ additions to the SoftLayer API.
com.softlayer.api
softlayer-api-client
- 0.3.0
+ 0.3.4
```
### Gradle
```groovy
-implementation 'com.softlayer.api:softlayer-api-client:0.3.0'
+implementation 'com.softlayer.api:softlayer-api-client:0.3.4'
```
### Kotlin
```kotlin
-compile("com.softlayer.api:softlayer-api-client:0.3.0")
+compile("com.softlayer.api:softlayer-api-client:0.3.4")
```
### Creating a Client
@@ -61,20 +61,36 @@ compile("com.softlayer.api:softlayer-api-client:0.3.0")
All clients are instances of `ApiClient`. Currently there is only one implementation, the `RestApiClient`. Simply
instantiate it and provide your credentials:
+
+#### Username and API Key
+For using a Classic Infrastructure or IBM Cloud API key. When using the IBM Cloud Api key, your username is the literal string `apikey`, more information about that can be found on the SLDN [Authenticating to the SoftLayer API](https://sldn.softlayer.com/article/authenticating-softlayer-api/#cloud-api) article.
+
+:warning: Make sure to avoid hard coding your username and API key when using the client! Always pull credentials from the environment, secure config, or other source.
+
```java
import com.softlayer.api.*;
-ApiClient client = new RestApiClient().withCredentials("my user", "my api key");
+ApiClient client = new RestApiClient().withCredentials(myUser, myApiKey);
+```
+
+#### Access Token
+Information on how to get a temporary api token can be found on the SLDN
+[Authenticating to the SoftLayer API](https://sldn.softlayer.com/article/authenticating-softlayer-api/#temp-token)
+article.
+
+```java
+import com.softlayer.api.*;
+ApiClient client = new RestApiClient().withBearerToken(myBearerToken);
```
If the end point isn't at the normal SoftLayer API, you can provide the prefix to the constructor of the
-`RestApiClient`. By default it is set to the public API endpoint, `https://api.softlayer.com/rest/v3.1/`.
+`RestApiClient`. By default, it is set to the public API endpoint, `https://api.softlayer.com/rest/v3.1/`.
If you are using the classic infrastructure private network, you can communicate with the API over that network by using the service URL instead:
```java
ApiClient client = new RestApiClient(RestApiClient.BASE_SERVICE_URL)
- .withCredentials("my user", "my api key");
+ .withCredentials(myUser, myApiKey);
```
### Making API Calls
@@ -156,7 +172,7 @@ for (Vlan vlan : service.getObject().getNetworkVlans()) {
All values of a type can be masked upon. If a value represents a primitive or collection of primitives, the same mask
it is called on is returned. Otherwise the mask of the other type is given. These translate into SoftLayer's
-[string-based object mask format](http://sldn.softlayer.com/article/Object-Masks). A string or an instance of a mask
+[string-based object mask format](https://sldn.softlayer.com/article/object-masks/). A string or an instance of a mask
can be given directly by calling `setMask` on the service. Note, when object masks are added on a service object, they
will be sent with every service call unless removed via `clearMask` or overwritten via `withNewMask` or `setMask`.
@@ -296,4 +312,4 @@ fully qualified class name of your implementation on a single line in a file in
## Copyright
-This software is Copyright (c) 2020 The SoftLayer Developer Network. See the bundled LICENSE file for more information.
+This software is Copyright (c) 2021 The SoftLayer Developer Network. See the bundled LICENSE file for more information.
diff --git a/examples/pom.xml b/examples/pom.xml
index 9cf4371..f90f564 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -1,17 +1,20 @@
4.0.0
+
+ 3.3.9
+
com.softlayer.api
softlayer-api-client-examples
jar
- 0.3.0
+ 0.3.4
softlayer-api-client-examples
- http://sldn.softlayer.com
+ https://sldn.softlayer.com/
The MIT License (MIT)
- http://opensource.org/licenses/MIT
+ https://opensource.org/licenses/MIT
repo
@@ -36,7 +39,7 @@
org.codehaus.mojo
exec-maven-plugin
- 1.6.0
+ 3.0.0
diff --git a/examples/src/main/java/com/softlayer/api/example/Example.java b/examples/src/main/java/com/softlayer/api/example/Example.java
index db2d386..32566fc 100644
--- a/examples/src/main/java/com/softlayer/api/example/Example.java
+++ b/examples/src/main/java/com/softlayer/api/example/Example.java
@@ -17,7 +17,14 @@ public void start(String[] args) throws Exception {
baseUrl += '/';
}
- run(new RestApiClient(baseUrl).withCredentials(args[0], args[1]));
+ RestApiClient client;
+ // mvn -e -q compile exec:java -Dexec.args="QuickTest Bearer eyJraWQ.....
+ if (args[0].trim().equals("Bearer")) {
+ client = new RestApiClient(baseUrl).withBearerToken(args[1]);
+ } else {
+ client = new RestApiClient(baseUrl).withCredentials(args[0], args[1]);
+ }
+ run(client);
}
/** Run the example with the given client */
diff --git a/examples/src/main/java/com/softlayer/api/example/QuickTest.java b/examples/src/main/java/com/softlayer/api/example/QuickTest.java
new file mode 100644
index 0000000..24701da
--- /dev/null
+++ b/examples/src/main/java/com/softlayer/api/example/QuickTest.java
@@ -0,0 +1,28 @@
+package com.softlayer.api.example;
+
+import com.softlayer.api.ApiClient;
+import com.softlayer.api.RestApiClient;
+import com.softlayer.api.service.Account;
+
+
+/** A quick example for testing if authentication works.
+
+cd softlayer-java/examples
+mvn -e -q compile exec:java -Dexec.args="QuickTest Bearer eyJraWQ.....
+*/
+public class QuickTest extends Example {
+
+ @Override
+ public void run(ApiClient client) throws Exception {
+ client.withLoggingEnabled();
+ System.out.format("Authorization: %s\n", client.getCredentials());
+ Account.Service service = Account.service(client);
+
+ Account account = service.getObject();
+ System.out.format("Account Name: %s\n", account.getCompanyName());
+ }
+
+ public static void main(String[] args) throws Exception {
+ new QuickTest().start(args);
+ }
+}
diff --git a/gen/pom.xml b/gen/pom.xml
index c646e34..768a3a5 100644
--- a/gen/pom.xml
+++ b/gen/pom.xml
@@ -1,13 +1,16 @@
4.0.0
+
+ 3.3.9
+
com.softlayer.api
softlayer-api-client-gen
jar
- 0.3.0
+ 0.3.4
softlayer-api-client-gen
- http://sldn.softlayer.com
+ https://sldn.softlayer.com/
The MIT License (MIT)
@@ -29,12 +32,12 @@
com.google.code.gson
gson
- 2.8.5
+ 2.8.9
junit
junit
- 4.13.1
+ 4.13.2
test
@@ -43,7 +46,7 @@
org.codehaus.mojo
exec-maven-plugin
- 1.6.0
+ 3.0.0
@@ -58,7 +61,7 @@
org.apache.maven.plugins
maven-javadoc-plugin
- 3.1.1
+ 3.3.1
${java.version}
diff --git a/gen/src/main/java/com/softlayer/api/gen/ClassWriter.java b/gen/src/main/java/com/softlayer/api/gen/ClassWriter.java
index 671c04f..2d4ef46 100644
--- a/gen/src/main/java/com/softlayer/api/gen/ClassWriter.java
+++ b/gen/src/main/java/com/softlayer/api/gen/ClassWriter.java
@@ -134,6 +134,10 @@ public ClassWriter emitProperty(TypeClass.Property property) throws IOException
if (property.meta.doc != null) {
emitJavadoc(property.meta.doc.replace("\n", "
\n"));
}
+
+ if (property.meta.deprecated) {
+ emitAnnotation("Deprecated");
+ }
Map params = new HashMap<>(2);
if (!property.name.equals(property.meta.name)) {
@@ -267,6 +271,10 @@ public ClassWriter emitServiceMethod(TypeClass.Method method, boolean async) thr
javadoc += "@see " + type.meta.name + "::" + method.meta.name + "";
emitJavadoc(javadoc);
+
+ if (method.meta.deprecated) {
+ emitAnnotation("Deprecated");
+ }
Map params = new HashMap<>(2);
if (!method.name.equals(method.meta.name)) {
@@ -279,6 +287,10 @@ public ClassWriter emitServiceMethod(TypeClass.Method method, boolean async) thr
} else {
// Otherwise, just a javadoc link
emitJavadoc("Async version of {@link Service#" + method.name + "}");
+
+ if (method.meta.deprecated) {
+ emitAnnotation("Deprecated");
+ }
}
String[] parameters = new String[method.parameters.size() * 2];
@@ -296,6 +308,9 @@ public ClassWriter emitServiceMethod(TypeClass.Method method, boolean async) thr
// Async has an extra callback method
if (async) {
+ if (method.meta.deprecated) {
+ emitAnnotation("Deprecated");
+ }
parameters = Arrays.copyOf(parameters, parameters.length + 2);
parameters[parameters.length - 2] = TYPE_RESPONSE_HANDLER + '<' + method.javaType + '>';
parameters[parameters.length - 1] = "callback";
@@ -324,6 +339,10 @@ public ClassWriter emitServiceMethod(TypeClass.Property property, boolean async)
javadoc += "@see " + type.meta.name + "::" + name + "";
emitJavadoc(javadoc);
+
+ if (property.meta.deprecated) {
+ emitAnnotation("Deprecated");
+ }
// Instance is only required if it's not an account property
if ("SoftLayer_Account".equals(type.meta.name)) {
@@ -334,6 +353,10 @@ public ClassWriter emitServiceMethod(TypeClass.Property property, boolean async)
} else {
// Otherwise, just a javadoc link
emitJavadoc("Async version of {@link Service#" + name + "}");
+
+ if (property.meta.deprecated) {
+ emitAnnotation("Deprecated");
+ }
}
String returnType = property.javaType;
@@ -355,17 +378,12 @@ public ClassWriter emitType() throws IOException {
emitPackage(type.packageName);
emitTypeImports();
-
- // Javadoc
- String javadoc = type.meta.typeDoc != null ? type.meta.typeDoc : type.meta.serviceDoc;
- if (javadoc == null) {
- javadoc = "";
- } else {
- javadoc = javadoc.replace("\n", "
\n") + "\n\n";
+
+ emitJavadoc(getTypeJavadoc());
+
+ if (type.meta.deprecated) {
+ emitAnnotation("Deprecated");
}
- javadoc += "@see " + type.meta.name + "";
- emitJavadoc(javadoc);
// Each type has a type attribute
emitAnnotation("ApiType", stringLiteral(type.meta.name));
@@ -432,6 +450,18 @@ public ClassWriter emitType() throws IOException {
emitMask().endType();
return this;
}
+
+ protected String getTypeJavadoc() {
+ String javadoc = type.meta.typeDoc != null ? type.meta.typeDoc : type.meta.serviceDoc;
+ if (javadoc == null) {
+ javadoc = "";
+ } else {
+ javadoc = javadoc.replace("\n", "
\n") + "\n\n";
+ }
+ javadoc += "@see " + type.meta.name + "";
+ return javadoc;
+ }
public ClassWriter emitTypeImports() throws IOException {
Map imports = new HashMap<>(type.imports);
diff --git a/gen/src/main/java/com/softlayer/api/gen/Meta.java b/gen/src/main/java/com/softlayer/api/gen/Meta.java
index 7a9ad8d..838af47 100644
--- a/gen/src/main/java/com/softlayer/api/gen/Meta.java
+++ b/gen/src/main/java/com/softlayer/api/gen/Meta.java
@@ -75,6 +75,7 @@ public static class Type {
public String serviceDoc;
public Map methods = Collections.emptyMap();
public boolean noservice;
+ public boolean deprecated;
}
/**
@@ -86,6 +87,7 @@ public static class Property {
public boolean typeArray;
public PropertyForm form;
public String doc;
+ public boolean deprecated;
}
public enum PropertyForm {
@@ -109,6 +111,7 @@ public static class Method {
public boolean filterable;
public boolean maskable;
public List parameters = Collections.emptyList();
+ public boolean deprecated;
}
/**
diff --git a/ghpages_secret.enc b/ghpages_secret.enc
deleted file mode 100644
index 00f2d2d..0000000
Binary files a/ghpages_secret.enc and /dev/null differ
diff --git a/pom.xml b/pom.xml
index 8bb7ed9..23bd176 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,17 +1,20 @@
4.0.0
+
+ 3.3.9
+
com.softlayer.api
softlayer-api-client
jar
- 0.3.0
+ 0.3.4
SoftLayer API Client for Java
API client for accessing the SoftLayer API
- http://sldn.softlayer.com
+ https://sldn.softlayer.com
The MIT License (MIT)
- http://opensource.org/licenses/MIT
+ https://opensource.org/licenses/MIT
repo
@@ -27,9 +30,8 @@
camporter
Cameron Porter
- cmporter@softlayer.com
- SoftLayer
- http://softlayer.com
+ IBM
+ https://ibm.com/cloud
owner
developer
@@ -41,18 +43,12 @@
scm:git:git@github.com:softlayer/softlayer-java.git
scm:git:git@github.com:softlayer/softlayer-java.git
git@github.com:softlayer/softlayer-java.git
- 0.3.0
+ 0.3.4
UTF-8
8
-
-
- jcenter
- http://jcenter.bintray.com/
-
-
ossrh
@@ -67,18 +63,18 @@
com.google.code.gson
gson
- 2.8.5
+ 2.8.9
junit
junit
- 4.13.1
+ 4.13.2
test
org.mockito
mockito-core
- 3.3.3
+ 4.2.0
test
@@ -109,7 +105,7 @@
org.apache.maven.plugins
maven-javadoc-plugin
- 3.1.1
+ 3.3.1
@@ -129,7 +125,7 @@
org.apache.maven.plugins
maven-gpg-plugin
- 1.6
+ 3.0.1
sign-artifacts
@@ -143,7 +139,7 @@
maven-invoker-plugin
- 3.2.1
+ 3.2.2
generate-services
@@ -162,6 +158,48 @@
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.7
+
+
+ **/*com/softlayer/api/service/**/*
+
+
+
+
+
+ prepare-agent
+
+
+
+ report
+ prepare-package
+
+ report
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ versions-maven-plugin
+ 2.8.1
+
+
+
+ dependency-updates-report
+ plugin-updates-report
+ property-updates-report
+
+
+
+
+
+
diff --git a/src/main/java/com/softlayer/api/ApiClient.java b/src/main/java/com/softlayer/api/ApiClient.java
index 092d686..a637995 100644
--- a/src/main/java/com/softlayer/api/ApiClient.java
+++ b/src/main/java/com/softlayer/api/ApiClient.java
@@ -1,5 +1,7 @@
package com.softlayer.api;
+import com.softlayer.api.http.HttpCredentials;
+
/** Common interface for all API clients. {@link RestApiClient} is the preferred implementation */
public interface ApiClient {
@@ -9,7 +11,28 @@ public interface ApiClient {
* @return This instance
*/
ApiClient withCredentials(String username, String apiKey);
-
+
+ /**
+ * Uses a HTTP Bearer token for authentication instead of API key.
+ *
+ * @return This instance
+ */
+ ApiClient withBearerToken(String token);
+
+ /**
+ * Enables logging for client API calls
+ *
+ * @return This instance
+ */
+ ApiClient withLoggingEnabled();
+
+ /**
+ * Returns the HTTP Authorization header
+ *
+ * @return This instance
+ */
+ HttpCredentials getCredentials();
+
/**
* Get a service for the given sets of classes and optional ID. It is not recommended to call this
* directly, but rather invoke the service method on the type class.
diff --git a/src/main/java/com/softlayer/api/RestApiClient.java b/src/main/java/com/softlayer/api/RestApiClient.java
index f587b33..43450c8 100644
--- a/src/main/java/com/softlayer/api/RestApiClient.java
+++ b/src/main/java/com/softlayer/api/RestApiClient.java
@@ -18,7 +18,9 @@
import com.softlayer.api.annotation.ApiMethod;
import com.softlayer.api.annotation.ApiService;
+import com.softlayer.api.http.HttpCredentials;
import com.softlayer.api.http.HttpBasicAuthCredentials;
+import com.softlayer.api.http.HttpBearerCredentials;
import com.softlayer.api.http.HttpClient;
import com.softlayer.api.http.HttpClientFactory;
import com.softlayer.api.http.HttpResponse;
@@ -64,7 +66,7 @@ public class RestApiClient implements ApiClient {
private HttpClientFactory httpClientFactory;
private JsonMarshallerFactory jsonMarshallerFactory;
private boolean loggingEnabled = false;
- private HttpBasicAuthCredentials credentials;
+ private HttpCredentials credentials;
/**
* Create a Rest client that uses the publically available API.
@@ -114,6 +116,7 @@ public void setLoggingEnabled(boolean loggingEnabled) {
this.loggingEnabled = loggingEnabled;
}
+ @Override
public RestApiClient withLoggingEnabled() {
this.loggingEnabled = true;
return this;
@@ -141,7 +144,14 @@ public RestApiClient withCredentials(String username, String apiKey) {
return this;
}
- public HttpBasicAuthCredentials getCredentials() {
+ @Override
+ public RestApiClient withBearerToken(String token) {
+ credentials = new HttpBearerCredentials(token);
+ return this;
+ }
+
+ @Override
+ public HttpCredentials getCredentials() {
return credentials;
}
diff --git a/src/main/java/com/softlayer/api/http/BuiltInHttpClientFactory.java b/src/main/java/com/softlayer/api/http/BuiltInHttpClientFactory.java
index 5cf49f0..2d96b32 100644
--- a/src/main/java/com/softlayer/api/http/BuiltInHttpClientFactory.java
+++ b/src/main/java/com/softlayer/api/http/BuiltInHttpClientFactory.java
@@ -89,7 +89,7 @@ public void setThreadPool(ExecutorService threadPool) {
class BuiltInHttpClient implements HttpClient, HttpResponse {
- final HttpBasicAuthCredentials credentials;
+ final HttpCredentials credentials;
final String method;
final String fullUrl;
final Map> headers;
@@ -101,11 +101,7 @@ public BuiltInHttpClient(
String fullUrl,
Map> headers
) {
- // We only support basic auth
- if (credentials != null && !(credentials instanceof HttpBasicAuthCredentials)) {
- throw new UnsupportedOperationException("Only basic auth is supported, not " + credentials.getClass());
- }
- this.credentials = (HttpBasicAuthCredentials) credentials;
+ this.credentials = credentials;
this.method = method;
this.fullUrl = fullUrl;
this.headers = headers;
diff --git a/src/main/java/com/softlayer/api/http/HttpBearerCredentials.java b/src/main/java/com/softlayer/api/http/HttpBearerCredentials.java
new file mode 100644
index 0000000..951f4f2
--- /dev/null
+++ b/src/main/java/com/softlayer/api/http/HttpBearerCredentials.java
@@ -0,0 +1,24 @@
+package com.softlayer.api.http;
+
+/** HTTP Bearer authorization support for IBM IAM Tokens.
+ *
+ * @see IAM Tokens
+ * @see Authenticating SoftLayer API
+ */
+public class HttpBearerCredentials implements HttpCredentials {
+
+ protected final String token;
+
+ public HttpBearerCredentials(String token) {
+ this.token = token;
+ }
+
+ /**
+ * Formats the token into a HTTP Authorization header.
+ *
+ * @return String
+ */
+ public String getHeader() {
+ return "Bearer " + token;
+ }
+}
diff --git a/src/main/java/com/softlayer/api/http/HttpCredentials.java b/src/main/java/com/softlayer/api/http/HttpCredentials.java
index a0ae093..a751a46 100644
--- a/src/main/java/com/softlayer/api/http/HttpCredentials.java
+++ b/src/main/java/com/softlayer/api/http/HttpCredentials.java
@@ -2,4 +2,5 @@
/** Base interface for all accepted HTTP credentials */
public interface HttpCredentials {
+ String getHeader();
}
diff --git a/src/test/java/com/softlayer/api/http/BuiltInHttpClientFactoryTest.java b/src/test/java/com/softlayer/api/http/BuiltInHttpClientFactoryTest.java
index ee40c56..15a355c 100644
--- a/src/test/java/com/softlayer/api/http/BuiltInHttpClientFactoryTest.java
+++ b/src/test/java/com/softlayer/api/http/BuiltInHttpClientFactoryTest.java
@@ -15,21 +15,6 @@
public class BuiltInHttpClientFactoryTest {
- @Test
- public void testGetHttpClientWithoutBasicAuth() {
- try {
- new BuiltInHttpClientFactory().getHttpClient(
- new HttpCredentials() { },
- "GET",
- "http://example.com",
- Collections.emptyMap()
- );
- fail();
- } catch (UnsupportedOperationException e) {
- assertTrue(e.getMessage().contains("basic auth"));
- }
- }
-
@Test
public void testGetThreadPoolDefaultsToDaemonThreads() throws Exception {
boolean daemon = new BuiltInHttpClientFactory().getThreadPool().submit(
@@ -38,6 +23,14 @@ public void testGetThreadPoolDefaultsToDaemonThreads() throws Exception {
assertTrue(daemon);
}
+ @Test
+ public void testGetThreadPoolLazyLoading() {
+ BuiltInHttpClientFactory factory = new BuiltInHttpClientFactory();
+ ExecutorService threadPool = factory.getThreadPool();
+ assertNotNull(threadPool);
+ assertEquals(threadPool, factory.getThreadPool());
+ }
+
@Test
public void testSetThreadPoolShutsDownNonUserDefined() {
BuiltInHttpClientFactory factory = new BuiltInHttpClientFactory();
diff --git a/src/test/java/com/softlayer/api/http/HttpBearerCredentialsTest.java b/src/test/java/com/softlayer/api/http/HttpBearerCredentialsTest.java
new file mode 100644
index 0000000..0a1d67d
--- /dev/null
+++ b/src/test/java/com/softlayer/api/http/HttpBearerCredentialsTest.java
@@ -0,0 +1,22 @@
+package com.softlayer.api.http;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class HttpBearerCredentialsTest {
+
+ public final String bearerToken = "qqqqwwwweeerrttyyuuiiooppasddfgfgjghjkjklZXxcvcvbvbnnbm";
+ @Test
+ public void testConstructor() {
+ HttpBearerCredentials authCredentials = new HttpBearerCredentials(bearerToken);
+ assertEquals(bearerToken, authCredentials.token);
+ }
+
+ @Test
+ public void testGetHeader() {
+ HttpBearerCredentials authCredentials = new HttpBearerCredentials(bearerToken);
+ String header = "Bearer " + bearerToken;
+ assertEquals(header, authCredentials.getHeader());
+ }
+}