1 19 20 package org.netbeans.modules.j2ee.archive.project; 21 22 import java.io.IOException ; 23 import javax.swing.JButton ; 24 import org.netbeans.spi.project.support.ant.GeneratedFilesHelper; 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.spi.project.support.ant.AntProjectHelper; 41 import org.netbeans.spi.project.support.ant.EditableProperties; 42 43 44 50 public class UpdateHelper { 51 52 private static final boolean TRANSPARENT_UPDATE = Boolean.getBoolean("carproject.transparentUpdate"); 53 private static final String BUILD_NUMBER = System.getProperty("netbeans.buildnumber"); private static final String MINIMUM_ANT_VERSION_ELEMENT = "minimum-ant-version"; 56 private final Project project; 57 private final AntProjectHelper helper; 58 private final AuxiliaryConfiguration cfg; 59 private final Notifier notifier; 60 private boolean alreadyAskedInWriteAccess; 61 private Element cachedElement; 63 64 72 UpdateHelper (Project project, AntProjectHelper helper, AuxiliaryConfiguration cfg, GeneratedFilesHelper genFileHelper, Notifier notifier) { 73 assert project != null && helper != null && cfg != null && genFileHelper != null && notifier != null; 74 this.project = project; 75 this.helper = helper; 76 this.cfg = cfg; 77 this.notifier = notifier; 78 } 79 80 85 public EditableProperties getProperties (final String path) { 86 return (EditableProperties) ProjectManager.mutex().readAccess(new Mutex.Action (){ 88 public Object run() { 89 if (!isCurrent() && AntProjectHelper.PROJECT_PROPERTIES_PATH.equals(path)) { return getUpdatedProjectProperties (); 91 } 92 else { 93 return helper.getProperties(path); 94 } 95 } 96 }); 97 } 98 99 107 public void putProperties (final String path, final EditableProperties props) { 108 ProjectManager.mutex().writeAccess( 109 new Runnable () { 110 public void run() { 111 if (isCurrent() || !AntProjectHelper.PROJECT_PROPERTIES_PATH.equals(path)) { helper.putProperties(path,props); 113 } 114 else if (canUpdate()) { 115 try { 116 saveUpdate (); 117 helper.putProperties(path,props); 118 } catch (IOException ioe) { 119 ErrorManager.getDefault().notify (ioe); 120 } 121 } 122 } 123 }); 124 } 125 126 134 public Element getPrimaryConfigurationData (final boolean shared) { 135 return (Element ) ProjectManager.mutex().readAccess(new Mutex.Action (){ 136 public Object run() { 137 if (!shared || isCurrent()) { return helper.getPrimaryConfigurationData(shared); 139 } 140 else { 141 return getUpdatedSharedConfigurationData (); 142 } 143 } 144 }); 145 } 146 147 156 public void putPrimaryConfigurationData (final Element element, final boolean shared) { 157 ProjectManager.mutex().writeAccess(new Runnable () { 158 public void run () { 159 if (!shared || isCurrent()) { 160 helper.putPrimaryConfigurationData(element, shared); 161 } else if (canUpdate()) { 162 try { 163 saveUpdate (); 164 helper.putPrimaryConfigurationData(element, shared); 165 } catch (IOException ioe) { 166 ErrorManager.getDefault().notify(ioe); 167 } 168 } 169 } 170 }); 171 } 172 173 178 public AntProjectHelper getAntProjectHelper () { 179 return this.helper; 180 } 181 182 187 public boolean requestSave () throws IOException { 188 if (isCurrent()) { 189 return true; 190 } 191 if (!canUpdate()) { 192 return false; 193 } 194 saveUpdate (); 195 return true; 196 } 197 198 202 public synchronized boolean isCurrent () { 203 214 return true; 216 } 217 218 private boolean canUpdate () { 219 if (TRANSPARENT_UPDATE) { 220 return true; 221 } 222 if (alreadyAskedInWriteAccess) { 224 return false; 225 } 226 else { 227 boolean canUpdate = this.notifier.canUpdate(); 228 if (!canUpdate) { 229 alreadyAskedInWriteAccess = true; 230 ProjectManager.mutex().postReadRequest(new Runnable () { 231 public void run() { 232 alreadyAskedInWriteAccess = false; 233 } 234 }); 235 } 236 return canUpdate; 237 } 238 } 239 240 private void saveUpdate () throws IOException { 241 this.helper.putPrimaryConfigurationData(getUpdatedSharedConfigurationData(),true); 242 this.cfg.removeConfigurationFragment("data","http://www.netbeans.org/ns/j2se-project/1",true); this.cfg.removeConfigurationFragment("data","http://www.netbeans.org/ns/j2se-project/2",true); ProjectManager.getDefault().saveProject (this.project); 245 } 249 250 private synchronized Element getUpdatedSharedConfigurationData () { 251 if (cachedElement == null) { 252 Element oldRoot = this.cfg.getConfigurationFragment("data","http://www.netbeans.org/ns/j2se-project/1",true); if (oldRoot != null) { 254 Document doc = oldRoot.getOwnerDocument(); 255 Element newRoot = doc.createElementNS (ArchiveProjectType.PROJECT_CONFIGURATION_NS,"data"); copyDocument (doc, oldRoot, newRoot); 257 Element sourceRoots = doc.createElementNS(ArchiveProjectType.PROJECT_CONFIGURATION_NS,"source-roots"); Element root = doc.createElementNS (ArchiveProjectType.PROJECT_CONFIGURATION_NS,"root"); root.setAttribute ("id","src.dir"); sourceRoots.appendChild(root); 261 newRoot.appendChild (sourceRoots); 262 Element testRoots = doc.createElementNS(ArchiveProjectType.PROJECT_CONFIGURATION_NS,"test-roots"); root = doc.createElementNS (ArchiveProjectType.PROJECT_CONFIGURATION_NS,"root"); root.setAttribute ("id","test.src.dir"); testRoots.appendChild (root); 266 newRoot.appendChild (testRoots); 267 cachedElement = updateMinAntVersion (newRoot, doc); 268 } else { 269 oldRoot = this.cfg.getConfigurationFragment("data","http://www.netbeans.org/ns/j2se-project/2",true); if (oldRoot != null) { 271 Document doc = oldRoot.getOwnerDocument(); 272 Element newRoot = doc.createElementNS (ArchiveProjectType.PROJECT_CONFIGURATION_NS,"data"); copyDocument (doc, oldRoot, newRoot); 274 cachedElement = updateMinAntVersion (newRoot, doc); 275 } 276 } 277 } 278 return cachedElement; 279 } 280 281 private synchronized EditableProperties getUpdatedProjectProperties () { 282 EditableProperties cachedProperties = this.helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH); 283 return cachedProperties; 294 } 295 296 private static void copyDocument (Document doc, Element from, Element to) { 297 NodeList nl = from.getChildNodes(); 298 int length = nl.getLength(); 299 for (int i=0; i< length; i++) { 300 Node node = nl.item (i); 301 Node newNode = null; 302 switch (node.getNodeType()) { 303 case Node.ELEMENT_NODE: 304 Element oldElement = (Element ) node; 305 newNode = doc.createElementNS(ArchiveProjectType.PROJECT_CONFIGURATION_NS,oldElement.getTagName()); 306 NamedNodeMap m = oldElement.getAttributes(); 307 Element newElement = (Element ) newNode; 308 for (int index = 0; index < m.getLength(); index++) { 309 Node attr = m.item(index); 310 newElement.setAttribute(attr.getNodeName(), attr.getNodeValue()); 311 } 312 copyDocument(doc,oldElement,newElement); 313 break; 314 case Node.TEXT_NODE: 315 Text oldText = (Text ) node; 316 newNode = doc.createTextNode(oldText.getData()); 317 break; 318 case Node.COMMENT_NODE: 319 Comment oldComment = (Comment ) node; 320 newNode = doc.createComment(oldComment.getData()); 321 break; 322 } 323 if (newNode != null) { 324 to.appendChild (newNode); 325 } 326 } 327 } 328 public static final String MINIMUM_ANT_VERSION = "1.6.5"; 330 private static Element updateMinAntVersion (final Element root, final Document doc) { 331 NodeList list = root.getElementsByTagNameNS (ArchiveProjectType.PROJECT_CONFIGURATION_NS,MINIMUM_ANT_VERSION_ELEMENT); 332 if (list.getLength() == 1) { 333 Element me = (Element ) list.item(0); 334 list = me.getChildNodes(); 335 if (list.getLength() == 1) { 336 me.replaceChild (doc.createTextNode(MINIMUM_ANT_VERSION), list.item(0)); 337 return root; 338 } 339 } 340 assert false : "Invalid project file"; return root; 342 } 343 344 348 public static Notifier createDefaultNotifier () { 349 return new Notifier() { 350 public boolean canUpdate() { 351 JButton updateOption = new JButton (NbBundle.getMessage(UpdateHelper.class, "CTL_UpdateOption")); 352 updateOption.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(UpdateHelper.class, "AD_UpdateOption")); 353 return DialogDisplayer.getDefault().notify( 354 new NotifyDescriptor (NbBundle.getMessage(UpdateHelper.class,"TXT_ProjectUpdate", BUILD_NUMBER), 355 NbBundle.getMessage(UpdateHelper.class,"TXT_ProjectUpdateTitle"), 356 NotifyDescriptor.DEFAULT_OPTION, 357 NotifyDescriptor.WARNING_MESSAGE, 358 new Object [] { 359 updateOption, 360 NotifyDescriptor.CANCEL_OPTION 361 }, 362 updateOption)) == updateOption; 363 } 364 }; 365 } 366 367 371 public static interface Notifier { 372 376 public boolean canUpdate (); 377 } 378 } 379 | Popular Tags |