All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.anotheria.anosite.photoserver.api.photo.fs.PhotoStorageFSService Maven / Gradle / Ivy

The newest version!
package net.anotheria.anosite.photoserver.api.photo.fs;

import net.anotheria.anoprise.dualcrud.CrudService;
import net.anotheria.anoprise.dualcrud.CrudServiceException;
import net.anotheria.anoprise.dualcrud.ItemNotFoundException;
import net.anotheria.anoprise.dualcrud.Query;
import net.anotheria.anoprise.dualcrud.SaveableID;
import net.anotheria.anosite.photoserver.api.photo.PhotoFileHolder;
import net.anotheria.anosite.photoserver.api.photo.PhotoStorageUtil;
import net.anotheria.anosite.photoserver.service.storage.StorageConfig;
import net.anotheria.util.StringUtils;
import net.anotheria.util.concurrency.IdBasedLock;
import net.anotheria.util.concurrency.IdBasedLockManager;
import net.anotheria.util.concurrency.SafeIdBasedLockManager;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;

/**
 * Store photo in FS system.
 *
 * @author ykalapusha
 */
public class PhotoStorageFSService implements CrudService {
    /**
     * {@link Logger} instance.
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(PhotoStorageFSService.class);
    /**
     * Lock manager for safe operations with files.
     */
    private static final IdBasedLockManager LOCK_MANAGER = new SafeIdBasedLockManager<>();


    @Override
    public PhotoFileHolder create(PhotoFileHolder photoFileHolder) throws CrudServiceException {
        String fileLocation = photoFileHolder.getFileLocation();
        File file = new File(fileLocation);
        // checking folder structure and creating if needed
        if (!file.exists())
            if (!file.mkdirs())
                throw new CrudServiceException("writePhoto([ " + photoFileHolder + "]) fail. Can't create needed folder structure.");

        String fileName = photoFileHolder.getFilePath();
        // checking file name
        if (StringUtils.isEmpty(fileName))
            throw new CrudServiceException("Wrong photo file name[" + fileName + "].");

        file = new File(fileName);
        // removing previously stored file if it exist
        removePhoto(photoFileHolder);

        // synchronizing on fileName for preventing concurrent modifications on same file
        IdBasedLock lock = LOCK_MANAGER.obtainLock(fileName);
        lock.lock();

        FileOutputStream out = null;
        try {
            out = new FileOutputStream(file);
            // buffered copy from input to output
            IOUtils.copyLarge(photoFileHolder.getPhotoFileInputStream(), out);
            out.flush();
        } catch (IOException ioe) {
            String message = "writePhoto(InputStream, " + photoFileHolder + ") fail.";
            LOGGER.error(message, ioe);
            throw new CrudServiceException(message, ioe);
        } finally {
            // closing output with ignoring exceptions
            IOUtils.closeQuietly(out);
            // closing synchronization
            lock.unlock();
        }
        return photoFileHolder;
    }

    @Override
    public PhotoFileHolder read(SaveableID id) throws CrudServiceException, ItemNotFoundException {
        String fileName = id.getSaveableId().split("______USER_ID______")[0];
        // checking file name
        if (StringUtils.isEmpty(fileName))
            throw new CrudServiceException("Wrong photo file name[" + fileName + "].");

        File file = new File(fileName);
        // checking is photo file exist
        if (!file.exists() || file.isDirectory())
            throw new ItemNotFoundException("getPhoto(" + id + ") fail. Photo not exist or it a directory.");


        try {
            String userId = id.getSaveableId().split("______USER_ID______")[1];
            PhotoFileHolder photoFileHolder = new PhotoFileHolder(PhotoStorageUtil.getId(id.getOwnerId()), PhotoStorageUtil.getOriginalId(id.getOwnerId()), PhotoStorageUtil.getExtension(id.getOwnerId()), userId);
            photoFileHolder.setPhotoFileInputStream(Files.newInputStream(file.toPath()));
            return photoFileHolder;
        } catch (IOException e) {
            throw new ItemNotFoundException("Item [" + id + "] not found.");
        }
    }

    @Override
    public PhotoFileHolder update(PhotoFileHolder photoFileHolder) throws CrudServiceException {
        return create(photoFileHolder);
    }

    @Override
    public void delete(PhotoFileHolder photoFileHolder) throws CrudServiceException {
        photoFileHolder.setFileLocation(StorageConfig.getStoreFolderPath(String.valueOf(photoFileHolder.getUserId())));
        removePhoto(photoFileHolder);
    }

    @Override
    public PhotoFileHolder save(PhotoFileHolder photoFileHolder) throws CrudServiceException {
        return create(photoFileHolder);
    }

    @Override
    public boolean exists(PhotoFileHolder photoFileHolder) throws CrudServiceException {
        return new File(photoFileHolder.getFilePath()).exists();
    }

    @Override
    public List query(Query q) throws CrudServiceException {
        return null;
    }

    public void removePhoto(final PhotoFileHolder photoFileHolder) throws CrudServiceException {
        String fileName = photoFileHolder.getFilePath();
        // checking file name
        if (StringUtils.isEmpty(fileName))
            throw new RuntimeException("Wrong photo file name[" + fileName + "].");

        File file = new File(fileName);
        // checking is a file not a directory
        if (file.exists() && file.isDirectory()) {
            String message = "removePhoto(" + photoFileHolder + ") fail. File is a folder.";
            LOGGER.error(message);
            throw new CrudServiceException(message);
        }

        // synchronizing on fileName for preventing concurrent modifications on same file
        IdBasedLock lock = LOCK_MANAGER.obtainLock(fileName);
        lock.lock();

        try {
            file.delete();
            removeCachedVersions(photoFileHolder.getFileLocation(), photoFileHolder.getId());
        } finally {
            lock.unlock();
        }
    }

    private void removeCachedVersions(final String location, final String fileName) {
        File dir = new File(location);
        if (!dir.isDirectory()) {
            LOGGER.warn("Location[" + location + "] not a directory or not exist.");
            return;
        }

        String[] files = dir.list();
        if (files == null || files.length == 0)
            return;

        for (String file : files)
            if (file.startsWith(fileName)) {
                File toDelete = new File(location + File.separator + file);
                if (toDelete.isDirectory())
                    continue;

                toDelete.delete();
            }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy