Java tutorial
/* * 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); } } // _________________________________________________________________________ }