Skip to content

Commit

Permalink
Merge pull request #319 from kagemomiji/issue212-media-file-repository
Browse files Browse the repository at this point in the history
#212 implemented MediaFileRepository to replace MediaFileDao
  • Loading branch information
kagemomiji authored Dec 3, 2023
2 parents e20118c + f11b408 commit bdbad53
Show file tree
Hide file tree
Showing 101 changed files with 2,485 additions and 2,452 deletions.
Original file line number Diff line number Diff line change
@@ -1,49 +1,25 @@
package org.airsonic.player.ajax;

import org.airsonic.player.domain.CoverArt;
import org.airsonic.player.domain.CoverArt.EntityType;
import org.airsonic.player.domain.LastFmCoverArt;
import org.airsonic.player.domain.MediaFile;
import org.airsonic.player.domain.MusicFolder;
import org.airsonic.player.service.CoverArtService;
import org.airsonic.player.service.LastFmService;
import org.airsonic.player.service.MediaFileService;
import org.airsonic.player.service.MediaFolderService;
import org.airsonic.player.service.SecurityService;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.simp.annotation.SendToUser;
import org.springframework.stereotype.Controller;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.List;

@Controller
@MessageMapping("/coverart")
public class CoverArtWSController {
private static final Logger LOG = LoggerFactory.getLogger(CoverArtWSController.class);
public static final Logger LOG = LoggerFactory.getLogger(CoverArtWSController.class);

@Autowired
private SecurityService securityService;
@Autowired
private MediaFileService mediaFileService;
@Autowired
private LastFmService lastFmService;
@Autowired
private MediaFolderService mediaFolderService;
@Autowired
private CoverArtService coverArtService;

@MessageMapping("/search")
Expand All @@ -61,74 +37,14 @@ public List<LastFmCoverArt> searchCoverArt(CoverArtSearchRequest req) {
@SendToUser(broadcast = false)
public String setCoverArtImage(CoverArtSetRequest req) {
try {
MediaFile mediaFile = mediaFileService.getMediaFile(req.getId());
saveCoverArt(mediaFile, req.getUrl());
coverArtService.setCoverArtImageFromUrl(req.getId(), req.getUrl());
return "OK";
} catch (Exception e) {
LOG.warn("Failed to save cover art for media file {}", req.getId(), e);
return e.toString();
}
}

private void saveCoverArt(MediaFile dir, String url) throws Exception {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(20 * 1000) // 20 seconds
.setSocketTimeout(20 * 1000) // 20 seconds
.build();
HttpGet method = new HttpGet(url);
method.setConfig(requestConfig);

// Attempt to resolve proper suffix.
String suffix = "jpg";
if (url.toLowerCase().endsWith(".gif")) {
suffix = "gif";
} else if (url.toLowerCase().endsWith(".png")) {
suffix = "png";
}

// Check permissions.
MusicFolder folder = mediaFolderService.getMusicFolderById(dir.getFolderId());
Path fullPath = dir.getFullPath(folder.getPath());
Path newCoverFile = fullPath.resolve("cover." + suffix);
if (!securityService.isWriteAllowed(folder.getPath().relativize(newCoverFile), folder)) {
throw new SecurityException("Permission denied: " + StringEscapeUtils.escapeHtml(newCoverFile.toString()));
}

try (CloseableHttpClient client = HttpClients.createDefault();
CloseableHttpResponse response = client.execute(method);
InputStream input = response.getEntity().getContent()) {

// If file exists, create a backup.
backup(newCoverFile, fullPath.resolve("cover." + suffix + ".backup"));

// Write file.
Files.copy(input, newCoverFile, StandardCopyOption.REPLACE_EXISTING);
}

CoverArt coverArt = new CoverArt(dir.getId(), EntityType.MEDIA_FILE, folder.getPath().relativize(newCoverFile).toString(), dir.getFolderId(), true);
coverArtService.upsert(coverArt);

}

private void backup(Path newCoverFile, Path backup) {
if (Files.exists(newCoverFile)) {
try {
Files.move(newCoverFile, backup, StandardCopyOption.REPLACE_EXISTING);
LOG.info("Backed up old image file to {}", backup);
} catch (IOException e) {
LOG.warn("Failed to create image file backup {}", backup, e);
}
}
}

public void setSecurityService(SecurityService securityService) {
this.securityService = securityService;
}

public void setMediaFileService(MediaFileService mediaFileService) {
this.mediaFileService = mediaFileService;
}

public void setLastFmService(LastFmService lastFmService) {
this.lastFmService = lastFmService;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.airsonic.player.ajax;

import org.airsonic.player.dao.MediaFileDao;
import org.airsonic.player.domain.MediaFile;
import org.airsonic.player.domain.MusicFolder;
import org.airsonic.player.domain.Player;
Expand Down Expand Up @@ -39,8 +38,6 @@ public class PlaylistWSController {
@Autowired
private PlaylistService playlistService;
@Autowired
private MediaFileDao mediaFileDao;
@Autowired
private MediaFolderService mediaFolderService;
@Autowired
private PlayerService playerService;
Expand Down Expand Up @@ -93,7 +90,7 @@ public int createPlaylistForStarredSongs(Principal p) {

Playlist result = createPlaylist(name, false, username);
List<MusicFolder> musicFolders = mediaFolderService.getMusicFoldersForUser(username);
List<MediaFile> songs = mediaFileDao.getStarredFiles(0, Integer.MAX_VALUE, username, musicFolders);
List<MediaFile> songs = mediaFileService.getStarredSongs(0, Integer.MAX_VALUE, username, musicFolders);
Integer playlistId = result.getId();
playlistService.setFilesInPlaylist(playlistId, songs);
playlistService.broadcastFileChange(playlistId, false, true);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.airsonic.player.ajax;

import org.airsonic.player.dao.MediaFileDao;
import org.airsonic.player.service.MediaFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.stereotype.Controller;
Expand All @@ -11,20 +11,18 @@
@Controller
@MessageMapping("/rate/mediafile")
public class StarWSController {

@Autowired
private MediaFileDao mediaFileDao;
private MediaFileService mediaFileService;

@MessageMapping("/star")
public void star(Principal user, List<Integer> ids) {
mediaFileDao.starMediaFiles(ids, user.getName());
mediaFileService.starMediaFiles(ids, user.getName());
}

@MessageMapping("/unstar")
public void unstar(Principal user, List<Integer> ids) {
mediaFileDao.unstarMediaFiles(ids, user.getName());
mediaFileService.unstarMediaFiles(ids, user.getName());
}

public void setMediaFileDao(MediaFileDao mediaFileDao) {
this.mediaFileDao = mediaFileDao;
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package org.airsonic.player.ajax;

import org.airsonic.player.domain.MediaFile;
import org.airsonic.player.domain.MusicFolder;
import org.airsonic.player.service.MediaFileService;
import org.airsonic.player.service.MediaFolderService;
import org.airsonic.player.service.metadata.MetaData;
import org.airsonic.player.service.metadata.MetaDataParser;
import org.airsonic.player.service.metadata.MetaDataParserFactory;
Expand All @@ -29,8 +27,6 @@ public class TagWSController {
private MetaDataParserFactory metaDataParserFactory;
@Autowired
private MediaFileService mediaFileService;
@Autowired
private MediaFolderService mediaFolderService;

/**
* Updated tags for a given music file.
Expand All @@ -43,9 +39,8 @@ public class TagWSController {
public String setTags(@Validated TagData data) {
try {
MediaFile file = mediaFileService.getMediaFile(data.getMediaFileId());
MusicFolder folder = mediaFolderService.getMusicFolderById(file.getFolderId());

MetaDataParser parser = metaDataParserFactory.getParser(file.getFullPath(folder.getPath()));
MetaDataParser parser = metaDataParserFactory.getParser(file.getFullPath());

if (!parser.isEditingSupported()) {
return "Tag editing of " + FilenameUtils.getExtension(file.getPath()) + " files is not supported.";
Expand All @@ -60,7 +55,7 @@ public String setTags(@Validated TagData data) {
return "SKIPPED";
}

MetaData newMetaData = parser.getMetaData(file.getFullPath(folder.getPath()));
MetaData newMetaData = parser.getMetaData(file.getFullPath());

// Note: album artist is intentionally not set, as it is not user-changeable.
newMetaData.setArtist(data.getArtist());
Expand All @@ -71,8 +66,8 @@ public String setTags(@Validated TagData data) {
newMetaData.setTrackNumber(data.getTrack());
parser.setMetaData(file, newMetaData);

mediaFileService.refreshMediaFile(file, folder);
mediaFileService.refreshMediaFile(mediaFileService.getParentOf(file), folder);
mediaFileService.refreshMediaFile(file);
mediaFileService.refreshMediaFile(mediaFileService.getParentOf(file));
return "UPDATED";

} catch (Exception x) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import org.airsonic.player.security.JWTAuthenticationToken;
import org.airsonic.player.service.JWTSecurityService;
import org.airsonic.player.service.MediaFileService;
import org.airsonic.player.service.MediaFolderService;
import org.airsonic.player.service.SecurityService;
import org.airsonic.player.service.SettingsService;
import org.airsonic.player.service.metadata.MetaData;
Expand Down Expand Up @@ -64,8 +63,6 @@ public class CaptionsController {
@Autowired
private MediaFileService mediaFileService;
@Autowired
private MediaFolderService mediaFolderService;
@Autowired
private SecurityService securityService;
@Autowired
private SettingsService settingsService;
Expand Down Expand Up @@ -119,7 +116,7 @@ public ResponseEntity<Resource> handleRequest(
}
time = Files.getLastModifiedTime(captionsFile).toInstant();
} else {
Path videoFullPath = video.getFullPath(mediaFolderService.getMusicFolderById(video.getFolderId()).getPath());
Path videoFullPath = video.getFullPath();
resource = getConvertedResource(videoFullPath, res.getIdentifier(), effectiveFormat);
time = Files.getLastModifiedTime(videoFullPath).toInstant();
}
Expand Down Expand Up @@ -234,7 +231,7 @@ public List<CaptionInfo> listCaptions(MediaFile video, String basePath, String e
}

public MetaData getVideoMetaData(MediaFile video) {
Path videoFullPath = video.getFullPath(mediaFolderService.getMusicFolderById(video.getFolderId()).getPath());
Path videoFullPath = video.getFullPath();
MetaDataParser parser = this.metaDataParserFactory.getParser(videoFullPath);
return (parser != null) ? parser.getMetaData(videoFullPath) : null;
}
Expand Down Expand Up @@ -265,7 +262,7 @@ public List<Path> findExternalCaptionsForVideo(MediaFile video) {
if (parent == null) {
return Collections.emptyList();
}
Path parentPath = parent.getFullPath(mediaFolderService.getMusicFolderById(parent.getFolderId()).getPath());
Path parentPath = parent.getFullPath();

try (Stream<Path> children = Files.walk(parentPath)) {
return children.parallel()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ private CoverArtRequest(CoverArt coverArt, Supplier<String> keyGenerator, Suppli
}

public String getKey() {
return Optional.ofNullable(coverArt).map(c -> coverArt.getFolderId() + "/" + coverArt.getPath())
return Optional.ofNullable(coverArt).map(c -> coverArt.getFolder()).map(folder -> folder.getId() + "/" + coverArt.getPath())
.orElseGet(keyGenerator);
}

Expand Down Expand Up @@ -555,7 +555,7 @@ private class MediaFileCoverArtRequest extends CoverArtRequest {

private MediaFileCoverArtRequest(MediaFile mediaFile, Integer proxyId) {
super(coverArtService.get(EntityType.MEDIA_FILE, mediaFile.getId()),
() -> mediaFile.getFolderId() + "/" + mediaFile.getPath(),
() -> mediaFile.getFolder().getId() + "/" + mediaFile.getPath(),
() -> mediaFile.getChanged());
this.dir = mediaFile;
this.proxyId = proxyId;
Expand Down Expand Up @@ -589,7 +589,7 @@ private class VideoCoverArtRequest extends CoverArtRequest {
private VideoCoverArtRequest(MediaFile mediaFile, int offset) {
this.mediaFile = mediaFile;
this.offset = offset;
keyGenerator = () -> mediaFile.getFolderId() + "/" + mediaFile.getPath() + "/" + offset;
keyGenerator = () -> mediaFile.getFolder().getId() + "/" + mediaFile.getPath() + "/" + offset;
lastModifiedGenerator = () -> mediaFile.getChanged();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,6 @@ public class DownloadController {
@Autowired
private MediaFileService mediaFileService;
@Autowired
private MediaFolderService mediaFolderService;
@Autowired
private CoverArtService coverArtService;

@GetMapping
Expand All @@ -126,7 +124,7 @@ public ResponseEntity<Resource> handleRequest(Principal p,
};

MediaFile mediaFile = id.map(mediaFileService::getMediaFile).orElse(null);
Collection<Pair<Path, Integer>> additionalFiles = Collections.emptyList();
Collection<Pair<Path, MusicFolder>> additionalFiles = Collections.emptyList();

if (mediaFile != null) {
if (!securityService.isFolderAccessAllowed(mediaFile, user.getUsername())) {
Expand All @@ -139,7 +137,7 @@ public ResponseEntity<Resource> handleRequest(Principal p,
if (indices == null) {
CoverArt art = coverArtService.get(EntityType.MEDIA_FILE, mediaFile.getId());
if (!CoverArt.NULL_ART.equals(art)) {
additionalFiles = Collections.singletonList(Pair.of(art.getRelativePath(), art.getFolderId()));
additionalFiles = Collections.singletonList(Pair.of(art.getRelativePath(), art.getFolder()));
}
}
response = prepareResponse(mediaFileService.getChildrenOf(mediaFile, true, false, true), indices, statusSupplier, statusCloser, additionalFiles);
Expand Down Expand Up @@ -190,7 +188,7 @@ private static long zipSize(Stream<Entry<String, Long>> paths) {
}

private ResponseDTO prepareResponse(List<MediaFile> files, List<Integer> indices,
Supplier<TransferStatus> statusSupplier, Consumer<TransferStatus> statusCloser, Collection<Pair<Path, Integer>> additionalFiles)
Supplier<TransferStatus> statusSupplier, Consumer<TransferStatus> statusCloser, Collection<Pair<Path, MusicFolder>> additionalFiles)
throws IOException {
if (indices == null) {
indices = IntStream.range(0, files.size()).boxed().collect(Collectors.toList());
Expand All @@ -206,7 +204,7 @@ private ResponseDTO prepareResponse(List<MediaFile> files, List<Integer> indices
if (indices.size() == 1 && (additionalFiles == null || additionalFiles.size() == 0)) {
// single file
MediaFile file = files.get(indices.get(0));
Path path = file.getFullPath(mediaFolderService.getMusicFolderById(file.getFolderId()).getPath());
Path path = file.getFullPath();
long changed = file.getChanged() == null ? -1 : file.getChanged().toEpochMilli();
return new ResponseDTO(
new MonitoredResource(
Expand All @@ -222,10 +220,13 @@ private ResponseDTO prepareResponse(List<MediaFile> files, List<Integer> indices
// get a list of all paths under the tree, plus their zip names and sizes
Collection<Pair<Path, Pair<String, Long>>> pathsToZip = Stream
.concat(
indices.stream().map(index -> Objects.isNull(index) ? null : files.get(index)).filter(Objects::nonNull).map(x -> Pair.of(x.getRelativePath(), x.getFolderId())),
indices.stream()
.map(index -> Objects.isNull(index) ? null : files.get(index))
.filter(Objects::nonNull)
.map(x -> Pair.of(x.getRelativePath(), x.getFolder())),
additionalFiles.stream().filter(Objects::nonNull))
.flatMap(pf -> {
MusicFolder mf = mediaFolderService.getMusicFolderById(pf.getRight());
MusicFolder mf = pf.getRight();
Path p = mf.getPath().resolve(pf.getLeft());
Path parent = p.getParent();
try (Stream<Path> paths = Files.walk(p)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ private List<MediaFileWithUrlInfo> getMedia(HttpServletRequest request, Share sh
if (share != null) {
return shareService.getSharedFiles(share.getId(), musicFolders)
.stream()
.filter(f -> Files.exists(f.getFullPath(mediaFolderService.getMusicFolderById(f.getFolderId()).getPath())))
.filter(f -> Files.exists(f.getFullPath()))
.flatMap(f -> {
if (f.isDirectory()) {
return mediaFileService.getVisibleChildrenOf(f, false, true).stream()
Expand Down
Loading

0 comments on commit bdbad53

Please sign in to comment.