KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > web > project > UpdateHelper


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.web.project;
21
22 import java.io.IOException JavaDoc;
23 import java.net.URL JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.List JavaDoc;
27 import javax.swing.JButton JavaDoc;
28 import org.netbeans.api.project.libraries.LibraryManager;
29 import org.netbeans.modules.web.project.api.WebProjectUtilities;
30 import org.netbeans.modules.web.project.classpath.ClassPathSupport;
31 import org.netbeans.modules.web.project.ui.customizer.WebProjectProperties;
32 import org.netbeans.spi.project.support.ant.ReferenceHelper;
33 import org.openide.filesystems.FileObject;
34 import org.openide.filesystems.FileUtil;
35 import org.openide.filesystems.Repository;
36 import org.w3c.dom.Comment JavaDoc;
37 import org.w3c.dom.Document JavaDoc;
38 import org.w3c.dom.Element JavaDoc;
39 import org.w3c.dom.NamedNodeMap JavaDoc;
40 import org.w3c.dom.Node JavaDoc;
41 import org.w3c.dom.NodeList JavaDoc;
42 import org.w3c.dom.Text JavaDoc;
43 import org.openide.DialogDisplayer;
44 import org.openide.ErrorManager;
45 import org.openide.NotifyDescriptor;
46 import org.openide.util.NbBundle;
47 import org.openide.util.Mutex;
48 import org.netbeans.api.project.Project;
49 import org.netbeans.api.project.ProjectManager;
50 import org.netbeans.spi.project.AuxiliaryConfiguration;
51 import org.netbeans.spi.project.support.ant.AntProjectHelper;
52 import org.netbeans.spi.project.support.ant.EditableProperties;
53
54
55 /**
56  * Proxy for the AntProjectHelper which defers the update of the project metadata
57  * to explicit user action. Currently it is hard coded for update from
58  * "http://www.netbeans.org/ns/web-project/1" to "http://www.netbeans.org/ns/web-project/2".
59  * In future it should define plugable SPI.
60  */

