Java tutorial
/* This softtware use BSD licence (http://opensource.org/licenses/BSD-3-Clause) Copyright (c) 2013, Martin Lebeda All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Martin Lebeda nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ import java.io.File; import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Paths; import java.nio.file.attribute.DosFileAttributeView; import java.nio.file.attribute.GroupPrincipal; import java.nio.file.attribute.PosixFileAttributeView; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; import java.nio.file.attribute.UserPrincipal; import java.nio.file.attribute.UserPrincipalLookupService; import java.nio.file.attribute.UserPrincipalNotFoundException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.Predicate; import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.TrueFileFilter; import org.apache.commons.io.filefilter.WildcardFileFilter; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; // TODO Lebeda - repolace marbes.cz to gmail.com /** * @author <a href="mailto:martin.lebeda@gmail.com">Martin Lebeda</a> * Date: 13.11.13 */ public class RestoreService { final static Logger logger = LoggerFactory.getLogger(RestoreService.class); private String bckIdxName; private Repository repository; private List<String> pathToRestoreList; private final String targetPath; /** * Create instance of object for restore files from backup. * * @param bckIdxName indexname for restore source * @param repository repository service * @param pathToRestoreList path patern for restore * @param targetPath target path for restore, if blank, restore to original path */ public RestoreService(String bckIdxName, Repository repository, List<String> pathToRestoreList, String targetPath) { this.bckIdxName = bckIdxName; this.repository = repository; this.pathToRestoreList = pathToRestoreList; this.targetPath = targetPath; } public static void setAdvancedAttributes(final VOBackupFile voBackupFile, final File file) throws IOException { // advanced attributes // owner if (StringUtils.isNotBlank(voBackupFile.getOwner())) { try { UserPrincipalLookupService lookupService = FileSystems.getDefault().getUserPrincipalLookupService(); UserPrincipal userPrincipal = lookupService.lookupPrincipalByName(voBackupFile.getOwner()); Files.setOwner(file.toPath(), userPrincipal); } catch (UserPrincipalNotFoundException e) { logger.warn("Cannot set owner {}", voBackupFile.getOwner()); } } if (Files.getFileStore(file.toPath()).supportsFileAttributeView(DosFileAttributeView.class) && BooleanUtils.isTrue(voBackupFile.getDosAttr())) { Files.setAttribute(file.toPath(), "dos:hidden", BooleanUtils.isTrue(voBackupFile.getDosHidden())); Files.setAttribute(file.toPath(), "dos:archive", BooleanUtils.isTrue(voBackupFile.getDosArchive())); Files.setAttribute(file.toPath(), "dos:readonly", BooleanUtils.isTrue(voBackupFile.getDosReadOnly())); Files.setAttribute(file.toPath(), "dos:system", BooleanUtils.isTrue(voBackupFile.getDosSystem())); } if (Files.getFileStore(file.toPath()).supportsFileAttributeView(PosixFileAttributeView.class) && BooleanUtils.isTrue(voBackupFile.getPosixAttr())) { try { UserPrincipalLookupService lookupService = FileSystems.getDefault().getUserPrincipalLookupService(); GroupPrincipal groupPrincipal = lookupService .lookupPrincipalByGroupName(voBackupFile.getPosixGroup()); Files.getFileAttributeView(file.toPath(), PosixFileAttributeView.class, LinkOption.NOFOLLOW_LINKS) .setGroup(groupPrincipal); } catch (UserPrincipalNotFoundException e) { logger.warn("Cannot set group {}", voBackupFile.getOwner()); } if (StringUtils.isNotBlank(voBackupFile.getPosixPermitions())) { Set<PosixFilePermission> perms = PosixFilePermissions.fromString(voBackupFile.getPosixPermitions()); Files.setPosixFilePermissions(file.toPath(), perms); } } } /** * execute restore process * * @throws Exception */ public void run() throws Exception { // load index Collection<File> bckIdxCollection = FileUtils.listFiles(repository.getMetaPath(), new WildcardFileFilter(bckIdxName + "*"), TrueFileFilter.INSTANCE); // TODO Lebeda - check only one index file // find files ro restore Set<VOBackupFile> oldFileSet = repository.collectBackupedFilesFromIndex(bckIdxCollection); Set<VOBackupFile> restoreFileSet = new HashSet<>(); for (final String path : pathToRestoreList) { //noinspection unchecked restoreFileSet.addAll((Collection<VOBackupFile>) CollectionUtils.select(oldFileSet, new Predicate() { @Override public boolean evaluate(Object object) { VOBackupFile voBackupFile = (VOBackupFile) object; return StringUtils.startsWithIgnoreCase(voBackupFile.getPath(), path + File.separator); } })); } // create directory if not exists for (String pathForRestore : pathToRestoreList) { pathForRestore = changedPathToRestore(pathForRestore, targetPath); File baseFile = new File(pathForRestore); if (!baseFile.exists()) { //noinspection ResultOfMethodCallIgnored baseFile.mkdirs(); // TODO Lebeda - oetit hodnotu } } // find files in directory List<VOBackupFile> newFileList = new ArrayList<>(); for (String pathForRestore : pathToRestoreList) { pathForRestore = changedPathToRestore(pathForRestore, targetPath); //noinspection unchecked final Collection<File> fileColection = FileUtils.listFiles(new File(pathForRestore), TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE); for (File file : fileColection) { newFileList.add(new VOBackupFile(file)); } } // delete files not in index (new or changed) //noinspection unchecked final Collection<VOBackupFile> toDelete = (Collection<VOBackupFile>) CollectionUtils.subtract(newFileList, restoreFileSet); for (VOBackupFile voBackupFile : toDelete) { FileUtils.forceDelete(new File(voBackupFile.getPath())); logger.debug("deleted file: {}", voBackupFile.getPath()); } // restore files not in direcroty //noinspection unchecked final Collection<VOBackupFile> toRestore = (Collection<VOBackupFile>) CollectionUtils .subtract(restoreFileSet, newFileList); final Collection<VOBackupFile> toTime = new ArrayList<>(); for (VOBackupFile voBackupFile : toRestore) { String path = changedPathToRestore(voBackupFile.getPath(), targetPath); if (!voBackupFile.isSymLink()) { if (voBackupFile.isDirectory()) { File dir = new File(path); dir.mkdirs(); // TODO Lebeda - zajistit oeten toTime.add(voBackupFile); setAdvancedAttributes(voBackupFile, dir); } else if (voBackupFile.getSize() == 0) { File file = new File(path); file.createNewFile(); // TODO Lebeda - oetit file.setLastModified(voBackupFile.getModify().getTime()); setAdvancedAttributes(voBackupFile, file); } else if (StringUtils.isNotBlank(voBackupFile.getFileHash())) { repository.restoreFile(voBackupFile, path); } else { // TODO Lebeda - chyba // LoggerTools.log("unable to restore ${it}") } } } // symlinks restore at end for (VOBackupFile voBackupFile : toRestore) { String path = changedPathToRestore(voBackupFile.getPath(), targetPath); if (voBackupFile.isSymLink()) { Files.createSymbolicLink(Paths.get(path), Paths.get(voBackupFile.getSymlinkTarget())); } } for (VOBackupFile voBackupFile : toTime) { String path = changedPathToRestore(voBackupFile.getPath(), targetPath); File dir = new File(path); dir.setLastModified(voBackupFile.getModify().getTime()); } } /** * create filename and path for restore. * * @param pathForRestore original path of backupd file * @param targetPath new apth for restore, if blank restore directly to riginal path * @return path for restore file */ private String changedPathToRestore(String pathForRestore, String targetPath) { String result; if (StringUtils.isNotBlank(targetPath)) { result = Paths.get(targetPath, pathForRestore.replace(":", File.separator)).toString(); } else { result = pathForRestore; } return result; } }