/* * Copyright 2004 - 2008 Christian Sprajc. All rights reserved. * * This file is part of PowerFolder. * * PowerFolder 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. * * PowerFolder 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 PowerFolder. If not, see <http://www.gnu.org/licenses/>. * * $Id$ */ package de.dal33t.powerfolder.message; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.logging.Logger; import de.dal33t.powerfolder.Controller; import de.dal33t.powerfolder.Member; import de.dal33t.powerfolder.light.FolderInfo; import de.dal33t.powerfolder.util.ByteSerializer; import de.dal33t.powerfolder.util.Convert; import de.dal33t.powerfolder.util.FileUtils; import de.dal33t.powerfolder.util.Reject; import de.dal33t.powerfolder.util.StreamUtils; import de.dal33t.powerfolder.util.Util; /** * List of available folders * * @author <a href="mailto:totmacher@powerfolder.com">Christian Sprajc </a> * @version $Revision: 1.9 $ */ public class FolderList extends Message { private static final long serialVersionUID = 101L; private static Logger LOG = Logger.getLogger(FolderList.class.getName()); /** List of public folders. LEFT for backward compatibility */ public FolderInfo[] folders = new FolderInfo[0]; /** Secret folders, Folder IDs are encrypted with magic Id */ public FolderInfo[] secretFolders; /** * Boolean to indicate that the source also has joined matching meta * folders. */ public boolean joinedMetaFolders; public FolderList() { // Serialisation constructor } /** * Constructor which splits up public and secret folder into own array. * Folder Ids of secret folders will be encrypted with magic Id sent by * remote node * * @param allFolders * @param remoteMagicId * the magic id which was sent by the remote side */ public FolderList(Collection<FolderInfo> allFolders, String remoteMagicId) { Reject.ifBlank(remoteMagicId, "Remote magic id is blank"); // Split folderlist into secret and public list // Encrypt secret folder ids with magic id List<FolderInfo> secretFos = new ArrayList<FolderInfo>( allFolders.size()); for (FolderInfo folderInfo : allFolders) { // Send secret folder infos if magic id is not empty // Clone folderinfo String secureId = folderInfo.calculateSecureId(remoteMagicId); // Set Id to secure Id FolderInfo secretFolder = new FolderInfo(folderInfo.getName(), secureId); // Secret folder, encrypt folder id with magic id secretFos.add(secretFolder); } this.secretFolders = new FolderInfo[secretFos.size()]; this.joinedMetaFolders = true; secretFos.toArray(secretFolders); } public boolean contains(FolderInfo foInfo, String magicId) { String secureId = foInfo.calculateSecureId(magicId); for (FolderInfo folder : secretFolders) { if (folder.id.equals(secureId)) { return true; } } return false; } /** * @param member * the {@link Member} to store this {@link FolderList} relative * to. * @return true if this {@link FolderList} could be stored. * @see #load(Member) * @deprecated #2569 */ public synchronized boolean store(Member member) { return store(getMemberFile(member)); } /** * @param file * the file to store this {@link FolderList} in. * @return true if this {@link FolderList} could be stored to that file. * @see #load(File) * @deprecated #2569 */ public synchronized boolean store(File file) { Reject.ifNull(file, "File"); if (file.getParentFile() != null) { file.getParentFile().mkdirs(); } try { byte[] buf = ByteSerializer.serializeStatic(this, false); FileUtils.copyFromStreamToFile(new ByteArrayInputStream(buf), file); return true; } catch (Exception e) { LOG.warning("Unable to store to " + file + ". " + e + ". " + this); return false; } } /** * @param member * the {@link Member} to load a {@link FolderList} previously * stored with {@link #store(Member)} from * @return the loaded {@link FolderList} or null if failed or not existing. * @deprecated #2569 */ public static FolderList load(Member member) { return load(getMemberFile(member)); } /** * @param file * the file to load a {@link FolderList} previously stored with * {@link #store(File)} from * @return the loaded {@link FolderList} or null if failed or not existing. * @deprecated #2569 */ public static FolderList load(File file) { Reject.ifNull(file, "File"); if (!file.exists()) { return null; } InputStream in = null; try { in = new BufferedInputStream(new FileInputStream(file)); byte[] buf = StreamUtils.readIntoByteArray(in); return (FolderList) ByteSerializer.deserializeStatic(buf, false); } catch (Exception e) { LOG.warning("Unable to load to " + file + ". " + e); return null; } finally { if (in != null) { try { in.close(); } catch (IOException e) { } } } } public static void removeMemberFiles(Controller controller) { try { FileUtils.recursiveDelete(new File(Controller .getMiscFilesLocation(), controller.getConfigName() + ".temp/nodes")); } catch (IOException e) { LOG.severe("Unable to deleted FolderList temporary files. " + e); } } private static File getMemberFile(Member member) { String idPath = new String(Util.encodeHex(Util.md5(member.getId() .getBytes(Convert.UTF8)))); return new File(Controller.getMiscFilesLocation(), member .getController().getConfigName() + ".temp/nodes/" + idPath + ".FolderList"); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (joinedMetaFolders ? 1231 : 1237); result = prime * result + Arrays.hashCode(secretFolders); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; FolderList other = (FolderList) obj; if (joinedMetaFolders != other.joinedMetaFolders) return false; if (!Arrays.equals(secretFolders, other.secretFolders)) return false; return true; } public String toString() { return "FolderList: " + secretFolders.length + " folders"; } }