61 public class UpdateHelper {
62
63     private static final boolean TRANSPARENT_UPDATE = Boolean.getBoolean("webproject.transparentUpdate"); //NOI18N
64
private static final String JavaDoc BUILD_NUMBER = System.getProperty("netbeans.buildnumber"); // NOI18N
65

66     private final Project project;
67     private final AntProjectHelper helper;
68     private final AuxiliaryConfiguration cfg;
69     private final Notifier notifier;
70     private boolean alreadyAskedInWriteAccess;
71     private Boolean JavaDoc isCurrent;
72     private EditableProperties cachedProperties;
73     private Element JavaDoc cachedElement;
74     private static final String JavaDoc TAG_MINIMUM_ANT_VERSION = "minimum-ant-version"; // NOI18N
75
private static final String JavaDoc TAG_FILE = "file"; //NOI18N
76
private static final String JavaDoc TAG_LIBRARY = "library"; //NOI18N
77
private static final String JavaDoc ATTR_FILES = "files"; //NOI18N
78
private static final String JavaDoc ATTR_DIRS = "dirs"; //NOI18N
79

80     /**
81      * Creates new UpdateHelper
82      * @param project
83      * @param helper AntProjectHelper
84      * @param cfg AuxiliaryConfiguration
85      * @param notifier used to ask user about project update
86      */

87     UpdateHelper (Project project, AntProjectHelper helper, AuxiliaryConfiguration cfg, Notifier notifier) {
88         assert project != null && helper != null && cfg != null && notifier != null;
89         this.project = project;
90         this.helper = helper;
91         this.cfg = cfg;
92         this.notifier = notifier;
93     }
94    
95     /**
96      * Returns the AntProjectHelper.getProperties(), {@link AntProjectHelper#getProperties(String)}
97      * @param path a relative URI in the project directory.
98      * @return a set of properties
99      */

100     public EditableProperties getProperties (final String JavaDoc path) {
101         //Properties are the same in both webproject/1 and webproject/2
102
return (EditableProperties) ProjectManager.mutex().readAccess(new Mutex.Action (){
103             public Object JavaDoc run() {
104                 if (!isCurrent() && AntProjectHelper.PROJECT_PROPERTIES_PATH.equals(path)) { //Only project properties were changed
105
return getUpdatedProjectProperties ();
106                 }
107                 else {
108                     return helper.getProperties(path);
109                 }
110             }
111         });
112     }
113
114     /**
115      * In the case that the project is of current version or the properties are not {@link AntProjectHelper#PROJECT_PROPERTIES_PATH}
116      * it calls AntProjectHelper.putProperties(), {@link AntProjectHelper#putProperties(String, EditableProperties)}
117      * otherwise it asks user to updata project. If the user agrees with the project update, it does the update and calls
118      * AntProjectHelper.putProperties().
119      * @param path a relative URI in the project directory.
120      * @param props a set of properties
121      */

122     public void putProperties (final String JavaDoc path, final EditableProperties props) {
123         ProjectManager.mutex().writeAccess(
124             new Runnable JavaDoc () {
125                 public void run() {
126                     if (isCurrent() || !AntProjectHelper.PROJECT_PROPERTIES_PATH.equals(path)) { //Only project props should cause update
127
helper.putProperties(path,props);
128                     }
129                     else if (canUpdate()) {
130                         try {
131                             saveUpdate (props);
132                             helper.putProperties(path,props);
133                         } catch (IOException JavaDoc ioe) {
134                             ErrorManager.getDefault().notify (ioe);
135                         }
136                     }
137                 }
138             });
139     }
140
141     /**
142      * In the case that the project is of current version or shared is false it delegates to
143      * AntProjectHelper.getPrimaryConfigurationData(), {@link AntProjectHelper#getPrimaryConfigurationData(boolean)}.
144      * Otherwise it creates an in memory update of shared configuration data and returns it.
145      * @param shared if true, refers to <code>project.xml</code>, else refers to
146      * <code>private.xml</code>
147      * @return the configuration data that is available
148      */

149     public Element JavaDoc getPrimaryConfigurationData (final boolean shared) {
150         return (Element JavaDoc) ProjectManager.mutex().readAccess(new Mutex.Action (){
151             public Object JavaDoc run() {
152                 if (!shared || isCurrent()) { //Only shared props should cause update
153
return helper.getPrimaryConfigurationData(shared);
154                 }
155                 else {
156                     return getUpdatedSharedConfigurationData ();
157                 }
158             }
159         });
160     }
161
162     /**
163      * In the case that the project is of current version or shared is false it calls AntProjectHelper.putPrimaryConfigurationData(),
164      * {@link AntProjectHelper#putPrimaryConfigurationData(Element, boolean)}.
165      * Otherwise it asks user to update the project. If the user agrees with the project update, it does the update and calls
166      * AntProjectHelper.PrimaryConfigurationData().
167      * @param element the configuration data
168      * @param shared if true, refers to <code>project.xml</code>, else refers to
169      * <code>private.xml</code>
170      */

171     public void putPrimaryConfigurationData (final Element JavaDoc element, final boolean shared) {
172         ProjectManager.mutex().writeAccess(new Runnable JavaDoc () {
173             public void run () {
174                 if (!shared || isCurrent()) {
175                     helper.putPrimaryConfigurationData(element, shared);
176                 } else if (canUpdate()) {
177                     try {
178                         saveUpdate (null);
179                         helper.putPrimaryConfigurationData(element, shared);
180                     } catch (IOException JavaDoc ioe) {
181                         ErrorManager.getDefault().notify(ioe);
182                     }
183                 }
184             }
185         });
186     }
187
188     /**
189      * Returns an AntProjectHelper. The helper may not be used for accessing/storing project metadata.
190      * For project metadata manipulation the UpdateHelper must be used.
191      * @return AntProjectHelper
192      */

193     public AntProjectHelper getAntProjectHelper () {
194         return this.helper;
195     }
196
197     /**
198      * Request an saving of update. If the project is not of current version the user will be asked to update the project.
199      * If the user agrees with an update the project is updated.
200      * @return true if the metadata are of current version or updated
201      */

202     public boolean requestSave () throws IOException JavaDoc{
203         if (isCurrent()) {
204             return true;
205         }
206         if (!canUpdate()) {
207             return false;
208         }
209         saveUpdate (null);
210         return true;
211     }
212     
213     /**
214      * Returns true if the project is of current version.
215      * @return true if the project is of current version, otherwise false.
216      */

217     public synchronized boolean isCurrent () {
218         if (this.isCurrent == null) {
219             this.isCurrent = this.cfg.getConfigurationFragment("data","http://www.netbeans.org/ns/web-project/1",true) == null //NOI18N
220
&& this.cfg.getConfigurationFragment("data","http://www.netbeans.org/ns/web-project/2",true) == null? //NOI18N
221
Boolean.TRUE : Boolean.FALSE;
222         }
223         return isCurrent.booleanValue();
224     }
225
226     private boolean canUpdate () {
227         if (TRANSPARENT_UPDATE) {
228             return true;
229         }
230         //Ask just once under a single write access
231
if (alreadyAskedInWriteAccess) {
232             return false;
233         }
234         else {
235             boolean canUpdate = this.notifier.canUpdate();
236             if (!canUpdate) {
237                 alreadyAskedInWriteAccess = true;
238                 ProjectManager.mutex().postReadRequest(new Runnable JavaDoc() {
239                     public void run() {
240                         alreadyAskedInWriteAccess = false;
241                     }
242                 });
243             }
244             return canUpdate;
245         }
246     }
247
248     private void saveUpdate (EditableProperties props) throws IOException JavaDoc {
249         this.helper.putPrimaryConfigurationData(getUpdatedSharedConfigurationData(),true);
250         if (this.cfg.getConfigurationFragment("data","http://www.netbeans.org/ns/web-project/1",true) != null) { //NOI18N
251
this.cfg.removeConfigurationFragment("data","http://www.netbeans.org/ns/web-project/1",true); //NOI18N
252
} else {
253             this.cfg.removeConfigurationFragment("data","http://www.netbeans.org/ns/web-project/2",true); //NOI18N
254
}
255         
256         boolean putProps = false;
257         
258         // AB: fix for #55597: should not update the project without adding the properties
259
// update is only done once, so if we don't add the properties now, we don't get another chance to do so
260
if (props == null) {
261             props = getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
262             putProps = true;
263         }
264
265         //add properties needed by 4.1 project
266
if(props != null) {
267             props.put("test.src.dir", "test"); //NOI18N
268
props.put("build.test.classes.dir", "${build.dir}/test/classes"); //NOI18N
269
props.put("build.test.results.dir", "${build.dir}/test/results"); //NOI18N
270
props.put("conf.dir","${source.root}/conf"); //NOI18N
271
props.put("jspcompilation.classpath", "${jspc.classpath}:${javac.classpath}");
272             
273             props.setProperty(WebProjectProperties.JAVAC_TEST_CLASSPATH, new String JavaDoc[] {
274                 "${javac.classpath}:", // NOI18N
275
"${build.classes.dir}:", // NOI18N
276
"${libs.junit.classpath}", // NOI18N
277
});
278             props.setProperty(WebProjectProperties.RUN_TEST_CLASSPATH, new String JavaDoc[] {
279                 "${javac.test.classpath}:", // NOI18N
280
"${build.test.classes.dir}", // NOI18N
281
});
282             props.setProperty(WebProjectProperties.DEBUG_TEST_CLASSPATH, new String JavaDoc[] {
283                 "${run.test.classpath}", // NOI18N
284
});
285             
286             props.put(WebProjectProperties.BUILD_EAR_CLASSES_DIR, "${build.ear.web.dir}/WEB-INF/classes");
287             props.put(WebProjectProperties.BUILD_EAR_WEB_DIR, "${build.dir}/ear-module");
288             props.put(WebProjectProperties.WAR_EAR_NAME, props.getProperty(WebProjectProperties.WAR_NAME));
289             props.put(WebProjectProperties.DIST_WAR_EAR, "${dist.dir}/${war.ear.name}");
290             
291             if (props.getProperty(WebProjectProperties.LIBRARIES_DIR) == null) {
292                 props.setProperty(WebProjectProperties.LIBRARIES_DIR, "${" + WebProjectProperties.WEB_DOCBASE_DIR + "}/WEB-INF/lib"); //NOI18N
293
}
294         }
295         
296         if(props != null) {
297             //remove jsp20 and servlet24 libraries
298
ReferenceHelper refHelper = new ReferenceHelper(helper, cfg, helper.getStandardPropertyEvaluator());
299             ClassPathSupport cs = new ClassPathSupport( helper.getStandardPropertyEvaluator(), refHelper, helper,
300                                         WebProjectProperties.WELL_KNOWN_PATHS,
301                                         WebProjectProperties.LIBRARY_PREFIX,
302                                         WebProjectProperties.LIBRARY_SUFFIX,
303                                         WebProjectProperties.ANT_ARTIFACT_PREFIX );
304             Iterator JavaDoc items = cs.itemsIterator((String JavaDoc)props.get( WebProjectProperties.JAVAC_CLASSPATH ), ClassPathSupport.TAG_WEB_MODULE_LIBRARIES);
305             ArrayList JavaDoc cpItems = new ArrayList JavaDoc();
306             while(items.hasNext()) {
307                 ClassPathSupport.Item cpti = (ClassPathSupport.Item)items.next();
308                 String JavaDoc propertyName = cpti.getReference();
309                 if(propertyName != null) {
310                     String JavaDoc libname = propertyName.substring("${libs.".length());
311                     if(libname.indexOf(".classpath}") != -1) libname = libname.substring(0, libname.indexOf(".classpath}"));
312                     
313                     if(!("servlet24".equals(libname) || "jsp20".equals(libname))) { //NOI18N
314
cpItems.add(cpti);
315                     }
316                 }
317             }
318             String JavaDoc[] javac_cp = cs.encodeToStrings(cpItems.iterator(), ClassPathSupport.TAG_WEB_MODULE_LIBRARIES );
319             props.setProperty( WebProjectProperties.JAVAC_CLASSPATH, javac_cp );
320         }
321         
322         if (putProps) {
323             helper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, props);
324         }
325
326         ProjectManager.getDefault().saveProject (this.project);
327         synchronized(this) {
328             this.isCurrent = Boolean.TRUE;
329         }
330         
331         //fire project updated
332
if(projectUpdateListener != null) projectUpdateListener.projectUpdated();
333         
334         //create conf dir if doesn't exist and copy default manifest inside
335
try {
336             //I cannot use ${conf.dir} since the PE doesn't know about it
337
//String confDir = helper.getStandardPropertyEvaluator().evaluate("${source.root}/conf"); //NOI18N
338
FileObject prjFO = project.getProjectDirectory();
339             // folder creation will throw IOE if already exists
340
// use the hard coded string due to issue #54882 - since the 4.0 supports creation of only jakarta structure projects the conf dir is always in project root
341
FileObject confDirFO = prjFO.createFolder("conf");//NOI18N
342
// copyfile will throw IOE if the file already exists
343
FileUtil.copyFile(Repository.getDefault().getDefaultFileSystem().findResource("org-netbeans-modules-web-project/MANIFEST.MF"), confDirFO, "MANIFEST"); //NOI18N
344
}catch(IOException JavaDoc e) {
345             //just ignore
346
}
347             
348     }
349
350     private synchronized Element JavaDoc getUpdatedSharedConfigurationData () {
351         if (cachedElement == null) {
352             int version = 1;
353             Element JavaDoc oldRoot = this.cfg.getConfigurationFragment("data","http://www.netbeans.org/ns/web-project/1",true); //NOI18N
354
if (oldRoot == null) {
355                 version = 2;
356                 oldRoot = this.cfg.getConfigurationFragment("data","http://www.netbeans.org/ns/web-project/2",true); //NOI18N
357
}
358             final String JavaDoc ns = version == 1 ? "http://www.netbeans.org/ns/web-project/1" : "http://www.netbeans.org/ns/web-project/2"; //NOI18N
359
if (oldRoot != null) {
360                 Document JavaDoc doc = oldRoot.getOwnerDocument();
361                 Element JavaDoc newRoot = doc.createElementNS (WebProjectType.PROJECT_CONFIGURATION_NAMESPACE,"data"); //NOI18N
362
copyDocument (doc, oldRoot, newRoot);
363                 if (version == 1) {
364                     //1->2 upgrade
365
Element JavaDoc sourceRoots = doc.createElementNS(WebProjectType.PROJECT_CONFIGURATION_NAMESPACE,"source-roots"); //NOI18N
366
Element JavaDoc root = doc.createElementNS (WebProjectType.PROJECT_CONFIGURATION_NAMESPACE,"root"); //NOI18N
367
root.setAttribute ("id","src.dir"); //NOI18N
368
sourceRoots.appendChild(root);
369                     newRoot.appendChild (sourceRoots);
370                     Element JavaDoc testRoots = doc.createElementNS(WebProjectType.PROJECT_CONFIGURATION_NAMESPACE,"test-roots"); //NOI18N
371
root = doc.createElementNS (WebProjectType.PROJECT_CONFIGURATION_NAMESPACE,"root"); //NOI18N
372
root.setAttribute ("id","test.src.dir"); //NOI18N
373
testRoots.appendChild (root);
374                     newRoot.appendChild (testRoots);
375                 }
376                 if (version == 1 || version == 2) {
377                     //2->3 upgrade
378
NodeList JavaDoc libList = newRoot.getElementsByTagNameNS(ns, TAG_LIBRARY);
379                     for (int i = 0; i < libList.getLength(); i++) {
380                         if (libList.item(i).getNodeType() == Node.ELEMENT_NODE) {
381                             Element JavaDoc library = (Element JavaDoc) libList.item(i);
382                             Node JavaDoc webFile = library.getElementsByTagNameNS(ns, TAG_FILE).item(0);
383                             //remove ${ and } from the beginning and end
384
String JavaDoc webFileText = findText(webFile);
385                             webFileText = webFileText.substring(2, webFileText.length() - 1);
386 // warIncludesMap.put(webFileText, pathInWarElements.getLength() > 0 ? findText((Element) pathInWarElements.item(0)) : Item.PATH_IN_WAR_NONE);
387
if (webFileText.startsWith ("lib.")) {
388                                 String JavaDoc libName = webFileText.substring(6, webFileText.indexOf(".classpath")); //NOI18N
389
List JavaDoc/*<URL>*/ roots = LibraryManager.getDefault().getLibrary(libName).getContent("classpath"); //NOI18N
390
ArrayList JavaDoc files = new ArrayList JavaDoc ();
391                                 ArrayList JavaDoc dirs = new ArrayList JavaDoc ();
392                                 for (Iterator JavaDoc it = roots.iterator(); it.hasNext();) {
393                                     URL JavaDoc rootUrl = (URL JavaDoc) it.next();
394                                     FileObject root = org.openide.filesystems.URLMapper.findFileObject (rootUrl);
395                                     if ("jar".equals(rootUrl.getProtocol())) { //NOI18N
396
root = FileUtil.getArchiveFile (root);
397                                     }
398                                     if (root != null) {
399                                         if (root.isData()) {
400                                             files.add(root);
401                                         } else {
402                                             dirs.add(root);
403                                         }
404                                     }
405                                 }
406                                 if (files.size() > 0) {
407                                     library.setAttribute(ATTR_FILES, "" + files.size());
408                                 }
409                                 if (dirs.size() > 0) {
410                                     library.setAttribute(ATTR_DIRS, "" + dirs.size());
411                                 }
412                             }
413                         }
414                     }
415                 }
416                 cachedElement = updateMinAntVersion(newRoot, doc);
417             }
418         }
419         return cachedElement;
420     }
421
422     private synchronized EditableProperties getUpdatedProjectProperties () {
423         if (cachedProperties == null) {
424             cachedProperties = this.helper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
425             //The javadoc.additionalparam was not in NB 4.0
426
if (cachedProperties.get (WebProjectProperties.JAVADOC_ADDITIONALPARAM)==null) {
427                 cachedProperties.put (WebProjectProperties.JAVADOC_ADDITIONALPARAM,""); //NOI18N
428
}
429         }
430         return this.cachedProperties;
431     }
432     
433     private static void copyDocument (Document JavaDoc doc, Element JavaDoc from, Element JavaDoc to) {
434         NodeList JavaDoc nl = from.getChildNodes();
435         int length = nl.getLength();
436         for (int i=0; i< length; i++) {
437             Node JavaDoc node = nl.item (i);
438             Node JavaDoc newNode = null;
439             switch (node.getNodeType()) {
440                 case Node.ELEMENT_NODE:
441                     Element JavaDoc oldElement = (Element JavaDoc) node;
442                     newNode = doc.createElementNS(WebProjectType.PROJECT_CONFIGURATION_NAMESPACE,oldElement.getTagName());
443                     NamedNodeMap JavaDoc m = oldElement.getAttributes();
444                     Element JavaDoc newElement = (Element JavaDoc) newNode;
445                     for (int index = 0; index < m.getLength(); index++) {
446                         Node JavaDoc attr = m.item(index);
447                         newElement.setAttribute(attr.getNodeName(), attr.getNodeValue());
448                     }
449                     copyDocument(doc,oldElement,(Element JavaDoc)newNode);
450                     break;
451                 case Node.TEXT_NODE:
452                     Text JavaDoc oldText = (Text JavaDoc) node;
453                     newNode = doc.createTextNode(oldText.getData());
454                     break;
455                 case Node.COMMENT_NODE:
456                     Comment JavaDoc oldComment = (Comment JavaDoc) node;
457                     newNode = doc.createComment(oldComment.getData());
458                     break;
459             }
460             if (newNode != null) {
461                 to.appendChild (newNode);
462             }
463         }
464     }
465     
466     private static Element JavaDoc updateMinAntVersion (final Element JavaDoc root, final Document JavaDoc doc) {
467         NodeList JavaDoc list = root.getElementsByTagNameNS (WebProjectType.PROJECT_CONFIGURATION_NAMESPACE,TAG_MINIMUM_ANT_VERSION);
468         if (list.getLength() == 1) {
469             Element JavaDoc me = (Element JavaDoc) list.item(0);
470             list = me.getChildNodes();
471             if (list.getLength() == 1) {
472                 me.replaceChild (doc.createTextNode(WebProjectUtilities.MINIMUM_ANT_VERSION), list.item(0));
473                 return root;
474             }
475         }
476         assert false : "Invalid project file"; //NOI18N
477
return root;
478     }
479
480     /**
481      * Creates an default Notifier. The default notifier displays a dialog warning user about project update.
482      * @return notifier
483      */

