package org.sigmah.server.handler; /* * #%L * Sigmah * %% * Copyright (C) 2010 - 2016 URD * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import com.google.inject.Inject; import com.google.inject.Singleton; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.HashMap; import org.sigmah.server.dispatch.impl.UserDispatch; import org.sigmah.server.domain.value.FileVersion; import org.sigmah.server.file.FileStorageProvider; import org.sigmah.server.handler.base.AbstractCommandHandler; import org.sigmah.server.mail.ModelMailService; import org.sigmah.shared.command.UploadSlice; import org.sigmah.shared.command.result.VoidResult; import org.sigmah.shared.dispatch.CommandException; import org.sigmah.shared.dto.referential.EmailKey; import org.sigmah.shared.dto.referential.EmailKeyEnum; import org.sigmah.shared.dto.referential.EmailType; import org.sigmah.shared.dto.value.FileVersionDTO; import org.sigmah.shared.util.ValueResultUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author Raphaƫl Calabro (rcalabro@ideia.fr) */ @Singleton public class UploadSliceHandler extends AbstractCommandHandler<UploadSlice, VoidResult> { private static final Logger LOGGER = LoggerFactory.getLogger(PrepareFileUploadHandler.class); @Inject private FileStorageProvider fileStorageProvider; @Inject private ModelMailService modelMailService; @Override protected VoidResult execute(UploadSlice command, UserDispatch.UserExecutionContext context) throws CommandException { final FileVersionDTO fileVersionDTO = command.getFileVersionDTO(); // Searching the original file version in database. final FileVersion fileVersion = em().find(FileVersion.class, fileVersionDTO.getId()); final String path; if(fileVersion != null) { path = fileVersion.getPath(); } else { path = generateNameForNullPathFile(command, context); } final String sliceName = path + '.' + command.getOffset(); try(final OutputStream outputStream = fileStorageProvider.create(sliceName)) { outputStream.write(command.getData()); } catch (IOException ex) { LOGGER.error("An error occured while creating the file slice '" + sliceName + "'.", ex); } if(command.isLast()) { // Patch everything together. final byte[] bytes = new byte[1024]; try(final OutputStream outputStream = fileStorageProvider.create(path)) { for(int offset = 0; offset < fileVersionDTO.getSize();) { final String slice = path + '.' + offset; // Read the content of the slice. try(final InputStream inputStream = fileStorageProvider.open(slice)) { int read = inputStream.read(bytes); while(read != -1) { offset += read; outputStream.write(bytes, 0, read); read = inputStream.read(bytes); } } catch(IOException ex) { LOGGER.error("An error occured while reading the slice '" + slice + "'.", ex); } // Remove the slice. try { fileStorageProvider.delete(slice); } catch(IOException ex) { LOGGER.error("An error occured while removing the slice '" + slice + "'.", ex); } } } catch (IOException ex) { LOGGER.error("An error occured while patching the file slice together into file '" + fileVersionDTO.getPath() + "'.", ex); } if(fileVersion == null) { try { try { sendFileByEmail(fileVersionDTO, path, context); } finally { fileStorageProvider.delete(path); } } catch(IOException ex) { LOGGER.error("An error occured while accessing the unused file '" + path + "'.", ex); } } } return null; } private String generateNameForNullPathFile(UploadSlice command, UserDispatch.UserExecutionContext context) { final String fileName = ValueResultUtils.normalizeFileName(command.getFileVersionDTO().getName()); return context.getUser().getEmail() + '_' + command.getFileVersionDTO().getId() + '_' + fileName; } private void sendFileByEmail(FileVersionDTO fileVersion, String path, UserDispatch.UserExecutionContext context) throws IOException { // Full name. final String firstName = context.getUser().getFirstName(); final String lastName = context.getUser().getName(); final String fullName = firstName.isEmpty() ? lastName : firstName + ' ' + lastName; // Normalized file name. final String fileName = fileVersion.getName() + '.' + fileVersion.getExtension(); // Send the mail. final HashMap<EmailKey, String> parameters = new HashMap<>(); parameters.put(EmailKeyEnum.USER_USERNAME, fullName); parameters.put(EmailKeyEnum.FILE_NAME, fileName); try(InputStream inputStream = fileStorageProvider.open(path)) { modelMailService.send(EmailType.OFFLINE_FILE_CONFLICT, parameters, fileName, inputStream, context.getLanguage(), new String[] {context.getUser().getEmail()}); } } }