1 19 20 package org.netbeans.modules.ruby.railsprojects; 21 22 import java.io.IOException ; 23 import javax.swing.JButton ; 24 import org.netbeans.modules.ruby.railsprojects.ui.customizer.RailsProjectProperties; 25 import org.w3c.dom.Comment ; 26 import org.w3c.dom.Document ; 27 import org.w3c.dom.Element ; 28 import org.w3c.dom.NamedNodeMap ; 29 import org.w3c.dom.Node ; 30 import org.w3c.dom.NodeList ; 31 import org.w3c.dom.Text ; 32 import org.openide.DialogDisplayer; 33 import org.openide.ErrorManager; 34 import org.openide.NotifyDescriptor; 35 import org.openide.util.NbBundle; 36 import org.openide.util.Mutex; 37 import org.netbeans.api.project.Project; 38 import org.netbeans.api.project.ProjectManager; 39 import org.netbeans.spi.project.AuxiliaryConfiguration; 40 import org.netbeans.modules.ruby.spi.project.support.rake.RakeProjectHelper; 41 import org.netbeans.modules.ruby.spi.project.support.rake.EditableProperties; 42 import org.netbeans.modules.ruby.spi.project.support.rake.GeneratedFilesHelper; 43 44 45 53 public class UpdateHelper { 54 55 private static final boolean TRANSPARENT_UPDATE = Boolean.getBoolean("j2seproject.transparentUpdate"); 56 private static final String BUILD_NUMBER = System.getProperty("netbeans.buildnumber"); private static final String MINIMUM_ANT_VERSION_ELEMENT = "minimum-ant-version"; 58 59 private final Project project; 60 private final RakeProjectHelper helper; 61 private final AuxiliaryConfiguration cfg; 62 private final GeneratedFilesHelper genFileHelper; 63 private final Notifier notifier; 64 private boolean alreadyAskedInWriteAccess; 65 private Boolean isCurrent; 66 private Element cachedElement; 67 68 76 UpdateHelper (Project project, RakeProjectHelper helper, AuxiliaryConfiguration cfg, GeneratedFilesHelper genFileHelper, Notifier notifier) { 77 assert project != null && helper != null && cfg != null && genFileHelper != null && notifier != null; 78 this.project = project; 79 this.helper = helper; 80 this.cfg = cfg; 81 this.genFileHelper = genFileHelper; 82 this.notifier = notifier; 83 } 84 85 90 public EditableProperties getProperties (final String path) { 91 return ProjectManager.mutex().readAccess(new Mutex.Action<EditableProperties>(){ 93 public EditableProperties run() { 94 if (!isCurrent() && RakeProjectHelper.PROJECT_PROPERTIES_PATH.equals(path)) { return getUpdatedProjectProperties (); 96 } 97 else { 98 return helper.getProperties(path); 99 } 100 } 101 }); 102 } 103 104 112 public void putProperties (final String path, final EditableProperties props) { 113 ProjectManager.mutex().writeAccess( 114 new Runnable () { 115 public void run() { 116 if (isCurrent() || !RakeProjectHelper.PROJECT_PROPERTIES_PATH.equals(path)) { helper.putProperties(path,props); 118 } 119 else if (canUpdate()) { 120 try { 121 saveUpdate (); 122 helper.putProperties(path,props); 123 } catch (IOException ioe) { 124 ErrorManager.getDefault().notify (ioe); 125 } 126 } 127 } 128 }); 129 } 130 131 139 public Element getPrimaryConfigurationData (final boolean shared) { 140 return ProjectManager.mutex().readAccess(new Mutex.Action<Element >(){ 141 public Element run() { 142 if (!shared || isCurrent()) { return helper.getPrimaryConfigurationData(shared); 144 } 145 else { 146 return getUpdatedSharedConfigurationData (); 147 } 148 } 149 }); 150 } 151 152 161 public void putPrimaryConfigurationData (final Element element, final boolean shared) { 162 ProjectManager.mutex().writeAccess(new Runnable () { 163 public void run () { 164 if (!shared || isCurrent()) { 165 helper.putPrimaryConfigurationData(element, shared); 166 } else if (canUpdate()) { 167 try { 168 saveUpdate (); 169 helper.putPrimaryConfigurationData(element, shared); 170 } catch (IOException ioe) { 171 ErrorManager.getDefault().notify(ioe); 172 } 173 } 174 } 175 }); 176 } 177 178 183 public RakeProjectHelper getRakeProjectHelper () { 184 return this.helper; 185 } 186 187 192 public boolean requestSave () throws IOException { 193 if (isCurrent()) { 194 return true; 195 } 196 if (!canUpdate()) { 197 return false; 198 } 199 saveUpdate (); 200 return true; 201 } 202 203 207 public synchronized boolean isCurrent () { 208 return true; 218 } 219 220 private boolean canUpdate () { 221 if (TRANSPARENT_UPDATE) { 222 return true; 223 } 224 if (alreadyAskedInWriteAccess) { 226 return false; 227 } 228 else { 229 boolean canUpdate = this.notifier.canUpdate(); 230 if (!canUpdate) { 231 alreadyAskedInWriteAccess = true; 232 ProjectManager.mutex().postReadRequest(new Runnable () { 233 public void run() { 234 alreadyAskedInWriteAccess = false; 235 } 236 }); 237 } 238 return canUpdate; 239 } 240 } 241 242 private void saveUpdate () throws IOException { 243 this.helper.putPrimaryConfigurationData(getUpdatedSharedConfigurationData(),true); 244 ProjectManager.getDefault().saveProject (this.project); 247 synchronized(this) { 248 this.isCurrent = Boolean.TRUE; 249 } 250 } 251 252 private synchronized Element getUpdatedSharedConfigurationData () { 253 if (cachedElement == null) { 254 } 280 return cachedElement; 281 } 282 283 private synchronized EditableProperties getUpdatedProjectProperties () { 284 EditableProperties cachedProperties = this.helper.getProperties(RakeProjectHelper.PROJECT_PROPERTIES_PATH); 285 return cachedProperties; 286 } 287 288 private static void copyDocument (Document doc, Element from, Element to) { 289 NodeList nl = from.getChildNodes(); 290 int length = nl.getLength(); 291 for (int i=0; i< length; i++) { 292 Node node = nl.item (i); 293 Node newNode = null; 294 switch (node.getNodeType()) { 295 case Node.ELEMENT_NODE: 296 Element oldElement = (Element ) node; 297 newNode = doc.createElementNS(RailsProjectType.PROJECT_CONFIGURATION_NAMESPACE,oldElement.getTagName()); 298 NamedNodeMap m = oldElement.getAttributes(); 299 Element newElement = (Element ) newNode; 300 for (int index = 0; index < m.getLength(); index++) { 301 Node attr = m.item(index); 302 newElement.setAttribute(attr.getNodeName(), attr.getNodeValue()); 303 } 304 copyDocument(doc,oldElement,newElement); 305 break; 306 case Node.TEXT_NODE: 307 Text oldText = (Text ) node; 308 newNode = doc.createTextNode(oldText.getData()); 309 break; 310 case Node.COMMENT_NODE: 311 Comment oldComment = (Comment ) node; 312 newNode = doc.createComment(oldComment.getData()); 313 break; 314 } 315 if (newNode != null) { 316 to.appendChild (newNode); 317 } 318 } 319 } 320 321 339 public static Notifier createDefaultNotifier () { 340 return new Notifier() { 341 public boolean canUpdate() { 342 JButton updateOption = new JButton (NbBundle.getMessage(UpdateHelper.class, "CTL_UpdateOption")); 343 updateOption.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(UpdateHelper.class, "AD_UpdateOption")); 344 return DialogDisplayer.getDefault().notify( 345 new NotifyDescriptor (NbBundle.getMessage(UpdateHelper.class,"TXT_ProjectUpdate", BUILD_NUMBER), 346 NbBundle.getMessage(UpdateHelper.class,"TXT_ProjectUpdateTitle"), 347 NotifyDescriptor.DEFAULT_OPTION, 348 NotifyDescriptor.WARNING_MESSAGE, 349 new Object [] { 350 updateOption, 351 NotifyDescriptor.CANCEL_OPTION 352 }, 353 updateOption)) == updateOption; 354 } 355 }; 356 } 357 358 362 public static interface Notifier { 363 367 public boolean canUpdate (); 368 } 369 } 370 | Popular Tags |