484     public static Notifier createDefaultNotifier () {
485         return new Notifier() {
486             public boolean canUpdate() {
487                 JButton JavaDoc updateOption = new JButton JavaDoc (NbBundle.getMessage(UpdateHelper.class, "CTL_UpdateOption"));
488                 return DialogDisplayer.getDefault().notify(
489                     new NotifyDescriptor (NbBundle.getMessage(UpdateHelper.class,"TXT_ProjectUpdate", BUILD_NUMBER),
490                         NbBundle.getMessage(UpdateHelper.class,"TXT_ProjectUpdateTitle"),
491                         NotifyDescriptor.DEFAULT_OPTION,
492                         NotifyDescriptor.WARNING_MESSAGE,
493                         new Object JavaDoc[] {
494                             updateOption,
495                             NotifyDescriptor.CANCEL_OPTION
496                         },
497                         updateOption)) == updateOption;
498             }
499         };
500     }
501
502     /**
503      * Extract nested text from a node.
504      * Currently does not handle coalescing text nodes, CDATA sections, etc.
505      * @param parent a parent node
506      * @return the nested text, or null if none was found
507      */

508     private static String JavaDoc findText(Node JavaDoc parent) {
509         NodeList JavaDoc l = parent.getChildNodes();
510         for (int i = 0; i < l.getLength(); i++) {
511             if (l.item(i).getNodeType() == Node.TEXT_NODE) {
512                 Text JavaDoc text = (Text JavaDoc)l.item(i);
513                 return text.getNodeValue();
514             }
515         }
516         return null;
517     }
518
519     /**
520      * Interface used by the UpdateHelper to ask user about
521      * the project update.
522      */

523     public static interface Notifier {
524         /**
525          * Asks user to update the project
526          * @return true if the project should be updated
527          */

528         public boolean canUpdate ();
529     }
530     
531     private ProjectUpdateListener projectUpdateListener = null;
532     
533     public void setProjectUpdateListener(ProjectUpdateListener l) {
534         this.projectUpdateListener = l;
535     }
536     
537     /** Used to notify someone that the project needs to be updated.
538      * A workaround for #54077 - Import 4.0 project - remove Servlet/JSP APIs */

539     public static interface ProjectUpdateListener {
540         public void projectUpdated();
541     }
542     
543 }
544
Popular Tags