KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > j2ee > sun > share > config > ModuleDDSupport


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 package org.netbeans.modules.j2ee.sun.share.config;
41
42 import java.util.*;
43 import java.beans.*;
44
45 import javax.enterprise.deploy.spi.*;
46 import javax.enterprise.deploy.spi.exceptions.*;
47 import javax.enterprise.deploy.model.*;
48 import javax.enterprise.deploy.shared.*;
49
50 import org.openide.*;
51 import org.openide.nodes.*;
52 import org.openide.util.WeakListeners;
53
54 import org.netbeans.modules.schema2beans.*;
55 import org.netbeans.modules.j2ee.deployment.plugins.api.*;
56 import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider;
57 import org.netbeans.modules.j2ee.deployment.devmodules.api.J2eeModule;
58
59
60 /**
61  */

62 public class ModuleDDSupport implements PropertyChangeListener {
63
64     public static final String JavaDoc SEPARATOR = "/"; //NOI18N
65
public static final String JavaDoc WEBSERVICES_XML = "webservices.xml"; //NOI18N
66
private static Map filenameToPathMap = null;
67
68     private Map rootMap = new HashMap(5); // DD location string -> DDRoot
69
private Map configMap = new IdentityHashMap(5); // DD object -> ConfigBeanStorage
70
private Map beanMap = Collections.synchronizedMap(new IdentityHashMap()); // BaseBean -> StandardDDImpl
71
private Map leafMap = Collections.synchronizedMap(new IdentityHashMap()); // BaseProp -> StandardDDImpl
72
private Map listenerMap = Collections.synchronizedMap(new IdentityHashMap(5)); // BaseBean -> weak listener instance; //
73
private Set xpathListeners = new HashSet();
74     private J2eeModuleProvider provider;
75     private DeploymentConfiguration config;
76     
77     private static Map moduleDDlocationMap = new HashMap(10);
78
79     static {
80         moduleDDlocationMap.put(J2eeModule.EAR,
81         new String JavaDoc[] {J2eeModule.APP_XML});
82         moduleDDlocationMap.put(J2eeModule.WAR,
83         new String JavaDoc[] {J2eeModule.WEB_XML,J2eeModule.WEBSERVICES_XML});
84         moduleDDlocationMap.put(J2eeModule.EJB,
85         new String JavaDoc[] {J2eeModule.EJBJAR_XML,J2eeModule.EJBSERVICES_XML});
86         moduleDDlocationMap.put(J2eeModule.CONN,
87         new String JavaDoc[] { J2eeModule.CONNECTOR_XML});
88         moduleDDlocationMap.put(J2eeModule.CLIENT,
89         new String JavaDoc[] { 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 ModuleDDSupport(J2eeModuleProvider provider, DeploymentConfiguration config) {
97         this.provider = provider;
98         this.config = config;
99         String JavaDoc[] ddLocs = getDDPaths(provider.getJ2eeModule().getModuleType());
100         for(int i = 0; i < ddLocs.length; i++) {
101             createRoot(ddLocs[i]);
102         }
103     }
104
105     private ModuleType getModuleType() {
106         return (ModuleType) provider.getJ2eeModule().getModuleType();
107     }
108     
109     private BaseBean getDeploymentDescriptor(String JavaDoc ddLoc) {
110         return provider.getJ2eeModule().getDeploymentDescriptor(ddLoc);
111     }
112     
113     private DDRoot createRoot(String JavaDoc ddLoc) {
114         BaseBean bean = getDeploymentDescriptor(ddLoc);
115         if (bean == null) { // no support for that descriptor
116
return null;
117         }
118         while(!bean.isRoot()) {
119             bean = bean.parent();
120         }
121         DDRoot root = new DDRoot(new DDNodeBean(null,bean,this));
122         rootMap.put(ddLoc,root);
123         beanMap.put(bean,root);
124
125         PropertyChangeListener weakListener = WeakListeners.propertyChange(this,root.proxy.bean);
126         listenerMap.put(bean, weakListener);
127         bean.addPropertyChangeListener(weakListener);
128         
129         return root;
130     }
131
132     public DeployableObject getDeployableObject() {
133         return config.getDeployableObject();
134     }
135
136     // This is broken in jsr88 that I even have to supply this
137
public DDRoot getDDBeanRoot() {
138         String JavaDoc loc = ((String JavaDoc[]) moduleDDlocationMap.get(getModuleType()))[0];
139         return getDDBeanRoot(loc);
140     }
141
142     public DDRoot getDDBeanRoot(String JavaDoc loc) {
143         DDRoot root = (DDRoot) rootMap.get(loc);
144         
145         // primary DD should be ready when this is called
146
// so this updating is only for non-primary DD's
147
if (root == null && ! isPrimaryDD(loc, getType())) {
148             root = createRoot(loc);
149             DDRoot proot = getPrimaryDD();
150             ConfigBeanStorage configRoot = (ConfigBeanStorage) configMap.get(proot);
151             
152             if (root != null && configRoot != null) {
153                 DConfigBeanRoot cbroot = (DConfigBeanRoot) configRoot.getConfigBean();
154                 DConfigBean cb = cbroot.getDConfigBean(root);
155                 if (cb != null) {
156                     try {
157                         ConfigBeanStorage cbs = new ConfigBeanStorage(cb, null, configRoot.getStorage());
158                         configMap.put(root, cbs);
159                     } catch (Exception JavaDoc ex) {
160                         ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
161                     }
162                 }
163             }
164         }
165         return root;
166     }
167
168     public ModuleType getType() {
169         return getModuleType();
170     }
171
172     public String JavaDoc getVersion() {
173         return provider.getJ2eeModule().getModuleVersion();
174     }
175
176     /* PENDING get from CompilationUnit */
177     public Class JavaDoc getClassFromScope(String JavaDoc cls) {
178         return null; // provider.getClassFromScope(cls);
179
}
180
181     public Node[] getNodes() {
182         String JavaDoc[] ddLocs = (String JavaDoc[]) moduleDDlocationMap.get(getModuleType());
183         List ret = new ArrayList();
184         for(int i = 0; i < ddLocs.length; i++) {
185             Object JavaDoc dd = rootMap.get(ddLocs[i]);
186             if(dd == null) {
187                 continue;
188             }
189             ConfigBeanStorage cbs = (ConfigBeanStorage) configMap.get(dd);
190             if(cbs != null) {
191                 Node n = cbs.getNode();
192                 if (n != null) {
193                     ret.add(n);
194                 } else {
195                     throw new RuntimeException JavaDoc("CBS.getNode returned null"); //NOI18N
196
}
197             }
198         }
199         return (Node[]) ret.toArray(new Node[ret.size()]);
200     }
201
202     public void resetConfigCache() {
203         configMap = new IdentityHashMap(5); // DD object -> ConfigBeanStorage
204
xpathListeners = new HashSet();
205     }
206
207     public void createConfigs(ConfigurationStorage storage) throws ConfigurationException {
208         String JavaDoc[] ddLocs = (String JavaDoc[]) moduleDDlocationMap.get(getModuleType());
209         DDRoot root = (DDRoot) rootMap.get(ddLocs[0]);
210         DConfigBeanRoot cbroot = config.getDConfigBeanRoot(root);
211         ConfigBeanStorage cbs = new ConfigBeanStorage(cbroot, null, storage);
212         configMap.put(root,cbs);
213
214         for(Iterator it = rootMap.keySet().iterator(); it.hasNext() ;) {
215             String JavaDoc ddLoc = (String JavaDoc) it.next();
216             if (isPrimaryDD(ddLoc, getModuleType())) {
217                 continue;
218             }
219             root = (DDRoot) rootMap.get(ddLoc);
220             DConfigBean cb = cbroot.getDConfigBean(root);
221             if(cb == null) {
222                 continue;
223             }
224             ConfigBeanStorage cbStorage = new ConfigBeanStorage(cb, null, storage);
225             configMap.put(root,cbStorage);
226         }
227     }
228
229     static public boolean isPrimaryDD(String JavaDoc ddLocation, Object JavaDoc type) {
230         String JavaDoc[] ddLocs = (String JavaDoc[]) moduleDDlocationMap.get(type);
231         if (ddLocs.length < 1) {
232             return false;
233         }
234         return ddLocs[0].equals(ddLocation);
235     }
236     
237     static private Map filenameToPathMap() {
238         if (filenameToPathMap == null) {
239             filenameToPathMap = new HashMap();
240             
241             filenameToPathMap.put(filename(J2eeModule.APP_XML), J2eeModule.APP_XML);
242             filenameToPathMap.put(filename(J2eeModule.WEB_XML), J2eeModule.WEB_XML);
243             filenameToPathMap.put(filename(J2eeModule.EJBJAR_XML), J2eeModule.EJBJAR_XML);
244             filenameToPathMap.put(filename(J2eeModule.CONNECTOR_XML), J2eeModule.CONNECTOR_XML);
245             filenameToPathMap.put(filename(J2eeModule.CLIENT_XML), J2eeModule.CLIENT_XML);
246
247             filenameToPathMap.put(J2eeModule.APP_XML, J2eeModule.APP_XML);
248             filenameToPathMap.put(J2eeModule.WEB_XML, J2eeModule.WEB_XML);
249             filenameToPathMap.put(J2eeModule.EJBJAR_XML, J2eeModule.EJBJAR_XML);
250             filenameToPathMap.put(J2eeModule.CONNECTOR_XML, J2eeModule.CONNECTOR_XML);
251             filenameToPathMap.put(J2eeModule.CLIENT_XML, J2eeModule.CLIENT_XML);
252         }
253         return filenameToPathMap;
254     }
255
256     static private String JavaDoc filename(String JavaDoc path) {
257         int i = path.lastIndexOf(SEPARATOR);
258         return path.substring(i+1);
259     }
260     
261     static public String JavaDoc filenameToPath(String JavaDoc filename, Object JavaDoc type) {
262         if (filename.endsWith(WEBSERVICES_XML)) {
263             if (J2eeModule.EJB.equals(type)) {
264                 return J2eeModule.EJBSERVICES_XML;
265             } else {
266                 return J2eeModule.WEBSERVICES_XML;
267             }
268         }
269         String JavaDoc name = (String JavaDoc) filenameToPathMap().get(filename);
270         if (name == null) {
271             name = filename;
272         }
273         return name;
274     }
275     
276     public DDRoot getPrimaryDD() {
277         ModuleType type = this.getType();
278         String JavaDoc[] ddLocs = (String JavaDoc[]) moduleDDlocationMap.get(type);
279         if (ddLocs.length < 1) {
280             return null;
281         }
282         return (DDRoot) rootMap.get(ddLocs[0]);
283     }
284
285     /* Called when the module/app is closed from the ide, clean up listeners and
286      * references */

287     public void cleanup() {
288         // stop listening to DD changes
289
for (Iterator i = rootMap.values().iterator(); i.hasNext();) {
290             DDRoot root = (DDRoot)i.next();
291             
292             PropertyChangeListener weakListener = (PropertyChangeListener) listenerMap.get(root.proxy.bean);
293             root.proxy.bean.removePropertyChangeListener(weakListener);
294             
295             // !PW Is this a good idea to add this here? What are the repercussions?
296
ConfigBeanStorage cbs = (ConfigBeanStorage) configMap.get(root);
297             try {
298                 if(config != null && cbs != null && cbs.bean != null) {
299                     config.removeDConfigBean((DConfigBeanRoot)cbs.bean);
300                 }
301             } catch (BeanNotFoundException bnfe) {
302                 // Log this, it shouldn't happen
303
ErrorManager.getDefault().log("BeanNotFoundException caught by ModuleDDSupport: " + bnfe.getMessage());
304             }
305         }
306         
307         listenerMap = null;
308         rootMap = null;
309         configMap = null;
310         beanMap = null;
311         xpathListeners = null;
312         leafMap = null;
313         provider = null;
314     }
315
316     /* Called when the module is removed from the app. */
317     // Not called from anywhere anymore, probably because multi-module support is
318
// disabled at the moment.
319
// public void dispose(DeploymentConfiguration config) {
320
// for(Iterator it = configMap.entrySet().iterator(); it.hasNext(); ) {
321
// Map.Entry entry = (Map.Entry) it.next();
322
// DDRoot root = (DDRoot) entry.getKey();
323
// ConfigBeanStorage cbs = (ConfigBeanStorage) entry.getValue();
324
// root.proxy.bean.removePropertyChangeListener(weakListener);
325
// try {
326
// config.removeDConfigBean((DConfigBeanRoot)cbs.bean);
327
// } catch (BeanNotFoundException bnfe) {
328
// // IGNORE
329
// }
330
// }
331
// }
332

333     StandardDDImpl getBean(BaseBean bean) {
334         // System.out.println("Getting bean for " + bean);
335
// System.out.println(bean.fullName());
336
// System.out.println(bean.dtdName());
337
if (bean == null) {
338             return null;
339         }
340         
341         if (beanMap == null) {
342             return null;
343         }
344         
345         StandardDDImpl ret = (StandardDDImpl) beanMap.get(bean);
346         
347         if (ret == null) {
348             /*
349             DDCommon base;
350             // System.out.println("Creating new bean");
351             BaseBean bb = bean;
352             while(!bb.isRoot()) {
353                 bb = bb.parent();
354                 if (bb== null) {
355                     // We are in an unattached tree, we have expressed no prior
356                     // interest in this Xpath so we just toss it.
357                     // See: addTemporaryBean in this object
358                     return null;
359                 }
360
361             }
362             if(bb == root.proxy.bean) base = new DDNodeBean(bean,this);
363             else { // must build proxy tree
364                 if (bean.isRoot()) {
365                     // PENDING This probably means that there is an error, can it legaly happen?
366                     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
367                 }
368                 StandardDDImpl parent = getBean(bean.parent());
369                 base = new DDProxy(parent.proxy,bean,bean.dtdName(),this);
370             }
371              **/

372             if (bean.parent() != null) {
373                 ret = new StandardDDImpl(new DDNodeBean(bean,this));
374                 beanMap.put(bean,ret);
375             }
376         }
377         return ret;
378     }
379
380     // for indexed leaf properties
381
StandardDDImpl getBean(BaseProperty prop,int index) {
382
383         if(index < 0) {
384             return getBean(prop);
385         }
386
387         if (!leafMap.containsKey(prop)) {
388             leafMap.put(prop, new StandardDDImpl[index + 1]);
389         } else if (((StandardDDImpl[])leafMap.get(prop)).length <= index) {
390             StandardDDImpl[] a = (StandardDDImpl[])leafMap.get(prop);
391             StandardDDImpl[] b = new StandardDDImpl[index + 1];
392
393             leafMap.put(prop, b);
394             for (int i = 0; i < a.length; i++) {
395                 b[i] = a[i];
396             }
397         }
398
399         StandardDDImpl[] arr = (StandardDDImpl[])leafMap.get(prop);
400         StandardDDImpl elem = arr[index];
401
402         if (elem == null) {
403             elem = new StandardDDImpl(new DDLeafBean(prop, index, this));
404             arr[index] = elem;
405         }
406
407         return elem;
408      }
409
410     // for non-indexed leaf properties
411
StandardDDImpl getBean(BaseProperty prop) {
412        StandardDDImpl elem = (StandardDDImpl) leafMap.get(prop);
413        if(elem == null) {
414           elem = new StandardDDImpl(new DDLeafBean(prop, this));
415           leafMap.put(prop,elem);
416        }
417        return elem;
418     }
419
420     StandardDDImpl getBean(String JavaDoc name) {
421         return getBean(name,getDDBeanRoot().proxy.bean);
422     }
423
424     StandardDDImpl getBean(String JavaDoc name,BaseBean rootBean) {
425         Bean parent = GraphManager.getPropertyParent(rootBean, name);
426         if (parent == null) {
427             return getDDBeanRoot();
428         }
429         String JavaDoc shortName = GraphManager.getPropertyName(name);
430         int index = GraphManager.getPropertyIndex(rootBean, name);
431         // System.out.println(name);
432
// System.out.println(index);
433

434         BaseProperty prop = parent.getProperty(shortName);
435
436         if(index < 0 && prop.isIndexed()) {
437             index = 0;
438         }
439
440         StandardDDImpl ret;
441         if(prop.isBean()) {
442             if(prop.isIndexed()) {
443                 ret = getBean((BaseBean) parent.getValue(shortName,index));
444             } else {
445                 ret = getBean((BaseBean) parent.getValue(shortName));
446             }
447         }
448         else {
449             if(prop.isIndexed()) {
450                 ret = getBean(prop,index);
451             } else {
452                 ret = getBean(prop);
453             }
454         }
455         // System.out.println(ret.proxy.bean.fullName());
456
// System.out.println(((Object)ret.proxy.bean).toString());
457
return ret;
458     }
459
460     void addXpathListener(DDCommon bean, String JavaDoc xpath, XpathListener listen) {
461         xpathListeners.add(new XpathListenerStorage(bean,xpath,listen));
462     }
463
464     void removeXpathListener(DDCommon bean, String JavaDoc xpath, XpathListener listen) {
465         xpathListeners.remove(new XpathListenerStorage(bean,xpath,listen));
466     }
467
468     /* functional spec for processing the PropertyChangeEvents:
469      *
470      * Ways in which listeners are added:
471      * 1. Customizer/Sheet Listeners
472      * 2. ConfigBean getChildBean()
473      * 3. ConfigBean associated Bean.
474      * 4. Xpath listeners (in all situations just fire XpathEvent)
475      *
476      * Types of Events:
477      * 1. Bean added
478      * 2. Bean removed
479      * 3. Bean changed
480      *
481      * 4. Plugin added
482      * 5. Plugin removed
483      * 6. Listener added
484      *
485      * Location of Event:
486      * 1. Current bean
487      * 2. Descendant bean
488      * 3. Ancestor bean (removal only)
489      *
490      * Other event type:
491      *
492      * Case-by-case breakdown:
493      *
494      * Location of Event: Current Bean
495      *
496      * Added Removed Changed
497      *
498      * Listener: N/A remove listener N/A
499      * getChild(): if matches,
500      * Call ConfigBean.getChild()
501      * Add it to parent property
502      * sheet if necessary.
503      * N/A N/A
504      * Bean: fire notifyStandardDDBean changed.
505      *
506      * Location of Event: Descendant Bean
507      *
508      * Added Removed Changed
509      *
510      * Listener: N/A
511      * getChild(): see above N/A N/A
512      * Bean: fire notifyStandardDDBean changed
513      *
514      * Location of Event: Ancestor Bean
515      *
516      * Added Removed Changed
517      *
518      * Listener: N/A
519      * getChild(): check match N/A N/A
520      * Bean: if removed is self,
521      * call removeChildBean()
522      * on parent
523      *
524      * Other events:
525      * ListenerAdded PluginAdded PluginRemoved
526      * Listener: N/A Calculate display for new remove display
527      * plugin
528      * getChild(): Calculate display Call all getChild() remove listeners
529      * for associated methods applicable
530      * ConfigBean
531      * bean: as above as above remove listeners
532      */

533
534     public void propertyChange(PropertyChangeEvent event) {
535
536         Object JavaDoc oldValue = event.getOldValue();
537         // System.out.println("Old value" + oldValue);
538
Object JavaDoc newValue = event.getNewValue();
539         // System.out.println("New value" + newValue);
540
String JavaDoc name = event.getPropertyName();
541
542         // System.out.println("Processing ddbeans event " + name);
543
// System.out.println("From source " + event.getSource());
544
// System.out.println(event.getSource().getClass());
545
if(rootMap == null) {
546             ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, new Exception JavaDoc(
547                     "ModuleDDSupport: Unexpected change event (NAME=" + name + ", old=" + oldValue +
548                     ", new=" + newValue + ") received on previously removed DDBean->DConfigBean graph. See IZ 81332."));
549             // Do not process events if this support object has been destroyed.
550
return;
551         }
552         
553         try {
554             StandardDDImpl eventBean = null;
555             if(newValue == null && oldValue instanceof BaseBean) {
556                 eventBean = getBean((BaseBean) oldValue);
557             } else {
558                 Object JavaDoc eventObj = oldValue != null ? oldValue : newValue;
559                 if (!(eventObj instanceof BaseBean)) {
560                     eventObj = event.getSource();
561                 }
562                 if (eventObj instanceof BaseBean) {
563                     BaseBean root = (BaseBean) eventObj;
564                     while (! root.isRoot()) {
565                         root = root.parent();
566                     }
567                     //check if same root that we saw
568
boolean rootInCache = false;
569                     for (Iterator ddRoots=rootMap.values().iterator(); ddRoots.hasNext();) {
570                         DDRoot ddroot = (DDRoot) ddRoots.next();
571                         if (ddroot.proxy != null && ddroot.proxy.bean == root) {
572                             rootInCache = true;
573                             break;
574                         }
575                     }
576                     if (rootInCache) {
577                         eventBean = getBean(name, root);
578                     }
579                 }
580                 if (eventBean == null) {
581                     eventBean = getBean(name);
582                 }
583             }
584
585             // this is the case where an array assignment is made
586
// too change a whole set of properties, and to make
587
// sense of the events. Our UI only generates these
588
// array assignments if the oldvalue is non-null.
589
if (eventBean == null && oldValue instanceof Object JavaDoc[]) {
590                 // process separate propertyChange events for each
591
// array element.
592
List newElements = new ArrayList();
593                 if(newValue != null) {
594                     Object JavaDoc[] newValues = (Object JavaDoc[])newValue;
595                     for (int i=0; i<newValues.length; i++) {
596                         if (newValues[i] == null) {
597                             continue;
598                         }
599                         newElements.add(newValues[i]);
600                     }
601                 }
602                 Object JavaDoc[] values = (Object JavaDoc[]) oldValue;
603                 for(int i = 0; i < values.length; i++) {
604                     Object JavaDoc value = values[i];
605                     // PENDING tracking indicies of non-BaseBean
606
// properties does not work.
607
if(!(value instanceof BaseBean)) {
608                         break;
609                     }
610                     // no change in this element
611
if(newElements.contains(value)) {
612                         newElements.remove(value);
613                         continue;
614                     }
615                     StandardDDImpl valueBean = getBean((BaseBean)value);
616                     // I still don't know anything about this bean.
617
if(valueBean == null) {
618                         continue;
619                     }
620                     // this element has been removed.
621
processEvent(value,null,valueBean.proxy,event);
622                 }
623                 /*for(Iterator i = newElements.iterator();i.hasNext();) {
624                     i.next();
625                     // PENDING ignore for now - these should have already
626                     // generated events for adds?
627                 }*/

628             }
629
630             // swallow events we know nothing about.
631
if (eventBean == null) {
632                 return;
633             }
634
635             if(oldValue == null && eventBean.proxy.isProxy()) {
636                 eventBean.setProxy(new DDNodeBean((DDProxy)eventBean.proxy));
637                 return; // swallow this event
638
}
639
640             processEvent(oldValue,newValue,eventBean.proxy,event);
641
642         } catch (Exception JavaDoc e) {
643             ErrorManager.getDefault().notify(e);
644         }
645     }
646
647     void processEvent(Object JavaDoc oldValue, Object JavaDoc newValue, DDCommon eventBean, PropertyChangeEvent event) {
648
649         // System.out.println("Processing event on " + eventBean);
650

651
652         // Start with just XpathEvents.
653
// 0. Make the StandardDDBean for the Event, get its Xpath.
654
// 1. Iterate through all the listeners. // optimize lookup later
655
// 2. for listener l
656
// 3. Make the listener's xpath.
657
// 4. If (3) is related to source, continue.
658
// 5. Find the real BB + xpath for the listener
659
// 6. Check the ancestry relationship between the Event's BB
660
// and the Listener's BB
661
// 7. If share ancestry, Construct XpathEvent, fire.
662

663         // PENDING should get from source + property
664

665         String JavaDoc eventDtdPath = eventBean.getXpath();
666
667         Object JavaDoc type = XpathEvent.BEAN_CHANGED;
668         if(oldValue == null) {
669             type = XpathEvent.BEAN_ADDED;
670         }
671         if(newValue == null) {
672             type = XpathEvent.BEAN_REMOVED;
673         }
674         XpathEvent xe = new XpathEvent(eventBean.container,type);
675         xe.setChangeEvent(event);
676
677
678         Object JavaDoc xpathListenerArray[] = xpathListeners.toArray();
679         for (int i = 0; i < xpathListenerArray.length; i++) {
680             XpathListenerStorage x = (XpathListenerStorage) xpathListenerArray[i];
681             if (x.bean == null) {
682                 continue;
683             }
684             String JavaDoc xp = x.getNormalizedPath();
685
686             // System.out.println("Checking against listener " + xp);
687

688             //PENDING - handle delete events on completely different code path?
689
// need to get this code working for DDBean ancestry traversal.
690
DDCommon leftBean,rightBean;
691             if(eventDtdPath.startsWith(xp)) {
692                 // System.out.println("Event dtd is smaller");
693
leftBean = x.bean;
694                 rightBean = eventBean;
695             } else if(xp.startsWith(eventDtdPath)) {
696                 // System.out.println("Event dtd is bigger");
697
leftBean = eventBean;
698                 rightBean = x.bean;
699             } else {
700                 continue;
701             }
702             while (leftBean != rightBean && rightBean != null) {
703                 rightBean = rightBean.parent;
704             }
705             if(leftBean == rightBean) {
706                 x.listen.fireXpathEvent(xe);
707             }
708         }
709         // should look through DDBeans we know about and check for
710
// relative listeners that way. This perhaps means we pop
711
// up the event bean ancestor list and just look up the DDBean
712
// directly to process events.
713
eventBean.fireEvent(xe);
714         // PENDING remove should remove the DDBean and any children from the cache.
715

716     }
717
718     private class XpathListenerStorage {
719         private DDCommon bean = null;
720         private String JavaDoc xpath;
721         private boolean xpathRelative;
722         private XpathListener listen;
723         private String JavaDoc normal = null;
724
725         XpathListenerStorage(DDCommon bean,String JavaDoc xpath,XpathListener listen) {
726             this.bean = bean;
727             this.xpath = xpath;
728             this.listen = listen;
729             xpathRelative = ! xpath.startsWith(SEPARATOR);
730         }
731
732         public String JavaDoc getNormalizedPath() {
733             if(normal == null) {
734                 String JavaDoc base = xpath;
735                 if (xpathRelative) {
736                     base = bean.getXpath() + SEPARATOR + base;
737                 }
738                 normal = normalizePath(base);
739             }
740             return normal;
741         }
742
743         public String JavaDoc toString() {
744             return bean + " " + xpath + " " + listen;
745         }
746
747         public int hashCode() { return listen.hashCode(); }
748
749         public boolean equals(Object JavaDoc o) {
750             if(o instanceof XpathListenerStorage) {
751                 XpathListenerStorage x = (XpathListenerStorage) o;
752                 return (x.bean == bean) && (x.xpath == xpath) && (x.listen == listen);
753             }
754             return false;
755         }
756
757     }
758
759     static String JavaDoc normalizePath(String JavaDoc path) {
760         boolean absolute = path.startsWith(SEPARATOR);
761         StringTokenizer tokens = new StringTokenizer(path, SEPARATOR, false);
762
763         LinkedList l = new LinkedList();
764
765         while(tokens.hasMoreElements()) {
766             l.addLast(tokens.nextElement());
767         }
768
769         for(int i = 0 ; i < l.size(); ) {
770             String JavaDoc tok = (String JavaDoc) l.get(i);
771             if(tok.equals(".")) {
772                 l.remove(i);
773             } else if(tok.equals("..") && i > 0 && !l.get(i-1).equals("..")) {
774                 l.remove(i);
775                 l.remove(i-1);
776                 i--;
777             } else {
778                 i++;
779             }
780         }
781
782         StringBuffer JavaDoc ret = new StringBuffer JavaDoc();
783
784         for(int i = 0; i < l.size(); i++) {
785             if(absolute || i > 0) {
786                 ret.append(SEPARATOR);
787             }
788             ret.append(l.get(i));
789         }
790
791         return ret.toString();
792
793     }
794     
795     public J2eeModuleProvider getProvider() {
796         return provider;
797     }
798 }
799
Popular Tags