net.blogracy.controller.MediaController.java Source code

Java tutorial

Introduction

Here is the source code for net.blogracy.controller.MediaController.java

Source

/*
 * Copyright (c)  2011 Enrico Franchi, Michele Tomaiuolo and University of Parma.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package net.blogracy.controller;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.security.InvalidParameterException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

import net.blogracy.config.Configurations;
import net.blogracy.util.FileUtils;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.commons.codec.binary.Base32;
import org.apache.shindig.protocol.conversion.BeanConverter;
import org.apache.shindig.protocol.conversion.BeanJsonConverter;
import org.apache.shindig.social.core.model.ActivityEntryImpl;
import org.apache.shindig.social.core.model.ActivityObjectImpl;
import org.apache.shindig.social.core.model.AlbumImpl;
import org.apache.shindig.social.core.model.MediaItemImpl;
import org.apache.shindig.social.opensocial.model.ActivityEntry;
import org.apache.shindig.social.opensocial.model.ActivityObject;
import org.apache.shindig.social.opensocial.model.Album;
import org.apache.shindig.social.opensocial.model.MediaItem;
import org.apache.shindig.social.opensocial.model.MediaItem.Type;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.Module;
import com.google.inject.name.Names;

/**
 * Generic functions to manipulate feeds are defined in this class.
 */
public class MediaController {

    static final DateFormat ISO_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
    static final String CACHE_FOLDER = Configurations.getPathConfig().getCachedFilesDirectoryPath();

    private static final MediaController theInstance = new MediaController();
    private static final FileSharing sharing = new FileSharing();
    private static final ActivitiesController activities = new ActivitiesController();
    private static final DistributedHashTable dht = new DistributedHashTable();

    private static BeanJsonConverter CONVERTER = new BeanJsonConverter(Guice.createInjector(new Module() {
        @Override
        public void configure(Binder b) {
            b.bind(BeanConverter.class).annotatedWith(Names.named("shindig.bean.converter.json"))
                    .to(BeanJsonConverter.class);
        }
    }));

    public static MediaController getSingleton() {
        return theInstance;
    }

    public MediaController() {
        ISO_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
    }

    /**
     * Create a new Album for the user. Adds the album to the user's recordDB
     * entry Adds the action to the ActivityStream (verb: create)
     * 
     * @param userId
     * @param photoAlbumName
     */
    public synchronized String createPhotoAlbum(String userId, String photoAlbumTitle) {
        if (userId == null)
            throw new InvalidParameterException("userId cannot be null");

        if (photoAlbumTitle == null || photoAlbumTitle.isEmpty())
            return null;

        String albumHash = null;
        try {
            albumHash = sharing.hash(userId + photoAlbumTitle);
            Album album = new AlbumImpl();
            album.setTitle(photoAlbumTitle);
            album.setId(albumHash);
            album.setOwnerId(userId);
            List<Type> types = new ArrayList<Type>();
            types.add(Type.IMAGE);
            album.setMediaType(types);
            // Album is empty where created
            album.setMediaItemCount(0);

            final List<ActivityEntry> feed = activities.getFeed(userId);
            final ActivityEntry entry = new ActivityEntryImpl();
            entry.setVerb("create");
            ActivityObject mediaAlbumObject = new ActivityObjectImpl();
            mediaAlbumObject.setObjectType("collection");
            mediaAlbumObject.setContent(photoAlbumTitle);
            entry.setObject(mediaAlbumObject);

            entry.setPublished(ISO_DATE_FORMAT.format(new Date()));
            entry.setContent(photoAlbumTitle);

            feed.add(0, entry);
            String feedUri = activities.seedActivityStream(userId, feed);

            // Append another album into the user's recordDB
            JSONObject recordDb = DistributedHashTable.getSingleton().getRecord(userId);

            if (recordDb == null)
                recordDb = new JSONObject();

            JSONArray albums = recordDb.optJSONArray("albums");

            if (albums != null) {
                // Simply append new album
                albums.put(new JSONObject(CONVERTER.convertToString(album)));
            } else {
                albums = new JSONArray();
                albums.put(new JSONObject(CONVERTER.convertToString(album)));
            }

            DistributedHashTable.getSingleton().store(userId, feedUri, entry.getPublished(), albums,
                    recordDb.optJSONArray("mediaItems"));

        } catch (Exception e) {
            e.printStackTrace();
        }

        return albumHash;
    }

