/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.opensocial.shindig.service; import com.liferay.document.library.kernel.model.DLFileEntry; import com.liferay.document.library.kernel.service.DLAppLocalServiceUtil; import com.liferay.document.library.kernel.service.DLAppServiceUtil; import com.liferay.opensocial.shindig.util.SerializerUtil; import com.liferay.opensocial.shindig.util.ShindigUtil; import com.liferay.portal.kernel.dao.orm.QueryUtil; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.model.Group; import com.liferay.portal.kernel.model.User; import com.liferay.portal.kernel.repository.model.FileEntry; import com.liferay.portal.kernel.repository.model.FileVersion; import com.liferay.portal.kernel.service.ServiceContext; import com.liferay.portal.kernel.service.UserLocalServiceUtil; import com.liferay.portal.kernel.servlet.HttpHeaders; import com.liferay.portal.kernel.util.FileUtil; import com.liferay.portal.kernel.util.GetterUtil; import com.liferay.portal.kernel.util.Http; import com.liferay.portal.kernel.util.HttpUtil; import com.liferay.portal.kernel.util.MimeTypesUtil; import com.liferay.portal.kernel.util.StringPool; import com.liferay.social.kernel.model.SocialRelationConstants; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.concurrent.Future; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.http.HttpServletResponse; import org.apache.shindig.auth.SecurityToken; import org.apache.shindig.common.util.ImmediateFuture; import org.apache.shindig.protocol.ProtocolException; import org.apache.shindig.protocol.RestfulCollection; import org.apache.shindig.social.core.model.MediaItemImpl; import org.apache.shindig.social.opensocial.model.MediaItem; import org.apache.shindig.social.opensocial.model.MediaItem.Type; import org.apache.shindig.social.opensocial.spi.CollectionOptions; import org.apache.shindig.social.opensocial.spi.GroupId; import org.apache.shindig.social.opensocial.spi.MediaItemService; import org.apache.shindig.social.opensocial.spi.UserId; /** * @author Dennis Ju */ public class LiferayMediaItemService implements MediaItemService { public Future<Void> createMediaItem( UserId userId, String appId, String albumId, MediaItem mediaItem, SecurityToken securityToken) throws ProtocolException { try { doCreateMediaItem(userId, appId, albumId, mediaItem, securityToken); return ImmediateFuture.newInstance(null); } catch (Exception e) { if (_log.isDebugEnabled()) { _log.debug(e, e); } throw new ProtocolException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage(), e); } } public Future<Void> deleteMediaItem( UserId userId, String appId, String albumId, String mediaItemId, SecurityToken securityToken) throws ProtocolException { try { doDeleteMediaItem( userId, appId, albumId, mediaItemId, securityToken); return ImmediateFuture.newInstance(null); } catch (Exception e) { if (_log.isDebugEnabled()) { _log.debug(e, e); } throw new ProtocolException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage(), e); } } public Future<MediaItem> getMediaItem( UserId userId, String appId, String albumId, String mediaItemId, Set<String> fields, SecurityToken securityToken) throws ProtocolException { try { MediaItem mediaItem = doGetMediaItem( userId, appId, albumId, mediaItemId, fields, securityToken); return ImmediateFuture.newInstance(mediaItem); } catch (Exception e) { if (_log.isDebugEnabled()) { _log.debug(e, e); } throw new ProtocolException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage(), e); } } public Future<RestfulCollection<MediaItem>> getMediaItems( Set<UserId> userIds, GroupId groupId, String appId, Set<String> fields, CollectionOptions collectionOptions, SecurityToken securityToken) throws ProtocolException { try { RestfulCollection<MediaItem> mediaItems = doGetMediaItems( userIds, groupId, appId, fields, collectionOptions, securityToken); return ImmediateFuture.newInstance(mediaItems); } catch (Exception e) { if (_log.isDebugEnabled()) { _log.debug(e, e); } throw new ProtocolException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage(), e); } } public Future<RestfulCollection<MediaItem>> getMediaItems( UserId userId, String appId, String albumId, Set<String> fields, CollectionOptions collectionOptions, SecurityToken securityToken) throws ProtocolException { try { RestfulCollection<MediaItem> mediaItems = doGetMediaItems( userId, appId, albumId, fields, collectionOptions, securityToken); return ImmediateFuture.newInstance(mediaItems); } catch (Exception e) { if (_log.isDebugEnabled()) { _log.debug(e, e); } throw new ProtocolException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage(), e); } } public Future<RestfulCollection<MediaItem>> getMediaItems( UserId userId, String appId, String albumId, Set<String> mediaItemIds, Set<String> fields, CollectionOptions collectionOptions, SecurityToken securityToken) throws ProtocolException { try { RestfulCollection<MediaItem> mediaItems = doGetMediaItems( userId, appId, albumId, mediaItemIds, fields, collectionOptions, securityToken); return ImmediateFuture.newInstance(mediaItems); } catch (Exception e) { if (_log.isDebugEnabled()) { _log.debug(e, e); } throw new ProtocolException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage(), e); } } public Future<Void> updateMediaItem( UserId userId, String appId, String albumId, String mediaItemId, MediaItem mediaItem, SecurityToken securityToken) throws ProtocolException { try { doUpdateMediaItem( userId, appId, albumId, mediaItemId, mediaItem, securityToken); return ImmediateFuture.newInstance(null); } catch (Exception e) { if (_log.isDebugEnabled()) { _log.debug(e, e); } throw new ProtocolException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage(), e); } } protected void doCreateMediaItem( UserId userId, String appId, String albumId, MediaItem mediaItem, SecurityToken securityToken) throws Exception { doUpdateMediaItem( userId, appId, albumId, null, mediaItem, securityToken); } protected void doDeleteMediaItem( UserId userId, String appId, String albumId, String mediaItemId, SecurityToken securityToken) throws Exception { long mediaItemIdLong = GetterUtil.getLong(mediaItemId); DLAppServiceUtil.deleteFileEntry(mediaItemIdLong); } protected MediaItem doGetMediaItem( UserId userId, String appId, String albumId, String mediaItemId, Set<String> fields, SecurityToken securityToken) throws Exception { long mediaItemIdLong = GetterUtil.getLong(mediaItemId); FileEntry fileEntry = DLAppServiceUtil.getFileEntry(mediaItemIdLong); return toMediaItem(fileEntry, fields, securityToken); } protected RestfulCollection<MediaItem> doGetMediaItems( Set<UserId> userIds, GroupId groupId, String appId, Set<String> fields, CollectionOptions collectionOptions, SecurityToken securityToken) throws Exception { List<MediaItem> mediaItems = new ArrayList<>(); for (UserId userId : userIds) { long userIdLong = GetterUtil.getLong( userId.getUserId(securityToken)); User user = UserLocalServiceUtil.getUserById(userIdLong); if (!ShindigUtil.isValidUser(user)) { continue; } List<FileEntry> fileEntries = new ArrayList<>(); GroupId.Type groupIdType = groupId.getType(); if (groupIdType.equals(GroupId.Type.all) || groupIdType.equals(GroupId.Type.friends) || groupIdType.equals(GroupId.Type.groupId)) { List<User> socialUsers = UserLocalServiceUtil.getSocialUsers( user.getUserId(), SocialRelationConstants.TYPE_BI_FRIEND, QueryUtil.ALL_POS, QueryUtil.ALL_POS, null); for (User socialUser : socialUsers) { Group group = socialUser.getGroup(); List<FileEntry> friendFileEntries = DLAppServiceUtil.getGroupFileEntries( group.getGroupId(), socialUser.getUserId(), collectionOptions.getFirst(), collectionOptions.getMax()); fileEntries.addAll(friendFileEntries); } } else if (groupIdType.equals(GroupId.Type.self)) { Group group = user.getGroup(); fileEntries = DLAppServiceUtil.getGroupFileEntries( group.getGroupId(), user.getUserId(), collectionOptions.getFirst(), collectionOptions.getMax()); } for (FileEntry fileEntry : fileEntries) { MediaItem.Type mediaItemType = toMediaItemType( StringPool.PERIOD.concat(fileEntry.getExtension())); if (mediaItemType == null) { continue; } MediaItem mediaItem = toMediaItem( fileEntry, fields, securityToken); mediaItems.add(mediaItem); } } return new RestfulCollection<>( mediaItems, collectionOptions.getFirst(), mediaItems.size(), collectionOptions.getMax()); } protected RestfulCollection<MediaItem> doGetMediaItems( UserId userId, String appId, String albumId, Set<String> fields, CollectionOptions collectionOptions, SecurityToken securityToken) throws Exception { long userIdLong = GetterUtil.getLong(userId.getUserId(securityToken)); User user = UserLocalServiceUtil.getUserById(userIdLong); List<MediaItem> mediaItems = new ArrayList<>(); if (!ShindigUtil.isValidUser(user)) { return new RestfulCollection<>( mediaItems, collectionOptions.getFirst(), mediaItems.size(), collectionOptions.getMax()); } Group group = user.getGroup(); long groupIdLong = group.getGroupId(); long albumIdLong = GetterUtil.getLong(albumId); List<FileEntry> fileEntries = DLAppServiceUtil.getFileEntries( groupIdLong, albumIdLong); for (FileEntry fileEntry : fileEntries) { MediaItem.Type mediaItemType = toMediaItemType( StringPool.PERIOD.concat(fileEntry.getExtension())); if (mediaItemType == null) { continue; } MediaItem mediaItem = toMediaItem(fileEntry, fields, securityToken); mediaItems.add(mediaItem); } return new RestfulCollection<>( mediaItems, collectionOptions.getFirst(), mediaItems.size(), collectionOptions.getMax()); } protected RestfulCollection<MediaItem> doGetMediaItems( UserId userId, String appId, String albumId, Set<String> mediaItemIds, Set<String> fields, CollectionOptions collectionOptions, SecurityToken securityToken) throws Exception { long userIdLong = GetterUtil.getLong(userId.getUserId(securityToken)); User user = UserLocalServiceUtil.getUserById(userIdLong); List<MediaItem> mediaItems = new ArrayList<>(); if (!ShindigUtil.isValidUser(user)) { return new RestfulCollection<>( mediaItems, collectionOptions.getFirst(), mediaItems.size(), collectionOptions.getMax()); } Group group = user.getGroup(); long groupIdLong = group.getGroupId(); long albumIdLong = GetterUtil.getLong(albumId); List<FileEntry> fileEntries = DLAppServiceUtil.getFileEntries( groupIdLong, albumIdLong); for (FileEntry fileEntry : fileEntries) { MediaItem.Type mediaItemType = toMediaItemType( StringPool.PERIOD.concat(fileEntry.getExtension())); if (mediaItemType == null) { continue; } MediaItem mediaItem = toMediaItem(fileEntry, fields, securityToken); if (mediaItemIds.contains(mediaItem.getId())) { mediaItems.add(mediaItem); } } return new RestfulCollection<>( mediaItems, collectionOptions.getFirst(), mediaItems.size(), collectionOptions.getMax()); } protected void doUpdateMediaItem( UserId userId, String appId, String albumId, String mediaItemId, MediaItem mediaItem, SecurityToken securityToken) throws Exception { long userIdLong = GetterUtil.getLong(userId.getUserId(securityToken)); User user = UserLocalServiceUtil.getUserById(userIdLong); if (!ShindigUtil.isValidUser(user)) { return; } Group group = user.getGroup(); long groupIdLong = group.getGroupId(); Http.Options options = new Http.Options(); options.setLocation(mediaItem.getUrl()); byte[] byteArray = HttpUtil.URLtoByteArray(options); String fileName = getFileName(mediaItem, options); String contentType = MimeTypesUtil.getContentType(fileName); ServiceContext serviceContext = new ServiceContext(); serviceContext.setAddGroupPermissions(true); serviceContext.setAddGuestPermissions(true); serviceContext.setAttribute("sourceFileName", fileName); serviceContext.setExpandoBridgeAttributes( SerializerUtil.toExpandoAttributes( mediaItem, _MEDIA_ITEM_FIELDS, user.getCompanyId(), DLFileEntry.class.getName())); serviceContext.setScopeGroupId(groupIdLong); if (mediaItemId == null) { long albumIdLong = GetterUtil.getLong(albumId); DLAppServiceUtil.addFileEntry( groupIdLong, albumIdLong, fileName, contentType, mediaItem.getTitle(), mediaItem.getDescription(), StringPool.BLANK, byteArray, serviceContext); } else { long mediaItemIdLong = GetterUtil.getLong(mediaItemId); FileEntry fileEntry = DLAppLocalServiceUtil.getFileEntry( mediaItemIdLong); serviceContext.setCreateDate(fileEntry.getCreateDate()); serviceContext.setModifiedDate(fileEntry.getModifiedDate()); DLAppServiceUtil.updateFileEntry( fileEntry.getFileEntryId(), fileName, contentType, mediaItem.getTitle(), mediaItem.getDescription(), StringPool.BLANK, false, byteArray, serviceContext); } } protected String getFileName(MediaItem mediaItem, Http.Options options) { Http.Response response = options.getResponse(); String contentDisposition = response.getHeader( HttpHeaders.CONTENT_DISPOSITION); if (contentDisposition == null) { return FileUtil.getShortFileName(mediaItem.getUrl()); } Matcher fileNameMatcher = _fileNamePattern.matcher(contentDisposition); if (fileNameMatcher.find()) { return fileNameMatcher.group(1); } else { return mediaItem.getTitle(); } } protected MediaItem toMediaItem( FileEntry fileEntry, Set<String> fields, SecurityToken securityToken) throws Exception { MediaItem mediaItem = new MediaItemImpl(); mediaItem.setAlbumId(String.valueOf(fileEntry.getFolderId())); mediaItem.setCreated(String.valueOf(fileEntry.getCreateDate())); mediaItem.setDescription(fileEntry.getDescription()); mediaItem.setId(String.valueOf(fileEntry.getFileEntryId())); mediaItem.setLastUpdated(String.valueOf(fileEntry.getModifiedDate())); mediaItem.setMimeType( MimeTypesUtil.getContentType( StringPool.PERIOD.concat(fileEntry.getExtension()))); mediaItem.setNumViews(String.valueOf(fileEntry.getReadCount())); mediaItem.setTitle(fileEntry.getTitle()); mediaItem.setType( toMediaItemType( StringPool.PERIOD.concat(fileEntry.getExtension()))); String fileEntryURL = ShindigUtil.getFileEntryURL( securityToken.getDomain(), fileEntry.getFileEntryId()); mediaItem.setUrl(fileEntryURL); FileVersion fileVersion = fileEntry.getLatestFileVersion(); SerializerUtil.copyProperties( fileVersion.getAttributes(), mediaItem, _MEDIA_ITEM_FIELDS); return mediaItem; } protected MediaItem.Type toMediaItemType(String fileName) { String contentType = MimeTypesUtil.getContentType(fileName); if (contentType.startsWith("audio")) { return Type.AUDIO; } else if (contentType.startsWith("image")) { return Type.IMAGE; } else if (contentType.startsWith("video")) { return Type.VIDEO; } else { return null; } } private static final MediaItem.Field[] _MEDIA_ITEM_FIELDS = { MediaItem.Field.DURATION, MediaItem.Field.FILE_SIZE, MediaItem.Field.LANGUAGE, MediaItem.Field.LOCATION, MediaItem.Field.NUM_COMMENTS, MediaItem.Field.NUM_VOTES, MediaItem.Field.RATING, MediaItem.Field.START_TIME, MediaItem.Field.TAGGED_PEOPLE, MediaItem.Field.TAGS, MediaItem.Field.THUMBNAIL_URL }; private static final Log _log = LogFactoryUtil.getLog( LiferayMediaItemService.class); private static final Pattern _fileNamePattern = Pattern.compile( ".*?filename=\"?([^\";]+)"); }