net.paissad.minus.api.MinusUtils.java Source code

Java tutorial

Introduction

Here is the source code for net.paissad.minus.api.MinusUtils.java

Source

/*
 * This file is part of Minus-Java.
 * 
 * Minus-Java is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Minus-Java is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Minus-Java. If not, see <http://www.gnu.org/licenses/>.
 */

package net.paissad.minus.api;

import static net.paissad.minus.utils.HttpClientUtils.ExpectedResponseType.HTTP_ENTITY;
import static net.paissad.minus.utils.HttpClientUtils.ExpectedResponseType.STRING;

import java.awt.Dimension;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.message.BasicHeader;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import net.paissad.minus.MinusConstants;
import net.paissad.minus.api.event.MinusEvent;
import net.paissad.minus.api.event.SimpleMessageEvent;
import net.paissad.minus.api.listener.MinusListener;
import net.paissad.minus.api.listener.ProgressListener;
import net.paissad.minus.exception.MinusException;
import net.paissad.minus.utils.CommonUtils;
import net.paissad.minus.utils.HttpClientUtils;
import net.paissad.minus.utils.JSONUtils;

/**
 * @author Papa Issa DIAKHATE (paissad)
 * 
 */
class MinusUtils implements MinusConstants {

    private MinusUtils() {
    }

    /**
     * 
     * @param user - The user who wants to sign in.
     * @param listener - The listener which will receive response messages from
     *            MinusUtils.
     * @return <tt>true</tt> if the sign in is ok, <tt>false</tt> otherwise.
     * @throws MinusException
     */
    static boolean signIn(MinusUser user, final MinusListener<Map<String, Object>> listener) throws MinusException {

        Map<String, String> params = new HashMap<String, String>();
        params.put(PARAM_USERNAME, user.getUsername());
        params.put(PARAM_PASSWORD, user.getPassword());

        try {
            MinusHttpResponse minusResp = HttpClientUtils.doPost(MINUS_SIGNIN_URL, params, user.getSessionId(),
                    null, STRING);
            String httpResponse = (String) minusResp.getHttpResponse();
            user.setSessionId(minusResp.getSessionId());
            validateHttpResponse(httpResponse);

            Map<String, Object> jsonResult = JSONUtils.getMapFromJSONString(httpResponse);
            validateJsonResult(jsonResult);

            Boolean isSuccess = ((Boolean) jsonResult.get(RESPONSE_KEY_SUCCESS));

            if (isSuccess == null) {
                throw new MinusException("The response string for 'success' should never be null ... weird.");
            }

            sendMessageToListenerIfNotNull(jsonResult, listener);

            return isSuccess;

        } catch (Exception e) {
            throw new MinusException("Error while Signing In : " + e.getMessage(), e);
        }
    }

    /**
     * Signs out the user.
     * 
     * @param user
     * 
     * @throws MinusException
     */
    static void signOut(MinusUser user) throws MinusException {

        try {
            MinusHttpResponse minusResp = HttpClientUtils.doGet(MINUS_SIGN_OUT_URL, null, null, null, STRING);
            String httpResponse = (String) minusResp.getHttpResponse();
            validateHttpResponse(httpResponse);

        } catch (Exception e) {
            throw new MinusException("Error while Signing Out : " + e.getMessage(), e);
        }
    }

    /**
     * Register a user to Minus.
     * 
     * @param username
     * @param password
     * @param confirmPassword
     * @param email - If <code>null</code> is specified, then an empty String
     *            will
     *            be used instead.
     * @param listener
     * @return <code>true</code> if the registration succeeded,
     *         <code>false</code> otherwise.
     * @throws MinusException
     */
    static boolean registerUser(final String username, final String password, final String confirmPassword,
            final String email, final MinusListener<Map<String, Object>> listener) throws MinusException {

        try {
            Map<String, String> params = new HashMap<String, String>();
            params.put(PARAM_USERNAME, username);
            params.put(PARAM_PASSWORD_1, password);
            params.put(PARAM_PASSWORD_2, confirmPassword);
            // We must include email in any cases.
            final String emailParameterValue = (email == null) ? "" : email;
            params.put(PARAM_EMAIL, emailParameterValue);

            MinusHttpResponse minusResp = HttpClientUtils.doPost(MINUS_REGISTER_URL, params, null, null, STRING);
            String httpResponse = (String) minusResp.getHttpResponse();
            validateHttpResponse(httpResponse);

            Map<String, Object> jsonResult = JSONUtils.getMapFromJSONString(httpResponse);
            validateJsonResult(jsonResult);

            Boolean isSuccess = (Boolean) jsonResult.get(RESPONSE_KEY_SUCCESS);
            if (isSuccess == null) {
                throw new IllegalStateException("The 'success' key response for registration should not be null.");
            }

            sendMessageToListenerIfNotNull(jsonResult, listener);

            return isSuccess;

        } catch (Exception e) {
            throw new MinusException("Error while doing registration : " + e.getMessage(), e);
        }
    }

