1 19 20 package org.netbeans.bluej; 21 22 import java.io.IOException ; 23 import javax.swing.JButton ; 24 import org.w3c.dom.Comment ; 25 import org.w3c.dom.Document ; 26 import org.w3c.dom.Element ; 27 import org.w3c.dom.NamedNodeMap ; 28 import org.w3c.dom.Node ; 29 import org.w3c.dom.NodeList ; 30 import org.w3c.dom.Text ; 31 import org.openide.DialogDisplayer; 32 import org.openide.ErrorManager; 33 import org.openide.NotifyDescriptor; 34 import org.openide.util.NbBundle; 35 import org.openide.util.Mutex; 36 import org.netbeans.api.project.Project; 37 import org.netbeans.api.project.ProjectManager; 38 import org.netbeans.spi.project.AuxiliaryConfiguration; 39 import org.netbeans.spi.project.support.ant.AntProjectHelper; 40 import org.netbeans.spi.project.support.ant.EditableProperties; 41 import org.netbeans.spi.project.support.ant.GeneratedFilesHelper; 42 43 44 52 public class UpdateHelper { 53 54 private static final boolean TRANSPARENT_UPDATE = Boolean.getBoolean("j2seproject.transparentUpdate"); private static final String BUILD_NUMBER = System.getProperty("netbeans.buildnumber"); private static final String MINIMUM_ANT_VERSION_ELEMENT = "minimum-ant-version"; 58 private final Project project; 59 private final AntProjectHelper helper; 60 private final AuxiliaryConfiguration cfg; 61 private final GeneratedFilesHelper genFileHelper; 62 private final Notifier notifier; 63 private boolean alreadyAskedInWriteAccess; 64 private Boolean isCurrent; 65 private Element cachedElement; 66 67 75 UpdateHelper (Project project, AntProjectHelper helper, AuxiliaryConfiguration cfg, GeneratedFilesHelper genFileHelper, Notifier notifier) { 76 assert project != null && helper != null && cfg != null && genFileHelper != null && notifier != null; 77 this.project = project; 78 this.helper = helper; 79 this.cfg = cfg; 80 this.genFileHelper = genFileHelper; 81 this.notifier = notifier; 82 } 83 84 89 public EditableProperties getProperties (final String path) { 90 return (EditableProperties) ProjectManager.mutex().readAccess(new Mutex.Action (){ 92 public Object run() { 93 if (!isCurrent() && AntProjectHelper.PROJECT_PROPERTIES_PATH.equals(path)) { return getUpdatedProjectProperties (); 95 } 96 else { 97 return helper.getProperties(path); 98 } 99 } 100 }); 101 } 102 103 111 public void putProperties (final String path, final EditableProperties props) { 112 ProjectManager.mutex().writeAccess( 113 new Runnable () { 114 public void run() { 115 if (isCurrent() || !AntProjectHelper.PROJECT_PROPERTIES_PATH.equals(path)) { helper.putProperties(path,props); 117 } 118 else if (canUpdate()) { 119 try { 120 saveUpdate (); 121 helper.putProperties(path,props); 122 } catch (IOException ioe) { 123 ErrorManager.getDefault().notify (ioe); 124 } 125 } 126 } 127 }); 128 } 129 130 138 public Element getPrimaryConfigurationData (final boolean shared) { 139 return (Element ) ProjectManager.mutex().readAccess(new Mutex.Action (){ 140 public Object run() { 141 if (!shared || isCurrent()) { return helper.getPrimaryConfigurationData(shared); 143 } 144 else { 145 return getUpdatedSharedConfigurationData (); 146 } 147 } 148 }); 149 } 150 151 160 public void putPrimaryConfigurationData (final Element element, final boolean shared) { 161 ProjectManager.mutex().writeAccess(new Runnable () { 162 public void run () { 163 if (!shared || isCurrent()) { 164 helper.putPrimaryConfigurationData(element, shared); 165 } else if (canUpdate()) { 166 try { 167 saveUpdate (); 168 helper.putPrimaryConfigurationData(element, shared); 169 } catch (IOException ioe) { 170 ErrorManager.getDefault().notify(ioe); 171 } 172 } 173 } 174 }); 175 } 176 177 182 public AntProjectHelper getAntProjectHelper () { 183 return this.helper; 184 } 185 186 191 public boolean requestSave () throws IOException { 192 if (isCurrent()) { 193 return true; 194 } 195 if (!canUpdate()) { 196 return false; 197 } 198 saveUpdate (); 199 return true; 200 } 201 202 206 public synchronized boolean isCurrent () { 207 return true; 208 } 209 210 private boolean canUpdate () { 211 if (TRANSPARENT_UPDATE) { 212 return true; 213 } 214 if (alreadyAskedInWriteAccess) { 216 return false; 217 } 218 else { 219 boolean canUpdate = this.notifier.canUpdate(); 220 if (!canUpdate) { 221 alreadyAskedInWriteAccess = true; 222 ProjectManager.mutex().postReadRequest(new Runnable () { 223 public void run() { 224 alreadyAskedInWriteAccess = false; 225 } 226 }); 227 } 228 return canUpdate; 229 } 230 } 231 232 private void saveUpdate () throws IOException { 233 this.helper.putPrimaryConfigurationData(getUpdatedSharedConfigurationData(),true); 234 ProjectManager.getDefault().saveProject (this.project); 237 synchronized(this) { 238 this.isCurrent = Boolean.TRUE; 239 } 240 } 241 242 private synchronized Element getUpdatedSharedConfigurationData () { 243 if (cachedElement == null) { 244 Element oldRoot = this.cfg.getConfigurationFragment("data","http://www.netbeans.org/ns/j2se-project/1",true); if (oldRoot != null) { 246 Document doc = oldRoot.getOwnerDocument(); 247 Element newRoot = doc.createElementNS (BluejProjectType.PROJECT_CONFIGURATION_NAMESPACE,"data"); copyDocument (doc, oldRoot, newRoot); 249 Element sourceRoots = doc.createElementNS(BluejProjectType.PROJECT_CONFIGURATION_NAMESPACE,"source-roots"); Element root = doc.createElementNS (BluejProjectType.PROJECT_CONFIGURATION_NAMESPACE,"root"); root.setAttribute ("id","src.dir"); sourceRoots.appendChild(root); 253 newRoot.appendChild (sourceRoots); 254 Element testRoots = doc.createElementNS(BluejProjectType.PROJECT_CONFIGURATION_NAMESPACE,"test-roots"); root = doc.createElementNS (BluejProjectType.PROJECT_CONFIGURATION_NAMESPACE,"root"); root.setAttribute ("id","test.src.dir"); testRoots.appendChild (root); 258 newRoot.appendChild (testRoots); 259 cachedElement = updateMinAntVersion (newRoot, doc); 260 } else { 261 oldRoot = this.cfg.getConfigurationFragment("data","http://www.netbeans.org/ns/j2se-project/2",true); if (oldRoot != null) { 263 Document doc = oldRoot.getOwnerDocument(); 264 Element newRoot = doc.createElementNS (BluejProjectType.PROJECT_CONFIGURATION_NAMESPACE,"data"); copyDocument (doc, oldRoot, newRoot); 266 cachedElement = updateMinAntVersion (newRoot, doc); 267 } 268 } 269 } 270 return cachedElement; 271 } 272 273 private synchronized EditableProperties getUpdatedProjectProperties () { 274 EditableProperties cachedProperties = this.helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH); 275 if (cachedProperties.get (BluejProject.JAVADOC_ADDITIONALPARAM)==null) { 277 cachedProperties.put (BluejProject.JAVADOC_ADDITIONALPARAM,""); } 279 if (cachedProperties.get ("build.generated.dir")==null) { cachedProperties.put ("build.generated.dir","${build.dir}/generated"); } 282 if (cachedProperties.get ("meta.inf.dir")==null) { cachedProperties.put ("meta.inf.dir","${src.dir}/META-INF"); } 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(BluejProjectType.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 static final String MINIMUM_ANT_VERSION = "1.6.5"; 323 private static Element updateMinAntVersion (final Element root, final Document doc) { 324 NodeList list = root.getElementsByTagNameNS (BluejProjectType.PROJECT_CONFIGURATION_NAMESPACE,MINIMUM_ANT_VERSION_ELEMENT); 325 if (list.getLength() == 1) { 326 Element me = (Element ) list.item(0); 327 list = me.getChildNodes(); 328 if (list.getLength() == 1) { 329 me.replaceChild (doc.createTextNode(MINIMUM_ANT_VERSION), list.item(0)); 330 return root; 331 } 332 } 333 assert false : "Invalid project file"; return root; 335 } 336 337 341 public static Notifier createDefaultNotifier () { 342 return new Notifier() { 343 public boolean canUpdate() { 344 JButton updateOption = new JButton (NbBundle.getMessage(UpdateHelper.class, "CTL_UpdateOption")); 345 updateOption.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(UpdateHelper.class, "AD_UpdateOption")); 346 return DialogDisplayer.getDefault().notify( 347 new NotifyDescriptor (NbBundle.getMessage(UpdateHelper.class,"TXT_ProjectUpdate", BUILD_NUMBER), 348 NbBundle.getMessage(UpdateHelper.class,"TXT_ProjectUpdateTitle"), 349 NotifyDescriptor.DEFAULT_OPTION, 350 NotifyDescriptor.WARNING_MESSAGE, 351 new Object [] { 352 updateOption, 353 NotifyDescriptor.CANCEL_OPTION 354 }, 355 updateOption)) == updateOption; 356 } 357 }; 358 } 359 360 364 public static interface Notifier { 365 369 public boolean canUpdate (); 370 } 371 } 372 | Popular Tags |