    /**
     * Get the photo albums from recordDb given the userId.
     * 
     * @param userId
     */
    public List<Album> getAlbums(String userId) {
        if (userId == null)
            throw new InvalidParameterException("userId cannot be null");

        List<Album> albums = new ArrayList<Album>();
        try {
            JSONObject recordDb = DistributedHashTable.getSingleton().getRecord(userId);

            if (recordDb == null)
                return albums;

            JSONArray albumArray = recordDb.optJSONArray("albums");

            if (albumArray != null) {
                for (int i = 0; i < albumArray.length(); ++i) {
                    JSONObject singleAlbumObject = albumArray.getJSONObject(i);
                    Album entry = (Album) CONVERTER.convertToObject(singleAlbumObject, Album.class);
                    albums.add(entry);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return albums;
    }

    /**
     * Get the images from recordDb given the userId and the associated albumId
     * 
     * @param userId
     * @param albumId
     * @return
     */
    public List<MediaItem> getMediaItems(String userId, String albumId) {
        if (userId == null)
            throw new InvalidParameterException("userId cannot be null");

        if (albumId == null)
            throw new InvalidParameterException("albumId cannot be null");

        List<MediaItem> mediaItems = new ArrayList<MediaItem>();

        try {
            JSONObject recordDb = DistributedHashTable.getSingleton().getRecord(userId);

            if (recordDb == null)
                return mediaItems;

            JSONArray mediaItemsArray = recordDb.optJSONArray("mediaItems");

            if (mediaItemsArray != null) {
                for (int i = 0; i < mediaItemsArray.length(); ++i) {
                    JSONObject singleAlbumObject = mediaItemsArray.getJSONObject(i);
                    MediaItem entry = (MediaItem) CONVERTER.convertToObject(singleAlbumObject, MediaItem.class);

                    if (entry.getAlbumId().equals(albumId))
                        mediaItems.add(entry);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return mediaItems;
    }

    /**
     * Gets the images from recordDb given the userId and the associated
     * albumId. Attempts to download the images from DHT. If successful, set's
     * the URL with the cached image link
     * 
     * @param userId
     * @param albumId
     * @return
     */
    public List<MediaItem> getMediaItemsWithCachedImages(String userId, String albumId) {

        if (userId == null)
            throw new InvalidParameterException("userId cannot be null");

        if (albumId == null)
            throw new InvalidParameterException("albumId cannot be null");

        List<MediaItem> mediaItems = this.getMediaItems(userId, albumId);

        for (MediaItem item : mediaItems) {
            String itemMagneUri = item.getUrl();
            sharing.download(itemMagneUri);
            item.setUrl("cache/" + sharing.getHashFromMagnetURI(itemMagneUri));
        }

        return mediaItems;
    }

    /***
     * Add multiple MediaItems to an album. It updates the user's recordDb and
     * notifies the action in the user's Activity Stream (verb: add)
     * 
     * @param userId
     * @param albumId
     * @param photos
     * @return
     */
    public synchronized List<String> addMediaItemsToAlbum(String userId, String albumId, Map<File, String> photos) {
        if (photos == null)
            return null;

        if (userId == null)
            throw new InvalidParameterException("userId cannot be null");

        if (albumId == null)
            throw new InvalidParameterException("albumId cannot be null");

        Album album = null;
        for (Album a : this.getAlbums(userId)) {
            if (a.getId().equals(albumId)) {
                album = a;
                break;
            }
        }

        if (album == null)
            throw new InvalidParameterException(
                    "AlbumId " + albumId + " does not match to a valid album for the user " + userId);

        List<String> hashList = new ArrayList<String>();
        List<MediaItem> listOfMediaItems = new ArrayList<MediaItem>();

        final List<ActivityEntry> feed = activities.getFeed(userId);
        final String publishedDate = ISO_DATE_FORMAT.format(new Date());

        try {

            for (Entry<File, String> mapEntry : photos.entrySet()) {
                File photo = mapEntry.getKey();
                String mimeType = mapEntry.getValue();
                String fileHash = sharing.hash(photo);

                final File photoCachedFile = new File(CACHE_FOLDER + File.separator + fileHash);

                FileUtils.copyFile(photo, photoCachedFile);
                photo.delete();

                final String fileUrl = sharing.seed(photoCachedFile);

                final ActivityEntry entry = new ActivityEntryImpl();
                entry.setVerb("add");
                entry.setPublished(publishedDate);
                entry.setContent(sharing.getHashFromMagnetURI(fileUrl));

                ActivityObject mediaItemObject = new ActivityObjectImpl();
                mediaItemObject.setObjectType("image");
                mediaItemObject.setContent(sharing.getHashFromMagnetURI(fileUrl));
                mediaItemObject.setUrl(fileUrl);
                entry.setObject(mediaItemObject);

                ActivityObject mediaAlbumObject = new ActivityObjectImpl();
                mediaAlbumObject.setObjectType("collection");
                mediaAlbumObject.setContent(album.getTitle());
                mediaAlbumObject.setId(album.getId());
                entry.setTarget(mediaAlbumObject);

                feed.add(0, entry);

                MediaItem mediaItem = new MediaItemImpl();
                mediaItem.setAlbumId(albumId);
                mediaItem.setId(sharing.getHashFromMagnetURI(fileUrl));
                mediaItem.setUrl(fileUrl);
                mediaItem.setLastUpdated(publishedDate);
                mediaItem.setMimeType(mimeType);

                if (album.getMediaMimeType() == null)
                    album.setMediaMimeType(new ArrayList<String>());

                List<String> albumMimeTypes = album.getMediaMimeType();

                if (!albumMimeTypes.contains(mimeType))
                    albumMimeTypes.add(mimeType);

                listOfMediaItems.add(mediaItem);
                hashList.add(sharing.getHashFromMagnetURI(fileUrl));
            }

            album.setMediaItemCount(album.getMediaItemCount() + photos.size());

            String feedUri = activities.seedActivityStream(userId, feed);

            // Update the album accordingly
            JSONObject recordDb = DistributedHashTable.getSingleton().getRecord(userId);

            if (recordDb == null)
                recordDb = new JSONObject();

            JSONArray albums = recordDb.optJSONArray("albums");

            for (int i = 0; i < albums.length(); ++i) {
                JSONObject singleAlbumObject = albums.getJSONObject(i);
                Album entry1 = (Album) CONVERTER.convertToObject(singleAlbumObject, Album.class);

                if (entry1.getId().equals(albumId)) {
                    albums.put(i, new JSONObject(CONVERTER.convertToString(album)));
                    break;
                }
            }

            // Add all the newly created mediaItems
            JSONArray mediaItems = recordDb.optJSONArray("mediaItems");

            if (mediaItems == null)
                mediaItems = new JSONArray();

            for (MediaItem mediaItem : listOfMediaItems) {
                // Simply append new album
                mediaItems.put(new JSONObject(CONVERTER.convertToString(mediaItem)));
            }

            DistributedHashTable.getSingleton().store(userId, feedUri, publishedDate, albums, mediaItems);

            return hashList;

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /***
     * Adds a single MediaItem file to an Album. It updates the user's recordDb
     * and notifies the action in the user's Activity Stream (verb: remove)
     * 
     * @param userId
     * @param albumId
     * @param photo
     * @param mimeType
     * @return
     */
    public synchronized String addMediaItemToAlbum(String userId, String albumId, File photo, String mimeType) {
        Map<File, String> map = new HashMap<File, String>();
        map.put(photo, mimeType);
        List<String> hashes = this.addMediaItemsToAlbum(userId, albumId, map);

        return (hashes != null && !hashes.isEmpty()) ? hashes.get(0) : null;
    }

    /***
     * A Media Item is removed from an album
     * 
     * @param userId
     * @param albumId
     * @param mediaId
     */
    public synchronized void deletePhotoFromAlbum(String userId, String albumId, String mediaId) {
        if (mediaId == null)
            throw new InvalidParameterException("mediaId cannot be null");

        if (userId == null)
            throw new InvalidParameterException("userId cannot be null");

        if (albumId == null)
            throw new InvalidParameterException("albumId cannot be null");

        Album album = null;
        for (Album a : this.getAlbums(userId)) {
            if (a.getId().equals(albumId)) {
                album = a;
                break;
            }
        }

        if (album == null)
            throw new InvalidParameterException(
                    "AlbumId " + albumId + " does not correspond to a valid album for the user " + userId);
        try {

            List<MediaItem> mediaItems = this.getMediaItems(userId, albumId);

            for (Iterator<MediaItem> iter = mediaItems.iterator(); iter.hasNext();) {
                MediaItem mediaItem = iter.next();
                if (mediaId.equals(mediaItem.getId()) && albumId.equals(mediaItem.getAlbumId()))
                    iter.remove();
            }

            album.setMediaItemCount(mediaItems.size());

            final List<ActivityEntry> feed = activities.getFeed(userId);
            final ActivityEntry entry = new ActivityEntryImpl();
            entry.setVerb("remove");
            entry.setPublished(ISO_DATE_FORMAT.format(new Date()));
            entry.setContent(mediaId);

            ActivityObject mediaItemObject = new ActivityObjectImpl();
            mediaItemObject.setObjectType("image");
            mediaItemObject.setContent(mediaId);
            entry.setObject(mediaItemObject);

            ActivityObject mediaAlbumObject = new ActivityObjectImpl();
            mediaAlbumObject.setObjectType("collection");
            mediaAlbumObject.setContent(album.getTitle());
            mediaAlbumObject.setId(album.getId());
            entry.setTarget(mediaAlbumObject);

            feed.add(0, entry);
            String feedUri = activities.seedActivityStream(userId, feed);

            JSONObject recordDb = DistributedHashTable.getSingleton().getRecord(userId);

            if (recordDb == null)
                recordDb = new JSONObject();

            JSONArray albums = recordDb.optJSONArray("albums");

            // update albums
            if (albums != null) {
                for (int i = 0; i < albums.length(); ++i) {
                    JSONObject singleAlbumObject = albums.getJSONObject(i);
                    Album entry1 = (Album) CONVERTER.convertToObject(singleAlbumObject, Album.class);

                    if (entry1.getId().equals(albumId)) {
                        albums.put(i, new JSONObject(CONVERTER.convertToString(album)));
                        break;
                    }
                }
            }

            JSONArray list = new JSONArray();
            JSONArray mediaItemsArray = recordDb.optJSONArray("mediaItems");
            if (mediaItemsArray != null) {
                for (int i = 0; i < mediaItemsArray.length(); ++i) {
                    JSONObject singleMediaItemObject = mediaItemsArray.getJSONObject(i);
                    MediaItem entry1 = (MediaItem) CONVERTER.convertToObject(singleMediaItemObject,
                            MediaItem.class);
                    if (!mediaId.equals(entry1.getId()) || !albumId.equals(entry1.getAlbumId()))
                        list.put(singleMediaItemObject);
                }
            }

            dht.store(userId, feedUri, entry.getPublished(), albums, list);

        } catch (Exception e) {
            e.printStackTrace();

        }
    }
}