PageRenderTime 66ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 0ms

/blogracy-web/src/main/java/net/blogracy/controller/MediaController.java

https://github.com/rik0/blogracy
Java | 558 lines | 371 code | 102 blank | 85 comment | 79 complexity | a2f072f807b748d2fd33d1ed26493eb6 MD5 | raw file
  1. /*
  2. * Copyright (c) 2011 Enrico Franchi, Michele Tomaiuolo and University of Parma.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. * THE SOFTWARE.
  21. */
  22. package net.blogracy.controller;
  23. import java.io.File;
  24. import java.io.FileReader;
  25. import java.io.FileWriter;
  26. import java.io.IOException;
  27. import java.security.InvalidParameterException;
  28. import java.security.MessageDigest;
  29. import java.security.NoSuchAlgorithmException;
  30. import java.text.DateFormat;
  31. import java.text.SimpleDateFormat;
  32. import java.util.TimeZone;
  33. import java.util.ArrayList;
  34. import java.util.Date;
  35. import java.util.HashMap;
  36. import java.util.Iterator;
  37. import java.util.List;
  38. import java.util.Map;
  39. import java.util.Map.Entry;
  40. import javax.jms.Connection;
  41. import javax.jms.ConnectionFactory;
  42. import javax.jms.DeliveryMode;
  43. import javax.jms.Destination;
  44. import javax.jms.Message;
  45. import javax.jms.MessageConsumer;
  46. import javax.jms.MessageListener;
  47. import javax.jms.MessageProducer;
  48. import javax.jms.Session;
  49. import javax.jms.TextMessage;
  50. import net.blogracy.config.Configurations;
  51. import net.blogracy.util.FileUtils;
  52. import org.apache.activemq.ActiveMQConnection;
  53. import org.apache.activemq.ActiveMQConnectionFactory;
  54. import org.apache.commons.codec.binary.Base32;
  55. import org.apache.shindig.protocol.conversion.BeanConverter;
  56. import org.apache.shindig.protocol.conversion.BeanJsonConverter;
  57. import org.apache.shindig.social.core.model.ActivityEntryImpl;
  58. import org.apache.shindig.social.core.model.ActivityObjectImpl;
  59. import org.apache.shindig.social.core.model.AlbumImpl;
  60. import org.apache.shindig.social.core.model.MediaItemImpl;
  61. import org.apache.shindig.social.opensocial.model.ActivityEntry;
  62. import org.apache.shindig.social.opensocial.model.ActivityObject;
  63. import org.apache.shindig.social.opensocial.model.Album;
  64. import org.apache.shindig.social.opensocial.model.MediaItem;
  65. import org.apache.shindig.social.opensocial.model.MediaItem.Type;
  66. import org.json.JSONArray;
  67. import org.json.JSONException;
  68. import org.json.JSONObject;
  69. import org.json.JSONTokener;
  70. import com.google.inject.Binder;
  71. import com.google.inject.Guice;
  72. import com.google.inject.Module;
  73. import com.google.inject.name.Names;
  74. /**
  75. * Generic functions to manipulate feeds are defined in this class.
  76. */
  77. public class MediaController {
  78. static final DateFormat ISO_DATE_FORMAT = new SimpleDateFormat(
  79. "yyyy-MM-dd'T'HH:mm:ss'Z'");
  80. static final String CACHE_FOLDER = Configurations.getPathConfig()
  81. .getCachedFilesDirectoryPath();
  82. private static final MediaController theInstance = new MediaController();
  83. private static final FileSharing sharing = new FileSharing();
  84. private static final ActivitiesController activities = new ActivitiesController();
  85. private static final DistributedHashTable dht = new DistributedHashTable();
  86. private static BeanJsonConverter CONVERTER = new BeanJsonConverter(
  87. Guice.createInjector(new Module() {
  88. @Override
  89. public void configure(Binder b) {
  90. b.bind(BeanConverter.class)
  91. .annotatedWith(
  92. Names.named("shindig.bean.converter.json"))
  93. .to(BeanJsonConverter.class);
  94. }
  95. }));
  96. public static MediaController getSingleton() {
  97. return theInstance;
  98. }
  99. public MediaController() {
  100. ISO_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
  101. }
  102. /**
  103. * Create a new Album for the user. Adds the album to the user's recordDB
  104. * entry Adds the action to the ActivityStream (verb: create)
  105. *
  106. * @param userId
  107. * @param photoAlbumName
  108. */
  109. public synchronized String createPhotoAlbum(String userId,
  110. String photoAlbumTitle) {
  111. if (userId == null)
  112. throw new InvalidParameterException("userId cannot be null");
  113. if (photoAlbumTitle == null || photoAlbumTitle.isEmpty())
  114. return null;
  115. String albumHash = null;
  116. try {
  117. albumHash = sharing.hash(userId + photoAlbumTitle);
  118. Album album = new AlbumImpl();
  119. album.setTitle(photoAlbumTitle);
  120. album.setId(albumHash);
  121. album.setOwnerId(userId);
  122. List<Type> types = new ArrayList<Type>();
  123. types.add(Type.IMAGE);
  124. album.setMediaType(types);
  125. // Album is empty where created
  126. album.setMediaItemCount(0);
  127. final List<ActivityEntry> feed = activities.getFeed(userId);
  128. final ActivityEntry entry = new ActivityEntryImpl();
  129. entry.setVerb("create");
  130. ActivityObject mediaAlbumObject = new ActivityObjectImpl();
  131. mediaAlbumObject.setObjectType("collection");
  132. mediaAlbumObject.setContent(photoAlbumTitle);
  133. entry.setObject(mediaAlbumObject);
  134. entry.setPublished(ISO_DATE_FORMAT.format(new Date()));
  135. entry.setContent(photoAlbumTitle);
  136. feed.add(0, entry);
  137. String feedUri = activities.seedActivityStream(userId, feed);
  138. // Append another album into the user's recordDB
  139. JSONObject recordDb = DistributedHashTable.getSingleton()
  140. .getRecord(userId);
  141. if (recordDb == null)
  142. recordDb = new JSONObject();
  143. JSONArray albums = recordDb.optJSONArray("albums");
  144. if (albums != null) {
  145. // Simply append new album
  146. albums.put(new JSONObject(CONVERTER.convertToString(album)));
  147. } else {
  148. albums = new JSONArray();
  149. albums.put(new JSONObject(CONVERTER.convertToString(album)));
  150. }
  151. DistributedHashTable.getSingleton().store(userId, feedUri,
  152. entry.getPublished(), albums,
  153. recordDb.optJSONArray("mediaItems"));
  154. } catch (Exception e) {
  155. e.printStackTrace();
  156. }
  157. return albumHash;
  158. }
  159. /**
  160. * Get the photo albums from recordDb given the userId.
  161. *
  162. * @param userId
  163. */
  164. public List<Album> getAlbums(String userId) {
  165. if (userId == null)
  166. throw new InvalidParameterException("userId cannot be null");
  167. List<Album> albums = new ArrayList<Album>();
  168. try {
  169. JSONObject recordDb = DistributedHashTable.getSingleton()
  170. .getRecord(userId);
  171. if (recordDb == null)
  172. return albums;
  173. JSONArray albumArray = recordDb.optJSONArray("albums");
  174. if (albumArray != null) {
  175. for (int i = 0; i < albumArray.length(); ++i) {
  176. JSONObject singleAlbumObject = albumArray.getJSONObject(i);
  177. Album entry = (Album) CONVERTER.convertToObject(
  178. singleAlbumObject, Album.class);
  179. albums.add(entry);
  180. }
  181. }
  182. } catch (Exception e) {
  183. e.printStackTrace();
  184. }
  185. return albums;
  186. }
  187. /**
  188. * Get the images from recordDb given the userId and the associated albumId
  189. *
  190. * @param userId
  191. * @param albumId
  192. * @return
  193. */
  194. public List<MediaItem> getMediaItems(String userId, String albumId) {
  195. if (userId == null)
  196. throw new InvalidParameterException("userId cannot be null");
  197. if (albumId == null)
  198. throw new InvalidParameterException("albumId cannot be null");
  199. List<MediaItem> mediaItems = new ArrayList<MediaItem>();
  200. try {
  201. JSONObject recordDb = DistributedHashTable.getSingleton()
  202. .getRecord(userId);
  203. if (recordDb == null)
  204. return mediaItems;
  205. JSONArray mediaItemsArray = recordDb.optJSONArray("mediaItems");
  206. if (mediaItemsArray != null) {
  207. for (int i = 0; i < mediaItemsArray.length(); ++i) {
  208. JSONObject singleAlbumObject = mediaItemsArray
  209. .getJSONObject(i);
  210. MediaItem entry = (MediaItem) CONVERTER.convertToObject(
  211. singleAlbumObject, MediaItem.class);
  212. if (entry.getAlbumId().equals(albumId))
  213. mediaItems.add(entry);
  214. }
  215. }
  216. } catch (Exception e) {
  217. e.printStackTrace();
  218. }
  219. return mediaItems;
  220. }
  221. /**
  222. * Gets the images from recordDb given the userId and the associated
  223. * albumId. Attempts to download the images from DHT. If successful, set's
  224. * the URL with the cached image link
  225. *
  226. * @param userId
  227. * @param albumId
  228. * @return
  229. */
  230. public List<MediaItem> getMediaItemsWithCachedImages(String userId,
  231. String albumId) {
  232. if (userId == null)
  233. throw new InvalidParameterException("userId cannot be null");
  234. if (albumId == null)
  235. throw new InvalidParameterException("albumId cannot be null");
  236. List<MediaItem> mediaItems = this.getMediaItems(userId, albumId);
  237. for (MediaItem item : mediaItems) {
  238. String itemMagneUri = item.getUrl();
  239. sharing.download(itemMagneUri);
  240. item.setUrl("cache/" + sharing.getHashFromMagnetURI(itemMagneUri));
  241. }
  242. return mediaItems;
  243. }
  244. /***
  245. * Add multiple MediaItems to an album. It updates the user's recordDb and
  246. * notifies the action in the user's Activity Stream (verb: add)
  247. *
  248. * @param userId
  249. * @param albumId
  250. * @param photos
  251. * @return
  252. */
  253. public synchronized List<String> addMediaItemsToAlbum(String userId,
  254. String albumId, Map<File, String> photos) {
  255. if (photos == null)
  256. return null;
  257. if (userId == null)
  258. throw new InvalidParameterException("userId cannot be null");
  259. if (albumId == null)
  260. throw new InvalidParameterException("albumId cannot be null");
  261. Album album = null;
  262. for (Album a : this.getAlbums(userId)) {
  263. if (a.getId().equals(albumId)) {
  264. album = a;
  265. break;
  266. }
  267. }
  268. if (album == null)
  269. throw new InvalidParameterException("AlbumId " + albumId
  270. + " does not match to a valid album for the user " + userId);
  271. List<String> hashList = new ArrayList<String>();
  272. List<MediaItem> listOfMediaItems = new ArrayList<MediaItem>();
  273. final List<ActivityEntry> feed = activities.getFeed(userId);
  274. final String publishedDate = ISO_DATE_FORMAT.format(new Date());
  275. try {
  276. for (Entry<File, String> mapEntry : photos.entrySet()) {
  277. File photo = mapEntry.getKey();
  278. String mimeType = mapEntry.getValue();
  279. String fileHash = sharing.hash(photo);
  280. final File photoCachedFile = new File(CACHE_FOLDER
  281. + File.separator + fileHash);
  282. FileUtils.copyFile(photo, photoCachedFile);
  283. photo.delete();
  284. final String fileUrl = sharing.seed(photoCachedFile);
  285. final ActivityEntry entry = new ActivityEntryImpl();
  286. entry.setVerb("add");
  287. entry.setPublished(publishedDate);
  288. entry.setContent(sharing.getHashFromMagnetURI(fileUrl));
  289. ActivityObject mediaItemObject = new ActivityObjectImpl();
  290. mediaItemObject.setObjectType("image");
  291. mediaItemObject.setContent(sharing
  292. .getHashFromMagnetURI(fileUrl));
  293. mediaItemObject.setUrl(fileUrl);
  294. entry.setObject(mediaItemObject);
  295. ActivityObject mediaAlbumObject = new ActivityObjectImpl();
  296. mediaAlbumObject.setObjectType("collection");
  297. mediaAlbumObject.setContent(album.getTitle());
  298. mediaAlbumObject.setId(album.getId());
  299. entry.setTarget(mediaAlbumObject);
  300. feed.add(0, entry);
  301. MediaItem mediaItem = new MediaItemImpl();
  302. mediaItem.setAlbumId(albumId);
  303. mediaItem.setId(sharing.getHashFromMagnetURI(fileUrl));
  304. mediaItem.setUrl(fileUrl);
  305. mediaItem.setLastUpdated(publishedDate);
  306. mediaItem.setMimeType(mimeType);
  307. if (album.getMediaMimeType() == null)
  308. album.setMediaMimeType(new ArrayList<String>());
  309. List<String> albumMimeTypes = album.getMediaMimeType();
  310. if (!albumMimeTypes.contains(mimeType))
  311. albumMimeTypes.add(mimeType);
  312. listOfMediaItems.add(mediaItem);
  313. hashList.add(sharing.getHashFromMagnetURI(fileUrl));
  314. }
  315. album.setMediaItemCount(album.getMediaItemCount() + photos.size());
  316. String feedUri = activities.seedActivityStream(userId, feed);
  317. // Update the album accordingly
  318. JSONObject recordDb = DistributedHashTable.getSingleton()
  319. .getRecord(userId);
  320. if (recordDb == null)
  321. recordDb = new JSONObject();
  322. JSONArray albums = recordDb.optJSONArray("albums");
  323. for (int i = 0; i < albums.length(); ++i) {
  324. JSONObject singleAlbumObject = albums.getJSONObject(i);
  325. Album entry1 = (Album) CONVERTER.convertToObject(
  326. singleAlbumObject, Album.class);
  327. if (entry1.getId().equals(albumId)) {
  328. albums.put(i,
  329. new JSONObject(CONVERTER.convertToString(album)));
  330. break;
  331. }
  332. }
  333. // Add all the newly created mediaItems
  334. JSONArray mediaItems = recordDb.optJSONArray("mediaItems");
  335. if (mediaItems == null)
  336. mediaItems = new JSONArray();
  337. for (MediaItem mediaItem : listOfMediaItems) {
  338. // Simply append new album
  339. mediaItems.put(new JSONObject(CONVERTER
  340. .convertToString(mediaItem)));
  341. }
  342. DistributedHashTable.getSingleton().store(userId, feedUri,
  343. publishedDate, albums, mediaItems);
  344. return hashList;
  345. } catch (Exception e) {
  346. e.printStackTrace();
  347. return null;
  348. }
  349. }
  350. /***
  351. * Adds a single MediaItem file to an Album. It updates the user's recordDb
  352. * and notifies the action in the user's Activity Stream (verb: remove)
  353. *
  354. * @param userId
  355. * @param albumId
  356. * @param photo
  357. * @param mimeType
  358. * @return
  359. */
  360. public synchronized String addMediaItemToAlbum(String userId,
  361. String albumId, File photo, String mimeType) {
  362. Map<File, String> map = new HashMap<File, String>();
  363. map.put(photo, mimeType);
  364. List<String> hashes = this.addMediaItemsToAlbum(userId, albumId, map);
  365. return (hashes != null && !hashes.isEmpty()) ? hashes.get(0) : null;
  366. }
  367. /***
  368. * A Media Item is removed from an album
  369. *
  370. * @param userId
  371. * @param albumId
  372. * @param mediaId
  373. */
  374. public synchronized void deletePhotoFromAlbum(String userId,
  375. String albumId, String mediaId) {
  376. if (mediaId == null)
  377. throw new InvalidParameterException("mediaId cannot be null");
  378. if (userId == null)
  379. throw new InvalidParameterException("userId cannot be null");
  380. if (albumId == null)
  381. throw new InvalidParameterException("albumId cannot be null");
  382. Album album = null;
  383. for (Album a : this.getAlbums(userId)) {
  384. if (a.getId().equals(albumId)) {
  385. album = a;
  386. break;
  387. }
  388. }
  389. if (album == null)
  390. throw new InvalidParameterException("AlbumId " + albumId
  391. + " does not correspond to a valid album for the user "
  392. + userId);
  393. try {
  394. List<MediaItem> mediaItems = this.getMediaItems(userId, albumId);
  395. for (Iterator<MediaItem> iter = mediaItems.iterator(); iter
  396. .hasNext();) {
  397. MediaItem mediaItem = iter.next();
  398. if (mediaId.equals(mediaItem.getId())
  399. && albumId.equals(mediaItem.getAlbumId()))
  400. iter.remove();
  401. }
  402. album.setMediaItemCount(mediaItems.size());
  403. final List<ActivityEntry> feed = activities.getFeed(userId);
  404. final ActivityEntry entry = new ActivityEntryImpl();
  405. entry.setVerb("remove");
  406. entry.setPublished(ISO_DATE_FORMAT.format(new Date()));
  407. entry.setContent(mediaId);
  408. ActivityObject mediaItemObject = new ActivityObjectImpl();
  409. mediaItemObject.setObjectType("image");
  410. mediaItemObject.setContent(mediaId);
  411. entry.setObject(mediaItemObject);
  412. ActivityObject mediaAlbumObject = new ActivityObjectImpl();
  413. mediaAlbumObject.setObjectType("collection");
  414. mediaAlbumObject.setContent(album.getTitle());
  415. mediaAlbumObject.setId(album.getId());
  416. entry.setTarget(mediaAlbumObject);
  417. feed.add(0, entry);
  418. String feedUri = activities.seedActivityStream(userId, feed);
  419. JSONObject recordDb = DistributedHashTable.getSingleton()
  420. .getRecord(userId);
  421. if (recordDb == null)
  422. recordDb = new JSONObject();
  423. JSONArray albums = recordDb.optJSONArray("albums");
  424. // update albums
  425. if (albums != null) {
  426. for (int i = 0; i < albums.length(); ++i) {
  427. JSONObject singleAlbumObject = albums.getJSONObject(i);
  428. Album entry1 = (Album) CONVERTER.convertToObject(
  429. singleAlbumObject, Album.class);
  430. if (entry1.getId().equals(albumId)) {
  431. albums.put(
  432. i,
  433. new JSONObject(CONVERTER.convertToString(album)));
  434. break;
  435. }
  436. }
  437. }
  438. JSONArray list = new JSONArray();
  439. JSONArray mediaItemsArray = recordDb.optJSONArray("mediaItems");
  440. if (mediaItemsArray != null) {
  441. for (int i = 0; i < mediaItemsArray.length(); ++i) {
  442. JSONObject singleMediaItemObject = mediaItemsArray
  443. .getJSONObject(i);
  444. MediaItem entry1 = (MediaItem) CONVERTER.convertToObject(
  445. singleMediaItemObject, MediaItem.class);
  446. if (!mediaId.equals(entry1.getId())
  447. || !albumId.equals(entry1.getAlbumId()))
  448. list.put(singleMediaItemObject);
  449. }
  450. }
  451. dht.store(userId, feedUri, entry.getPublished(), albums, list);
  452. } catch (Exception e) {
  453. e.printStackTrace();
  454. }
  455. }
  456. }