Giter Site home page Giter Site logo

box-java-sdk's Introduction

“box-dev-logo”

Box Java SDK

Project Status Platform License Build main Coverage

The Box Java SDK for interacting with the Box Content API.

Latest Release

Latest release can be found here.

Upgrades

You can read about how to migrate to the 4 version here.

Versions

We use a modified version of Semantic Versioning for all changes. See version strategy for details which is effective from 30 July 2022.

Supported Version

Only the current MAJOR version of SDK is supported. New features, functionality, bug fixes, and security updates will only be added to the current MAJOR version.

A current release is on the leading edge of our SDK development, and is intended for customers who are in active development and want the latest and greatest features. Instead of stating a release date for a new feature, we set a fixed minor or patch release cadence of maximum 2-3 months (while we may release more often). At the same time, there is no schedule for major or breaking release. Instead, we will communicate one quarter in advance the upcoming breaking change to allow customers to plan for the upgrade. We always recommend that all users run the latest available minor release for whatever major version is in use. We highly recommend upgrading to the latest SDK major release at the earliest convenient time and before the EOL date.

Version schedule

Version Supported Environments State First Release EOL/Terminated
4 Java 8 and up Supported 17 Jan 2023 TBD
3 Java 8 and up EOL 17 Jan 2022 17 Jan 2023
2 EOL 07 Jan 2016 17 Jan 2022
1 EOL 15 Apr 2015 07 Jan 2016

Getting Started

Getting Started Docs: https://developer.box.com/guides/tooling/sdks/java/ API Reference: https://developer.box.com/reference/

JVM

The SDK can be obtained by adding it as a maven dependency, cloning the source into your project, or by downloading one of the precompiled JARs from the releases page on GitHub.

If you are developing application for Android visit our Android guide

IF YOU USE THE JAR, you'll also need to include several dependencies:

  1. minimal-json v0.9.5 Maven: com.eclipsesource.minimal-json:minimal-json:0.9.5
  2. jose4j v0.9.4 Maven: org.bitbucket.b_c:jose4j:0.9.4
  3. bouncycastle bcprov-jdk18on v1.78.1 Maven: org.bouncycastle:bcprov-jdk18on:1.78.1
  4. bouncycastle bcpkix-jdk18on v1.78.1 Maven: org.bouncycastle:bcpkix-jdk18on:1.78.1
  5. Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 7 If you don't install this, you'll get an exception about key length or exception about parsing PKCS private key for Box Developer Edition. This is not a Box thing, this is a U.S. Government requirement concerning strong encryption. The listed jar is for Oracle JRE. There might be other similar JARs for different JRE versions like the one below for IBM JDK Java Cryptography Extension for IBM JDK
  6. okhttp v4.12.0 Maven: com.squareup.okhttp3:okhttp:4.12.0
  7. okio-jvm v3.2.0 Maven: com.squareup.okio:okio-jvm:3.2.0
  8. kotlin-stdlib v1.6.20 Maven: org.jetbrains.kotlin:kotlin-stdlib:1.6.20
  9. kotlin-stdlib-common v1.6.20 Maven: org.jetbrains.kotlin:kotlin-stdlib-common:1.6.20

An app has to be authorized by the admin of the enterprise before these tests. It's always good to begin with the Getting Started Section at Box's developer website.

Android

If you are developing application for Android visit our Android guide.

Box Java SDK and other frameworks

Box Java SDK utilizes the OkHttp client as its underlying component. This client is widely adopted by various frameworks, which can occasionally result in issues. We recommend considering library upgrades or excluding OkHttp from those frameworks or the software development kit (SDK) to determine if that resolves the problems. Typically, it is advisable to search for any reports or instances where others encountered similar issues when using the specific framework alongside an external OkHttp client.

Quick Test

Following things work only if the app has been configured and authorized as mentioned here

Here is a simple example of how to authenticate with the API using a developer token and then print the ID and name of each item in your root folder.

BoxAPIConnection api = new BoxAPIConnection("developer-token");
BoxFolder rootFolder = BoxFolder.getRootFolder(api);
for (BoxItem.Info itemInfo : rootFolder) {
    System.out.format("[%s] %s\n", itemInfo.getID(), itemInfo.getName());
}

For more details on how to get started, check out the overview guide. It has a short explanation of how the SDK works and how you can get started using it.

Sample Projects

Three sample projects can be found in src/example.

Main

This project will output your name and a list of the files and folders in your root directory.

To run the project, first provide a developer token in src/example/java/com/box/sdk/example/Main.java. You can obtain a developer token from your application's developer console.

public final class Main {
    private static final String DEVELOPER_TOKEN = "<YOUR_DEVELOPER_TOKEN>";

    // ...
}

