/* * Copyright 2012 Evernote Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.evernote.client.android; import com.evernote.client.conn.mobile.TEvernoteHttpClient; import com.evernote.edam.error.EDAMNotFoundException; import com.evernote.edam.error.EDAMSystemException; import com.evernote.edam.error.EDAMUserException; import com.evernote.edam.type.LinkedNotebook; import com.evernote.edam.userstore.AuthenticationResult; import com.evernote.thrift.TException; import com.evernote.thrift.protocol.TBinaryProtocol; import com.evernote.thrift.transport.TTransportException; import java.io.File; import java.util.Map; /** * A class to produce User and Note store clients. * * * @author @briangriffey * @author @tylersmithnet */ public class ClientFactory { private static final String LOGTAG = "ClientFactory"; private static final String USER_AGENT_KEY = "User-Agent"; private String mUserAgent; private Map<String, String> mCustomHeaders; private File mTempDir; /** * Private constructor */ private ClientFactory() {} /** * This should always be requested through an {@link com.evernote.client.android.EvernoteSession} */ ClientFactory(String userAgent, File tempDir) { mUserAgent = userAgent; mTempDir = tempDir; } /** * Create a new NoteStore client. Each call to this method will return * a new NoteStore.Client instance. The returned client can be used for any * number of API calls, but is NOT thread safe. * * @throws IllegalStateException if @link #isLoggedIn() is false. * @throws TTransportException if an error occurs setting up the * connection to the Evernote service. */ public AsyncNoteStoreClient createNoteStoreClient() throws TTransportException { if(EvernoteSession.getOpenSession() == null || EvernoteSession.getOpenSession().getAuthenticationResult() == null) { throw new IllegalStateException(); } TEvernoteHttpClient transport = new TEvernoteHttpClient(EvernoteSession.getOpenSession().getAuthenticationResult().getNoteStoreUrl(), mUserAgent, mTempDir); TBinaryProtocol protocol = new TBinaryProtocol(transport); return new AsyncNoteStoreClient(protocol, protocol, EvernoteSession.getOpenSession().getAuthenticationResult().getAuthToken()); } /** * This is an async call to retrieve a business note store. * * @param callback to receive results from creating NoteStore */ public void createBusinessNoteStoreClientAsync(final OnClientCallback<AsyncBusinessNoteStoreClient> callback) { AsyncReflector.execute(this, callback, "createBusinessNoteStoreClient"); } /** * * Create a new Business NoteStore client. Each call to this method will return * a new NoteStore.Client instance. The returned client can be used for any * number of API calls, but is NOT thread safe. * * This method will check expiration time for the business authorization token, this is a network request * * This method is synchronous * * @throws TException * @throws EDAMUserException * @throws EDAMSystemException User is not part of a business */ public AsyncBusinessNoteStoreClient createBusinessNoteStoreClient() throws TException, EDAMUserException, EDAMSystemException { com.evernote.client.android.AuthenticationResult authResult = EvernoteSession.getOpenSession().getAuthenticationResult(); if(authResult.getBusinessAuthToken() == null || authResult.getBusinessAuthTokenExpiration() < System.currentTimeMillis()) { AuthenticationResult businessAuthResult = createUserStoreClient().getClient().authenticateToBusiness(authResult.getAuthToken()); authResult.setBusinessAuthToken(businessAuthResult.getAuthenticationToken()); authResult.setBusinessAuthTokenExpiration(businessAuthResult.getExpiration()); authResult.setBusinessNoteStoreUrl(businessAuthResult.getNoteStoreUrl()); authResult.setBusinessUser(businessAuthResult.getUser()); } TEvernoteHttpClient transport = new TEvernoteHttpClient(authResult.getBusinessNoteStoreUrl(), mUserAgent, mTempDir); TBinaryProtocol protocol = new TBinaryProtocol(transport); return new AsyncBusinessNoteStoreClient(protocol, protocol, authResult.getBusinessAuthToken(), this); } /** * Creates a LinkedNoteStoreClient from a {@link LinkedNotebook} asynchronously * * @param notebook * @param callback */ public void createLinkedNoteStoreClientAsync(LinkedNotebook notebook, OnClientCallback<AsyncLinkedNoteStoreClient> callback) { AsyncReflector.execute(this, callback, "createLinkedNoteStoreClient", notebook); } /** * Creates a LinkedNoteStoreClient from a {@link LinkedNotebook} synchronously * * @param linkedNotebook */ public AsyncLinkedNoteStoreClient createLinkedNoteStoreClient(LinkedNotebook linkedNotebook) throws EDAMUserException, EDAMSystemException, TException, EDAMNotFoundException { com.evernote.client.android.AuthenticationResult authResult = EvernoteSession.getOpenSession().getAuthenticationResult(); TEvernoteHttpClient transport = new TEvernoteHttpClient(linkedNotebook.getNoteStoreUrl(), mUserAgent, mTempDir); TBinaryProtocol protocol = new TBinaryProtocol(transport); AsyncLinkedNoteStoreClient sharedNoteStore = new AsyncLinkedNoteStoreClient(protocol, protocol, authResult.getAuthToken(), this); AuthenticationResult sharedAuthKey = sharedNoteStore.getAsyncClient().getClient().authenticateToSharedNotebook(linkedNotebook.getShareKey(), authResult.getAuthToken()); sharedNoteStore.setAuthToken(sharedAuthKey.getAuthenticationToken()); return sharedNoteStore; } /** * Create a new UserStore client. Each call to this method will return * a new UserStore.Client instance. The returned client can be used for any * number of API calls, but is NOT thread safe. * * @throws IllegalStateException if @link #isLoggedIn() is false. * @throws TTransportException if an error occurs setting up the * connection to the Evernote service. * */ public AsyncUserStoreClient createUserStoreClient() throws IllegalStateException, TTransportException { if(EvernoteSession.getOpenSession() == null || EvernoteSession.getOpenSession().getAuthenticationResult() == null) { throw new IllegalStateException(); } return createUserStoreClient(EvernoteSession.getOpenSession().getAuthenticationResult().getEvernoteHost()); } /** * Creates a UserStore client interface that can be used to send requests to a * particular UserStore server. For example, the following would provide a * handle to make requests from the "MyClient" application to talk to the * Evernote server at "www.evernote.com" : * <p/> * <pre> * UserStore.Iface userStore = factory.createUserStoreClient("www.evernote.com", * "MyClient (Java)"); * </pre> * <p/> * This call does not actually initiate any communications with the UserStore, * it only creates the handle that will be used. * * @param url the hostname (or numeric IP address) for the server that we should * communicate with. This will attempt to use HTTPS to talk to that * server unless the hostname contains a port number component, in * which case we'll use plaintext HTTP. * @param url the hostname (or numeric IP address) for the server that we should * communicate with. This will attempt to use HTTPS to talk to that * server unless the hostname contains a port number component, in * which case we'll use plaintext HTTP. * @return * @throws TTransportException */ AsyncUserStoreClient createUserStoreClient(String url) throws TTransportException { return createUserStoreClient(url, 0); } /** * Create a new UserStore client. Each call to this method will return * a new UserStore.Client instance. The returned client can be used for any * number of API calls, but is NOT thread safe. * * @param url to connect to * @param port to connect on * * @throws IllegalStateException if @link #isLoggedIn() is false. * @throws TTransportException if an error occurs setting up the * connection to the Evernote service. * */ AsyncUserStoreClient createUserStoreClient(String url, int port) throws TTransportException { String serviceUrl = getFullUrl(url, port); TEvernoteHttpClient transport = new TEvernoteHttpClient(serviceUrl, mUserAgent, mTempDir); if (mCustomHeaders != null) { for (Map.Entry<String, String> header : mCustomHeaders.entrySet()) { transport.setCustomHeader(header.getKey(), header.getValue()); } } if (mUserAgent != null) { transport.setCustomHeader(USER_AGENT_KEY, mUserAgent); } TBinaryProtocol protocol = new TBinaryProtocol(transport); String authToken = null; if(EvernoteSession.getOpenSession().isLoggedIn()) { authToken = EvernoteSession.getOpenSession().getAuthenticationResult().getAuthToken(); } return new AsyncUserStoreClient(protocol, protocol, authToken); } private String getFullUrl(String serviceUrl, int port) { String url = ""; if (port != 0) serviceUrl += ":" + port; if (!serviceUrl.startsWith("http")) { url = serviceUrl.contains(":") ? "http://" : "https://"; } url += serviceUrl + "/edam/user"; return url; } /** * The user agent defined for the connection */ public String getUserAgent() { return mUserAgent; } /** * Set a custom UserAgent String for the client connection * * @param mUserAgent */ public void setUserAgent(String mUserAgent) { this.mUserAgent = mUserAgent; } /** * if non-null, this is a mapping of HTTP headers to values which * will be included in the request. */ public Map<String, String> getCustomHeaders() { return mCustomHeaders; } /** * Allows custom headers to be defined for the Client connection * * @param mCustomHeaders */ public void setCustomHeaders(Map<String, String> mCustomHeaders) { this.mCustomHeaders = mCustomHeaders; } /** * a temporary directory in which large outgoing Thrift messages will * be cached to disk before they are sent */ public File getTempDir() { return mTempDir; } /** * sets the temporary directory in which large outgoing Thrift messages will * be cached to disk before they are sent * * @param mTempDir */ public void setTempDir(File mTempDir) { this.mTempDir = mTempDir; } }