/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.java.sip.communicator.util; import java.io.*; import org.jitsi.service.fileaccess.*; import net.java.sip.communicator.service.protocol.*; /** * The AvatarCacheUtils allows to cache an avatar or to obtain the * image of a cached avatar by specifying a contact or an account address. * * @author Yana Stamcheva */ public class AvatarCacheUtils { /** * The logger for this class. */ private final static Logger logger = Logger.getLogger(AvatarCacheUtils.class); /** * The name (i.e. not the whole path) of the directory in which the avatar * files are to be cached for later reuse. */ private final static String AVATAR_DIR = "avatarcache"; /** * Characters and their replacement in created folder names */ private final static String[][] ESCAPE_SEQUENCES = new String[][] { {"&", "&_amp"}, {"/", "&_sl"}, {"\\\\", "&_bs"}, // the char \ {":", "&_co"}, {"\\*", "&_as"}, // the char * {"\\?", "&_qm"}, // the char ? {"\"", "&_pa"}, // the char " {"<", "&_lt"}, {">", "&_gt"}, {"\\|", "&_pp"} // the char | }; /** * Returns the bytes of the avatar image stored for the account * corresponding to the given protocol provider. * * @param protocolProvider the ProtocolProviderService, which * account avatar image we're looking for * @return the bytes of the avatar image stored for the account * corresponding to the given protocol provider */ public static byte[] getCachedAvatar( ProtocolProviderService protocolProvider) { String avatarPath = getCachedAvatarPath(protocolProvider); byte[] cachedAvatar = getLocallyStoredAvatar(avatarPath); /* * Caching a zero-length avatar happens but such an avatar isn't * very useful. */ if ((cachedAvatar != null) && (cachedAvatar.length > 0)) return cachedAvatar; return null; } /** * Returns the bytes of the avatar image stored for the account * corresponding to the given protocol provider. * * @param protocolProvider the ProtocolProviderService, which * account avatar image we're looking for * @return the bytes of the avatar image stored for the account * corresponding to the given protocol provider */ public static byte[] getCachedAvatar(Contact protocolContact) { String avatarPath = getCachedAvatarPath(protocolContact); byte[] cachedAvatar = getLocallyStoredAvatar(avatarPath); /* * Caching a zero-length avatar happens but such an avatar isn't * very useful. */ if ((cachedAvatar != null) && (cachedAvatar.length > 0)) return cachedAvatar; return null; } /** * Returns the bytes of the avatar image stored for the account * corresponding to the given protocol provider. * * @param protocolProvider the ProtocolProviderService, which * account avatar image we're looking for * @return the bytes of the avatar image stored for the account * corresponding to the given protocol provider */ public static String getCachedAvatarPath( ProtocolProviderService protocolProvider) { return AVATAR_DIR + File.separator + escapeSpecialCharacters( protocolProvider.getAccountID().getAccountUniqueID()) + File.separator + escapeSpecialCharacters( protocolProvider.getAccountID().getAccountUniqueID()); } /** * Returns the bytes of the avatar image stored for the account * corresponding to the given protocol provider. * * @param protocolProvider the ProtocolProviderService, which * account avatar image we're looking for * @return the bytes of the avatar image stored for the account * corresponding to the given protocol provider */ public static String getCachedAvatarPath(Contact protocolContact) { return AVATAR_DIR + File.separator + escapeSpecialCharacters( protocolContact .getProtocolProvider() .getAccountID().getAccountUniqueID()) + File.separator + escapeSpecialCharacters(protocolContact.getAddress()); } /** * Returns the bytes of the avatar image stored for the account * corresponding to the given protocol provider. * * @param protocolProvider the ProtocolProviderService, which * account avatar image we're looking for * @return the bytes of the avatar image stored for the account * corresponding to the given protocol provider */ public static String getCachedAvatarPath( ProtocolProviderService protocolProvider, String contactAddress) { return AVATAR_DIR + File.separator + escapeSpecialCharacters( protocolProvider.getAccountID().getAccountUniqueID()) + File.separator + escapeSpecialCharacters(contactAddress); } /** * Returns the avatar image corresponding to the given avatar path. * * @param avatarPath The path to the lovally stored avatar. * @return the avatar image corresponding to the given avatar path. */ private static byte[] getLocallyStoredAvatar(String avatarPath) { try { File avatarFile = UtilActivator .getFileAccessService() .getPrivatePersistentFile(avatarPath, FileCategory.CACHE); if(avatarFile.exists()) { FileInputStream avatarInputStream = new FileInputStream(avatarFile); byte[] bs = null; try { int available = avatarInputStream.available(); if (available > 0) { bs = new byte[available]; avatarInputStream.read(bs); } } finally { avatarInputStream.close(); } if (bs != null) return bs; } } catch (Exception ex) { logger.error( "Could not read avatar image from file " + avatarPath, ex); } return null; } /** * Replaces the characters that we must escape used for the created * filename. * * @param id the String which is to have its characters escaped * @return a String derived from the specified id by * escaping characters */ private static String escapeSpecialCharacters(String id) { String resultId = id; for (int j = 0; j < ESCAPE_SEQUENCES.length; j++) { resultId = resultId. replaceAll(ESCAPE_SEQUENCES[j][0], ESCAPE_SEQUENCES[j][1]); } return resultId; } /** * Stores avatar bytes in the given Contact. * * @param protoContact The contact in which we store the avatar. * @param avatarBytes The avatar image bytes. */ public static void cacheAvatar( Contact protoContact, byte[] avatarBytes) { String avatarDirPath = AVATAR_DIR + File.separator + escapeSpecialCharacters( protoContact .getProtocolProvider() .getAccountID().getAccountUniqueID()); String avatarFileName = escapeSpecialCharacters(protoContact.getAddress()); cacheAvatar(avatarDirPath, avatarFileName, avatarBytes); } /** * Stores avatar bytes for the account corresponding to the given * protocolProvider. * * @param protocolProvider the protocol provider corresponding to the * account, which avatar we're storing * @param avatarBytes the avatar image bytes */ public static void cacheAvatar( ProtocolProviderService protocolProvider, byte[] avatarBytes) { String accountUID = protocolProvider.getAccountID().getAccountUniqueID(); String avatarDirPath = AVATAR_DIR + File.separator + escapeSpecialCharacters(accountUID); String avatarFileName = escapeSpecialCharacters(accountUID); cacheAvatar(avatarDirPath, avatarFileName, avatarBytes); } /** * Stores avatar bytes for the account corresponding to the given * protocolProvider. * * @param avatarDirPath the directory in which the file will be stored * @param avatarFileName the name of the avatar file * @param avatarBytes the avatar image bytes */ private static void cacheAvatar(String avatarDirPath, String avatarFileName, byte[] avatarBytes) { File avatarDir = null; File avatarFile = null; try { FileAccessService fileAccessService = UtilActivator.getFileAccessService(); avatarDir = fileAccessService.getPrivatePersistentDirectory( avatarDirPath, FileCategory.CACHE); avatarFile = fileAccessService.getPrivatePersistentFile( new File(avatarDirPath, avatarFileName).toString(), FileCategory.CACHE); if(!avatarFile.exists()) { if (!avatarDir.exists() && !avatarDir.mkdirs()) { throw new IOException( "Failed to create directory: " + avatarDir.getAbsolutePath()); } if (!avatarFile.createNewFile()) { throw new IOException( "Failed to create file" + avatarFile.getAbsolutePath()); } } FileOutputStream fileOutStream = new FileOutputStream(avatarFile); try { fileOutStream.write(avatarBytes); fileOutStream.flush(); } finally { fileOutStream.close(); } } catch (Exception ex) { logger.error( "Failed to store avatar. dir =" + avatarDir + " file=" + avatarFile, ex); } } }