Then just invoke gradle runExample to run the Main example!

Other projects

Below projects need app configurations stored in JSON format in config.json file at location src/example/config/.

This configuration file can be downloaded from your application's Configuration tab in the developer console

CreateAppUser

This project will output the user id of enterprise admin and will create a new App User for the enterprise.

To run the project, first provide the name of the app user in src/example/java/com/box/sdk/example/CreateAppUser.java.

public final class CreateAppUser {

    private static final String APP_USER_NAME = "";
    private static final String EXTERNAL_APP_USER_ID = "";

    // ...
}

Then just invoke gradle runCreateAppUser to run the CreateAppUser example!

Note: The JCE bundled with oracle JRE supports keys upto 128 bit length only. To use larger cryptographic keys, install JCE Unlimited Strength Jurisdiction Policy Files.

AccessAsAppUser

This project will retrieve the information of the given App User and will list the files/folders under root folder.

To run the project, first provide the Id of the app user in src/example/java/com/box/sdk/example/CreateAppUser.java.

public final class AccessAsAppUser {

    private static final String USER_ID = "";

    // ...
}

Then just invoke gradle runAccessAsAppUser to run the AccessAsAppUser example!

Note: The JCE bundled with oracle JRE supports keys upto 128 bit length only. To use larger cryptographic keys, install JCE Unlimited Strength Jurisdiction Policy Files.

BoxDeveloperEditionAPIConnectionAsEnterpriseUser

This example shows how to get tokens for an enterprise user, say admin of the enterprise and do actions on behalf of admin.

To run the project, follow below steps

  1. Turn on Enterprise in Application Access section in Developer Console for the app

  2. Turn on Generate User Access Tokens in Advanced Features section in Developer Console for the app

  3. Provide the Id of the admin user (or any enterprise user) in src/example/java/com/box/sdk/example/BoxDeveloperEditionAPIConnectionAsEnterpriseUser.java.

public final class BoxDeveloperEditionAPIConnectionAsEnterpriseUser {

   private static final String USER_ID = "";
   // ...
   Reader reader = new FileReader("src/example/config/config.json");
   BoxConfig boxConfig = BoxConfig.readFrom(reader);
   IAccessTokenCache accessTokenCache = new InMemoryLRUAccessTokenCache(10);

   BoxDeveloperEditionAPIConnection api = new BoxDeveloperEditionAPIConnection(
           USER_ID,
           DeveloperEditionEntityType.USER,
           boxConfig,
           accessTokenCache
   );
}

Compatibility

The Box Java SDK is compatible with Java 8 and up.

Building

The SDK uses Gradle for its build system. SDK comes with Gradle wrapper. Running ./gradlew build from the root of the repository will compile, lint, and test the SDK.

$ ./gradlew build

The SDK also includes integration tests which make real API calls, and therefore are run separately from unit tests. Integration tests should be run against a test account since they create and delete data. To run the integration tests, remove the .template extension from src/test/config/config.properties.template and fill in your test account's information. Then run:

$ ./gradlew integrationTest

Documentation

You can find guides and tutorials in the doc directory.

Javadocs are generated when gradle javadoc is run and can be found in build/doc/javadoc.

FIPS 140-2 Compliance

To generate a Json Web Signature used for retrieving tokens in the JWT authentication method, the Box Java SDK decrypts an encrypted private key. For this purpose, Box Java SDK uses libraries (org.bouncycastle:bcpkix-jdk18on:1.77 and org.bouncycastle:bcprov-jdk18on:1.77) that are NOT compatible with FIPS 140-2 validated cryptographic library (org.bouncycastle:bc-fips).

There are two ways of ensuring that decryption operation is FIPS-compiant.

  1. You can provide a custom implementation of the IPrivateKeyDecryptor interface, which performs the decryption operation using FIPS-certified library of your choice. The interface requires the implementation of just one method:
PrivateKey decryptPrivateKey(String encryptedPrivateKey, String passphrase);

After implementing the custom decryptor, you need to set your custom decryptor class in the Box Config. Below is an example of setting up a BoxDeveloperEditionAPIConnection with a config file and the custom decryptor.

Reader reader = new FileReader(JWT_CONFIG_PATH);
BoxConfig boxConfig = BoxConfig.readFrom(reader);
boxConfig.setPrivateKeyDecryptor(customDecryptor)
BoxDeveloperEditionAPIConnection api = BoxDeveloperEditionAPIConnection.getAppEnterpriseConnection(boxConfig);
  1. Alternative method is to override the Bouncy Castle libraries to the v.1.57 version, which are compatible with the FIPS 140-2 validated cryptographic library (org.bouncycastle:bc-fips).

