1 13 14 package org.netbeans.modules.ruby.railsprojects; 15 16 import java.beans.PropertyChangeEvent ; 17 import java.beans.PropertyChangeListener ; 18 import java.beans.PropertyChangeSupport ; 19 import java.io.IOException ; 20 import java.io.InputStream ; 21 import java.text.Collator ; 22 import java.util.ArrayList ; 23 import java.util.Collection ; 24 import java.util.Collections ; 25 import java.util.Comparator ; 26 import java.util.HashMap ; 27 import java.util.List ; 28 import java.util.Map ; 29 import java.util.Properties ; 30 import java.util.Set ; 31 import java.util.logging.Level ; 32 import java.util.logging.Logger ; 33 import org.netbeans.api.project.ProjectManager; 34 import org.netbeans.modules.ruby.railsprojects.ui.customizer.CustomizerProviderImpl; 35 import org.netbeans.modules.ruby.railsprojects.ui.customizer.RailsCompositePanelProvider; 36 import org.netbeans.spi.project.ActionProvider; 37 import org.netbeans.spi.project.ProjectConfiguration; 38 import org.netbeans.spi.project.ProjectConfigurationProvider; 39 import org.netbeans.modules.ruby.spi.project.support.rake.EditableProperties; 40 import org.openide.filesystems.FileChangeAdapter; 41 import org.openide.filesystems.FileChangeListener; 42 import org.openide.filesystems.FileEvent; 43 import org.openide.filesystems.FileObject; 44 import org.openide.filesystems.FileRenameEvent; 45 import org.openide.filesystems.FileUtil; 46 import org.openide.util.NbBundle; 47 import org.openide.util.Utilities; 48 49 53 public final class RailsConfigurationProvider implements ProjectConfigurationProvider<RailsConfigurationProvider.Config> { 54 55 private static final Logger LOGGER = Logger.getLogger(RailsConfigurationProvider.class.getName()); 56 57 60 public static final String PROP_CONFIG = "config"; 64 public static final String CONFIG_PROPS_PATH = "nbproject/private/config.properties"; 66 public static final class Config implements ProjectConfiguration { 67 68 public final String name; 69 private final String displayName; 70 public Config(String name, String displayName) { 71 this.name = name; 72 this.displayName = displayName; 73 } 74 public String getDisplayName() { 75 return displayName; 76 } 77 public int hashCode() { 78 return name != null ? name.hashCode() : 0; 79 } 80 public boolean equals(Object o) { 81 return (o instanceof Config) && Utilities.compareObjects(name, ((Config) o).name); 82 } 83 public String toString() { 84 return "RailsConfigurationProvider.Config[" + name + "," + displayName + "]"; } 86 } 87 88 private static final Config DEFAULT = new Config(null, 89 NbBundle.getMessage(RailsConfigurationProvider.class, "RailsConfigurationProvider.default.label")); 90 91 private final RailsProject p; 92 private final PropertyChangeSupport pcs = new PropertyChangeSupport (this); 93 private final FileChangeListener fcl = new FileChangeAdapter() { 94 public void fileFolderCreated(FileEvent fe) { 95 update(fe); 96 } 97 public void fileDataCreated(FileEvent fe) { 98 update(fe); 99 } 100 public void fileDeleted(FileEvent fe) { 101 update(fe); 102 } 103 public void fileRenamed(FileRenameEvent fe) { 104 update(fe); 105 } 106 private void update(FileEvent ev) { 107 LOGGER.log(Level.FINEST, "Received {0}", ev); 108 Set <String > oldConfigs = configs != null ? configs.keySet() : Collections.<String >emptySet(); 109 configDir = p.getProjectDirectory().getFileObject("nbproject/configs"); if (configDir != null) { 111 configDir.removeFileChangeListener(fclWeak); 112 configDir.addFileChangeListener(fclWeak); 113 LOGGER.log(Level.FINEST, "(Re-)added listener to {0}", configDir); 114 } else { 115 LOGGER.log(Level.FINEST, "No nbproject/configs exists"); 116 } 117 calculateConfigs(); 118 Set <String > newConfigs = configs.keySet(); 119 if (!oldConfigs.equals(newConfigs)) { 120 LOGGER.log(Level.FINER, "Firing " + ProjectConfigurationProvider.PROP_CONFIGURATIONS + ": {0} -> {1}", new Object [] {oldConfigs, newConfigs}); 121 pcs.firePropertyChange(ProjectConfigurationProvider.PROP_CONFIGURATIONS, null, null); 122 } 124 } 125 }; 126 private final FileChangeListener fclWeak; 127 private FileObject configDir; 128 private Map <String ,Config> configs; 129 130 public RailsConfigurationProvider(RailsProject p) { 131 this.p = p; 132 fclWeak = FileUtil.weakFileChangeListener(fcl, null); 133 FileObject nbp = p.getProjectDirectory().getFileObject("nbproject"); if (nbp != null) { 135 nbp.addFileChangeListener(fclWeak); 136 LOGGER.log(Level.FINEST, "Added listener to {0}", nbp); 137 configDir = nbp.getFileObject("configs"); if (configDir != null) { 139 configDir.addFileChangeListener(fclWeak); 140 LOGGER.log(Level.FINEST, "Added listener to {0}", configDir); 141 } 142 } 143 p.evaluator().addPropertyChangeListener(new PropertyChangeListener () { 144 public void propertyChange(PropertyChangeEvent evt) { 145 if (PROP_CONFIG.equals(evt.getPropertyName())) { 146 LOGGER.log(Level.FINER, "Refiring " + PROP_CONFIG + " -> " + ProjectConfigurationProvider.PROP_CONFIGURATION_ACTIVE); 147 pcs.firePropertyChange(ProjectConfigurationProvider.PROP_CONFIGURATION_ACTIVE, null, null); 148 } 149 } 150 }); 151 } 152 153 private void calculateConfigs() { 154 configs = new HashMap <String ,Config>(); 155 if (configDir != null) { 156 for (FileObject kid : configDir.getChildren()) { 157 if (!kid.hasExt("properties")) { 158 continue; 159 } 160 try { 161 InputStream is = kid.getInputStream(); 162 try { 163 Properties p = new Properties (); 164 p.load(is); 165 String name = kid.getName(); 166 String label = p.getProperty("$label"); configs.put(name, new Config(name, label != null ? label : name)); 168 } finally { 169 is.close(); 170 } 171 } catch (IOException x) { 172 LOGGER.log(Level.INFO, null, x); 173 } 174 } 175 } 176 LOGGER.log(Level.FINEST, "Calculated configurations: {0}", configs); 177 } 178 179 public Collection <Config> getConfigurations() { 180 calculateConfigs(); 181 List <Config> l = new ArrayList <Config>(); 182 l.addAll(configs.values()); 183 Collections.sort(l, new Comparator <Config>() { 184 Collator c = Collator.getInstance(); 185 public int compare(Config c1, Config c2) { 186 return c.compare(c1.getDisplayName(), c2.getDisplayName()); 187 } 188 }); 189 l.add(0, DEFAULT); 190 return l; 191 } 192 193 public Config getActiveConfiguration() { 194 calculateConfigs(); 195 String config = p.evaluator().getProperty(PROP_CONFIG); 196 if (config != null && configs.containsKey(config)) { 197 return configs.get(config); 198 } else { 199 return DEFAULT; 200 } 201 } 202 203 public void setActiveConfiguration(Config c) throws IllegalArgumentException , IOException { 204 if (c != DEFAULT && !configs.values().contains(c)) { 205 throw new IllegalArgumentException (); 206 } 207 final String n = c.name; 208 EditableProperties ep = p.getUpdateHelper().getProperties(CONFIG_PROPS_PATH); 209 if (Utilities.compareObjects(n, ep.getProperty(PROP_CONFIG))) { 210 return; 211 } 212 if (n != null) { 213 ep.setProperty(PROP_CONFIG, n); 214 } else { 215 ep.remove(PROP_CONFIG); 216 } 217 p.getUpdateHelper().putProperties(CONFIG_PROPS_PATH, ep); 218 pcs.firePropertyChange(ProjectConfigurationProvider.PROP_CONFIGURATION_ACTIVE, null, null); 219 ProjectManager.getDefault().saveProject(p); 220 assert p.getProjectDirectory().getFileObject(CONFIG_PROPS_PATH) != null; 221 } 222 223 public boolean hasCustomizer() { 224 return true; 225 } 226 227 public void customize() { 228 p.getLookup().lookup(CustomizerProviderImpl.class).showCustomizer(RailsCompositePanelProvider.RUN); 229 } 230 231 public boolean configurationsAffectAction(String command) { 232 return command.equals(ActionProvider.COMMAND_RUN) || 233 command.equals(ActionProvider.COMMAND_DEBUG); 234 } 235 236 public void addPropertyChangeListener(PropertyChangeListener lst) { 237 pcs.addPropertyChangeListener(lst); 238 } 239 240 public void removePropertyChangeListener(PropertyChangeListener lst) { 241 pcs.removePropertyChangeListener(lst); 242 } 243 244 } 245 | Popular Tags |