    /**
     * Uploads a file to MinusUtils.com.
     * 
     * @param user - The user for who to upload the item.
     * @param gallery - The gallery where to upload the item.
     * @param fileToUpload - The file to upload.
     * @param filename - The name to use after uploading the file. If
     *            <tt>null</tt>, then use the name of the file to upload
     *            specified in argument.
     * @param listener
     * @return The uploaded item.
     * @throws MinusException
     */
    static MinusItem uploadItem(MinusUser user, MinusGallery gallery, final File fileToUpload,
            final String filename, final MinusListener<Map<String, Object>> listener) throws MinusException {

        if (user == null) {
            throw new IllegalArgumentException("The user for who to upload the item cannot be null.");
        }
        if (gallery == null) {
            throw new IllegalArgumentException(
                    "The user " + user + " must specify a gallery to use before uploading an item.");
        }
        if (fileToUpload == null) {
            throw new IllegalArgumentException("The file/item to upload cannot be null.");
        }

        // The name of the file to use when storing it to the Minus server.
        final String fName = (filename == null || filename.trim().isEmpty()) ? fileToUpload.getName() : filename;

        Map<String, String> params = new HashMap<String, String>();
        params.put(PARAM_EDITOR_ID, gallery.getEditorId());
        params.put(PARAM_KEY, "OK");
        params.put(PARAM_FILENAME, fName);

        try {
            MinusHttpResponse minusResp = HttpClientUtils.doUpload(MINUS_UPLOAD_ITEM_URL, params,
                    user.getSessionId(), fileToUpload, fName);
            String httpResponse = (String) minusResp.getHttpResponse();
            validateHttpResponse(httpResponse);

            Map<String, Object> jsonResult = JSONUtils.getMapFromJSONString(httpResponse);
            validateJsonResult(jsonResult);

            String id = (String) jsonResult.get(RESPONSE_KEY_ID);
            int width = ((Long) jsonResult.get(RESPONSE_KEY_WIDTH)).intValue();
            int height = ((Long) jsonResult.get(RESPONSE_KEY_HEIGHT)).intValue();
            String filesize = (String) jsonResult.get(RESPONSE_KEY_FILESIZE);

            sendMessageToListenerIfNotNull(jsonResult, listener);

            // We should update the 'state' of the gallery.
            return new MinusItem(fName, "http://" + MINUS_DOMAIN_NAME + "/l" + id, width, height, filesize);

        } catch (Exception e) {
            throw new MinusException("Error while uploading the item (" + fileToUpload + ") : " + e.getMessage(),
                    e);
        }
    }

