1 19 package org.netbeans.modules.j2ee.ejbjarproject; 20 21 import java.beans.PropertyChangeEvent ; 22 import java.beans.PropertyChangeListener ; 23 import java.beans.PropertyChangeSupport ; 24 import java.io.File ; 25 import java.net.MalformedURLException ; 26 import java.net.URL ; 27 import java.net.URI ; 28 import java.util.Arrays ; 29 import java.util.ArrayList ; 30 import java.util.Collections ; 31 import java.util.Iterator ; 32 import java.util.List ; 33 import java.util.Map ; 34 import java.util.HashMap ; 35 import java.text.MessageFormat ; 36 import org.openide.ErrorManager; 37 import org.openide.filesystems.FileObject; 38 import org.openide.filesystems.FileUtil; 39 import org.openide.util.NbBundle; 40 import org.openide.util.WeakListeners; 41 import org.openide.util.Mutex; 42 import org.w3c.dom.Element ; 43 import org.w3c.dom.NodeList ; 44 import org.w3c.dom.Document ; 45 import org.netbeans.spi.project.support.ant.AntProjectHelper; 46 import org.netbeans.spi.project.support.ant.AntProjectEvent; 47 import org.netbeans.spi.project.support.ant.AntProjectListener; 48 import org.netbeans.spi.project.support.ant.EditableProperties; 49 import org.netbeans.spi.project.support.ant.PropertyEvaluator; 50 import org.netbeans.spi.project.support.ant.ReferenceHelper; 51 import org.netbeans.api.project.ProjectManager; 52 import org.netbeans.api.java.project.JavaProjectConstants; 53 54 59 public final class SourceRoots { 60 61 public static final String PROP_ROOT_PROPERTIES = "rootProperties"; public static final String PROP_ROOTS = "roots"; 64 public static final String DEFAULT_SOURCE_LABEL = NbBundle.getMessage(SourceRoots.class, "NAME_src.dir"); 65 public static final String DEFAULT_TEST_LABEL = NbBundle.getMessage(SourceRoots.class, "NAME_test.src.dir"); 66 67 private final UpdateHelper helper; 68 private final PropertyEvaluator evaluator; 69 private final ReferenceHelper refHelper; 70 private final String elementName; 71 private final String newRootNameTemplate; 72 private List sourceRootProperties; 73 private List sourceRootNames; 74 private List sourceRoots; 75 private List sourceRootURLs; 76 private final PropertyChangeSupport support; 77 private final ProjectMetadataListener listener; 78 private final boolean isTest; 79 private final File projectDir; 80 81 88 SourceRoots (UpdateHelper helper, PropertyEvaluator evaluator, ReferenceHelper refHelper, String elementName, boolean isTest, String newRootNameTemplate) { 89 assert helper != null && evaluator != null && refHelper != null && elementName != null && newRootNameTemplate != null; 90 this.helper = helper; 91 this.evaluator = evaluator; 92 this.refHelper = refHelper; 93 this.elementName = elementName; 94 this.isTest = isTest; 95 this.newRootNameTemplate = newRootNameTemplate; 96 this.projectDir = FileUtil.toFile(this.helper.getAntProjectHelper().getProjectDirectory()); 97 this.support = new PropertyChangeSupport (this); 98 this.listener = new ProjectMetadataListener(); 99 this.evaluator.addPropertyChangeListener (WeakListeners.propertyChange(this.listener,this.evaluator)); 100 this.helper.getAntProjectHelper().addAntProjectListener ((AntProjectListener)WeakListeners.create(AntProjectListener.class, this.listener,this.helper)); 101 } 102 103 104 110 public String [] getRootNames () { 111 return (String []) ProjectManager.mutex().readAccess(new Mutex.Action() { 112 public Object run() { 113 synchronized (SourceRoots.this) { 114 if (sourceRootNames == null) { 115 readProjectMetadata(); 116 } 117 } 118 return sourceRootNames.toArray (new String [sourceRootNames.size()]); 119 } 120 }); 121 } 122 123 127 public String [] getRootProperties () { 128 return (String []) ProjectManager.mutex().readAccess(new Mutex.Action() { 129 public Object run() { 130 synchronized (SourceRoots.this) { 131 if (sourceRootProperties == null) { 132 readProjectMetadata(); 133 } 134 } 135 return sourceRootProperties.toArray (new String [sourceRootProperties.size()]); 136 } 137 }); 138 } 139 140 144 public FileObject[] getRoots () { 145 return (FileObject[]) ProjectManager.mutex().readAccess(new Mutex.Action () { 146 public Object run () { 147 synchronized (this) { 148 if (sourceRoots == null) { 150 String [] srcProps = getRootProperties(); 151 List result = new ArrayList (); 152 for (int i = 0; i<srcProps.length; i++) { 153 String prop = evaluator.getProperty(srcProps[i]); 154 if (prop != null) { 155 FileObject f = helper.getAntProjectHelper().resolveFileObject(prop); 156 if (f == null) { 157 continue; 158 } 159 if (FileUtil.isArchiveFile(f)) { 160 f = FileUtil.getArchiveRoot(f); 161 } 162 result.add(f); 163 } 164 } 165 sourceRoots = Collections.unmodifiableList(result); 166 } 167 } 168 return sourceRoots.toArray(new FileObject[sourceRoots.size()]); 169 } 170 }); 171 } 172 173 177 public URL [] getRootURLs() { 178 return (URL []) ProjectManager.mutex().readAccess(new Mutex.Action () { 179 public Object run () { 180 synchronized (this) { 181 if (sourceRootURLs == null) { 183 String [] srcProps = getRootProperties(); 184 List result = new ArrayList (); 185 for (int i = 0; i<srcProps.length; i++) { 186 String prop = evaluator.getProperty(srcProps[i]); 187 if (prop != null) { 188 File f = helper.getAntProjectHelper().resolveFile(prop); 189 try { 190 result.add(EjbJarProjectUtil.getRootURL(f,null)); 191 } catch (MalformedURLException e) { 192 ErrorManager.getDefault().notify(e); 193 } 194 } 195 } 196 sourceRootURLs = Collections.unmodifiableList(result); 197 } 198 } 199 return sourceRootURLs.toArray(new URL [sourceRootURLs.size()]); 200 } 201 }); 202 } 203 204 208 public void addPropertyChangeListener (PropertyChangeListener listener) { 209 this.support.addPropertyChangeListener (listener); 210 } 211 212 216 public void removePropertyChangeListener (PropertyChangeListener listener) { 217 this.support.removePropertyChangeListener (listener); 218 } 219 220 221 226 public void putRoots (final URL [] roots, final String [] labels) { 227 ProjectManager.mutex().writeAccess( 228 new Mutex.Action () { 229 public Object run() { 230 String [] originalProps = getRootProperties(); 231 URL [] originalRoots = getRootURLs(); 232 Map oldRoots2props = new HashMap (); 233 for (int i=0; i<originalProps.length;i++) { 234 oldRoots2props.put (originalRoots[i],originalProps[i]); 235 } 236 Map newRoots2lab = new HashMap (); 237 for (int i=0; i<roots.length;i++) { 238 newRoots2lab.put (roots[i],labels[i]); 239 } 240 Element cfgEl = helper.getPrimaryConfigurationData(true); 241 NodeList nl = cfgEl.getElementsByTagNameNS(EjbJarProjectType.PROJECT_CONFIGURATION_NAMESPACE, elementName); 242 assert nl.getLength() == 1 : "Illegal project.xml"; Element ownerElement = (Element ) nl.item(0); 244 NodeList rootsNodes = ownerElement.getElementsByTagNameNS(EjbJarProjectType.PROJECT_CONFIGURATION_NAMESPACE, "root"); while (rootsNodes.getLength()>0) { 247 Element root = (Element ) rootsNodes.item(0); 248 ownerElement.removeChild(root); 249 } 250 List newRoots = Arrays.asList(roots); 252 Map propsToRemove = new HashMap (oldRoots2props); 253 propsToRemove.keySet().removeAll(newRoots); 254 EditableProperties props = helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH); 255 for (Iterator it = propsToRemove.values().iterator(); it.hasNext();) { 256 String propName = (String ) it.next (); 257 props.remove(propName); 258 } 259 helper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH,props); 260 Document doc = ownerElement.getOwnerDocument(); 262 oldRoots2props.keySet().retainAll(newRoots); 263 for (Iterator it = newRoots.iterator(); it.hasNext();) { 264 URL newRoot = (URL ) it.next (); 265 String rootName = (String ) oldRoots2props.get (newRoot); 266 if (rootName == null) { 267 props = helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH); 269 String [] names = newRoot.getPath().split("/"); rootName = MessageFormat.format(newRootNameTemplate,new Object []{names[names.length-1],""}); int rootIndex = 1; 272 while (props.containsKey(rootName)) { 273 rootIndex++; 274 rootName = MessageFormat.format(newRootNameTemplate,new Object []{names[names.length-1],new Integer (rootIndex)}); 275 } 276 File f = FileUtil.normalizeFile(new File (URI.create(newRoot.toExternalForm()))); 277 File projDir = FileUtil.toFile(helper.getAntProjectHelper().getProjectDirectory()); 278 String path = f.getAbsolutePath(); 279 String prjPath = projDir.getAbsolutePath()+File.separatorChar; 280 if (path.startsWith(prjPath)) { 281 path = path.substring(prjPath.length()); 282 } 283 else { 284 path = refHelper.createForeignFileReference(f, JavaProjectConstants.SOURCES_TYPE_JAVA); 285 props = helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH); 286 } 287 props.put(rootName,path); 288 helper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH,props); 289 } 290 Element newRootNode = doc.createElementNS(EjbJarProjectType.PROJECT_CONFIGURATION_NAMESPACE, "root"); newRootNode.setAttribute("id",rootName); String label = (String ) newRoots2lab.get (newRoot); 293 if (label != null && label.length()>0 && !label.equals (getRootDisplayName(null,rootName))) { newRootNode.setAttribute("name",label); } 296 ownerElement.appendChild (newRootNode); 297 } 298 helper.putPrimaryConfigurationData(cfgEl,true); 299 return null; 300 } 301 } 302 ); 303 } 304 305 311 public String getRootDisplayName (String rootName, String propName) { 312 if (rootName == null || rootName.length() ==0) { 313 if (isTest && "test.src.dir".equals(propName)) { rootName = DEFAULT_TEST_LABEL; 316 } 317 else if (!isTest && "src.dir".equals(propName)) { rootName = DEFAULT_SOURCE_LABEL; 319 } 320 else { 321 String propValue = evaluator.getProperty(propName); 324 File sourceRoot = propValue == null ? null : helper.getAntProjectHelper().resolveFile(propValue); 325 rootName = createInitialDisplayName(sourceRoot); 326 } 327 } 328 return rootName; 329 } 330 331 336 public String createInitialDisplayName (File sourceRoot) { 337 String rootName; 338 if (sourceRoot != null) { 339 String srPath = sourceRoot.getAbsolutePath(); 340 String pdPath = projectDir.getAbsolutePath() + File.separatorChar; 341 if (srPath.startsWith(pdPath)) { 342 rootName = srPath.substring(pdPath.length()); 343 } 344 else { 345 rootName = sourceRoot.getAbsolutePath(); 346 } 347 } 348 else { 349 rootName = isTest ? DEFAULT_TEST_LABEL : DEFAULT_SOURCE_LABEL; 350 } 351 return rootName; 352 } 353 354 private void resetCache (boolean isXMLChange, String propName) { 355 boolean fire = false; 356 synchronized (this) { 357 if (isXMLChange) { 359 this.sourceRootProperties = null; 360 this.sourceRootNames = null; 361 this.sourceRoots = null; 362 this.sourceRootURLs = null; 363 fire = true; 364 } else if (propName == null || (sourceRootProperties != null && sourceRootProperties.contains(propName))) { 365 this.sourceRoots = null; 366 this.sourceRootURLs = null; 367 fire = true; 368 } 369 } 370 if (fire) { 371 if (isXMLChange) { 372 this.support.firePropertyChange (PROP_ROOT_PROPERTIES,null,null); 373 } 374 this.support.firePropertyChange (PROP_ROOTS,null,null); 375 } 376 } 377 378 private void readProjectMetadata () { 379 Element cfgEl = helper.getPrimaryConfigurationData(true); 380 NodeList nl = cfgEl.getElementsByTagNameNS(EjbJarProjectType.PROJECT_CONFIGURATION_NAMESPACE, elementName); 381 assert nl.getLength() == 0 || nl.getLength() == 1 : "Illegal project.xml"; List rootProps = new ArrayList (); 383 List rootNames = new ArrayList (); 384 if (nl.getLength()==1) { 386 NodeList roots = ((Element )nl.item(0)).getElementsByTagNameNS(EjbJarProjectType.PROJECT_CONFIGURATION_NAMESPACE, "root"); for (int i=0; i<roots.getLength(); i++) { 388 Element root = (Element ) roots.item(i); 389 String value = root.getAttribute("id"); assert value.length() > 0 : "Illegal project.xml"; 391 rootProps.add(value); 392 value = root.getAttribute("name"); rootNames.add (value); 394 } 395 } 396 this.sourceRootProperties = Collections.unmodifiableList(rootProps); 397 this.sourceRootNames = Collections.unmodifiableList(rootNames); 398 } 399 400 private class ProjectMetadataListener implements PropertyChangeListener ,AntProjectListener { 401 402 public void propertyChange(PropertyChangeEvent evt) { 403 resetCache (false,evt.getPropertyName()); 404 } 405 406 public void configurationXmlChanged(AntProjectEvent ev) { 407 resetCache (true,null); 408 } 409 410 public void propertiesChanged(AntProjectEvent ev) { 411 } 413 } 414 415 public boolean isTest() { 416 return isTest; 417 } 418 } 419 | Popular Tags |