/* * Copyright (C) 2016 Didier Clermonté * Copyright (C) 2016 Christian Pierre Momon * * This file is part of Siba. * * Siba is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package org.dclermonte.siba.model; import java.io.BufferedOutputStream; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ResourceBundle; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; import org.apache.commons.compress.utils.IOUtils; import org.apache.commons.lang3.StringUtils; import org.dclermonte.siba.SibaException; /** * * @author dclermonte * */ public class SibaManager { private static final ResourceBundle BUNDLE = ResourceBundle.getBundle("org.dclermonte.siba.model.messages"); //$NON-NLS-1$ /** * This method perform the backup. * * @param fileToSave * @param target * @return * @throws SibaException */ public static File backup(final File fileToSave, File target) throws SibaException { File result; try { if ((fileToSave == null) || !(fileToSave.exists())) { throw new SibaException(BUNDLE.getString("sourceNotExist.text")); } else { if (!(fileToSave.isDirectory())) { throw new SibaException(BUNDLE.getString("NotDirectorySource.text")); } else { if ((target == null)) { target = new File(System.getProperty("user.dir")); } if (!(target.isDirectory())) { throw new SibaException(BUNDLE.getString("NotDirectoryTarget.text")); } else { int pathLength = fileToSave.getParentFile().getAbsolutePath().length(); LocalDateTime date = LocalDateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH'h'mm'mn'ss's'"); String textDate = date.format(formatter); String outputFileNameWithoutExtension = fileToSave.getName() + "-" + textDate; result = new File(target + "/" + outputFileNameWithoutExtension + ".tgz"); OutputStream gzipOutputStream = new GzipCompressorOutputStream( new BufferedOutputStream(new FileOutputStream(result))); TarArchiveOutputStream out = new TarArchiveOutputStream(gzipOutputStream); directoryToSave(fileToSave, out, pathLength); out.close(); fileCheckMD5(result, target + "/" + outputFileNameWithoutExtension + ".tgz.md5"); } } } } catch (IOException ioExceptionBackup) { throw new SibaException(BUNDLE.getString("ioExceptionBackup.text"), ioExceptionBackup); //$NON-NLS-1$ } finally { Closeable out = null; IOUtils.closeQuietly(out); } // return result; } /** * This method is used to check the file. * * @param choosenFile * @return * @throws SibaException */ public static boolean check(final File choosenFile) throws SibaException { boolean result; try { if (choosenFile.exists() && (choosenFile.length() > 32)) { FileReader fileReader = new FileReader(choosenFile); char[] md5 = new char[32]; byte[] md5byte = new byte[32]; char[] fileToCheck = new char[(int) (choosenFile.length()) - 32]; String md5String = new String(); for (int index = 0; index < 32; index++) { md5[index] = (char) fileReader.read(); md5byte[index] = (byte) md5[index]; md5String = md5String + md5[index]; } fileReader.read(); String fileNameToString = new String(); for (int index = 36; index < (choosenFile.length() + 2); index++) { fileToCheck[index - 36] = (char) fileReader.read(); fileNameToString = fileNameToString + fileToCheck[index - 36]; } fileReader.close(); File fileToCheck1; if (choosenFile.isAbsolute()) { fileToCheck1 = new File(choosenFile.getParent() + "/" + fileNameToString); } else { String path = System.getProperty("user.dir"); fileToCheck1 = new File(path + "/" + fileNameToString); } if (StringUtils.equals(md5String, md5(fileToCheck1))) { result = true; } else { result = false; } } else { throw new SibaException(BUNDLE.getString("NotExistFileToCheck.text")); } } catch (IOException ioExceptionCheck) { throw new SibaException(BUNDLE.getString("ioExceptionCheck.text"), ioExceptionCheck); //$NON-NLS-1$ } // return result; } /** * * This method generate ArchiveEntry. * * @param directory * @param outputStream * @param pathLength * @throws SibaException */ public static void directoryToSave(final File directory, final TarArchiveOutputStream outputStream, final int pathLength) throws SibaException { try { for (File file : directory.listFiles()) { if (file.isDirectory()) { if (file.listFiles().length == 0) { TarArchiveEntry tarArchiveEntry = new TarArchiveEntry(file); String pathPartiel = file.getPath().substring(pathLength); tarArchiveEntry.setName(pathPartiel); outputStream.putArchiveEntry(tarArchiveEntry); outputStream.closeArchiveEntry(); } else { directoryToSave(file, outputStream, pathLength); } } else { TarArchiveEntry tarArchiveEntry = new TarArchiveEntry(file); String pathPartiel = file.getPath().substring(pathLength); tarArchiveEntry.setName(pathPartiel); outputStream.putArchiveEntry(tarArchiveEntry); IOUtils.copy(new FileInputStream(file), outputStream); outputStream.closeArchiveEntry(); } } } catch (IOException ioExceptionTarEntry) { throw new SibaException(BUNDLE.getString("ioExceptionTarEntry.text"), ioExceptionTarEntry); //$NON-NLS-1$ } } /** * * This method Generate the file with MD5. * * @param directoryToSave * @param destination * @return * @throws SibaException */ public static File fileCheckMD5(final File directoryToSave, final String destination) throws SibaException { File result; try { result = new File(destination); FileWriter fileWriter = new FileWriter(result); fileWriter.write(md5(directoryToSave)); String newLine = System.getProperty("line.separator"); fileWriter.append(" " + directoryToSave.getName() + newLine); fileWriter.close(); } catch (IOException ioExceptionFileMD5) { throw new SibaException(BUNDLE.getString("ioExceptionFileMD5.text"), ioExceptionFileMD5); //$NON-NLS-1$ } // return result; } /** * This method calculate the MD5 itself. * * @param input * @return * @throws SibaException */ public static String md5(final File input) throws SibaException { String result; StringBuilder hashString = new StringBuilder(); try { byte[] byteInput = new byte[(int) input.length()]; FileInputStream fileInputStream = new FileInputStream(input); for (int index1 = 0; index1 < input.length(); index1++) { byteInput[index1] = (byte) fileInputStream.read(); } byte[] hash = null; MessageDigest messageDigest = MessageDigest.getInstance("MD5"); hash = messageDigest.digest(byteInput); for (int index = 0; index < hash.length; index++) { String hex = Integer.toHexString(hash[index]); if (hex.length() == 1) { hashString.append('0'); hashString.append(hex.charAt(hex.length() - 1)); } else { hashString.append(hex.substring(hex.length() - 2)); } } fileInputStream.close(); } catch (NoSuchAlgorithmException noSuchAlgorithmException) { throw new SibaException(BUNDLE.getString("noSuchAlgorithm.text"), noSuchAlgorithmException); //$NON-NLS-1$ } catch (IOException ioException) { throw new SibaException(BUNDLE.getString("ioExceptionMD5.text"), ioException); //$NON-NLS-1$ } result = hashString.toString(); // return result; } }