Before continuing please familiarize yourself with the API and it's methodology at https://api.sharefile.com/rest
All code is licensed under the MIT License.
applicationControlPlane
- Describes the domain that the ShareFile account is available on.
For example:sharefile.com
,securevdr.com
,sharefile.eu
, etc.authorizationUrl
- The initial url that should be visited to being web authentication.client_id
- The identifier that is uniquely identifies an OAuth client consumer.client_secret
- This is a shared secret that is required to exchange anOAuthAuthorizationCode
for anOAuthToken
.completionUri
- Alias forredirectUri
. Used primarily inOAuth2AuthenticationHelper
.OAuthAuthorizationCode
- One-time use code that is returned as part of an oauthcode
grant request.
We provide a class with the specific properties for this type of response.OAuthToken
- Used to authenticate with ShareFile, specifically using AccessToken - however, this is taken care of for you by the SDK.redirectUri
- Resource that can be used to track when authentication is complete. Generally, this resource is controlled by the OAuth client consumer.state
- Token created by the OAuth consumer to associate an authorization request with an authorization response.
In the servers
repository, the root-level pom.xml
should have sharefile-api listed as a dependency with the current version. It should also be listed in the pom.xml
for web
, without version. On build, it will look for the artifact in your local maven repository, or in github packages if it doesn't find it locally.
Note build.gradle
for this project has a section uploadArchives
for generating those artifacts. Since we're no longer hosting these packages on EFS, there's now only a single repository listed, your local maven repository (which should point at ~/.m2
). After building and deploying your new version to your local maven (./gradlew build && ./gradlew uploadArchives
), you can test against it by updating the pom.xml
file described above to point to your new version. When ready to deploy widely, you can publish the new version using the process described here https://everlaw.atlassian.net/wiki/spaces/ENG/pages/403963963/Github+Packages#Uploading-artifacts
The SDK is a pure Java code and you can build it using the Eclipse IDE (Kepler or higher) or using the Android Studio IDE. Simply point your IDE's import functionality to the SDK folder and it should be able to import the projects correctly. Make sure you have Java-7 JDK atleast. You could either generate .jar
files from the SDK and use them in your application projects or directly include the SDK Module in your Android application Project or Eclipse Workspace of the application.
Alternatively you can use the SDK without building the SDK code, if you are using Gradle or Maven, you can directly add the dependency as follows: (Always check for the latest version here on mavenCentral since we keep posting enhancements and bug fixes. Alternatively use 3.+ as the version code in dependencies.)
-
Gradle Dependency:
dependencies { compile 'com.citrix:sharefile-api:3.1.0' }
Gradle on Android might need the addional :
android { //... packagingOptions { exclude 'META-INF/DEPENDENCIES' exclude 'META-INF/LICENSE' exclude 'META-INF/NOTICE' } //... }
-
Maven Dependence:
<dependency> <groupId>com.citrix</groupId> <artifactId>sharefile-api</artifactId> <version>3.1.0</version> </dependency>
The project uses Java-7 source compatibility. So in case you see errors like :
- Error:(87, 46) java: diamond operator is not supported in -source 1.6 (use -source 7 or higher to enable diamond operator)
- Error:(281, 37) java: multi-catch statement is not supported in -source 1.6 (use -source 7 or higher to enable multi-catch statement)
To fix these set the follow settings depend on your IDE:
-
Android Studio:
File->Project Structure->Project language Level to 7.0
-
Eclipse :
File->Properties->JavaCompiler->Compiler Compliance level to 1.7
If you are using pro-guard, make sure to set the following in the configuration file.
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.citrix.sharefile.api.** { *; }
-
Initializing the SDK can be done as follows:
SFSdk.init("[client_id]","[client_secret]","[redirect_url]");
Optionally implement the ILog interface to read the logs generated when the SDK functions execute
SFSdk.setLogger(new ILog(){...});
Authentication with ShareFile v3 API makes use of OAuth 2.0 protocol. Some helper methods and classes are provided to make authentication easier for consumers.
-
Web Authentication [To be Done]
-
Password Authentication: Requires the consumer perform ShareFile account discovery, which is not currently documented. In order to complete this authentication the consumer will must know
username
,password
,subdomain
, andapplicationControlPlane
. In the sample below, these are assumed to have been obtained already.ISFOAuthService oAuthService = new SFOAuthService(); SFOAuth2Token authToken = oAuthService.authenticate (subdomain, apiControlPlane, username, password);
Or Asynchronously. Note: all the functions exposed by the SDK which make network calls have a synchronous as well as Async versions to simplify using the SDK on systems like Android where network calls need to executed asynchronously on a non-UI thread.
oAuthService.authenticateAsync(subdomain, apiControlPlane, username, password, oAuthTokenCallback);
-
SAML Authentication: This authentication support assumes you have a mechanism for obtaining a SAML assertion,
samlAssertion
from the user's IdP.ISFOAuthService oAuthService = new SFOAuthService(); SFOAuth2Token authToken = oAuthService.authenticate (subdomain, apiControlPlane, samlAssertion);
Or Asynchronously
oAuthService.authenticateAsync(subdomain, apiControlPlane, samlAssertion, oAuthTokenCallback);
-
Refreshing an OAuthToken: Any
OAuthToken
that is obtained using acode
grant type can be refreshed. This allows a consumer to silently reauthenticate with the ShareFile API without needing to prompt the user. This is useful if you plan on caching theOAuthToken
. The sample below assumes you have already pulled an instance ofOAuthToken
ascachedOAuthToken
from some local cache.ISFOAuthService oAuthService = new SFOAuthService(); SFOAuth2Token authToken = oAuthService.refreshOAuthToken(oldAuthToken);//equivalent Async function available
Once authenticated, getting information from ShareFile is pretty easy.
Below are some samples on what you can do, it assumes there is an instance of
ShareFileClient - sfClient
available. As mentioned previously: all the functions exposed by the SDK which make network calls have a synchronous(blocking) as well as Async versions to simplify using the SDK on systems like Android where network calls need to executed asynchronously on a non-UI thread.
The general pattern of sdk calls you can make is of the following type:
-
Blocking calls
try { SFObject object = apiClient.<some function>.execute(); } catch(SFSDKException exception) { //handle errors }
-
Async(Non-blocking) calls:
The Async versions of the functions take a callback function of the following type:
ISFApiResultCallback<T>
and return the appropriate results orSFSDKException
.ISFApiResultCallback<T> callback = new ISFApiResultCallback<T>() { @Override public void onSuccess(T returnValue) { //handle success } @Override public void onError(SFSDKException exception, ISFQuery<T> originalQuery) { //handle failure } }
Everything related to the ShareFile API can be accessed by using an instance of the SFApiClient
ISFApiClient apiClient = new SFApiClient(oAuthToken);
SFSession session = apiClient.sessions().login().execute(); //or executeAsync(callback)
apiClient.sessions().delete().execute(); // or executeAsync(callback)
A User in ShareFile derives from the SFPrincipal
object. For most consumers you
will be interested in SFUser
and SFAccountUser
. The SFAccountUser
type designates
the user to be an Employee and will have some additional properties available.
SFUser user = apiClient.users().get().execute(); //or executeAsync(callback)
This call will return the default folder for the currently authenticated SFUser
.
SFFolder folder = apiClient.items().get().execute(); //or executeAsync(callback)
SFODataFeed<SFItem> folderContents = apiClient.items().getChildren(parentURI).execute();
//or executeAsync(callback)
ArrayList<SFItem> children = folderContents.getFeed();
//Assuming you have got access to the (SFFolder) parentFolder object using one
//of the above methods of folder/children enumeration
SFFolder newFolder = new SFFolder();
newFolder.setName("new folder1");
apiClient.items().createFolder(parentFolder.geturl(),newFolder).execute(); //or executeAsync(callback)
SFSearchResults searchResult = apiClient.items().search("query").execute();
ArrayList<SFSearchResult> result = searchResult.getResults();
To browse search results (currently, there is no Uri
returned that points to the Item
):
SFSearchResult item = result.get(index);
URI uri = apiClient.getDefaultUrl(item.getId());
SFItem actualItem = apiClient.items().get(uri).execute();
There are some folders within ShareFile that are not easily discovered, however
the SDK can help you find them. These aliases are exposed on the SFFolderID
.
URI itemUri = apiClient.items().getDefaultUrl(SFFolderID.TOP);
SFFolder folder = apiClient.items.get(itemUri).execute(); //or executeAsync(callback)
SFFile fileToDownload;//Assuming you have obtained a valid SFFile object from the folder enumeration
OutputStream outputStream = new FileOutputStream("system specific file path");
TransferRunnable.IProgress progressListener = new TransferRunnable.IProgress()
{
@Override
public void bytesTransfered(long bytesTransfered) {}
@Override
public void onError(SFSDKException e, long bytesTransfered) {}
@Override
public void onComplete(long bytesTransfered) {}
};
SFDownloadRunnable downloader = apiClient.getDownloader(fileToDownload,outputStream, progressListener);
downloader.start(); // this is async by default
TransferRunnable.IProgress progressListener = new TransferRunnable.IProgress()
{
@Override
public void bytesTransfered(long bytesTrasnfered) {}
@Override
public void onError(SFSDKException e, long bytesTrasnfered) {}
@Override
public void onComplete(long bytesTrasnfered) {}
};
FileInputStream inputStream = new FileInputStream("system specific file path");
SFUploadRequestParams requestParams = new SFUploadRequestParams();
requestParams.setFileName("destinaltionFileName");
requestParams.setDetails("details");
requestParams.setFileSize((long) inputStream.available());
requestParams.seturl(parentUrl);
SFUploadRunnable uploader = apiClient.getUploader(requestParams,inputStream,progressListener);
uploader.start(); // this is async by default
Assuming you have the url that points to the Share API resource (ex. https://subdomain.sharefile.com/sf/v3/Shares(s0123456789)
), you can easily access the Items
shared. Depending on the share you may be required to already be authenticated.
URI uri = new URI("https://subdomain.sharefile.com/sf/v3/Shares(s0123456789)");
SFShare share = apiClient.shares().get(uri).execute();
SFODataFeed<SFItem> items = apiClient.shares().getItems(uri).execute();
ArrayList<SFItem> shareItems = items.getFeed();
Items associated with a Share
cannot be downloaded as you normally might, instead you need to use the Shares
API to download.
// assuming you already have shareItems as noted before
InputStream inputStream = apiClient.shares().downloadWithAlias(uri,share.getAliasID(),shareItems.get(0).getId()).execute();
ShareFile supports the oData protocol which provides standard ways of handling common tasks such as:
- Select specific properties
- Expand Navigation properties such as
Folder.Children
- Perform paging operations
The following Query
will only select the Name property. If you execute this,
all other properties will be their default values. This is convenient for
reducing payloads on the wire.
SFFolder folder = (SFFolder) apiClient.items().get().select("Name").execute();
The following Query
will expand Children
. Since we know we are querying for
a Folder
we can ask ShareFile to go ahead and return the list of Children. This
helps reduce the number of round trips required. Note Chlidren
is presented
as a ArrayList<SFItem>
instead of an SFODataFeed<SFItem>
.
SFFolder folder = (SFFolder) apiClient.items().get().expand("Children").execute();
ArrayList<SFItems> children = folder.getChildren();
When working with ODataFeed
responses, you can limit the size of the response
by using Top
and Skip
. The following Query
will return up to 10 Children
and skip the first 10.
SFODataFeed<SFItem> children = apiClient.items().getChildren(parenturl).top(10).skip(10).execute();
To support paging ODataFeed
will also return a nextLink which will compute the
Top and Skip values for you.
The ShareFile SDK is a pure Java SDK and can be directly used with Android apps. To make life simpler for the Android developers, the SDK Allows you to extend the SDK to suit some of the Android specific constructs as follows:
You can use the Android Log.*() mechanism so you can get the logs from execution of the SDK functions by implementing the ILog interface:
public class SFLogger implements ILog
{
@Override
public int v(String tag, String msg)
{
return Log.v("SF_"+tag, msg);
}
@Override
public int v(String tag, String msg, Throwable tr) {
return Log.v("SF_"+tag, msg);
}
//…. Lots more overrides
@Override
public int e(String tag, String msg, Throwable tr) {
return Log.v("SF_"+tag, msg,tr);
}
}
SFSdk.setLogger(new SFLogger());
The SDK Async functions rely on the Java Threads by default. You can use the Android AsyncTask instead by registering an AsyncTaskFactory with the SDK and creating your own AsyncTasks follows. This is a onetime thing which you can do in the Application().onCreate() of your Android app.
private static ISFAsyncTaskFactory asyncTaskFactory = new ISFAsyncTaskFactory()
{
@Override
protected ISFAsyncTask createNewTask()
{
return new SampleAsyncTask();
}
};
SFSdk.setAsyncTaskFactory(asyncTaskFactory);
Following is a sample Asynctask. Note the use of the IAsyncHelper
in the task.
public class SampleAsyncTask extends AsyncTask implements ISFAsyncTask
{
ISFAsyncHelper asyncHelper;
@Override
protected Object doInBackground(Object[] objects)
{
asyncHelper.execute();
return null;
}
@Override
protected void onPostExecute(Object o)
{
super.onPostExecute(o);
asyncHelper.onPostExecute();
}
@Override
public void start(ISFAsyncHelper asyncHelper)
{
this.asyncHelper = asyncHelper;
executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}