KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > j2ee > deployment > config > ModuleDeploymentSupport


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 /*
21
22 How to use this class to display ConfigBeans next to your deployment
23 descriptor fragments:
24
25 1. Create the basebean
26 2. Decide where you're going to potentially show sheets and customizers.
27 3. Implement ModuleSupportCallback (minimal implementation fine for now).
28 4. Create a ModuleDeploymentSupport instance.
29 5. Get the standardDDBean back from the MDS.
30 6. Query each of your plugins for their ConfigBeans.
31 7. Give the ConfigBeans back to your MDS.
32 8. When you want to show property sheets or components from the plugin,
33     call add{sheet,customizer}listener.
34 9. Receive the {Sheets,Customizers} and display them/remove them when
35     pertinent
36 10. When ModuleSupportCallback.beanModified() is called, activate the
37     save cookie on your DataObject.
38
39  */

40
41
42 package org.netbeans.modules.j2ee.deployment.config;
43
44 import javax.enterprise.deploy.spi.*;
45 import javax.enterprise.deploy.spi.exceptions.*;
46 import javax.enterprise.deploy.model.*;
47 import javax.enterprise.deploy.shared.*;
48 import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider;
49 import org.netbeans.modules.j2ee.deployment.plugins.api.*;
50 import org.netbeans.modules.j2ee.deployment.devmodules.api.J2eeModule;
51 import org.netbeans.modules.j2ee.deployment.impl.Server;
52 import org.netbeans.modules.schema2beans.*;
53 import org.openide.nodes.*;
54 import org.openide.*;
55 import org.openide.util.WeakListeners;
56
57 import java.util.*;
58
59 import java.beans.*;
60
61 public class ModuleDeploymentSupport implements PropertyChangeListener {
62
63     public static final String JavaDoc SEPARATOR = "/"; //NOI18N
64
public static final String JavaDoc WEBSERVICES_XML = "webservices.xml"; //NOI18N
65
private static Map filenameToPathMap = null;
66
67     private final DeployableObjectImpl obj;
68     private final Map rootMap = Collections.synchronizedMap(new HashMap(5)); // DD location string -> DDRoot
69
private final Map beanMap = Collections.synchronizedMap(new IdentityHashMap()); // BaseBean -> StandardDDImpl
70
private final Map leafMap = Collections.synchronizedMap(new IdentityHashMap()); // BaseProp -> StandardDDImpl
71
private final Set xpathListeners = Collections.synchronizedSet(new HashSet());
72     private final Map<DDRoot, PropertyChangeListener> propertyChangeListeners = Collections.synchronizedMap(new WeakHashMap());
73     private final J2eeModuleProvider provider;
74     private final boolean sendEvent;
75
76     private static Map moduleDDlocationMap = new HashMap(10);
77     static {
78         moduleDDlocationMap.put(J2eeModule.EAR, new String JavaDoc[] {
79             J2eeModule.APP_XML});
80         moduleDDlocationMap.put(J2eeModule.WAR, new String JavaDoc[] {
81             J2eeModule.WEB_XML,
82             J2eeModule.WEBSERVICES_XML});
83         moduleDDlocationMap.put(J2eeModule.EJB, new String JavaDoc[] {
84             J2eeModule.EJBJAR_XML,
85             J2eeModule.EJBSERVICES_XML});
86         moduleDDlocationMap.put(J2eeModule.CONN, new String JavaDoc[] {
87             J2eeModule.CONNECTOR_XML});
88         moduleDDlocationMap.put(J2eeModule.CLIENT, new String JavaDoc[] {
89             J2eeModule.CLIENT_XML});
90     }
91     
92     public static String JavaDoc[] getDDPaths(Object JavaDoc type) {
93         return (String JavaDoc[]) moduleDDlocationMap.get(type);
94     }
95     
96     public ModuleDeploymentSupport(J2eeModuleProvider provider, boolean sendEvent) {
97         this.provider = provider;
98         this.sendEvent = sendEvent;
99         obj = new DeployableObjectImpl(this);
100         String JavaDoc[] ddLocs = getDDPaths(provider.getJ2eeModule().getModuleType());
101         for(int i = 0; i < ddLocs.length; i++) {
102             createRoot(ddLocs[i]);
103         }
104     }
105
106     private ModuleType getModuleType() {
107         return (ModuleType) provider.getJ2eeModule().getModuleType();
108     }
109     
110     private BaseBean getDeploymentDescriptor(String JavaDoc ddLoc) {
111         return provider.getJ2eeModule().getDeploymentDescriptor(ddLoc);
112     }
113     
114     private DDRoot createRoot(String JavaDoc ddLoc) {
115         BaseBean bean = getDeploymentDescriptor(ddLoc);
116         if (bean == null) // no support for that descriptor
117
return null;
118         while(!bean.isRoot()) bean = bean.parent();
119         DDRoot root = new DDRoot(new DDNodeBean(null,bean,this));
120         rootMap.put(ddLoc,root);
121
122         beanMap.put(bean,root);
123         PropertyChangeListener weakListener = WeakListeners.propertyChange(this, root.proxy.bean);
124         propertyChangeListeners.put(root, weakListener);
125         root.proxy.bean.addPropertyChangeListener(weakListener);
126         return root;
127     }
128
129     public DeployableObjectImpl getDeployableObject() {
130         return obj;
131     }
132
133     // This is broken in jsr88 that I even have to supply this
134
public DDRoot getDDBeanRoot() {
135         String JavaDoc loc = ((String JavaDoc[]) moduleDDlocationMap.get(getModuleType()))[0];
136         return getDDBeanRoot(loc);
137     }
138
139     public DDRoot getDDBeanRoot(String JavaDoc loc) {
140         DDRoot root = (DDRoot) rootMap.get(loc);
141         
142         // primary DD should be ready when this is called
143
// so this updating is only for non-primary DD's
144
if (root == null && ! isPrimaryDD(loc, getType())) {
145             root = createRoot(loc);
146             DDRoot proot = getPrimaryDD();
147         }
148         return root;
149     }
150
151     public ModuleType getType() {
152         return getModuleType();
153     }
154
155     public String JavaDoc getVersion() {
156         return provider.getJ2eeModule().getModuleVersion();
157     }
158
159     /* PENDING get from CompilationUnit */
160     public Class JavaDoc getClassFromScope(String JavaDoc cls) {
161         return null; // provider.getClassFromScope(cls);
162
}
163
164     static public boolean isPrimaryDD(String JavaDoc ddLocation, Object JavaDoc type) {
165         String JavaDoc[] ddLocs = (String JavaDoc[]) moduleDDlocationMap.get(type);
166         if (ddLocs.length < 1)
167             return false;
168         return ddLocs[0].equals(ddLocation);
169     }
170     
171     static private Map filenameToPathMap() {
172         if (filenameToPathMap == null) {
173             filenameToPathMap = new HashMap();
174             
175             filenameToPathMap.put(filename(J2eeModule.APP_XML), J2eeModule.APP_XML);
176             filenameToPathMap.put(filename(J2eeModule.WEB_XML), J2eeModule.WEB_XML);
177             filenameToPathMap.put(filename(J2eeModule.EJBJAR_XML), J2eeModule.EJBJAR_XML);
178             filenameToPathMap.put(filename(J2eeModule.CONNECTOR_XML), J2eeModule.CONNECTOR_XML);
179             filenameToPathMap.put(filename(J2eeModule.CLIENT_XML), J2eeModule.CLIENT_XML);
180
181             filenameToPathMap.put(J2eeModule.APP_XML, J2eeModule.APP_XML);
182             filenameToPathMap.put(J2eeModule.WEB_XML, J2eeModule.WEB_XML);
183             filenameToPathMap.put(J2eeModule.EJBJAR_XML, J2eeModule.EJBJAR_XML);
184             filenameToPathMap.put(J2eeModule.CONNECTOR_XML, J2eeModule.CONNECTOR_XML);
185             filenameToPathMap.put(J2eeModule.CLIENT_XML, J2eeModule.CLIENT_XML);
186         }
187         return filenameToPathMap;
188     }
189
190     static private String JavaDoc filename(String JavaDoc path) {
191         int i = path.lastIndexOf(SEPARATOR);
192         return path.substring(i+1);
193     }
194     
195     static public String JavaDoc filenameToPath(String JavaDoc filename, Object JavaDoc type) {
196         if (filename.endsWith(WEBSERVICES_XML)) {
197             if (J2eeModule.EJB.equals(type)) {
198                 return J2eeModule.EJBSERVICES_XML;
199             } else {
200                 return J2eeModule.WEBSERVICES_XML;
201             }
202         }
203         String JavaDoc name = (String JavaDoc) filenameToPathMap().get(filename);
204         if (name == null)
205             name = filename;
206         return name;
207     }
208     
209     public DDRoot getPrimaryDD() {
210         ModuleType type = this.getType();
211         String JavaDoc[] ddLocs = (String JavaDoc[]) moduleDDlocationMap.get(type);
212         if (ddLocs.length < 1)
213             return null;
214         return (DDRoot) rootMap.get(ddLocs[0]);
215     }
216     
217     /* Called when the module/app is closed from the ide, clean up listeners and
218      * references */

219     public void cleanup() {
220         // stop listening to DD changes
221
DDRoot roots[];
222         synchronized (rootMap) {
223             roots = (DDRoot[]) rootMap.values().toArray(new DDRoot[rootMap.size()]);
224         }
225         for (DDRoot root: roots) {
226             PropertyChangeListener listener = propertyChangeListeners.get(root);
227             if (listener != null) {
228                 root.proxy.bean.removePropertyChangeListener(listener);
229             }
230         }
231     }
232
233 // /* Called when the module is removed from the app. */
234
// public void dispose(DeploymentConfiguration config) {
235
// for(Iterator it = configMap.entrySet().iterator(); it.hasNext(); ) {
236
// Map.Entry entry = (Map.Entry) it.next();
237
// DDRoot root = (DDRoot) entry.getKey();
238
// ConfigBeanStorage cbs = (ConfigBeanStorage) entry.getValue();
239
// root.proxy.bean.removePropertyChangeListener(weakListener);
240
// try {
241
// config.removeDConfigBean((DConfigBeanRoot)cbs.bean);
242
// } catch (BeanNotFoundException bnfe) {
243
// // IGNORE
244
// }
245
// }
246
// }
247

248     StandardDDImpl getBean(BaseBean bean) {
249         // System.out.println("Getting bean for " + bean);
250
// System.out.println(bean.fullName());
251
// System.out.println(bean.dtdName());
252
if (bean == null) return null;
253         StandardDDImpl ret = (StandardDDImpl) beanMap.get(bean);
254         
255         if (ret == null) {
256             /*
257             DDCommon base;
258             // System.out.println("Creating new bean");
259             BaseBean bb = bean;
260             while(!bb.isRoot()) {
261                 bb = bb.parent();
262                 if (bb== null) {
263                     // We are in an unattached tree, we have expressed no prior
264                     // interest in this Xpath so we just toss it.
265                     // See: addTemporaryBean in this object
266                     return null;
267                 }
268
269             }
270             if(bb == root.proxy.bean) base = new DDNodeBean(bean,this);
271             else { // must build proxy tree
272                 if (bean.isRoot()) {
273                     // PENDING This probably means that there is an error, can it legaly happen?
274                     throw new IllegalStateException("Found a bean rooted in a tree not previously registered with Module Deployment Support. Bean = : " + bean + "@" + Integer.toHexString(bean.hashCode())); //NO I18N
275                 }
276                 StandardDDImpl parent = getBean(bean.parent());
277                 base = new DDProxy(parent.proxy,bean,bean.dtdName(),this);
278             }
279              **/

280         if (bean.parent() != null) {
281                 ret = new StandardDDImpl(new DDNodeBean(bean,this));
282                 beanMap.put(bean,ret);
283             }
284         }
285         return ret;
286     }
287
288     // for indexed leaf properties
289
StandardDDImpl getBean(BaseProperty prop,int index) {
290
291         if(index < 0) return getBean(prop);
292
293         if (!leafMap.containsKey(prop)) {
294             leafMap.put(prop, new StandardDDImpl[index + 1]);
295         } else if (((StandardDDImpl[])leafMap.get(prop)).length <= index) {
296             StandardDDImpl[] a = (StandardDDImpl[])leafMap.get(prop);
297             StandardDDImpl[] b = new StandardDDImpl[index + 1];
298
299             leafMap.put(prop, b);
300             for (int i = 0; i < a.length; i++) {
301                 b[i] = a[i];
302             }
303         }
304
305         StandardDDImpl[] arr = (StandardDDImpl[])leafMap.get(prop);
306         StandardDDImpl elem = arr[index];
307
308         if (elem == null) {
309             elem = new StandardDDImpl(new DDLeafBean(prop, index, this));
310             arr[index] = elem;
311         }
312
313         return elem;
314      }
315
316     // for non-indexed leaf properties
317
StandardDDImpl getBean(BaseProperty prop) {
318        StandardDDImpl elem = (StandardDDImpl) leafMap.get(prop);
319        if(elem == null) {
320           elem = new StandardDDImpl(new DDLeafBean(prop, this));
321           leafMap.put(prop,elem);
322        }
323        return elem;
324     }
325
326     StandardDDImpl getBean(String JavaDoc name) {
327         return getBean(name,getDDBeanRoot().proxy.bean);
328     }
329
330     StandardDDImpl getBean(String JavaDoc name,BaseBean rootBean) {
331         Bean parent = GraphManager.getPropertyParent(rootBean, name);
332         if (parent == null) {
333             return getDDBeanRoot();
334         }
335         String JavaDoc shortName = GraphManager.getPropertyName(name);
336         int index = GraphManager.getPropertyIndex(rootBean, name);
337         // System.out.println(name);
338
// System.out.println(index);
339

340         BaseProperty prop = parent.getProperty(shortName);
341
342         if(index < 0 && prop.isIndexed()) index = 0;
343
344         StandardDDImpl ret;
345         if(prop.isBean()) {
346             if(prop.isIndexed())
347                 ret = getBean((BaseBean) parent.getValue(shortName,index));
348             else
349                 ret = getBean((BaseBean) parent.getValue(shortName));
350         }
351         else {
352             if(prop.isIndexed())
353                 ret = getBean(prop,index);
354             else
355                 ret = getBean(prop);
356         }
357         // System.out.println(ret.proxy.bean.fullName());
358
// System.out.println(((Object)ret.proxy.bean).toString());
359
return ret;
360     }
361
362     void addXpathListener(DDCommon bean, String JavaDoc xpath, XpathListener listen) {
363         if (sendEvent) {
364             xpathListeners.add(new XpathListenerStorage(bean,xpath,listen));
365         }
366     }
367
368     void removeXpathListener(DDCommon bean, String JavaDoc xpath, XpathListener listen) {
369         if (sendEvent) {
370             xpathListeners.remove(new XpathListenerStorage(bean,xpath,listen));
371         }
372     }
373
374     /* functional spec for processing the PropertyChangeEvents:
375      *
376      * Ways in which listeners are added:
377      * 1. Customizer/Sheet Listeners
378      * 2. ConfigBean getChildBean()
379      * 3. ConfigBean associated Bean.
380      * 4. Xpath listeners (in all situations just fire XpathEvent)
381      *
382      * Types of Events:
383      * 1. Bean added
384      * 2. Bean removed
385      * 3. Bean changed
386      *
387      * 4. Plugin added
388      * 5. Plugin removed
389      * 6. Listener added
390      *
391      * Location of Event:
392      * 1. Current bean
393      * 2. Descendant bean
394      * 3. Ancestor bean (removal only)
395      *
396      * Other event type:
397      *
398      * Case-by-case breakdown:
399      *
400      * Location of Event: Current Bean
401      *
402      * Added Removed Changed
403      *
404      * Listener: N/A remove listener N/A
405      * getChild(): if matches,
406      * Call ConfigBean.getChild()
407      * Add it to parent property
408      * sheet if necessary.
409      * N/A N/A
410      * Bean: fire notifyStandardDDBean changed.
411      *
412      * Location of Event: Descendant Bean
413      *
414      * Added Removed Changed
415      *
416      * Listener: N/A
417      * getChild(): see above N/A N/A
418      * Bean: fire notifyStandardDDBean changed
419      *
420      * Location of Event: Ancestor Bean
421      *
422      * Added Removed Changed
423      *
424      * Listener: N/A
425      * getChild(): check match N/A N/A
426      * Bean: if removed is self,
427      * call removeChildBean()
428      * on parent
429      *
430      * Other events:
431      * ListenerAdded PluginAdded PluginRemoved
432      * Listener: N/A Calculate display for new remove display
433      * plugin
434      * getChild(): Calculate display Call all getChild() remove listeners
435      * for associated methods applicable
436      * ConfigBean
437      * bean: as above as above remove listeners
438      */

439
440     public void propertyChange(PropertyChangeEvent event) {
441
442         Object JavaDoc oldValue = event.getOldValue();
443         // System.out.println("Old value" + oldValue);
444
Object JavaDoc newValue = event.getNewValue();
445         // System.out.println("New value" + newValue);
446
String JavaDoc name = event.getPropertyName();
447
448         // System.out.println("Processing ddbeans event " + name);
449
// System.out.println("From source " + event.getSource());
450
// System.out.println(event.getSource().getClass());
451

452         try {
453             StandardDDImpl eventBean = null;
454             if(newValue == null && oldValue instanceof BaseBean) {
455                 eventBean = getBean((BaseBean) oldValue);
456             }
457             else {
458                 Object JavaDoc eventObj = oldValue != null ? oldValue : newValue;
459                 if (!(eventObj instanceof BaseBean)) {
460                     eventObj = event.getSource();
461                 }
462                 if (eventObj instanceof BaseBean) {
463                     BaseBean root = (BaseBean) eventObj;
464                     while (! root.isRoot()) {
465                         root = root.parent();
466                     }
467                     //check if same root that we saw
468
boolean rootInCache = false;
469                     for (Iterator ddRoots=rootMap.values().iterator(); ddRoots.hasNext();) {
470                         DDRoot ddroot = (DDRoot) ddRoots.next();
471                         if (ddroot.proxy != null && ddroot.proxy.bean == root) {
472                             rootInCache = true;
473                             break;
474                         }
475                     }
476                     if (rootInCache) {
477                         eventBean = getBean(name, root);
478                     }
479                 }
480                 if (eventBean == null) {
481                     eventBean = getBean(name);
482                 }
483             }
484
485             // this is the case where an array assignment is made
486
// too change a whole set of properties, and to make
487
// sense of the events. Our UI only generates these
488
// array assignments if the oldvalue is non-null.
489
if (eventBean == null && oldValue instanceof Object JavaDoc[]) {
490                 // process separate propertyChange events for each
491
// array element.
492
List newElements = new ArrayList();
493                 if(newValue != null) {
494                     Object JavaDoc[] newValues = (Object JavaDoc[])newValue;
495                     for (int i=0; i<newValues.length; i++) {
496                         if (newValues[i] == null) {
497                             continue;
498                         }
499                         newElements.add(newValues[i]);
500                     }
501                 }
502                 Object JavaDoc[] values = (Object JavaDoc[]) oldValue;
503                 for(int i = 0; i < values.length; i++) {
504                     Object JavaDoc value = values[i];
505                     // PENDING tracking indicies of non-BaseBean
506
// properties does not work.
507
if(!(value instanceof BaseBean)) break;
508                     // no change in this element
509
if(newElements.contains(value)) {
510                         newElements.remove(value);
511                         continue;
512                     }
513                     StandardDDImpl valueBean = getBean((BaseBean)value);
514                     // I still don't know anything about this bean.
515
if(valueBean == null) continue;
516                     // this element has been removed.
517
processEvent(value,null,valueBean.proxy,event);
518                 }
519                 /*for(Iterator i = newElements.iterator();i.hasNext();) {
520                     i.next();
521                     // PENDING ignore for now - these should have already
522                     // generated events for adds?
523                 }*/

524             }
525
526             // swallow events we know nothing about.
527
if (eventBean == null) return;
528
529             if(oldValue == null && eventBean.proxy.isProxy()) {
530                 eventBean.setProxy(new DDNodeBean((DDProxy)eventBean.proxy));
531                 return; // swallow this event
532
}
533
534             processEvent(oldValue,newValue,eventBean.proxy,event);
535
536         } catch (Exception JavaDoc e) {
537             ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
538         }
539     }
540
541     void processEvent(Object JavaDoc oldValue, Object JavaDoc newValue, DDCommon eventBean, PropertyChangeEvent event) {
542
543         // System.out.println("Processing event on " + eventBean);
544

545
546         // Start with just XpathEvents.
547
// 0. Make the StandardDDBean for the Event, get its Xpath.
548
// 1. Iterate through all the listeners. // optimize lookup later
549
// 2. for listener l
550
// 3. Make the listener's xpath.
551
// 4. If (3) is related to source, continue.
552
// 5. Find the real BB + xpath for the listener
553
// 6. Check the ancestry relationship between the Event's BB
554
// and the Listener's BB
555
// 7. If share ancestry, Construct XpathEvent, fire.
556

557         // PENDING should get from source + property
558

559         String JavaDoc eventDtdPath = eventBean.getXpath();
560
561         Object JavaDoc type = XpathEvent.BEAN_CHANGED;
562         if(oldValue == null) type = XpathEvent.BEAN_ADDED;
563         if(newValue == null) type = XpathEvent.BEAN_REMOVED;
564         XpathEvent xe = new XpathEvent(eventBean.container,type);
565         xe.setChangeEvent(event);
566
567
568         Object JavaDoc xpathListenerArray[] = xpathListeners.toArray();
569         for (int i = 0; i < xpathListenerArray.length; i++) {
570             XpathListenerStorage x = (XpathListenerStorage) xpathListenerArray[i];
571             if (x.bean == null) {
572                 continue;
573             }
574             String JavaDoc xp = x.getNormalizedPath();
575
576             // System.out.println("Checking against listener " + xp);
577

578             //PENDING - handle delete events on completely different code path?
579
// need to get this code working for DDBean ancestry traversal.
580
DDCommon leftBean,rightBean;
581             if(eventDtdPath.startsWith(xp)) {
582                 // System.out.println("Event dtd is smaller");
583
leftBean = x.bean;
584                 rightBean = eventBean;
585             } else if(xp.startsWith(eventDtdPath)) {
586                 // System.out.println("Event dtd is bigger");
587
leftBean = eventBean;
588                 rightBean = x.bean;
589             } else continue;
590             while (leftBean != rightBean && rightBean != null)
591                 rightBean = rightBean.parent;
592             if(leftBean == rightBean) {
593                 x.listen.fireXpathEvent(xe);
594             }
595         }
596         // should look through DDBeans we know about and check for
597
// relative listeners that way. This perhaps means we pop
598
// up the event bean ancestor list and just look up the DDBean
599
// directly to process events.
600
// eventBean.fireEvent(xe);
601
// PENDING remove should remove the DDBean and any children from the cache.
602

603     }
604
605     private class XpathListenerStorage {
606         private DDCommon bean = null;
607         private String JavaDoc xpath;
608         private boolean xpathRelative;
609         private XpathListener listen;
610         private String JavaDoc normal = null;
611
612         XpathListenerStorage(DDCommon bean,String JavaDoc xpath,XpathListener listen) {
613             this.bean = bean;
614             this.xpath = xpath;
615             this.listen = listen;
616             xpathRelative = ! xpath.startsWith(SEPARATOR);
617         }
618
619         public String JavaDoc getNormalizedPath() {
620             if(normal == null) {
621                 String JavaDoc base = xpath;
622                 if (xpathRelative) {
623                     base = bean.getXpath() + SEPARATOR + base;
624                 }
625                 normal = normalizePath(base);
626             }
627             return normal;
628         }
629
630         public String JavaDoc toString() {
631             return bean + " " + xpath + " " + listen;
632         }
633
634         public int hashCode() { return listen.hashCode(); }
635
636         public boolean equals(Object JavaDoc o) {
637             if(o instanceof XpathListenerStorage) {
638                 XpathListenerStorage x = (XpathListenerStorage) o;
639                 return (x.bean == bean) && (x.xpath == xpath) && (x.listen == listen);
640             }
641             return false;
642         }
643
644     }
645
646     static String JavaDoc normalizePath(String JavaDoc path) {
647         boolean absolute = path.startsWith(SEPARATOR);
648         StringTokenizer tokens = new StringTokenizer(path, SEPARATOR, false);
649
650         LinkedList l = new LinkedList();
651
652         while(tokens.hasMoreElements())
653             l.addLast(tokens.nextElement());
654
655         for(int i = 0 ; i < l.size(); ) {
656             String JavaDoc tok = (String JavaDoc) l.get(i);
657             if(tok.equals(".")) l.remove(i);
658             else if(tok.equals("..") && i > 0 && !l.get(i-1).equals("..")) {
659                 l.remove(i);
660                 l.remove(i-1);
661                 i--;
662             } else i++;
663         }
664
665         StringBuffer JavaDoc ret = new StringBuffer JavaDoc();
666
667         for(int i = 0; i < l.size(); i++) {
668             if(absolute || i > 0) ret.append(SEPARATOR);
669             ret.append(l.get(i));
670         }
671
672         return ret.toString();
673
674     }
675     
676     public J2eeModuleProvider getProvider() {
677         return provider;
678     }
679 }
680
Popular Tags