use of org.alfresco.repo.domain.activities.ActivityPostEntity in project alfresco-repository by Alfresco.
the class ActivityPostDAOImpl method deletePosts.
public int deletePosts(Date keepDate, ActivityPostEntity.STATUS status) throws SQLException {
ActivityPostEntity params = new ActivityPostEntity();
params.setPostDate(keepDate);
params.setStatus(status.toString());
return template.delete("alfresco.activities.delete_activity_posts_older_than_date", params);
}
use of org.alfresco.repo.domain.activities.ActivityPostEntity in project alfresco-repository by Alfresco.
the class ActivityPostDAOImpl method updatePost.
public int updatePost(long id, String siteNetwork, String activityData, ActivityPostEntity.STATUS status) throws SQLException {
ActivityPostEntity post = new ActivityPostEntity();
post.setId(id);
post.setSiteNetwork(siteNetwork);
post.setActivityData(activityData);
post.setStatus(status.toString());
post.setLastModified(new Date());
return template.update("alfresco.activities.update_activity_post_data", post);
}
use of org.alfresco.repo.domain.activities.ActivityPostEntity in project alfresco-repository by Alfresco.
the class ActivityPostDAOImpl method updatePostStatus.
public int updatePostStatus(long id, ActivityPostEntity.STATUS status) throws SQLException {
ActivityPostEntity post = new ActivityPostEntity();
post.setId(id);
post.setStatus(status.toString());
post.setLastModified(new Date());
return template.update("alfresco.activities.update_activity_post_status", post);
}
use of org.alfresco.repo.domain.activities.ActivityPostEntity in project alfresco-repository by Alfresco.
the class FeedTaskProcessor method process.
public void process(int jobTaskNode, long minSeq, long maxSeq, RepoCtx ctx) throws Exception {
long startTime = System.currentTimeMillis();
if (logger.isDebugEnabled()) {
logger.debug("Process: jobTaskNode '" + jobTaskNode + "' from seq '" + minSeq + "' to seq '" + maxSeq + "' on this node from grid job.");
}
ActivityPostEntity selector = new ActivityPostEntity();
selector.setJobTaskNode(jobTaskNode);
selector.setMinId(minSeq);
selector.setMaxId(maxSeq);
selector.setStatus(ActivityPostEntity.STATUS.POSTED.toString());
List<ActivityPostEntity> activityPosts = null;
int totalGenerated = 0;
try {
activityPosts = selectPosts(selector);
if (logger.isDebugEnabled()) {
logger.debug("Process: " + activityPosts.size() + " activity posts");
}
// local caches for this run of activity posts
// site -> site members
Map<String, Set<String>> siteConnectedUsers = new HashMap<String, Set<String>>();
// user -> followers
Map<Pair<String, String>, Set<String>> followerConnectedUsers = new HashMap<Pair<String, String>, Set<String>>();
// <user, site> -> true/false (note: used when following, implied as true for site members)
Map<Pair<String, String>, Boolean> canUserReadSite = new HashMap<Pair<String, String>, Boolean>();
Map<String, List<FeedControlEntity>> userFeedControls = new HashMap<String, List<FeedControlEntity>>();
List<String> fmTemplates = Arrays.asList(new String[] { "activities/org/alfresco/generic.json.ftl" });
// for each activity post ...
for (ActivityPostEntity activityPost : activityPosts) {
String postingUserId = activityPost.getUserId();
String activityType = activityPost.getActivityType();
if (fmTemplates.size() == 0) {
logger.error("Skipping activity post " + activityPost.getId() + " since no specific/generic templates for activityType: " + activityType);
updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.ERROR);
continue;
}
Map<String, Object> model = null;
try {
model = JSONtoFmModel.convertJSONObjectToMap(activityPost.getActivityData());
} catch (JSONException je) {
logger.error("Skipping activity post " + activityPost.getId() + " due to invalid activity data: ", je);
updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.ERROR);
continue;
}
String nodeRefStr = (String) model.get(PostLookup.JSON_NODEREF);
try {
// If a nodeRef is present, then it must be valid.
if (nodeRefStr != null) {
// Attempt to create a nodeRef, making use of the constructor's validation.
new NodeRef(nodeRefStr);
}
} catch (Exception e) {
logger.error("Skipping activity post " + activityPost.getId() + " due to invalid nodeRef: " + nodeRefStr);
updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.ERROR);
continue;
}
// note: for MT share, site id should already be mangled - in addition to extra tenant domain info
String thisSite = activityPost.getSiteNetwork();
String tenantDomain = (String) model.get(PostLookup.JSON_TENANT_DOMAIN);
if (thisSite != null) {
if (tenantDomain != null) {
thisSite = getTenantName(thisSite, tenantDomain);
} else {
// for backwards compatibility
tenantDomain = getTenantDomain(thisSite);
}
}
if (tenantDomain == null) {
tenantDomain = TenantService.DEFAULT_DOMAIN;
}
model.put(ActivityFeedEntity.KEY_ACTIVITY_FEED_TYPE, activityPost.getActivityType());
model.put(ActivityFeedEntity.KEY_ACTIVITY_FEED_SITE, thisSite);
model.put("userId", activityPost.getUserId());
model.put("id", activityPost.getId());
// post date rather than time that feed is generated
model.put("date", activityPost.getPostDate());
model.put("xmldate", new ISO8601DateFormatMethod());
model.put("repoEndPoint", ctx.getRepoEndPoint());
// Get recipients of this post
Set<String> recipients = null;
try {
recipients = getRecipients(ctx, thisSite, activityPost.getUserId(), tenantDomain, siteConnectedUsers, followerConnectedUsers, canUserReadSite);
} catch (Exception e) {
logger.error("Skipping activity post " + activityPost.getId() + " since failed to get recipients: ", e);
updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.ERROR);
continue;
}
try {
startTransaction();
if (logger.isTraceEnabled()) {
logger.trace("Process: " + recipients.size() + " candidate connections for activity post " + activityPost.getId());
}
int excludedConnections = 0;
for (String recipient : recipients) {
List<FeedControlEntity> feedControls = null;
if (!recipient.equals("")) {
// Get user's feed controls
feedControls = userFeedControls.get(recipient);
if (feedControls == null) {
feedControls = getFeedControls(recipient);
userFeedControls.put(recipient, feedControls);
}
}
// filter based on opt-out feed controls (if any)
if (!acceptActivity(activityPost, feedControls)) {
excludedConnections++;
} else {
// node read permission check (if nodeRef is present)
if (!canRead(ctx, recipient, model)) {
excludedConnections++;
continue;
}
for (String fmTemplate : fmTemplates) {
String formatFound = FeedTaskProcessor.FEED_FORMAT_JSON;
ActivityFeedEntity feed = new ActivityFeedEntity();
// MNT-9104 If username contains uppercase letters the action of joining a site will not be displayed in "My activities"
if (!userNamesAreCaseSensitive) {
recipient = recipient.toLowerCase();
postingUserId = postingUserId.toLowerCase();
}
feed.setFeedUserId(recipient);
feed.setPostUserId(postingUserId);
feed.setActivityType(activityType);
String activitySummary = null;
// allows JSON to simply pass straight through
activitySummary = activityPost.getActivityData();
if (!activitySummary.equals("")) {
if (activitySummary.length() > ActivityFeedDAO.MAX_LEN_ACTIVITY_SUMMARY) {
logger.warn("Skip feed entry (activity post " + activityPost.getId() + ") since activity summary - exceeds " + ActivityFeedDAO.MAX_LEN_ACTIVITY_SUMMARY + " chars: " + activitySummary);
} else {
feed.setActivitySummary(activitySummary);
feed.setSiteNetwork(thisSite);
feed.setAppTool(activityPost.getAppTool());
feed.setPostDate(activityPost.getPostDate());
feed.setPostId(activityPost.getId());
feed.setFeedDate(new Date());
// Insert activity feed
// ignore returned feedId
insertFeedEntry(feed);
totalGenerated++;
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("Empty template result for activityType '" + activityType + "' using format '" + formatFound + "' hence skip feed entry (activity post " + activityPost.getId() + ")");
}
}
}
}
}
updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.PROCESSED);
commitTransaction();
if (logger.isDebugEnabled()) {
logger.debug("Processed: " + (recipients.size() - excludedConnections) + " connections for activity post " + activityPost.getId() + " (excluded " + excludedConnections + ")");
}
} finally {
endTransaction();
}
}
} catch (SQLException se) {
logger.error(se);
throw se;
} finally {
int postCnt = activityPosts == null ? 0 : activityPosts.size();
// TODO i18n info message
StringBuilder sb = new StringBuilder();
sb.append("Generated ").append(totalGenerated).append(" activity feed entr").append(totalGenerated == 1 ? "y" : "ies");
sb.append(" for ").append(postCnt).append(" activity post").append(postCnt != 1 ? "s" : "").append(" (in ").append(System.currentTimeMillis() - startTime).append(" msecs)");
logger.info(sb.toString());
}
}
use of org.alfresco.repo.domain.activities.ActivityPostEntity in project alfresco-repository by Alfresco.
the class ActivityPostServiceImpl method postActivity.
private void postActivity(final String activityType, String siteId, String appTool, String activityData, ActivityPostEntity.STATUS status, String userId, final Client client, final FileInfo contentNodeInfo) {
NodeRef nodeRef = null;
try {
// optional - default to empty string
if (siteId == null) {
siteId = "";
} else if (siteId.length() > ActivityPostDAO.MAX_LEN_SITE_ID) {
throw new IllegalArgumentException("Invalid siteId - exceeds " + ActivityPostDAO.MAX_LEN_SITE_ID + " chars: " + siteId);
}
// optional - default to empty string
if (appTool == null) {
appTool = "";
} else if (appTool.length() > ActivityPostDAO.MAX_LEN_APP_TOOL_ID) {
throw new IllegalArgumentException("Invalid app tool - exceeds " + ActivityPostDAO.MAX_LEN_APP_TOOL_ID + " chars: " + appTool);
}
// required
ParameterCheck.mandatoryString("activityType", activityType);
if (activityType.length() > ActivityPostDAO.MAX_LEN_ACTIVITY_TYPE) {
throw new IllegalArgumentException("Invalid activity type - exceeds " + ActivityPostDAO.MAX_LEN_ACTIVITY_TYPE + " chars: " + activityType);
}
if (ignoredActivityTypes != null && ignoredActivityTypes.contains(activityType)) {
// do not log the activity for ignored activity types.
logger.debug("Ignoring activity type for posting: " + activityType);
return;
}
// optional - default to empty string
if (activityData == null) {
activityData = "";
}
try {
if (activityData.length() > 0) {
JSONObject jo = new JSONObject(new JSONTokener(activityData));
if (AuthenticationUtil.isMtEnabled()) {
// MT share - add tenantDomain
jo.put(PostLookup.JSON_TENANT_DOMAIN, tenantService.getCurrentUserDomain());
activityData = jo.toString();
}
nodeRef = checkNodeRef(jo);
// ALF-10362 - belts-and-braces (note: Share sets "title" from cm:name)
if (jo.has(PostLookup.JSON_TITLE)) {
String title = jo.getString(PostLookup.JSON_TITLE);
if (title.length() > ActivityPostDAO.MAX_LEN_NAME) {
jo.put(PostLookup.JSON_TITLE, title.substring(0, 255));
activityData = jo.toString();
}
}
}
} catch (JSONException e) {
// throw new IllegalArgumentException("Invalid activity data - not valid JSON: " + e);
// According to test data in org/alfresco/repo/activities/script/test_activityService.js
// invalid JSON should be OK.
}
if (activityData.length() > ActivityPostDAO.MAX_LEN_ACTIVITY_DATA) {
throw new IllegalArgumentException("Invalid activity data - exceeds " + ActivityPostDAO.MAX_LEN_ACTIVITY_DATA + " chars: " + activityData);
}
// required
ParameterCheck.mandatoryString("userId", userId);
if (userId.length() > ActivityPostDAO.MAX_LEN_USER_ID) {
throw new IllegalArgumentException("Invalid user - exceeds " + ActivityPostDAO.MAX_LEN_USER_ID + " chars: " + userId);
}
} catch (IllegalArgumentException e) {
// log error and throw exception
logger.error(e);
throw new IllegalArgumentException("Failed to post activity: " + e, e);
}
try {
final Date postDate = new Date();
final ActivityPostEntity activityPost = new ActivityPostEntity();
final String network = tenantService.getName(siteId);
final String site = siteId;
final NodeRef finalNodeRef = nodeRef;
// MNT-9104 If username contains uppercase letters the action of joining a site will not be displayed in "My activities"
if (!userNamesAreCaseSensitive) {
userId = userId.toLowerCase();
}
activityPost.setUserId(userId);
activityPost.setSiteNetwork(network);
activityPost.setAppTool(appTool);
activityPost.setActivityData(activityData);
activityPost.setActivityType(activityType);
activityPost.setPostDate(postDate);
activityPost.setStatus(status.toString());
activityPost.setLastModified(postDate);
eventPublisher.publishEvent(new EventPreparator() {
@Override
public Event prepareEvent(String user, String networkId, String transactionId) {
String filename = null, nodeType = null, mime = null, encoding = null;
long size = 0l;
String nodeId = finalNodeRef != null ? finalNodeRef.getId() : null;
FileInfo fileInfo = contentNodeInfo;
// Use content info
if (fileInfo != null) {
if (logger.isDebugEnabled()) {
logger.debug("Enhancing the Activity Event with fileInfo provided for node " + nodeId);
}
if (nodeId == null) {
nodeId = fileInfo.getNodeRef().getId();
}
filename = fileInfo.getName();
nodeType = fileInfo.getType().toString();
if (!fileInfo.isFolder()) {
// It's a file so get more info
ContentData contentData = fileInfo.getContentData();
if (contentData != null) {
mime = contentData.getMimetype();
size = contentData.getSize();
encoding = contentData.getEncoding();
}
}
}
return new ActivityEvent(activityType, transactionId, networkId, user, nodeId, site, nodeType, client, activityPost.getActivityData(), filename, mime, size, encoding);
}
});
// hash the userid to generate a job task node
int nodeCount = estGridSize;
int userHashCode = userId.hashCode();
int nodeHash = (userHashCode % nodeCount) + 1;
activityPost.setJobTaskNode(nodeHash);
try {
long postId = postDAO.insertPost(activityPost);
if (logger.isDebugEnabled()) {
activityPost.setId(postId);
logger.debug("Posted: " + activityPost);
}
} catch (SQLException e) {
throw new AlfrescoRuntimeException("Failed to post activity: " + e, e);
} catch (Throwable t) {
throw new AlfrescoRuntimeException("Failed to post activity: " + t, t);
}
} catch (AlfrescoRuntimeException e) {
// log error, subsume exception (for post activity)
logger.error(e);
}
}
Aggregations