    /**
     * Retrieves items from a gallery.
     * 
     * @param user - The user who want to retrieve items.
     * @param gallery - The gallery for which we want to retrieve its items.
     * @param listener
     * @return The list of items stored in the specified gallery.
     * @throws MinusException
     * @see MinusGallery#getReaderId()
     */
    static List<MinusItem> getItems(final MinusUser user, MinusGallery gallery,
            final MinusListener<Map<String, Object>> listener) throws MinusException {

        if (user == null) {
            throw new IllegalArgumentException("The user for who to download items cannot be null.");
        }
        if (gallery == null) {
            throw new IllegalArgumentException(
                    "The user " + user + " must specify a non null gallery to use before downloading items.");
        }

        try {

            // The complete URL from where we will retrieve items.
            final String urlOfItems = MINUS_GET_ITEMS_URL + "/m" + gallery.getReaderId();

            MinusHttpResponse minusResp = HttpClientUtils.doGet(urlOfItems, null, user.getSessionId(), null,
                    STRING);
            String httpResponse = (String) minusResp.getHttpResponse();
            validateHttpResponse(httpResponse);

            Map<String, Object> jsonResult = JSONUtils.getMapFromJSONString(httpResponse);
            validateJsonResult(jsonResult);

            List<MinusItem> items = new ArrayList<MinusItem>();

            // String galleryTitle = (String)
            // jsonResult.get(RESPONSE_KEY_GALLERY_TITLE);
            @SuppressWarnings("unchecked")
            List<String> itemsNames = (List<String>) jsonResult.get(RESPONSE_KEY_ITEMS_NAME);

            @SuppressWarnings("unchecked")
            List<String> itemsURLs = (List<String>) jsonResult.get(RESPONSE_KEY_ITEMS_GALLERY);

            @SuppressWarnings("unchecked")
            List<JSONObject> dimensionsAsObjects = (List<JSONObject>) jsonResult.get(RESPONSE_KEY_IMAGE_SIZES);
            List<Dimension> itemsDimensions = new ArrayList<Dimension>();

            for (JSONObject obj : dimensionsAsObjects) {
                int width = ((Long) obj.get(RESPONSE_KEY_WIDTH)).intValue();
                int height = ((Long) obj.get(RESPONSE_KEY_HEIGHT)).intValue();
                itemsDimensions.add(new Dimension(width, height));
            }

            // Normally, itemsURLs, itemsNames & itemDimesions lists should have
            // the same length, we are going to trust minus api ;)
            for (int i = 0; i < itemsURLs.size(); i++) {
                final String name = itemsNames.get(i);
                final String shortURL = itemsURLs.get(i);
                final Dimension dimension = itemsDimensions.get(i);
                MinusItem oneItem = new MinusItem(name, shortURL, dimension, "-1L");
                items.add(oneItem);
            }

            sendMessageToListenerIfNotNull(jsonResult, listener);

            return items;

        } catch (Exception e) {
            throw new MinusException("Error while downloading items for user (" + user + ") from gallery ("
                    + gallery + ") : " + e.getMessage(), e);
        }
    }

    /**
     * Creates a gallery. The user's galleries will be updated by calling
     * {@link MinusUser#getGalleries(MinusListener)} after the creation of the
     * new gallery.
     * 
     * @param user - The user for which we create the gallery.
     * @param listener
     *            - The listener to use.
     * @return The instance of the created {@link MinusGallery}.
     * @throws MinusException
     */
    static MinusGallery createGallery(MinusUser user, final MinusListener<Map<String, Object>> listener)
            throws MinusException {

        try {
            MinusHttpResponse minusResp = HttpClientUtils.doGet(MINUS_CREATE_GALLERY_URL, null, user.getSessionId(),
                    null, STRING);
            String httpResponse = (String) minusResp.getHttpResponse();
            validateHttpResponse(httpResponse);

            Map<String, Object> jsonResult = JSONUtils.getMapFromJSONString(httpResponse);
            validateJsonResult(jsonResult);

            String editorId = (String) jsonResult.get(PARAM_EDITOR_ID);
            String readerId = (String) jsonResult.get(PARAM_READER_ID);

            sendMessageToListenerIfNotNull(jsonResult, listener);

            return new MinusGallery(user, editorId, readerId);

        } catch (Exception e) {
            throw new MinusException("Error while creating a gallery : " + e.getMessage(), e);
        }
    }

    /**
     * Use this to update the gallery name or change sort order.
     * 
     * @param user
     * @param gallery - The gallery to update.
     * @param itemsIDs - The items IDs. <b>NOTE</b>: the order of the
     *            declarations is important. The items will be sorted according
     *            to their index position in the array.
     * @param newName - The new name to use for the gallery. If
     *            <code>null</code> or empty, the gallery's name won't be
     *            changed.
     * @param listener
     * @throws MinusException
     */
    static void saveGallery(MinusUser user, MinusGallery gallery, final List<String> itemsIDs, final String newName,
            final MinusListener<Map<String, Object>> listener) throws MinusException {

        try {
            Map<String, String> params = new LinkedHashMap<String, String>();

            params.put(PARAM_ITEMS, JSONValue.toJSONString(itemsIDs));

            final String galleryName = (newName != null && !newName.trim().isEmpty()) ? newName : gallery.getName();
            params.put(PARAM_GALLERY_NAME, galleryName);

            params.put(PARAM_KEY, "OK");

            params.put(PARAM_ID, gallery.getEditorId());

            final String url = MINUS_SAVE_GALLERY_URL;
            HttpClientUtils.doPost(url, params, user.getSessionId(), null, STRING);

        } catch (Exception e) {
            throw new MinusException("Error while saving/updating the gallery [ " + gallery.getName() + ", "
                    + gallery.getEditorId() + " ]" + e.getMessage(), e);
        }
    }

