001package jmri.profile; 002 003import java.io.File; 004import java.io.IOException; 005import java.util.prefs.Preferences; 006import javax.annotation.Nonnull; 007import jmri.util.FileUtil; 008import jmri.util.FileUtilSupport; 009import jmri.util.node.NodeIdentity; 010import jmri.util.prefs.JmriConfigurationProvider; 011import jmri.util.prefs.JmriPreferencesProvider; 012import jmri.util.prefs.JmriUserInterfaceConfigurationProvider; 013import org.slf4j.Logger; 014import org.slf4j.LoggerFactory; 015 016/** 017 * Utility methods to get information about {@link jmri.profile.Profile}s. 018 * 019 * @author Randall Wood 2015 020 */ 021public class ProfileUtils { 022 023 private final static Logger log = LoggerFactory.getLogger(ProfileUtils.class); 024 025 /** 026 * Get the XMl configuration container for a given configuration profile. 027 * 028 * @param project The project to get the configuration container for, or 029 * null to get a configuration container that can apply to 030 * all projects on this computer 031 * @return An XML configuration container, possibly empty 032 */ 033 public static AuxiliaryConfiguration getAuxiliaryConfiguration(Profile project) { 034 return JmriConfigurationProvider.getConfiguration(project); 035 } 036 037 /** 038 * Get the preferences needed by a class for a given configuration profile. 039 * 040 * @param project The project to get the configuration for, or null to get a 041 * preferences object that can apply to all projects on this 042 * computer 043 * @param clazz The class requesting preferences 044 * @param shared True if the preferences are for all nodes (computers) this 045 * project may run on, false if the preferences are only for 046 * this node; ignored if the value of project is null 047 * @return The preferences 048 */ 049 public static Preferences getPreferences(Profile project, Class<?> clazz, boolean shared) { 050 return JmriPreferencesProvider.getPreferences(project, clazz, shared); 051 } 052 053 /** 054 * Get the XMl configuration container for a given configuration profile's 055 * user interface state. 056 * 057 * @param project The project to get the configuration container for, or 058 * null to get a configuration container that can apply to 059 * all projects on this computer 060 * @return An XML configuration container, possibly empty 061 */ 062 public static AuxiliaryConfiguration getUserInterfaceConfiguration(Profile project) { 063 return JmriUserInterfaceConfigurationProvider.getConfiguration(project); 064 } 065 066 /** 067 * Get the local cache directory for the given profile. 068 * <p> 069 * This cache is outside the profile for which the cache exists to prevent 070 * the possibility that different JMRI installations have different contents 071 * that would invalidate the cache if copied from one computer to another. 072 * 073 * @param project the project to get the cache directory for, or null to get 074 * the cache directory for all projects on this computer 075 * @param owner The class owning the cached information, or null to get 076 * the cache directory for the project 077 * @return a directory in which data can be cached 078 */ 079 public static File getCacheDirectory(Profile project, Class<?> owner) { 080 File cache = FileUtilSupport.getDefault().getCacheDirectory(); 081 if (project != null) { 082 cache = new File(cache, project.getId()); 083 } 084 if (owner != null) { 085 cache = new File(cache, JmriPreferencesProvider.findCNBForClass(owner)); 086 } 087 FileUtil.createDirectory(cache); 088 return cache; 089 } 090 091 /** 092 * Copy one profile configuration to another profile. 093 * 094 * @param source The source profile. 095 * @param destination The destination profile. 096 * @throws IllegalArgumentException If the destination profile is the active 097 * profile. 098 * @throws IOException If the copy cannot be completed. 099 */ 100 public static void copy(@Nonnull Profile source, @Nonnull Profile destination) throws IllegalArgumentException, IOException { 101 if (destination.equals(ProfileManager.getDefault().getActiveProfile())) { 102 throw new IllegalArgumentException("Target profile cannot be active profile."); 103 } 104 FileUtil.copy(source.getPath(), destination.getPath()); 105 File profile = new File(destination.getPath(), Profile.PROFILE); 106 File[] files = profile.listFiles((File pathname) -> (pathname.getName().endsWith(source.getUniqueId()))); 107 if (files != null) { 108 for (File file : files) { 109 if (!file.renameTo(new File(profile, file.getName().replace(source.getUniqueId(), destination.getUniqueId())))) { 110 throw new IOException("Unable to rename " + file + " to use new profile ID"); 111 } 112 } 113 } 114 destination.save(); 115 } 116 117 /** 118 * Copy the most recently modified former identity, if any, for the current computer 119 * in the given profile to the current storage identity of the current computer for 120 * the given profile. 121 * 122 * @param profile the profile containing identities to copy 123 * @return true if an existing identity is copied, false otherwise 124 * @throws IOException if unable to a copy an existing identity 125 */ 126 public static boolean copyPrivateContentToCurrentIdentity(@Nonnull Profile profile) throws IOException { 127 String uniqueId = "-" + profile.getUniqueId(); 128 File newPath = new File(new File(profile.getPath(), Profile.PROFILE), NodeIdentity.storageIdentity(profile)); 129 if (!newPath.exists()) { 130 File oldPath = null; 131 for (String identity : NodeIdentity.formerIdentities()) { 132 if (oldPath == null) { 133 File path = new File(new File(profile.getPath(), Profile.PROFILE), identity + uniqueId); 134 if (path.exists()) { 135 oldPath = path; 136 } 137 } else { 138 File path = new File(new File(profile.getPath(), Profile.PROFILE), identity + uniqueId); 139 if (path.exists() && path.lastModified() > oldPath.lastModified()) { 140 oldPath = path; 141 } 142 } 143 } 144 if (oldPath != null && oldPath.exists()) { 145 try { 146 log.info("Copying from old node \"{}\" to new node \"{}\"", oldPath, newPath); 147 FileUtil.copy(oldPath, newPath); 148 return true; 149 } catch (IOException ex) { 150 log.warn("Failed copying \"{}\" to \"{}\"", oldPath, newPath); 151 } 152 } 153 } 154 return false; 155 } 156}