1 19 20 package org.netbeans.modules.j2ee.ejbjarproject; 21 22 import java.io.IOException ; 23 import java.net.URL ; 24 import java.util.ArrayList ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import org.netbeans.modules.j2ee.ejbjarproject.api.EjbJarProjectGenerator; 28 import org.netbeans.modules.websvc.api.jaxws.project.GeneratedFilesHelper; 29 import org.w3c.dom.Comment ; 30 import org.w3c.dom.Document ; 31 import org.w3c.dom.Element ; 32 import org.w3c.dom.NamedNodeMap ; 33 import org.w3c.dom.Node ; 34 import org.w3c.dom.NodeList ; 35 import org.w3c.dom.Text ; 36 import org.openide.DialogDisplayer; 37 import org.openide.ErrorManager; 38 import org.openide.NotifyDescriptor; 39 import org.openide.util.NbBundle; 40 import org.openide.util.Mutex; 41 import org.netbeans.api.project.Project; 42 import org.netbeans.api.project.ProjectManager; 43 import org.netbeans.api.project.libraries.LibraryManager; 44 import org.netbeans.spi.project.AuxiliaryConfiguration; 45 import org.netbeans.spi.project.support.ant.AntProjectHelper; 46 import org.netbeans.spi.project.support.ant.EditableProperties; 47 import org.openide.filesystems.FileObject; 48 import org.openide.filesystems.FileUtil; 49 50 51 57 public class UpdateHelper { 58 59 private final Project project; 60 private final AntProjectHelper 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 private static final String BUILD_NUMBER = System.getProperty("netbeans.buildnumber"); private static final String INCLUDED_LIBRARY_ELEMENT = "included-library"; private static final String MINIMUM_ANT_VERSION_ELEMENT = "minimum-ant-version"; private static final String ATTR_FILES = "files"; private static final String ATTR_DIRS = "dirs"; 74 82 UpdateHelper (Project project, AntProjectHelper helper, AuxiliaryConfiguration cfg, GeneratedFilesHelper genFileHelper, Notifier notifier) { 83 assert project != null && helper != null && cfg != null && genFileHelper != null && notifier != null; 84 this.project = project; 85 this.helper = helper; 86 this.cfg = cfg; 87 this.genFileHelper = genFileHelper; 88 this.notifier = notifier; 89 } 90 91 96 public EditableProperties getProperties (String path) { 97 return this.helper.getProperties(path); 99 } 100 101 109 public void putProperties (final String path, final EditableProperties props) { 110 ProjectManager.mutex().writeAccess( 111 new Runnable () { 112 public void run() { 113 if (isCurrent() || !AntProjectHelper.PROJECT_PROPERTIES_PATH.equals(path)) { helper.putProperties(path,props); 115 } 116 else if (canUpdate()) { 117 try { 118 saveUpdate (props); 119 helper.putProperties(path,props); 120 } catch (IOException ioe) { 121 ErrorManager.getDefault().notify (ioe); 122 } 123 } 124 } 125 }); 126 } 127 128 136 public Element getPrimaryConfigurationData (final boolean shared) { 137 return (Element ) ProjectManager.mutex().readAccess(new Mutex.Action (){ 138 public Object run() { 139 if (!shared || isCurrent()) { return helper.getPrimaryConfigurationData(shared); 141 } 142 else { 143 return getUpdatedSharedConfigurationData (); 144 } 145 } 146 }); 147 } 148 149 158 public void putPrimaryConfigurationData (final Element element, final boolean shared) { 159 ProjectManager.mutex().writeAccess(new Runnable () { 160 public void run () { 161 if (!shared || isCurrent()) { 162 helper.putPrimaryConfigurationData(element, shared); 163 } else if (canUpdate()) { 164 try { 165 saveUpdate (null); 166 helper.putPrimaryConfigurationData(element, shared); 167 } catch (IOException ioe) { 168 ErrorManager.getDefault().notify(ioe); 169 } 170 } 171 } 172 }); 173 } 174 175 180 public AntProjectHelper getAntProjectHelper () { 181 return this.helper; 182 } 183 184 188 public boolean requestSave () throws IOException { 189 if (isCurrent()) { 190 return true; 191 } 192 if (!canUpdate()) { 193 return false; 194 } 195 saveUpdate (null); 196 return true; 197 } 198 199 203 public synchronized boolean isCurrent () { 204 if (this.isCurrent == null) { 205 this.isCurrent = this.cfg.getConfigurationFragment("data","http://www.netbeans.org/ns/j2ee-ejbjarproject/1",true) == null 206 && this.cfg.getConfigurationFragment("data","http://www.netbeans.org/ns/j2ee-ejbjarproject/2",true) == null? Boolean.TRUE : Boolean.FALSE; 208 } 209 return isCurrent.booleanValue(); 210 } 211 212 private boolean canUpdate () { 213 if (alreadyAskedInWriteAccess) { 215 return false; 216 } 217 else { 218 boolean canUpdate = this.notifier.canUpdate(); 219 if (!canUpdate) { 220 alreadyAskedInWriteAccess = true; 221 ProjectManager.mutex().postReadRequest(new Runnable () { 222 public void run() { 223 alreadyAskedInWriteAccess = false; 224 } 225 }); 226 } 227 return canUpdate; 228 } 229 } 230 231 private void saveUpdate (EditableProperties props) throws IOException { 232 this.helper.putPrimaryConfigurationData(getUpdatedSharedConfigurationData(),true); 233 if (this.cfg.getConfigurationFragment("data","http://www.netbeans.org/ns/j2ee-ejbjarproject/1",true) != null) { this.cfg.removeConfigurationFragment("data","http://www.netbeans.org/ns/j2ee-ejbjarproject/1",true); } else { 237 this.cfg.removeConfigurationFragment("data","http://www.netbeans.org/ns/j2ee-ejbjarproject/2",true); } 240 241 boolean putProps = false; 242 243 if (props == null) { 246 props = getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH); 247 putProps = true; 248 } 249 250 if(props != null) { 252 props.put("test.src.dir", "test"); } 254 255 if (putProps) { 256 helper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, props); 257 } 258 259 ProjectManager.getDefault().saveProject (this.project); 260 this.genFileHelper.refreshBuildScript(GeneratedFilesHelper.BUILD_IMPL_XML_PATH, UpdateHelper.class.getResource("resources/build-impl.xsl"), 261 ((EjbJarProject)project).findJaxWsFileObject(), 262 true); 263 synchronized(this) { 264 this.isCurrent = Boolean.TRUE; 265 } 266 } 267 268 private synchronized Element getUpdatedSharedConfigurationData () { 269 if (cachedElement == null) { 270 Element oldRoot = this.cfg.getConfigurationFragment("data","http://www.netbeans.org/ns/j2ee-ejbjarproject/1",true); 272 int version = 1; 273 if (oldRoot == null) { 274 version = 2; 275 oldRoot = this.cfg.getConfigurationFragment("data","http://www.netbeans.org/ns/j2ee-ejbjarproject/2",true); } 277 final String ns = version == 1 ? "http://www.netbeans.org/ns/j2ee-ejbjarproject/1" : "http://www.netbeans.org/ns/j2ee-ejbjarproject/2"; 279 if (oldRoot != null) { 280 Document doc = oldRoot.getOwnerDocument(); 281 Element newRoot = doc.createElementNS (EjbJarProjectType.PROJECT_CONFIGURATION_NAMESPACE,"data"); copyDocument (doc, oldRoot, newRoot); 283 if(version == 1) { 284 Element sourceRoots = doc.createElementNS(EjbJarProjectType.PROJECT_CONFIGURATION_NAMESPACE,"source-roots"); Element root = doc.createElementNS (EjbJarProjectType.PROJECT_CONFIGURATION_NAMESPACE,"root"); root.setAttribute ("id","src.dir"); sourceRoots.appendChild(root); 289 newRoot.appendChild (sourceRoots); 290 Element testRoots = doc.createElementNS(EjbJarProjectType.PROJECT_CONFIGURATION_NAMESPACE,"test-roots"); root = doc.createElementNS (EjbJarProjectType.PROJECT_CONFIGURATION_NAMESPACE,"root"); root.setAttribute ("id","test.src.dir"); testRoots.appendChild (root); 294 newRoot.appendChild (testRoots); 295 } 296 if(version == 1 || version == 2) { 297 NodeList libList = newRoot.getElementsByTagNameNS(ns, INCLUDED_LIBRARY_ELEMENT); 299 for (int i = 0; i < libList.getLength(); i++) { 300 if (libList.item(i).getNodeType() == Node.ELEMENT_NODE) { 301 Element library = (Element ) libList.item(i); 302 String fileText = findText(library); 303 if (fileText.startsWith ("libs.")) { 304 String libName = fileText.substring(6, fileText.indexOf(".classpath")); List roots = LibraryManager.getDefault().getLibrary(libName).getContent("classpath"); ArrayList files = new ArrayList (); 307 ArrayList dirs = new ArrayList (); 308 for (Iterator it = roots.iterator(); it.hasNext();) { 309 URL rootUrl = (URL ) it.next(); 310 FileObject root = org.openide.filesystems.URLMapper.findFileObject (rootUrl); 311 if ("jar".equals(rootUrl.getProtocol())) { root = FileUtil.getArchiveFile (root); 313 } 314 if (root != null) { 315 if (root.isData()) { 316 files.add(root); 317 } else { 318 dirs.add(root); 319 } 320 } 321 } 322 if (files.size() > 0) { 323 library.setAttribute(ATTR_FILES, "" + files.size()); 324 } 325 if (dirs.size() > 0) { 326 library.setAttribute(ATTR_DIRS, "" + dirs.size()); 327 } 328 } 329 } 330 } 331 } 332 333 cachedElement = updateMinAntVersion(newRoot, doc); 334 } 335 } 336 return cachedElement; 337 } 338 339 private static void copyDocument (Document doc, Element from, Element to) { 340 NodeList nl = from.getChildNodes(); 341 int length = nl.getLength(); 342 for (int i=0; i< length; i++) { 343 Node node = nl.item (i); 344 Node newNode = null; 345 switch (node.getNodeType()) { 346 case Node.ELEMENT_NODE: 347 Element oldElement = (Element ) node; 348 newNode = doc.createElementNS(EjbJarProjectType.PROJECT_CONFIGURATION_NAMESPACE,oldElement.getTagName()); 349 NamedNodeMap m = oldElement.getAttributes(); 351 Element newElement = (Element ) newNode; 352 for (int index = 0; index < m.getLength(); index++) { 353 Node attr = m.item(index); 354 newElement.setAttribute(attr.getNodeName(), attr.getNodeValue()); 355 } 356 copyDocument(doc,oldElement,(Element )newNode); 357 break; 358 case Node.TEXT_NODE: 359 Text oldText = (Text ) node; 360 newNode = doc.createTextNode(oldText.getData()); 361 break; 362 case Node.COMMENT_NODE: 363 Comment oldComment = (Comment ) node; 364 newNode = doc.createComment(oldComment.getData()); 365 break; 366 } 367 if (newNode != null) { 368 to.appendChild (newNode); 369 } 370 } 371 } 372 373 private static Element updateMinAntVersion (final Element root, final Document doc) { 374 NodeList list = root.getElementsByTagNameNS (EjbJarProjectType.PROJECT_CONFIGURATION_NAMESPACE,MINIMUM_ANT_VERSION_ELEMENT); 375 if (list.getLength() == 1) { 376 Element me = (Element ) list.item(0); 377 list = me.getChildNodes(); 378 if (list.getLength() == 1) { 379 me.replaceChild (doc.createTextNode(EjbJarProjectGenerator.MINIMUM_ANT_VERSION), list.item(0)); 380 return root; 381 } 382 } 383 assert false : "Invalid project file"; return root; 385 } 386 387 391 public static Notifier createDefaultNotifier () { 392 return new Notifier() { 393 public boolean canUpdate() { 394 return DialogDisplayer.getDefault().notify( 395 new NotifyDescriptor.Confirmation (NbBundle.getMessage(UpdateHelper.class,"TXT_ProjectUpdate",BUILD_NUMBER), 396 NbBundle.getMessage(UpdateHelper.class,"TXT_ProjectUpdateTitle"), 397 NotifyDescriptor.YES_NO_OPTION)) == NotifyDescriptor.YES_OPTION; 398 } 399 }; 400 } 401 402 408 private static String findText(Node parent) { 409 NodeList l = parent.getChildNodes(); 410 for (int i = 0; i < l.getLength(); i++) { 411 if (l.item(i).getNodeType() == Node.TEXT_NODE) { 412 Text text = (Text )l.item(i); 413 return text.getNodeValue(); 414 } 415 } 416 return null; 417 } 418 419 420 424 public static interface Notifier { 425 429 public boolean canUpdate (); 430 } 431 } 432 | Popular Tags |