    /**
     * 
     * @param user - The user who possess the gallery. (can be <tt>null</tt>
     *            since there is no need to sign in in order to download the
     *            zipball of a gallery).
     * @param gallery - The gallery for which we want to retrieve and zip all
     *            its items.
     * @param outputZipFile - Where to put the output zip file.
     * @param progressListener
     * @throws MinusException
     */
    static void downloadAllItems(final MinusUser user, final MinusGallery gallery, final File outputZipFile,
            final ProgressListener progressListener) throws MinusException {

        try {
            final String fakeRefererURL = "http://" + MINUS_DOMAIN_NAME + "/m" + gallery.getReaderId();
            final String url = fakeRefererURL + GALLERY_ZIP;
            final String sessionId = (user == null) ? null : user.getSessionId();
            Header additionalHeader = new BasicHeader("Referer", fakeRefererURL);
            MinusHttpResponse minusResp = HttpClientUtils.doGet(url, null, sessionId,
                    new Header[] { additionalHeader }, HTTP_ENTITY);
            HttpEntity entity = (HttpEntity) minusResp.getHttpResponse();
            InputStream in = null;
            OutputStream out = null;
            try {
                in = new BufferedInputStream(entity.getContent());
                out = new BufferedOutputStream(new FileOutputStream(outputZipFile));
                final int buffer = 4096;
                byte[] data = new byte[buffer];
                int bytesRead = 0;
                BasicProgressEvent event = new BasicProgressEvent(entity.getContentLength(), bytesRead);
                progressListener.onProgress(event);
                while ((bytesRead = in.read(data, 0, buffer)) != -1) {
                    out.write(data, 0, bytesRead);
                    event.add(bytesRead);
                    if (progressListener != null) {
                        progressListener.onProgress(event);
                    }
                }
                out.flush();
                out.close();

            } finally {
                CommonUtils.closeAllStreamsQuietly(in, out);
            }

        } catch (Exception e) {
            throw new MinusException(
                    "Error while downlading/zipping all items of the gallery " + gallery + " : " + e.getMessage(),
                    e);
        }
    }

    /**
     * 
     * @param user - The user who wants to change the visibility of its gallery.
     * @param editorId - The gallery for which we want to change its visibility.
     * @param scope - The visibility/scope to use.
     * @param listener
     * @return <code>true</code> if succeeded, <code>false</code> otherwise.
     * @throws MinusException
     */
    static boolean setScope(final MinusUser user, final String editorId, final GalleryScope scope)
            throws MinusException {

        if (user == null) {
            throw new IllegalArgumentException("The user cannot be null.");
        }
        if (editorId == null) {
            throw new IllegalArgumentException("The editor_id cannot be null.");
        }
        if (scope == null) {
            throw new IllegalArgumentException("The scope/visibility to set cannot be null.");
        }

        try {
            final String url = scope.getCallbackUrl() + "/" + editorId;

            MinusHttpResponse minusResp = HttpClientUtils.doGet(url, null, user.getSessionId(), null, STRING);
            String httpResponse = (String) minusResp.getHttpResponse();

            // If the operation succeeded, minus API should return nothing, ..
            // in other words, we expect an empty response. We assume that a non
            // empty response means a failure.
            return httpResponse.isEmpty();

        } catch (Exception e) {
            throw new MinusException("Error while change visibility of the gallery with editor_id = " + editorId
                    + " : " + e.getMessage(), e);
        }
    }

    // _________________________________________________________________________

    /**
     * Verify that the response is not <code>null</code> and not empty.
     * 
     * @param httpResponse
     * @throws IllegalStateException
     */
    static void validateHttpResponse(final String httpResponse) throws IllegalStateException {
        if (httpResponse == null || httpResponse.isEmpty()) {
            throw new IllegalStateException("The http response cannot be null or empty.");
        }
    }

    /**
     * Verify that the specified map is not <code>null</code> and not empty.
     * 
     * @param jsonResult
     * @throws IllegalStateException
     */
    static void validateJsonResult(Map<String, Object> jsonResult) throws IllegalStateException {
        if (jsonResult == null || jsonResult.isEmpty()) {
            throw new IllegalStateException("The JSON result cannot be null or empty.");
        }
    }

    /**
     * Sends a message to the specified listener if this listener is not
     * <code>null</code>.
     * 
     * @param message
     * @param listener
     * @throws MinusException
     */
    static void sendMessageToListenerIfNotNull(final Map<String, Object> message,
            final MinusListener<Map<String, Object>> listener) throws MinusException {

        if (listener != null) {
            MinusEvent<Map<String, Object>> event = new SimpleMessageEvent();
            event.setMessage(message);
            listener.execute(event);
        }
    }

    // _________________________________________________________________________

}