Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

keep log of dht lookups

  • Loading branch information...
commit fa9c8ebeb5c9ffaca861e5f076acef8c8e15655d 1 parent 234068e
mic authored
View
51 blogracy-web/src/main/java/net/blogracy/WebServer.java
@@ -1,31 +1,31 @@
package net.blogracy;
-import net.blogracy.model.users.User;
+import java.util.List;
+
+import net.blogracy.config.Configurations;
+import net.blogracy.controller.ActivitiesController;
import net.blogracy.controller.ChatController;
import net.blogracy.controller.DistributedHashTable;
import net.blogracy.controller.FileSharing;
-import net.blogracy.config.Configurations;
-import java.util.List;
+import net.blogracy.model.users.User;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;
-public class WebServer
-{
- public static void main(String[] args) throws Exception
- {
- String webDir = WebServer.class.getClassLoader().getResource("webapp").toExternalForm();
-
- Server server = new Server(8080);
-
+public class WebServer {
+
+ public static void main(String[] args) throws Exception {
+
+ String webDir = WebServer.class.getClassLoader().getResource("webapp")
+ .toExternalForm();
WebAppContext context = new WebAppContext();
context.setResourceBase(webDir);
- //context.setDescriptor(webDir + "/WEB-INF/web.xml");
- context.setContextPath("/");
- context.setParentLoaderPriority(true);
-
+ // context.setDescriptor(webDir + "/WEB-INF/web.xml");
+ // context.setContextPath("/");
+ // context.setParentLoaderPriority(true);
+
+ Server server = new Server(8080);
server.setHandler(context);
-
server.start();
// server.join();
@@ -34,20 +34,23 @@ public static void main(String[] args) throws Exception
String hash = friend.getHash().toString();
ChatController.getSingleton().joinChannel(hash);
}
- String id = Configurations.getUserConfig().getUser().getHash().toString();
+ String id = Configurations.getUserConfig().getUser().getHash()
+ .toString();
ChatController.getSingleton().joinChannel(id);
-
+
int TOTAL_WAIT = 5 * 60 * 1000; // 5 minutes
-
+
while (true) {
- FileSharing sharing = FileSharing.getSingleton();
- sharing.addFeedEntry(id, "" + new java.util.Date(), null);
-
+ ActivitiesController activities = ActivitiesController
+ .getSingleton();
+ activities.addFeedEntry(id, "" + new java.util.Date(), null);
+
// List<User> friends = Configurations.getUserConfig().getFriends();
int wait = TOTAL_WAIT / friends.size();
for (User friend : friends) {
- DistributedHashTable.getSingleton().lookup(friend.getHash().toString());
- FileSharing.getFeed(friend.getHash().toString());
+ DistributedHashTable.getSingleton().lookup(
+ friend.getHash().toString());
+ activities.getFeed(friend.getHash().toString());
Thread.currentThread().sleep(wait);
}
}
View
47 blogracy-web/src/main/java/net/blogracy/config/Configurations.java
@@ -23,8 +23,8 @@
package net.blogracy.config;
import java.io.File;
-import java.io.IOException;
import java.io.FileInputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.security.Key;
import java.security.KeyPair;
@@ -62,17 +62,7 @@
private static final String BLOGRACY_USER_FRIENDS = "blogracy.user.friends";
static private Properties loadProperties(String file) throws IOException {
- // ClassLoader loader = ClassLoader.getSystemClassLoader();
- // InputStream is = loader.getResourceAsStream(file);
- InputStream is = null;
- File f = new File(file);
- if (f.exists()) {
- is = new FileInputStream(f);
- } else {
- is = Configurations.class.getClassLoader()
- .getResourceAsStream(file);
- }
-
+ InputStream is = getResourceAsStream(file);
if (is != null) {
Properties properties = new Properties();
properties.load(is);
@@ -82,6 +72,19 @@ static private Properties loadProperties(String file) throws IOException {
}
}
+ static private InputStream getResourceAsStream(String file)
+ throws IOException {
+ InputStream is = null;
+ File f = new File(file);
+ if (f.exists()) {
+ is = new FileInputStream(f);
+ } else {
+ is = Configurations.class.getClassLoader()
+ .getResourceAsStream(file);
+ }
+ return is;
+ }
+
static public PathConfig getPathConfig() {
try {
@@ -180,22 +183,23 @@ public User getUser() {
}
return friends;
}
-
- public User getFriend(final String hash){
- for (User friend : this.getFriends())
- if(friend.getHash().toString().equals(hash))
- return friend;
- return null;
+
+ public User getFriend(final String hash) {
+ for (User friend : this.getFriends())
+ if (friend.getHash().toString().equals(hash))
+ return friend;
+ return null;
}
private User loadUser(String text) {
String[] hashAndNick = text.split(" ", 2);
User user = Users
.newUser(Hashes.fromString(hashAndNick[0]));
- if (hashAndNick.length == 2)
+ if (hashAndNick.length == 2) {
user.setLocalNick(hashAndNick[1]);
- else
+ } else {
user.setLocalNick(hashAndNick[0]);
+ }
return user;
}
@@ -206,8 +210,7 @@ public KeyPair getUserKeyPair() {
String alias = getUser().getLocalNick();
char[] password = new char[] { 'b', 'l', 'o', 'g', 'r',
'a', 'c', 'y' };
- InputStream is = Configurations.class.getClassLoader()
- .getResourceAsStream("blogracy.jks");
+ InputStream is = getResourceAsStream("blogracy.jks");
KeyStore keyStore = KeyStore.getInstance(KeyStore
.getDefaultType());
keyStore.load(is, password);
View
212 blogracy-web/src/main/java/net/blogracy/controller/ActivitiesController.java
@@ -0,0 +1,212 @@
+/*
+ * 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 ActivitiesController {
+
+ 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 FileSharing sharing = FileSharing.getSingleton();
+ private static final DistributedHashTable dht = DistributedHashTable
+ .getSingleton();
+ private static final ActivitiesController theInstance = new ActivitiesController();
+
+ 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 ActivitiesController getSingleton() {
+ return theInstance;
+ }
+
+ public ActivitiesController() {
+ ISO_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
+ }
+
+ static public List<ActivityEntry> getFeed(String user) {
+ List<ActivityEntry> result = new ArrayList<ActivityEntry>();
+ System.out.println("Getting feed: " + user);
+ JSONObject record = dht.getRecord(user);
+ if (record != null) {
+ try {
+ String latestHash = FileSharing.getHashFromMagnetURI(record
+ .getString("uri"));
+ File dbFile = new File(CACHE_FOLDER + File.separator
+ + latestHash + ".json");
+ if (!dbFile.exists() && record.has("prev")) {
+ latestHash = FileSharing.getHashFromMagnetURI(record
+ .getString("prev"));
+ dbFile = new File(CACHE_FOLDER + File.separator
+ + latestHash + ".json");
+ }
+ if (dbFile.exists()) {
+ System.out.println("Getting feed: "
+ + dbFile.getAbsolutePath());
+ JSONObject db = new JSONObject(new JSONTokener(
+ new FileReader(dbFile)));
+
+ JSONArray items = db.getJSONArray("items");
+ for (int i = 0; i < items.length(); ++i) {
+ JSONObject item = items.getJSONObject(i);
+ ActivityEntry entry = (ActivityEntry) CONVERTER
+ .convertToObject(item, ActivityEntry.class);
+ result.add(entry);
+ }
+ System.out.println("Feed loaded");
+ } else {
+ System.out.println("Feed not found");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return result;
+ }
+
+ public void addFeedEntry(String id, String text, File attachment) {
+ try {
+ String hash = sharing.hash(text);
+ File textFile = new File(CACHE_FOLDER + File.separator + hash
+ + ".txt");
+
+ FileWriter w = new FileWriter(textFile);
+ w.write(text);
+ w.close();
+
+ String textUri = sharing.seed(textFile);
+ String attachmentUri = null;
+ if (attachment != null) {
+ attachmentUri = sharing.seed(attachment);
+ }
+
+ final List<ActivityEntry> feed = getFeed(id);
+ final ActivityEntry entry = new ActivityEntryImpl();
+ entry.setVerb("post");
+ entry.setUrl(textUri);
+ entry.setPublished(ISO_DATE_FORMAT.format(new Date()));
+ entry.setContent(text);
+ if (attachment != null) {
+ ActivityObject enclosure = new ActivityObjectImpl();
+ enclosure.setUrl(attachmentUri);
+ entry.setObject(enclosure);
+ }
+ feed.add(0, entry);
+ String feedUri = seedActivityStream(id, feed);
+ DistributedHashTable.getSingleton().store(id, feedUri,
+ entry.getPublished());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public String seedActivityStream(String userId,
+ final List<ActivityEntry> feed) throws JSONException, IOException {
+ final File feedFile = new File(CACHE_FOLDER + File.separator + userId
+ + ".json");
+
+ JSONArray items = new JSONArray();
+ for (int i = 0; i < feed.size(); ++i) {
+ JSONObject item = new JSONObject(feed.get(i));
+ items.put(item);
+ }
+ JSONObject db = new JSONObject();
+
+ db.put("items", items);
+
+ FileWriter writer = new FileWriter(feedFile);
+ db.write(writer);
+ writer.close();
+
+ String feedUri = sharing.seed(feedFile);
+ return feedUri;
+ }
+}
View
98 blogracy-web/src/main/java/net/blogracy/controller/DistributedHashTable.java
@@ -31,6 +31,9 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.logging.FileHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
@@ -67,6 +70,57 @@
*/
public class DistributedHashTable {
+ class LookupListener implements MessageListener {
+ private String id;
+ private long start;
+
+ LookupListener(String id) {
+ this.id = id;
+ this.start = System.currentTimeMillis();
+ log.info("Lookup req: " + id);
+ log.getHandlers()[0].flush();
+ }
+
+ @Override
+ public void onMessage(Message response) {
+ try {
+ String msgText = ((TextMessage) response).getText();
+ log.info("Lookup ans: " + id + " @ "
+ + (System.currentTimeMillis() - start));
+ log.getHandlers()[0].flush();
+ JSONObject keyValue = new JSONObject(msgText);
+ String value = keyValue.getString("value");
+ PublicKey signerKey = JsonWebSignature.getSignerKey(value);
+ final JSONObject record = new JSONObject(
+ JsonWebSignature.verify(value, signerKey));
+ JSONObject currentRecord = getRecord(id);
+ if (currentRecord == null
+ || currentRecord.getString("version").compareTo(
+ record.getString("version")) < 0) {
+ String uri = record.getString("uri");
+ FileSharing fileSharing = FileSharing.getSingleton();
+ String hash = fileSharing.getHashFromMagnetURI(uri);
+ log.info("Download req: " + id + " @ "
+ + (System.currentTimeMillis() - start));
+ log.getHandlers()[0].flush();
+ fileSharing.downloadByHash(hash, ".json",
+ new MessageListener() {
+ public void onMessage(Message response) {
+ log.info("Download ans: "
+ + id
+ + " @ "
+ + (System.currentTimeMillis() - start));
+ log.getHandlers()[0].flush();
+ putRecord(record);
+ }
+ });
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
private ConnectionFactory connectionFactory;
private Connection connection;
private Session session;
@@ -80,15 +134,19 @@
.getCachedFilesDirectoryPath();
private HashMap<String, JSONObject> records = new HashMap<String, JSONObject>();
+ private Logger log;
- private static final DistributedHashTable THE_INSTANCE = new DistributedHashTable();
+ private static final DistributedHashTable theInstance = new DistributedHashTable();
public static DistributedHashTable getSingleton() {
- return THE_INSTANCE;
+ return theInstance;
}
public DistributedHashTable() {
try {
+ log = Logger.getLogger("net.blogracy.controller.dht");
+ log.addHandler(new FileHandler("dht.log"));
+
File recordsFile = new File(CACHE_FOLDER + File.separator
+ "records.json");
if (recordsFile.exists()) {
@@ -118,35 +176,7 @@ public void lookup(final String id) {
try {
Destination tempDest = session.createTemporaryQueue();
MessageConsumer responseConsumer = session.createConsumer(tempDest);
- responseConsumer.setMessageListener(new MessageListener() {
- @Override
- public void onMessage(Message response) {
- try {
- String msgText = ((TextMessage) response).getText();
- JSONObject keyValue = new JSONObject(msgText);
- String value = keyValue.getString("value");
- PublicKey signerKey = JsonWebSignature
- .getSignerKey(value);
- final JSONObject record = new JSONObject(JsonWebSignature
- .verify(value, signerKey));
- JSONObject currentRecord = getRecord(id);
- if (currentRecord == null
- || currentRecord.getString("version")
- .compareTo(record.getString("version")) < 0) {
- String uri = record.getString("uri");
- FileSharing fileSharing = FileSharing.getSingleton();
- String hash = fileSharing.getHashFromMagnetURI(uri);
- fileSharing.downloadByHash(hash, ".json", new MessageListener() {
- public void onMessage(Message response) {
- putRecord(record);
- }
- });
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- });
+ responseConsumer.setMessageListener(new LookupListener(id));
JSONObject record = new JSONObject();
record.put("id", id);
@@ -155,7 +185,6 @@ public void onMessage(Message response) {
message.setText(record.toString());
message.setJMSReplyTo(tempDest);
producer.send(lookupQueue, message);
-
} catch (Exception e) {
e.printStackTrace();
}
@@ -207,8 +236,9 @@ public void putRecord(JSONObject record) {
try {
String id = record.getString("id");
JSONObject old = records.get(id);
- if (old == null || record.getString("version")
- .compareTo(old.getString("version")) > 0) {
+ if (old == null
+ || record.getString("version").compareTo(
+ old.getString("version")) > 0) {
records.put(id, record);
}
} catch (JSONException e1) {
View
562 blogracy-web/src/main/java/net/blogracy/controller/FileSharing.java
@@ -98,7 +98,7 @@
static final String CACHE_FOLDER = Configurations.getPathConfig()
.getCachedFilesDirectoryPath();
- private static final FileSharing THE_INSTANCE = new FileSharing();
+ private static final FileSharing theInstance = new FileSharing();
private static BeanJsonConverter CONVERTER = new BeanJsonConverter(
Guice.createInjector(new Module() {
@@ -112,7 +112,7 @@ public void configure(Binder b) {
}));
public static FileSharing getSingleton() {
- return THE_INSTANCE;
+ return theInstance;
}
public static String hash(String text) {
@@ -153,7 +153,8 @@ public FileSharing() {
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
producer = session.createProducer(null);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
- seedSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ seedSession = connection.createSession(false,
+ Session.AUTO_ACKNOWLEDGE);
seedProducer = seedSession.createProducer(null);
seedProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
seedQueue = session.createQueue("seed");
@@ -167,7 +168,8 @@ public String seed(File file) {
String uri = null;
try {
Destination tempDest = seedSession.createTemporaryQueue();
- MessageConsumer responseConsumer = seedSession.createConsumer(tempDest);
+ MessageConsumer responseConsumer = seedSession
+ .createConsumer(tempDest);
JSONObject requestObj = new JSONObject();
requestObj.put("file", file.getAbsolutePath());
@@ -187,546 +189,7 @@ public String seed(File file) {
return uri;
}
- static public List<ActivityEntry> getFeed(String user) {
- List<ActivityEntry> result = new ArrayList<ActivityEntry>();
- System.out.println("Getting feed: " + user);
- JSONObject record = DistributedHashTable.getSingleton().getRecord(user);
- if (record != null) {
- try {
- String latestHash = FileSharing.getHashFromMagnetURI(record
- .getString("uri"));
- File dbFile = new File(CACHE_FOLDER + File.separator
- + latestHash + ".json");
- if (! dbFile.exists() && record.has("prev")) {
- latestHash = FileSharing.getHashFromMagnetURI(record
- .getString("prev"));
- dbFile = new File(CACHE_FOLDER + File.separator
- + latestHash + ".json");
- }
- if (dbFile.exists()) {
- System.out.println("Getting feed: " + dbFile.getAbsolutePath());
- JSONObject db = new JSONObject(new JSONTokener(new FileReader(
- dbFile)));
-
- JSONArray items = db.getJSONArray("items");
- for (int i = 0; i < items.length(); ++i) {
- JSONObject item = items.getJSONObject(i);
- ActivityEntry entry = (ActivityEntry) CONVERTER
- .convertToObject(item, ActivityEntry.class);
- result.add(entry);
- }
- System.out.println("Feed loaded");
- } else {
- System.out.println("Feed not found");
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- return result;
- }
-
- public void addFeedEntry(String id, String text, File attachment) {
- try {
- String hash = hash(text);
- File textFile = new File(CACHE_FOLDER + File.separator + hash
- + ".txt");
-
- FileWriter w = new FileWriter(textFile);
- w.write(text);
- w.close();
-
- String textUri = seed(textFile);
- String attachmentUri = null;
- if (attachment != null) {
- attachmentUri = seed(attachment);
- }
-
- final List<ActivityEntry> feed = getFeed(id);
- final ActivityEntry entry = new ActivityEntryImpl();
- entry.setVerb("post");
- entry.setUrl(textUri);
- entry.setPublished(ISO_DATE_FORMAT.format(new Date()));
- entry.setContent(text);
- if (attachment != null) {
- ActivityObject enclosure = new ActivityObjectImpl();
- enclosure.setUrl(attachmentUri);
- entry.setObject(enclosure);
- }
- feed.add(0, entry);
- String feedUri = seedActivityStream(id, feed);
- DistributedHashTable.getSingleton().store(id, feedUri,
- entry.getPublished());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- /**
- * 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 = 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 = 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 = 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();
- download(itemMagneUri);
- item.setUrl("cache/" + 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 = 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 = hash(photo);
-
- final File photoCachedFile = new File(CACHE_FOLDER
- + File.separator + fileHash);
-
- FileUtils.copyFile(photo, photoCachedFile);
- photo.delete();
-
- final String fileUrl = this.seed(photoCachedFile);
-
- final ActivityEntry entry = new ActivityEntryImpl();
- entry.setVerb("add");
- entry.setPublished(publishedDate);
- entry.setContent(getHashFromMagnetURI(fileUrl));
-
- ActivityObject mediaItemObject = new ActivityObjectImpl();
- mediaItemObject.setObjectType("image");
- mediaItemObject.setContent(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(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(getHashFromMagnetURI(fileUrl));
- }
-
- album.setMediaItemCount(album.getMediaItemCount() + photos.size());
-
- String feedUri = 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 = 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 = 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);
- }
- }
-
- DistributedHashTable.getSingleton().store(userId, feedUri,
- entry.getPublished(), albums, list);
-
- } catch (Exception e) {
- e.printStackTrace();
-
- }
- }
-
- private String seedActivityStream(String userId,
- final List<ActivityEntry> feed) throws JSONException, IOException {
- final File feedFile = new File(CACHE_FOLDER + File.separator + userId
- + ".json");
-
- JSONArray items = new JSONArray();
- for (int i = 0; i < feed.size(); ++i) {
- JSONObject item = new JSONObject(feed.get(i));
- items.put(item);
- }
- JSONObject db = new JSONObject();
-
- db.put("items", items);
-
- FileWriter writer = new FileWriter(feedFile);
- db.write(writer);
- writer.close();
-
- String feedUri = seed(feedFile);
- return feedUri;
- }
-
- static String getHashFromMagnetURI(String uri) {
+ public static String getHashFromMagnetURI(String uri) {
String hash = null;
int btih = uri.indexOf("xt=urn:btih:");
if (btih >= 0) {
@@ -751,8 +214,9 @@ public void download(final String uri, final String ext) {
public void downloadByHash(final String hash) {
downloadByHash(hash, null, null);
}
-
- public void downloadByHash(final String hash, final String ext, final MessageListener listener) {
+
+ public void downloadByHash(final String hash, final String ext,
+ final MessageListener listener) {
try {
Destination tempDest = session.createTemporaryQueue();
MessageConsumer responseConsumer = session.createConsumer(tempDest);
@@ -761,12 +225,14 @@ public void downloadByHash(final String hash, final String ext, final MessageLis
} else {
responseConsumer.setMessageListener(new MessageListener() {
@Override
- public void onMessage(Message response) {}
+ public void onMessage(Message response) {
+ }
});
}
String file = CACHE_FOLDER + File.separator + hash;
- if (ext != null) file += ext;
+ if (ext != null)
+ file += ext;
JSONObject sharedFile = new JSONObject();
sharedFile.put("uri", "magnet:?xt=urn:btih:" + hash);
sharedFile.put("file", file);
View
558 blogracy-web/src/main/java/net/blogracy/controller/MediaController.java
@@ -0,0 +1,558 @@
+/*
+ * 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();
+
+ }
+ }
+}
View
50 blogracy-web/src/main/java/net/blogracy/web/FileUpload.java
@@ -10,32 +10,34 @@
import javax.servlet.http.HttpServletResponse;
import net.blogracy.config.Configurations;
+import net.blogracy.controller.ActivitiesController;
import net.blogracy.controller.FileSharing;
public class FileUpload extends HttpServlet {
- protected void doPost(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
-
- File attachment = (File) req.getAttribute("userfile");
- String text = req.getParameter("usertext").trim();
-
- FileSharing sharing = FileSharing.getSingleton();
- // String id = sharing.hash("mic");
- String id = Configurations.getUserConfig().getUser().getHash()
- .toString();
-
- // TODO recipient of message/files? the publishing user or the profile's
- // user?
- // String dest = req.getParameter("user");
- sharing.addFeedEntry(id, text, attachment);
-
- PrintWriter outp = resp.getWriter();
- outp.write("<html>");
- outp.write("<head><title>FileUpload page</title></head>");
- outp.write("<body>");
- outp.write("<h2>" + text + "</h2>");
- outp.write("</body>");
- outp.write("</html>");
- }
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ File attachment = (File) req.getAttribute("userfile");
+ String text = req.getParameter("usertext").trim();
+
+ FileSharing sharing = FileSharing.getSingleton();
+ // String id = sharing.hash("mic");
+ String id = Configurations.getUserConfig().getUser().getHash()
+ .toString();
+
+ // TODO recipient of message/files? the publishing user or the profile's
+ // user?
+ // String dest = req.getParameter("user");
+ ActivitiesController activities = ActivitiesController.getSingleton();
+ activities.addFeedEntry(id, text, attachment);
+
+ PrintWriter outp = resp.getWriter();
+ outp.write("<html>");
+ outp.write("<head><title>FileUpload page</title></head>");
+ outp.write("<body>");
+ outp.write("<h2>" + text + "</h2>");
+ outp.write("</body>");
+ outp.write("</html>");
+ }
}
View
409 blogracy-web/src/main/java/net/blogracy/web/ImageGalleryUploader.java
@@ -16,6 +16,7 @@
import javax.servlet.http.HttpServletResponse;
import net.blogracy.controller.FileSharing;
+import net.blogracy.controller.MediaController;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
@@ -27,209 +28,207 @@
public class ImageGalleryUploader extends HttpServlet {
- private final String SERVLET_RELATIVE_URL = "ImageGalleryUploader";
- private final String CACHE_RELATIVE_URL = "cache/";
-
- /***
- * Retrieves the images that belong to the album
- */
- protected void doGet(HttpServletRequest request,
- HttpServletResponse response) throws ServletException, IOException {
-
- // Obtaining the current userId and albumId
- String userId = request.getParameter("userId");
- String albumId = request.getParameter("albumId");
-
- if (userId != null && albumId != null) {
- // Getting the media items from user's record db
- List<MediaItem> list = FileSharing.getSingleton()
- .getMediaItemsWithCachedImages(userId, albumId);
- response.setContentType("application/json");
-
- List<String> imageUrlList = new ArrayList<String>();
- for (MediaItem item : list) {
- imageUrlList.add(item.getUrl());
- }
-
- String jsonAnswer = toJSON(imageUrlList, albumId, userId);
- response.getWriter().write(jsonAnswer);
- }
- }
-
- /***
- * It's used for:
- * - creating a new album (it requires "user" and "galleryName" as parameters)
- * - uploading images to the album (it requires "user" and "albumId" as parameters alongside the actual files, request should be multipart content)
- */
- protected void doPost(HttpServletRequest request,
- HttpServletResponse response) throws ServletException, IOException {
-
- if (!ServletFileUpload.isMultipartContent(request))
- createNewPhotoAlbum(request);
- else
- addUploadedFilesToPhotoAlbum(request, response);
- }
-
-
- /**
- * A certain mediaId is removed from an album.
- * It requires "mediaId", "albumId" and "userId" as parameters
- */
- protected void doDelete(HttpServletRequest request,
- HttpServletResponse response) throws ServletException, IOException {
- String mediaId = request.getParameter("mediaId");
- String albumId = request.getParameter("albumId");
- String userId = request.getParameter("userId");
-
- try {
- FileSharing.getSingleton().deletePhotoFromAlbum(userId, albumId,
- mediaId);
- response.setStatus(HttpServletResponse.SC_OK);
- } catch (Exception e) {
- e.printStackTrace();
- response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- }
- }
-
-
-
- private void addUploadedFilesToPhotoAlbum(HttpServletRequest request,
- HttpServletResponse response) throws IOException {
- ServletFileUpload uploadHandler = new ServletFileUpload(
- new DiskFileItemFactory());
-
- // The userId and albumId are sent along with the request
- String userHash = null;
- String albumId = null;
- Map<FileItem, FileDTO> cachedFiles = new HashMap<FileItem, FileDTO>();
- Map<File,String> fileAndMimeTypeMap = new HashMap<File, String>();
-
- try {
- @SuppressWarnings("unchecked")
- List<FileItem> items = uploadHandler.parseRequest(request);
- for (FileItem item : items) {
- if (item.isFormField()) {
- String fieldName = item.getFieldName();
- if (fieldName.equalsIgnoreCase("user"))
- userHash = item.getString();
- else if (fieldName.equalsIgnoreCase("albumId"))
- albumId = item.getString();
-
- } else {
- File f = new File(item.getName());
- item.write(f);
- cachedFiles.put(item, new FileDTO(f));
- fileAndMimeTypeMap.put(f, item.getContentType());
- item.delete();
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
-
-
- List<String> hashes = FileSharing.getSingleton().addMediaItemsToAlbum(userHash, albumId, fileAndMimeTypeMap);
-
- int i = 0;
- for (Entry<FileItem, FileDTO> entry : cachedFiles.entrySet()){
- entry.getValue().setHash(hashes.get(i));
- ++i;
- }
-
- // Send a Json message to the imageGalleryUploader control
- // containing the file's data
- sendImageUploaderJsonReply(cachedFiles, response, albumId, userHash);
- }
-
- private void createNewPhotoAlbum(HttpServletRequest request) {
- // Obtaining the current user
- String user = request.getParameter("user");
-
- try {
- String galleryName = request.getParameter("galleryname");
-
- if (galleryName != null) {
- // Gallery creation
- FileSharing.getSingleton().createPhotoAlbum(user, galleryName);
-
- }
- } catch (Exception e) {
- System.out.println(e.getMessage());
- System.out.println(e.getStackTrace());
- }
- }
-
- private void sendImageUploaderJsonReply(Map<FileItem, FileDTO> cachedFiles,
- HttpServletResponse response, String albumId, String userId)
- throws IOException {
-
- response.setContentType("application/json");
-
- for (Entry<FileItem, FileDTO> entry : cachedFiles.entrySet()) {
- List<String> stringEntry = new ArrayList<String>();
- stringEntry.add(CACHE_RELATIVE_URL + entry.getValue().getHash());
- String jsonAnswer = toJSON(stringEntry, albumId, userId);
- response.getWriter().write(jsonAnswer);
- }
- }
-
- private String toJSON(Collection<String> fileNames, String albumId,
- String userId) throws IOException {
- JSONArray array = new JSONArray();
-
- try {
- for (String fileName : fileNames) {
- JSONObject json = new JSONObject();
- File currentFile = new File(fileName);
- System.out.println(fileName);
-
- json.put("name", "");
- json.put("size", String.valueOf(currentFile.length()));
- json.put("url", fileName);
- json.put("thumbnail_url", fileName);
- json.put("delete_url", String.format(SERVLET_RELATIVE_URL
- + "?mediaId=%s&albumId=%s&userId=%s",
- fileName.substring(CACHE_RELATIVE_URL.length()), albumId,
- userId));
- json.put("delete_type", "DELETE");
- array.put(json);
- }
-
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return array.toString();
- }
-
-
- /***
- * Auxiliary Data Transfer Object which keeps the File and its bittorrent hash string information
- *
- */
- public class FileDTO
- {
- public FileDTO(File associatedFile)
- {
- this.file = associatedFile;
- }
-
- public File getFile() {
- return file;
- }
-
- public String getHash() {
- return hash;
- }
-
- public void setHash(String hash) {
- this.hash = hash;
- }
- protected File file;
- protected String hash;
-
- public Entry<File,String> toEntry()
- {
- return new AbstractMap.SimpleEntry<File,String>(this.file, this.hash);
- }
- }
+ private final String SERVLET_RELATIVE_URL = "ImageGalleryUploader";
+ private final String CACHE_RELATIVE_URL = "cache/";
+
+ /***
+ * Retrieves the images that belong to the album
+ */
+ protected void doGet(HttpServletRequest request,
+ HttpServletResponse response) throws ServletException, IOException {
+
+ // Obtaining the current userId and albumId
+ String userId = request.getParameter("userId");
+ String albumId = request.getParameter("albumId");
+
+ if (userId != null && albumId != null) {
+ // Getting the media items from user's record db
+ List<MediaItem> list = MediaController.getSingleton()
+ .getMediaItemsWithCachedImages(userId, albumId);
+ response.setContentType("application/json");
+
+ List<String> imageUrlList = new ArrayList<String>();
+ for (MediaItem item : list) {
+ imageUrlList.add(item.getUrl());
+ }
+
+ String jsonAnswer = toJSON(imageUrlList, albumId, userId);
+ response.getWriter().write(jsonAnswer);
+ }
+ }
+
+ /***
+ * It's used for: - creating a new album (it requires "user" and
+ * "galleryName" as parameters) - uploading images to the album (it requires
+ * "user" and "albumId" as parameters alongside the actual files, request
+ * should be multipart content)
+ */
+ protected void doPost(HttpServletRequest request,
+ HttpServletResponse response) throws ServletException, IOException {
+
+ if (!ServletFileUpload.isMultipartContent(request))
+ createNewPhotoAlbum(request);
+ else
+ addUploadedFilesToPhotoAlbum(request, response);
+ }
+
+ /**
+ * A certain mediaId is removed from an album. It requires "mediaId",
+ * "albumId" and "userId" as parameters
+ */
+ protected void doDelete(HttpServletRequest request,
+ HttpServletResponse response) throws ServletException, IOException {
+ String mediaId = request.getParameter("mediaId");
+ String albumId = request.getParameter("albumId");
+ String userId = request.getParameter("userId");
+
+ try {
+ MediaController.getSingleton().deletePhotoFromAlbum(userId,
+ albumId, mediaId);
+ response.setStatus(HttpServletResponse.SC_OK);
+ } catch (Exception e) {
+ e.printStackTrace();
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ private void addUploadedFilesToPhotoAlbum(HttpServletRequest request,
+ HttpServletResponse response) throws IOException {
+ ServletFileUpload uploadHandler = new ServletFileUpload(
+ new DiskFileItemFactory());
+
+ // The userId and albumId are sent along with the request
+ String userHash = null;
+ String albumId = null;
+ Map<FileItem, FileDTO> cachedFiles = new HashMap<FileItem, FileDTO>();
+ Map<File, String> fileAndMimeTypeMap = new HashMap<File, String>();
+
+ try {
+ @SuppressWarnings("unchecked")
+ List<FileItem> items = uploadHandler.parseRequest(request);
+ for (FileItem item : items) {
+ if (item.isFormField()) {
+ String fieldName = item.getFieldName();
+ if (fieldName.equalsIgnoreCase("user"))
+ userHash = item.getString();
+ else if (fieldName.equalsIgnoreCase("albumId"))
+ albumId = item.getString();
+
+ } else {
+ File f = new File(item.getName());
+ item.write(f);
+ cachedFiles.put(item, new FileDTO(f));
+ fileAndMimeTypeMap.put(f, item.getContentType());
+ item.delete();
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ List<String> hashes = MediaController.getSingleton()
+ .addMediaItemsToAlbum(userHash, albumId, fileAndMimeTypeMap);
+
+ int i = 0;
+ for (Entry<FileItem, FileDTO> entry : cachedFiles.entrySet()) {
+ entry.getValue().setHash(hashes.get(i));
+ ++i;
+ }
+
+ // Send a Json message to the imageGalleryUploader control
+ // containing the file's data
+ sendImageUploaderJsonReply(cachedFiles, response, albumId, userHash);
+ }
+
+ private void createNewPhotoAlbum(HttpServletRequest request) {
+ // Obtaining the current user
+ String user = request.getParameter("user");
+
+ try {
+ String galleryName = request.getParameter("galleryname");
+
+ if (galleryName != null) {
+ // Gallery creation
+ MediaController.getSingleton().createPhotoAlbum(user,
+ galleryName);
+
+ }
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ System.out.println(e.getStackTrace());
+ }
+ }
+
+ private void sendImageUploaderJsonReply(Map<FileItem, FileDTO> cachedFiles,
+ HttpServletResponse response, String albumId, String userId)
+ throws IOException {
+
+ response.setContentType("application/json");
+
+ for (Entry<FileItem, FileDTO> entry : cachedFiles.entrySet()) {
+ List<String> stringEntry = new ArrayList<String>();
+ stringEntry.add(CACHE_RELATIVE_URL + entry.getValue().getHash());
+ String jsonAnswer = toJSON(stringEntry, albumId, userId);
+ response.getWriter().write(jsonAnswer);
+ }
+ }
+
+ private String toJSON(Collection<String> fileNames, String albumId,
+ String userId) throws IOException {
+ JSONArray array = new JSONArray();
+
+ try {
+ for (String fileName : fileNames) {
+ JSONObject json = new JSONObject();
+ File currentFile = new File(fileName);
+ System.out.println(fileName);
+
+ json.put("name", "");
+ json.put("size", String.valueOf(currentFile.length()));
+ json.put("url", fileName);
+ json.put("thumbnail_url", fileName);
+ json.put("delete_url", String.format(SERVLET_RELATIVE_URL
+ + "?mediaId=%s&albumId=%s&userId=%s",
+ fileName.substring(CACHE_RELATIVE_URL.length()),
+ albumId, userId));
+ json.put("delete_type", "DELETE");
+ array.put(json);
+ }
+
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return array.toString();
+ }
+
+ /***
+ * Auxiliary Data Transfer Object which keeps the File and its bittorrent
+ * hash string information
+ *
+ */
+ public class FileDTO {
+ public FileDTO(File associatedFile) {
+ this.file = associatedFile;
+ }
+
+ public File getFile() {
+ return file;
+ }
+
+ public String getHash() {
+ return hash;
+ }
+
+ public void setHash(String hash) {
+ this.hash = hash;
+ }
+
+ protected File file;
+ protected String hash;
+
+ public Entry<File, String> toEntry() {
+ return new AbstractMap.SimpleEntry<File, String>(this.file,
+ this.hash);
+ }
+ }
}
View
3  blogracy-web/src/main/webapp/user.jsp
@@ -1,6 +1,7 @@
<%@ page import="net.blogracy.model.hashes.Hashes" %>
<%@ page import="net.blogracy.model.users.Users" %>
<%@ page import="net.blogracy.controller.FileSharing" %>
+<%@ page import="net.blogracy.controller.ActivitiesController" %>
<%@ page import="net.blogracy.controller.ChatController" %>
<%@ page import="net.blogracy.config.Configurations" %>
<%@ page import="java.util.List" %>
@@ -22,7 +23,7 @@ pageContext.setAttribute("localUserHash", localUserHash);
pageContext.setAttribute("userHash", userHash);
pageContext.setAttribute("application", "Blogracy");
pageContext.setAttribute("user", Users.newUser(Hashes.fromString(userHash)));
-pageContext.setAttribute("feed", FileSharing.getFeed(userHash));
+pageContext.setAttribute("feed", ActivitiesController.getFeed(userHash));
pageContext.setAttribute("friends", Configurations.getUserConfig().getFriends());
pageContext.setAttribute("localUser", Configurations.getUserConfig().getUser());
pageContext.setAttribute("privateChannel", channel);
Please sign in to comment.
Something went wrong with that request. Please try again.