NOTE: This solution is not recommended as Bouncy Castle v.1.57 has some moderate vulnerabilities reported against those versions, including:

  • CVE-2020-26939 - Observable Differences in Behavior to Error Inputs in Bouncy Castle
  • CVE-2020-15522 - Timing based private key exposure in Bouncy Castle

Furthermore,using Bouncy Castle v.1.57 may lead to Bouncycastle BadPaddingException for JWT auth.

Gradle example

implementation('com.box:box-java-sdk:x.y.z') {
   exclude group: 'org.bouncycastle', module: 'bcprov-jdk15on'
   exclude group: 'org.bouncycastle', module: 'bcpkix-jdk15on'
}
runtimeOnly('org.bouncycastle:bcprov-jdk15on:1.57')
runtimeOnly('org.bouncycastle:bcpkix-jdk15on:1.57')

Maven example:

<dependencies>
   <dependency>
      <groupId>com.box</groupId>
      <artifactId>box-java-sdk</artifactId>
      <version>x.y.z</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <groupId>org.bouncycastle</groupId>
          <artifactId>bcprov-jdk15on</artifactId>
        </exclusion>
         <exclusion>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcpkix-jdk15on</artifactId>
         </exclusion>
      </exclusions> 
   </dependency>
   <dependency>
      <groupId>org.bouncycastle</groupId>
      <artifactId>bcprov-jdk15on</artifactId>
      <version>1.57</version>
      <scope>runtime</scope>
   </dependency>
   <dependency>
      <groupId>org.bouncycastle</groupId>
      <artifactId>bcpkix-jdk15on</artifactId>
      <version>1.57</version>
      <scope>runtime</scope>
   </dependency>
</dependencies>

Bouncycastle BadPaddingException for JWT auth

As of October 2023, RSA keypairs generated on the Developer Console (refer to the Generate a keypair guide) are no longer compatible with Bouncy Castle version 1.57, which was utilized in the Box Java SDK up to v4.6.1. Attempting to use a JWT configuration downloaded from the Developer Console results in a javax.crypto.BadPaddingException: pad block corrupted error. Prossible solutions:

  1. Upgrade to the v4.7.0 of Box Java SDK, which uses newer version of the Bouncy Castle library. (recommended)
  2. Manually generate a keypair using OpenSSL version 1.0.x and add the Public Key to the Developer Console. The manually add keypair guide provides assistance in this process.

Copyright and License

Copyright 2019 Box, Inc. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

box-java-sdk's People

Contributors

antusus avatar arjankowski avatar box-sdk-build avatar breach10ck avatar cburnette avatar congminh1254 avatar danielandefors avatar dmaynard avatar dorfire avatar gcurtis avatar gleb-urvanov avatar iamharish avatar karthikshanmugasundaram avatar lukaszsocha2 avatar mgrytsai avatar mhagmajer avatar mmarmol avatar mwwoda avatar nealwu avatar pjsimon avatar pmatte1 avatar ppaulauskas avatar preciselyalyss avatar rschaller-box avatar silvestrelosada avatar sohtsuka avatar sujaygarlanka avatar swfree avatar tarrencev avatar tluthra avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

box-java-sdk's Issues

Have BoxEvent provide source info

Right now, BoxEvent has a getSource() method which returns a BoxResource, effectively discarding any of the source info that the API returned along with an event. To improve this, the method should be changed to getSourceInfo() and return a BoxResource.Info instead. This will prevent clients from needing to make an additional getInfo() request after receiving an event.

Get items in the trash

Create a BoxTrash class that implements Iterable<BoxItem.Info> for iterating over all the items in the trash.

Search for items

Add a search() method to BoxFolder that will search for any items that are descendants of the folder. The ancestor_folder_ids query parameter can be used to accomplish this. To search the user's entire tree, search can be called on the root folder.

The search method should also take a SearchOptions object that allows for setting all the advanced query parameters accepted by the API.

Bug report for EventStream.java: IllegalStateException in isDuplicate

Hey Greg,

EventStream.java has the following method:

    /**
     * Indicates whether or not an event ID is a duplicate.
     *
     * <p>This method can be overridden by a subclass in order to provide custom de-duping logic.</p>
     *
     * @param  eventID the event ID.
     * @return         true if the event is a duplicate; otherwise false.
     */
    protected boolean isDuplicate(String eventID) {
        if (this.receivedEvents == null) {
            this.receivedEvents = new LinkedHashSet<String>(LRU_SIZE);
        }

        boolean newEvent = this.receivedEvents.add(eventID);
        if (newEvent && this.receivedEvents.size() > LRU_SIZE) {
            this.receivedEvents.iterator().remove();
        }

        return !newEvent;
    }

The line this.receivedEvents.iterator().remove(); results in an IllegalStateException because you can't call .remove() on an iterator before calling .next().

