001/*
002 * (C) Copyright 2015-2016 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Andre Justo
018 */
019package org.nuxeo.ecm.liveconnect.dropbox;
020
021import java.io.IOException;
022import java.io.InputStream;
023import java.net.URI;
024import java.util.Collections;
025import java.util.Locale;
026import java.util.Map;
027
028import javax.servlet.http.HttpServletRequest;
029
030import org.nuxeo.ecm.core.api.DocumentModel;
031import org.nuxeo.ecm.core.blob.BlobManager.UsageHint;
032import org.nuxeo.ecm.core.blob.ManagedBlob;
033import org.nuxeo.ecm.core.model.Document;
034import org.nuxeo.ecm.liveconnect.core.AbstractLiveConnectBlobProvider;
035import org.nuxeo.ecm.liveconnect.core.LiveConnectFile;
036import org.nuxeo.ecm.liveconnect.core.LiveConnectFileInfo;
037import org.nuxeo.ecm.platform.oauth2.providers.OAuth2ServiceProvider;
038
039import com.dropbox.core.DbxClient;
040import com.dropbox.core.DbxEntry;
041import com.dropbox.core.DbxException;
042import com.dropbox.core.DbxRequestConfig;
043import com.dropbox.core.DbxThumbnailFormat;
044import com.dropbox.core.DbxThumbnailSize;
045import com.google.api.client.auth.oauth2.Credential;
046import com.google.api.client.http.GenericUrl;
047import com.google.api.client.http.HttpRequestFactory;
048import com.google.api.client.http.HttpResponse;
049
050/**
051 * Provider for blobs getting information from Dropbox.
052 *
053 * @since 7.3
054 */
055public class DropboxBlobProvider extends AbstractLiveConnectBlobProvider<DropboxOAuth2ServiceProvider> {
056
057    private static final String APPLICATION_NAME = "Nuxeo/0";
058
059    private static final String FILE_CACHE_NAME = "dropbox";
060
061    private static final String DROPBOX_DOCUMENT_TO_BE_UPDATED_PP = "dropbox_document_to_be_updated";
062
063    @Override
064    protected String getCacheName() {
065        return FILE_CACHE_NAME;
066    }
067
068    @Override
069    public String getPageProviderNameForUpdate() {
070        return DROPBOX_DOCUMENT_TO_BE_UPDATED_PP;
071    }
072
073    @Override
074    public URI getURI(ManagedBlob blob, UsageHint usage, HttpServletRequest servletRequest) throws IOException {
075        LiveConnectFileInfo fileInfo = toFileInfo(blob);
076        String filePath = fileInfo.getFileId();
077        String url = null;
078        DbxClient client = getDropboxClient(getCredential(fileInfo));
079        try {
080            switch (usage) {
081            case STREAM:
082                url = client.createTemporaryDirectUrl(filePath).url;
083                break;
084            case DOWNLOAD:
085                url = client.createShareableUrl(filePath);
086                url = url.replace("dl=0", "dl=1"); // enable download flag in url
087                break;
088            case VIEW:
089                url = client.createShareableUrl(filePath);
090                break;
091            }
092        } catch (DbxException e) {
093            throw new IOException("Failed to get Dropbox file URI " + e);
094        }
095        return url == null ? null : asURI(url);
096    }
097
098    @Override
099    public Map<String, URI> getAvailableConversions(ManagedBlob blob, UsageHint hint) throws IOException {
100        return Collections.emptyMap();
101    }
102
103    @Override
104    public InputStream getThumbnail(ManagedBlob blob) throws IOException {
105        LiveConnectFileInfo fileInfo = toFileInfo(blob);
106        String filePath = fileInfo.getFileId();
107        try {
108            DbxClient.Downloader downloader = getDropboxClient(getCredential(fileInfo)).startGetThumbnail(
109                    DbxThumbnailSize.w64h64, DbxThumbnailFormat.bestForFileName(filePath, DbxThumbnailFormat.JPEG),
110                    filePath, null);
111
112            if (downloader == null) {
113                return null;
114            }
115            return downloader.body;
116        } catch (DbxException e) {
117            throw new IOException("Failed to get Dropbox file thumbnail " + e);
118        }
119    }
120
121    @Override
122    public InputStream getStream(ManagedBlob blob) throws IOException {
123        URI uri = getURI(blob, UsageHint.STREAM, null);
124        return uri == null ? null : doGet(uri);
125    }
126
127    @Override
128    public InputStream getConvertedStream(ManagedBlob blob, String mimeType, DocumentModel doc) throws IOException {
129        Map<String, URI> conversions = getAvailableConversions(blob, UsageHint.STREAM);
130        URI uri = conversions.get(mimeType);
131        if (uri == null) {
132            return null;
133        }
134        return doGet(uri);
135    }
136
137    @Override
138    public ManagedBlob freezeVersion(ManagedBlob blob, Document doc) throws IOException {
139        return null;
140    }
141
142    protected DbxClient getDropboxClient(Credential credential) throws IOException {
143        return getDropboxClient(credential.getAccessToken());
144    }
145
146    protected DbxClient getDropboxClient(String accessToken) throws IOException {
147        DbxRequestConfig config = new DbxRequestConfig(APPLICATION_NAME, Locale.getDefault().toString());
148        return new DbxClient(config, accessToken);
149    }
150
151    /**
152     * Executes a GET request
153     */
154    protected InputStream doGet(URI url) throws IOException {
155        HttpRequestFactory requestFactory = getOAuth2Provider().getRequestFactory();
156        HttpResponse response = requestFactory.buildGetRequest(new GenericUrl(url)).execute();
157        return response.getContent();
158    }
159
160    protected String getClientId() {
161        OAuth2ServiceProvider provider = getOAuth2Provider();
162        return provider != null ? provider.getClientId() : null;
163    }
164
165    @Override
166    protected LiveConnectFile retrieveFile(LiveConnectFileInfo fileInfo) throws IOException {
167        try {
168            DbxEntry fileMetadata = getDropboxClient(getCredential(fileInfo)).getMetadata(fileInfo.getFileId());
169            if (fileMetadata == null) {
170                return null;
171            }
172            return new DropboxLiveConnectFile(fileInfo, fileMetadata.asFile());
173        } catch (DbxException e) {
174            throw new IOException("Failed to retrieve Dropbox file metadata", e);
175        }
176    }
177
178}