Also, .iterator() doesn't guarantee that the elements will be returned in any particular order, so if you just call .remove() on the first element you get, you'll effectively be removing an element at random. I'm not sure exactly what your intention was here, but I just wanted to double check on that since I myself have lost a bunch of time to that problem in the past.

Thanks!

ClassCastException

version: boxjavalibv2-3.1.7 via maven
class: BoxClient
method: authenticate

public synchronized void authenticate(IAuthData authData) {
OAuthDataController oauthController = getOAuthDataController();
oauthController.setOAuthData((BoxOAuthToken) authData);
}

we store the oauth data with our own dataclasses. as i tried to authenticate with own IAuthData implementation, it crashed.
i think two of possible sollutions:

  1. oauthcontroller should use interface instead of BoxOAuthToken. i have not seen any point in the code, where the explicit implementation is needed
  2. methods which take interfaces should make sure the given object is an instance of wanted class or should create new instance of wanted class from interface.

Add a setter for an item's parent ID

An item's parent ID should be settable so that the item can be moved. This is needed in addition to a move() method so that bulk changes to an item's info can be done with one request.

Remove URL fields from BoxFolder and BoxFile

These classes have some URLs prebuilt and cached as field variables, which means they will be incorrect if the BoxAPIConnection base URL changes after the class is instantiated.

EventStream emitting duplicate events

The isDuplicate(...) method of EventStream incorrectly returns a value if it is duplicate. When a value is added to the LinkedHashSet, it returns true if it could be added, therefore not a duplicate. The return value needs to be the negative of the newEvent.

Document when BoxAPIExceptions can be thrown

All calls to a BoxAPIConnection right now throw the unchecked BoxAPIException on failure.

While this is fine for some situations, it can turn out to be troublesome in others when you want checked exceptions and deal with them the way you want. Especially since it is undocumented that this exception is thrown at all.

Is it possible to add checked exception calls? Or at least document that this unchecked exception is thrown?

Support ranged downloads

Add a downloadRange() method that allows you to specify a range of bytes for an HTTP range request.

Make the internal Info classes static

Making the Info classes static will make them a bit easier to create and eliminate the need for the obscure instance.new Info() syntax. It will also make testing easier, since mocking an Info class won't require that you also mock its enclosing class.

The Info constructors should be updated to require a BoxResource instance (since it can no longer be accessed with EnclosingClass.this).

Advanced search

Add a new search method that takes a SearchOptions object that allows for setting all the advanced query parameters accepted by the API.

Metadata support

This is a proposal for what using metadata might look like in the SDK. It should to cover the basic requirements of creating, updating, and removing metadata on files.

A Metadata class should be added that will support the default "properties" type. In the future, this class can be extended to possibly support other metadata types.

class Metadata extends BoxJSONObject {

    // Create new, empty metadata.
    Metadata() { ... }

    // Can be created from JSON in order to update existing metadata.
    Metadata(String json) { ... }

    // The following methods all return "this" for chaining when building a
    // JSON patch.
    Metadata add(String path, String value)
    Metadata replace(String path, String value)
    Metadata remove(String path)
    Metadata test(String path, String value)

    String get(String path)

    // Returns the patch JSON for updating existing metadata
    String getPatch() { ... }

    // Override BoxJSONObject method to return normal JSON for creating new
    // metadata.
    @Override
    String getPendingChanges() { ... }
}

Metadata can then be created, retrieved, updated, or deleted via the BoxFile class.

class BoxFile {
    // ...

    Metadata createMetadata(Metadata) { ... }
    Metadata getMetadata() { ... }
    Metadata updateMetadata(Metadata) { ... }
    void deleteMetadata() { ... }
}

An example of what it'd look like to use the SDK for updating the metadata on a file:

BoxFile myFile = new BoxFile(api, "id");
Metadata metadata = myFile.getMetadata()
    .add("/newKey", "new value")
    .test("/fruit", "apple")
    .remove("/fruit")
    .replace("existingKey", "new value");

myFile.updateMetadata(metadata);

Add comments to files

Add a method to BoxFile for adding new comments to the file. This method should automatically detect at-mentions to decide whether to use the message or tagged_message field.

Pick a different port for web server in unit tests

WireMock runs on port 8080, which is a pretty common port for running local web servers, so it may already be occupied. People will be less likely to encounter errors when running unit tests if a more random port were used.

Make token refresh thread-safe

It's possible for multiple requests to try and refresh the OAuth tokens simultaneously in a multithreaded environment. This could cause requests to fail or cause the API connection to enter an invalid state making it impossible to refresh.

A lock should be added so that only one call to BoxAPIConnection.refresh() can happen at once.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.