KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > j2ee > sun > share > configbean > Base


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 package org.netbeans.modules.j2ee.sun.share.configbean;
20
21 import java.util.ArrayList JavaDoc;
22 import java.util.Collection JavaDoc;
23 import java.util.Collections JavaDoc;
24 import java.util.HashMap JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.LinkedHashSet JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.Map JavaDoc;
29 import java.util.ResourceBundle JavaDoc;
30 import java.util.Set JavaDoc;
31 import java.util.logging.Level JavaDoc;
32
33 import java.text.MessageFormat JavaDoc;
34
35 import java.beans.PropertyChangeEvent JavaDoc;
36 import java.beans.PropertyChangeListener JavaDoc;
37 import java.beans.PropertyChangeSupport JavaDoc;
38 import java.beans.VetoableChangeListener JavaDoc;
39 import java.beans.VetoableChangeSupport JavaDoc;
40
41 import javax.enterprise.deploy.spi.DConfigBean JavaDoc;
42 import javax.enterprise.deploy.model.DDBean JavaDoc;
43 import javax.enterprise.deploy.model.XpathEvent JavaDoc;
44 import javax.enterprise.deploy.model.XpathListener JavaDoc;
45 import javax.enterprise.deploy.spi.exceptions.BeanNotFoundException JavaDoc;
46 import javax.enterprise.deploy.spi.exceptions.ConfigurationException JavaDoc;
47
48 import org.netbeans.modules.j2ee.sun.dd.api.CommonDDBean;
49 import org.netbeans.modules.j2ee.sun.dd.api.common.WebserviceEndpoint;
50 import org.netbeans.modules.j2ee.sun.dd.api.web.SunWebApp;
51
52 import org.netbeans.modules.j2ee.sun.share.Constants;
53 import org.openide.ErrorManager;
54
55 /** This is the base class for all DConfigBean objects in the SunONE App Server
56  * JSR88 implementation.
57  *
58  * @author Vince Kraemer
59  * @author Peter Williams
60  */

61 public abstract class Base implements Constants, DConfigBean JavaDoc, XpathListener JavaDoc, DConfigBeanUIFactory {
62
63     /** Resource bundle
64      */

65     protected static final ResourceBundle JavaDoc bundle = ResourceBundle.getBundle(
66         "org.netbeans.modules.j2ee.sun.share.configbean.Bundle"); // NOI18N
67

68     /** Property event names
69      */

70     public static final String JavaDoc DISPLAY_NAME = "displayName"; // NOI18N
71
public static final String JavaDoc DIRTY_PROPERTY = "dirty"; // NOI18N
72

73     /** Singleton object used as generic old value in property events to force
74      * them to be sent. (if the new value is "" or null, then using "" or null
75      * for the old value is problematic - when new & old values match, the event
76      * is not fired.
77      */

78     public static final Object JavaDoc GenericOldValue = new Object JavaDoc();
79
80     private DDBean JavaDoc dDBean;
81     private Base parent;
82     private String JavaDoc baseXpath;
83
84     /** Name of descriptor element this bean represents, e.g. sun-web-app, servlet-ref, etc. */
85     protected String JavaDoc descriptorElement;
86
87     /** isValid represents the valid state of the bean:
88      * null: unknown
89      * TRUE: bean is valid
90      * FALSE: bean has at least one invalid field.
91      */

92     private Boolean JavaDoc isValid = null;
93
94     /** Validation message database for this bean.
95      */

96     private ErrorMessageDB errorMessageDB = null;
97
98     /** Utility field used by bound properties. */
99     private PropertyChangeSupport JavaDoc propertyChangeSupport = new PropertyChangeSupport JavaDoc(this);
100
101     /** Utility field used by constrained properties. */
102     private VetoableChangeSupport JavaDoc vetoableChangeSupport = new VetoableChangeSupport JavaDoc(this);
103
104     private PropertyChangeListener JavaDoc validationListener = new PropertyChangeListener JavaDoc() {
105             public void propertyChange(PropertyChangeEvent JavaDoc evt) {
106                 if(ErrorMessageDB.VALIDATION_STATE_CHANGED.equals(evt.getPropertyName())) {
107                     validationStateChanged((Boolean JavaDoc) evt.getNewValue());
108                 }
109             }
110         };
111
112     /** identity property to aid in debugging. Displays absolute ID of bean in
113      * system.
114      */

115     private static int identitySource = 0;
116     private String JavaDoc identity;
117
118     public String JavaDoc getIdentity() {
119         return identity;
120     }
121
122     public void setIdentity(String JavaDoc id) {
123     }
124
125     /** Quickly set this bean to dirty so that Studio will add a SaveCookie
126      * for us.
127      */

128     private int dirtyFlag;
129
130     public void setDirty() {
131         int oldDirtyFlag = dirtyFlag;
132         dirtyFlag += 1;
133         getPCS().firePropertyChange(DIRTY_PROPERTY, oldDirtyFlag, dirtyFlag);
134     }
135
136     /** For use by the customizers when they modify a sub property of an element.
137      */

138     public void firePropertyChange(String JavaDoc propertyName, Object JavaDoc oldProperty, Object JavaDoc newProperty) {
139         getPCS().firePropertyChange(propertyName, oldProperty, newProperty);
140     }
141
142     /** Creates a new instance of Base */
143     protected Base() {
144         identity = Integer.toString(++identitySource);
145     }
146
147     /** Since we create DConfigBeans via default constructors, this is the real
148      * initialization method. Override this method if you need to do extra
149      * initialization in a derived class but make absolutely sure your first line
150      * is 'super.init(dDBean, parent)'!!!
151      *
152      * @param dDBean DDBean that this DConfigBean is bound to
153      * @param parent DConfigBean that is the parent of this bean. Will be null
154      * if this is a DConfigBeanRoot, otherwise, should have a value.
155      * @throws ConfigurationException
156      */

157     protected void init(DDBean JavaDoc dDBean, Base parent) throws ConfigurationException JavaDoc {
158         this.dDBean = dDBean;
159         this.parent = parent;
160         this.baseXpath = dDBean.getXpath();
161
162         // Build validation field list for this bean
163
// !PW We need a better way to do this. See comment by validationFieldList
164
// member definition.
165
updateValidationFieldList();
166
167         dDBean.addXpathListener(dDBean.getXpath(), this);
168         getMessageDB().addPropertyChangeListener(validationListener);
169     }
170     
171     /** Cleanup routine. This is called just before a DConfigBean is removed
172      * from the tree (and all caches).
173      */

174     protected void cleanup() {
175         // remove listeners
176
getMessageDB().removePropertyChangeListener(validationListener);
177         dDBean.removeXpathListener(dDBean.getXpath(), this);
178
179         // clear errorMessageDB
180
synchronized (this) {
181             errorMessageDB = null;
182         }
183
184         // remove from DConfigBean tree
185
if(parent != null) {
186             parent.removeChild(this);
187         }
188
189 // dDBean = null;
190
parent = null;
191     }
192
193     protected String JavaDoc getDescriptorElement() {
194         return descriptorElement;
195     }
196
197     protected void setDescriptorElement(String JavaDoc element) {
198         descriptorElement = element;
199     }
200
201     protected String JavaDoc getComponentName() {
202         return null;
203     }
204
205     protected String JavaDoc getAbsoluteXpath(String JavaDoc field) {
206         StringBuffer JavaDoc buf = new StringBuffer JavaDoc(baseXpath.length() + field.length() + 1);
207         buf.append(baseXpath);
208         buf.append("/"); // NOI18N
209
buf.append(field);
210         return buf.toString();
211     }
212
213     /* Does this class of DConfigBeans require JNDI names in general. Right now
214      * this means J2EE 1.3, 1.4 = Yes, JavaEE5 = No.
215      */

216     protected boolean requiresJndiName() {
217         return J2EEVersion.J2EE_1_4.compareSpecification(getJ2EEModuleVersion()) >= 0;
218     }
219
220
221     /** Named child bean data cache to prevent loss of data when named beans haven't
222      * been loaded yet and a save request comes in.
223      */

224     private Map JavaDoc namedBeanCache = new HashMap JavaDoc(11);
225
226     protected void saveNamedBeans(String JavaDoc type, String JavaDoc nameProperty, CommonDDBean [] data) {
227         if(data != null && data.length > 0) {
228             Map JavaDoc dataMap = new HashMap JavaDoc(data.length*3);
229             for(int i = 0; i < data.length; i++) {
230                 String JavaDoc beanName = (String JavaDoc) data[i].getValue(nameProperty);
231                 if(Utils.notEmpty(beanName)) {
232                     dataMap.put(beanName, data[i]);
233                 }
234             }
235             
236             namedBeanCache.put(type, dataMap);
237         }
238     }
239     
240     protected CommonDDBean removeNamedBean(String JavaDoc type, String JavaDoc beanName) {
241         CommonDDBean result = null;
242         Map JavaDoc dataMap = getNamedBeanMap(type);
243         if(dataMap != null) {
244             result = (CommonDDBean) dataMap.remove(beanName);
245         }
246         
247         return result;
248     }
249     
250     protected CommonDDBean removeCachedEndpoint(String JavaDoc hostType, String JavaDoc hostNameType,
251             String JavaDoc hostName, String JavaDoc endpointType, String JavaDoc portComponentName) {
252         // 1. get cache of host type
253
// 2. iterate cache for hostname
254
// 3. if found, remove endpoint(s) for portcomponentname from host entry
255
CommonDDBean removedEndpoint = null;
256         Map JavaDoc dataMap = getNamedBeanMap(hostType);
257         if(dataMap != null) {
258             try {
259                 Iterator JavaDoc entryIter = dataMap.entrySet().iterator();
260                 while(entryIter.hasNext()) {
261                     Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entryIter.next();
262                     CommonDDBean host = (CommonDDBean) entry.getValue();
263                     Object JavaDoc n = host.getValue(hostNameType);
264                     if(n instanceof String JavaDoc && hostName.equals((String JavaDoc) n)) {
265                         Object JavaDoc [] objs = host.getValues(endpointType);
266                         if(objs != null) {
267                             for(int i = 0; i < objs.length; i++) {
268                                 if(objs[i] instanceof WebserviceEndpoint) {
269                                     WebserviceEndpoint endpoint = (WebserviceEndpoint) objs[i];
270                                     if(portComponentName.equals(endpoint.getPortComponentName())) {
271                                         host.removeValue(endpointType, endpoint);
272                                         removedEndpoint = endpoint;
273                                     }
274                                 }
275                             }
276                         }
277                     }
278                 }
279             } catch(IllegalArgumentException JavaDoc ex) {
280                 // programmer bug if this happens.
281
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
282             }
283         }
284         return removedEndpoint;
285     }
286     
287     protected Map JavaDoc getNamedBeanMap(String JavaDoc type) {
288         return (Map JavaDoc) namedBeanCache.get(type);
289     }
290     
291     protected void saveAllNamedBeans(CommonDDBean parentBean) {
292         Iterator JavaDoc iter = getNamedBeanSpecs().iterator();
293         while(iter.hasNext()) {
294             NamedBean beanSpec = (NamedBean) iter.next();
295             try {
296                 Object JavaDoc data = parentBean.getValues(beanSpec.getType());
297                 if(data instanceof CommonDDBean []) {
298                     saveNamedBeans(beanSpec.getType(), beanSpec.getPropertyName(), (CommonDDBean []) data);
299                 } else if(data != null) {
300 // System.out.println("saveAllNamedBeans: unexpected datatype - " + data.getClass().getSimpleName());
301
}
302             } catch(Exception JavaDoc ex) {
303                 // if property does not exist, we'll get a runtime exception from schema2beans.
304
// System.out.println("saveAllNamedBeans: " + ex.getLocalizedMessage());
305
}
306         }
307     }
308     
309     protected void restoreAllNamedBeans(CommonDDBean parentBean, String JavaDoc version) {
310         Iterator JavaDoc iter = getNamedBeanSpecs().iterator();
311         while(iter.hasNext()) {
312             NamedBean beanSpec = (NamedBean) iter.next();
313             Map JavaDoc beanMap = getNamedBeanMap(beanSpec.getType());
314             restoreNamedBeans(beanMap, beanSpec.getType(), parentBean, version);
315         }
316     }
317     
318     protected void restoreNamedBeans(Map JavaDoc beanMap, String JavaDoc parentPropertyName, CommonDDBean parentBean, String JavaDoc version) {
319         if(beanMap != null && beanMap.size() > 0) {
320             for (Iterator JavaDoc beanIter = beanMap.entrySet().iterator(); beanIter.hasNext();) {
321                 try {
322                     Map.Entry JavaDoc entry = (Map.Entry JavaDoc) beanIter.next();
323                     CommonDDBean bean = (CommonDDBean) entry.getValue();
324                     parentBean.addValue(parentPropertyName, bean.cloneVersion(version));
325                 } catch(Exception JavaDoc ex) {
326                     // if property does not exist, ignore the runtime exception from schema2beans.
327
// System.out.println("restoreNamedBeans: " + ex.getLocalizedMessage());
328
}
329             }
330         }
331     }
332     
333     protected void updateNamedBeanCache(String JavaDoc type) {
334         if(parent != null) {
335             String JavaDoc name = getComponentName();
336             if(Utils.notEmpty(name)) {
337                 parent.removeNamedBean(type, name);
338             }
339         }
340     }
341     
342     protected Collection JavaDoc getNamedBeanSpecs() {
343         return Collections.EMPTY_LIST;
344     }
345     
346     private static Collection JavaDoc commonAppBeanSpecs = new ArrayList JavaDoc();
347     
348     static {
349         commonAppBeanSpecs.add(new NamedBean(SunWebApp.EJB_REF,
350                 org.netbeans.modules.j2ee.sun.dd.api.common.EjbRef.EJB_REF_NAME));
351         commonAppBeanSpecs.add(new NamedBean(SunWebApp.MESSAGE_DESTINATION_REF,
352                 org.netbeans.modules.j2ee.sun.dd.api.common.MessageDestinationRef.MESSAGE_DESTINATION_REF_NAME));
353         commonAppBeanSpecs.add(new NamedBean(SunWebApp.RESOURCE_ENV_REF,
354                 org.netbeans.modules.j2ee.sun.dd.api.common.ResourceEnvRef.RESOURCE_ENV_REF_NAME));
355         commonAppBeanSpecs.add(new NamedBean(SunWebApp.RESOURCE_REF,
356                 org.netbeans.modules.j2ee.sun.dd.api.common.ResourceRef.RES_REF_NAME));
357         commonAppBeanSpecs.add(new NamedBean(SunWebApp.SERVICE_REF,
358                 org.netbeans.modules.j2ee.sun.dd.api.common.ServiceRef.SERVICE_REF_NAME));
359     }
360     
361     protected static Collection JavaDoc getCommonNamedBeanSpecs() {
362         return commonAppBeanSpecs;
363     }
364     
365     protected static class NamedBean {
366         private final String JavaDoc type;
367         private final String JavaDoc propertyName;
368         
369         public NamedBean(final String JavaDoc t, final String JavaDoc pn) {
370             type = t;
371             propertyName = pn;
372         }
373         
374         public String JavaDoc getType() {
375             return type;
376         }
377         
378         public String JavaDoc getPropertyName() {
379             return propertyName;
380         }
381     }
382     
383
384     /** -----------------------------------------------------------------------
385      * Validation implementation
386      */

387     protected final synchronized ErrorMessageDB getMessageDB() {
388         if(errorMessageDB == null) {
389             errorMessageDB = ErrorMessageDB.createMessageDB();
390         }
391         return errorMessageDB;
392     }
393
394     /** !PW This member is interesting. It stores the list of fieldId's that this
395      * bean can validate. The list is built as the various derived classes add
396      * the fields they control to the list (see ejb's which are quite multi-tiered.)
397      * In that sense, two objects of the same type (2 ejb-ref's, 2 servlets, etc.)
398      * have the same list and should be able to use the same list. However, this
399      * field cannot be static because then it would be shared by all classes,
400      * irrespective of type. For now, it will be unique per bean, but a better
401      * way is probably some registry where beans of the same type can share the
402      * same list.
403      */

404     protected List JavaDoc validationFieldList = new ArrayList JavaDoc();
405
406     /** override this method (and call overridden version via super) to add
407      * fields to the validation field id list.
408      */

409     protected void updateValidationFieldList() {
410     }
411
412     public void validationStateChanged(Boolean JavaDoc newState) {
413         isValid = newState;
414         getPCS().firePropertyChange(DISPLAY_NAME, "", getDisplayName());
415     }
416
417     /** Returns previous result of validateFields() or invokes method if status is
418      * out of date.
419      *
420      * @return true if valid, false otherwise.
421      */

422     public boolean isValid() {
423         if(isValid == null) {
424             boolean tempValid = validateFields(true);
425             isValid = Boolean.valueOf(tempValid);
426         }
427
428         return isValid.booleanValue();
429     }
430
431     /** Validate the fields managed by this bean. Used by the customizers
432      * (and possibly incremental deployment.)
433      *
434      * @return true or false as to whether bean is valid or not.
435      */

436     public boolean validateFields(boolean shortCircuit) {
437         ErrorMessageDB messageDB = getMessageDB();
438         boolean result = true;
439
440         messageDB.clearErrors();
441         for(Iterator JavaDoc iter = validationFieldList.iterator(); iter.hasNext() && (result || !shortCircuit); ) {
442             boolean fieldResult = validateField((String JavaDoc) iter.next());
443             result = result && fieldResult;
444         }
445
446         isValid = Boolean.valueOf(result);
447
448         return result;
449     }
450
451     /** Validate a single field managed by this bean. Used by the customizers
452      * (and possibly incremental deployment.)
453      *
454      * @param field Field spec (xpath to this field in DTD, should be defined
455      * constant in bean class.)
456      * @return true or false as to whether field is valid or not.
457      */

458     public boolean validateField(String JavaDoc fieldId) {
459         return true;
460     }
461
462     /** -----------------------------------------------------------------------
463      * Implementation of XpathListener interface
464      */

465     public void fireXpathEvent(XpathEvent JavaDoc xpe) {
466 // dumpNotification("fireXpathEvent", xpe);
467
}
468
469     /* ------------------------------------------------------------------------
470      * Version retrieval methods
471      */

472     public J2EEBaseVersion getJ2EEModuleVersion() {
473         Base parent = getParent();
474         if(parent != null) {
475             return getParent().getJ2EEModuleVersion();
476         } else {
477             ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, new IllegalStateException JavaDoc("getJ2EEModuleVersion() called on child DConfigBean with null parent: " + this));
478         }
479         return null;
480     }
481
482     public ASDDVersion getAppServerVersion() {
483         Base parent = getParent();
484         if(parent != null) {
485             return getParent().getAppServerVersion();
486         } else {
487             ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, new IllegalStateException JavaDoc("getAppServerVersion() called on child DConfigBean with null parent: " + this));
488         }
489         return null;
490     }
491
492     /* ------------------------------------------------------------------------
493      * Child bean finder methods
494      */

495     protected DDBean JavaDoc getNameDD(String JavaDoc nameXpath) throws ConfigurationException JavaDoc {
496         DDBean JavaDoc nameDD = null;
497
498         DDBean JavaDoc[] beans = getDDBean().getChildBean(nameXpath);
499         if(beans.length == 1) {
500             // Found the DDBean we want.
501
nameDD = beans[0];
502         } else {
503             Object JavaDoc [] args = new Object JavaDoc[2];
504             args[0] = getDDBean().getXpath();
505             args[1] = nameXpath;
506
507             if(beans.length > 1) {
508                 throw Utils.makeCE("ERR_DDBeanHasDuplicateRequiredXpaths", args, null); // NOI18N
509
} else {
510                 throw Utils.makeCE("ERR_DDBeanMissingRequiredXpath", args, null); // NOI18N
511
}
512         }
513
514         return nameDD;
515     }
516
517     protected void validateDDBean(DDBean JavaDoc ddBean) throws ConfigurationException JavaDoc {
518         // DDBean cannot be null
519
if(ddBean == null) {
520             throw Utils.makeCE("ERR_DDBeanIsNull", null, null); // NOI18N
521
}
522
523         // DDBean's xpath cannot be null
524
if(ddBean.getXpath() == null) {
525             throw Utils.makeCE("ERR_DDBeanHasNullXpath", null, null); // NOI18N
526
}
527
528         // Note: DDBean's text field can be empty (and so presumably can be null).
529
}
530
531
532
533     /* ------------------------------------------------------------------------
534      * DConfigBean interface methods
535      */

536     /** Returns the beans that hold configuration data for particular
537      * subelements of the application.xml
538      * @param dDBean DDBean representing an xpath for which we want to attach a DConfigBean.
539      * @throws ConfigurationException if there is an error creating the sub-bean
540      * @return The DConfigBean that holds extended configuration data.
541      */

542     public DConfigBean JavaDoc getDConfigBean(DDBean JavaDoc dDBean)
543             throws javax.enterprise.deploy.spi.exceptions.ConfigurationException JavaDoc {
544         try {
545             jsr88Logger.entering(Base.class.toString(),"getDConfigBean",dDBean);
546
547             validateDDBean(dDBean);
548             Base dcbResult = getDCBInstance(dDBean);
549
550             // !PW If we get a result from the cache, we should verify that the bean
551
// return is the correct type for the DDBean passed in, in case someone
552
// is trying to reuse DDBean objects (ala Vince in his test case!)
553

554             if(dcbResult == null) {
555                 dcbResult = getDCBFactoryMgr().createDCB(dDBean, this);
556
557                 if(dcbResult != null) {
558                     putDCBInstance(dcbResult);
559                     addChild(dcbResult);
560
561                     // Lastly, if this bean is a member of a group, return the head
562
// of the group to the caller.
563
//
564
Base groupHead = dcbResult.getDCBHead();
565                     if(groupHead != null) {
566                         dcbResult = groupHead;
567                     }
568                     
569                     // !PW FIXME bug workaround IZ 41214
570
beanAdded(dcbResult.getDDBean().getXpath());
571                 }
572             }
573
574             return dcbResult;
575         } catch(java.lang.AssertionError JavaDoc ex) {
576             ConfigurationException JavaDoc ce = new ConfigurationException JavaDoc();
577             ce.initCause(ex);
578             throw ce;
579         } catch(RuntimeException JavaDoc ex) {
580             throw Utils.makeCE("ERR_UnknownConfigException", null, ex); // NOI18N
581
}
582     }
583
584     /** !PW FIXME Workaround for broken XpathEvent.BEAN_ADDED not being sent.
585      * Override this method (see WebAppRoot) to be notified if a child bean
586      * is created. See IZ 41214
587      */

588     protected void beanAdded(String JavaDoc xpath) {
589     }
590
591     /** !PW FIXME Workaround for broken XpathEvent.BEAN_REMOVED not being sent.
592      * Override this method (see WebAppRoot) to be notified if a child bean
593      * is destroyed. See IZ 41214
594      */

595     protected void beanRemoved(String JavaDoc xpath) {
596     }
597
598     /**
599      * @return
600      */

601     public DDBean JavaDoc getDDBean() {
602         return this.dDBean;
603     }
604
605     /** Xpaths that this bean extends. Each DConfigBean that has children will
606      * provide an array of xpaths (which, by the way, are happen to be the keys
607      * in the factory mapping for those children).
608      * @return The array of xpaths that are interesting to this DConfigBean instance
609      */

610     public String JavaDoc[] getXpaths() {
611         return getDCBFactoryMgr().getFactoryKeys();
612     }
613
614     /** The DDBean (or one of it's children) that this DConfigBean is bound to
615      * has changed.
616      *
617      * @param xpathEvent
618      */

619     public void notifyDDChange(XpathEvent JavaDoc xpathEvent) {
620 // dumpNotification("notifyDDChange", xpathEvent);
621
}
622
623 // protected void dumpNotification(String fnName, XpathEvent xpathEvent) {
624
// String type;
625
//
626
// if(xpathEvent.isAddEvent()) {
627
// type = "BEAN_ADD";
628
// } else if(xpathEvent.isRemoveEvent()) {
629
// type = "BEAN_REMOVE";
630
// } else if(xpathEvent.isChangeEvent()) {
631
// type = "BEAN_CHANGE";
632
// } else {
633
// type = "UNKNOWN TYPE";
634
// }
635
//
636
// System.out.println(fnName + ": XPATHEVENT: " + type +
637
// ", DCB identity = " + getIdentity() +
638
// ", DCB type = " + getClass().getName() +
639
// ", xpath = " + xpathEvent.getBean().getXpath() +
640
// ", DCB xpath = " + getDDBean().getXpath());
641
// }
642

643         /** JSR-88: Removes a child DConfigBean from this bean.
644          * Spec interpretation note: If the dConfigBean parameter refers to a bean
645          * that has it's own children, those children are also removed, ad infinitum.
646          *
647      * @param dConfigBean The child DConfigBean to remove from this DConfigBean
648      * @throws BeanNotFoundException
649      */

650     public void removeDConfigBean(DConfigBean JavaDoc dConfigBean) throws BeanNotFoundException JavaDoc {
651         if(dConfigBean != null) {
652             if(dConfigBean.getDDBean() != null) {
653                 if(((Base) dConfigBean).getParent() == this) {
654                     // Handle children first.
655

656                     // Can't use iterator here or we will possibly get a ConcurrentModificationException
657
// as the children clean themselves up.
658
Base beanToRemove = (Base) dConfigBean;
659                     Object JavaDoc children[] = beanToRemove.getChildren().toArray();
660                     for(int i = 0; i < children.length; i++) {
661                         try {
662                             beanToRemove.removeDConfigBean((Base) children[i]);
663                         } catch(BeanNotFoundException JavaDoc ex) {
664                             // This would suggest a corrupt tree or bad code somewhere if it happens.
665
// Catch & log it and continue cleaning the tree.
666
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
667                         }
668                     }
669
670                     DDBean JavaDoc key = dConfigBean.getDDBean();
671                     beanToRemove = removeDCBInstance(key);
672
673                     if(beanToRemove != null) {
674                         if(beanToRemove instanceof BaseRoot) {
675                             // remove from root cache as well.
676
BaseRoot rootBean = (BaseRoot) getConfig().getDCBRootCache().remove(key);
677
678                             if(rootBean != null) {
679                                 assert(rootBean == beanToRemove); // these should be the same, right?
680
}
681                         } else if(beanToRemove instanceof BaseModuleRef) {
682                             // Clean up patch list - the patch list should be empty, but you never know...
683
getConfig().getPatchList().remove(key);
684                         }
685                     }
686
687                     if(beanToRemove != null) {
688                         // !PW FIXME 1st half - workaround for IZ 41214 (see method comment)
689
String JavaDoc beanXpath = beanToRemove.getDDBean().getXpath();
690
691                         // cleanup bean before throwing away
692
beanToRemove.cleanup();
693                         beanToRemove = null;
694
695                         // !PW FIXME 2nd half - workaround for IZ 41214 (see method comment)
696
beanRemoved(beanXpath);
697                     } else {
698                         Object JavaDoc [] args = new Object JavaDoc [2];
699                         args[0] = dConfigBean.getDDBean();
700                         args[1] = key.getXpath();
701                         throw new BeanNotFoundException JavaDoc(MessageFormat.format(
702                             bundle.getString("ERR_DConfigBeanNotFoundOnRemove"), args));
703                     }
704                 } else {
705                     // The parent of the DConfigBean parameter is not this instance - spec violation.
706
throw new BeanNotFoundException JavaDoc(
707                         bundle.getString("ERR_DConfigBeanWrongParentOnRemove"));
708                 }
709             } else {
710                 // DDBean is null. This could be that this DConfigBean has
711
// previously been removed.
712
throw new BeanNotFoundException JavaDoc(
713                     bundle.getString("ERR_DConfigBeanNotFoundOnRemoveNullDDBean"));
714             }
715         } else {
716             // DConfigBean is null
717
throw new BeanNotFoundException JavaDoc(
718                 bundle.getString("ERR_DConfigBeanNotFoundOnRemoveNullDConfigBean"));
719         }
720     }
721
722     /**
723      * @param pCL
724      */

725     public void addPropertyChangeListener(PropertyChangeListener JavaDoc pCL) {
726         propertyChangeSupport.addPropertyChangeListener(pCL);
727     }
728
729     /**
730      * @param pCL
731      */

732     public void removePropertyChangeListener(PropertyChangeListener JavaDoc pCL) {
733         propertyChangeSupport.removePropertyChangeListener(pCL);
734     }
735
736     /**
737      * @return
738      */

739     protected PropertyChangeSupport JavaDoc getPCS() {
740         return propertyChangeSupport;
741     }
742
743     /**
744      * @return
745      */

746     protected VetoableChangeSupport JavaDoc getVCS() {
747         return vetoableChangeSupport;
748     }
749
750     /** Adds a VetoableChangeListener to the listener list.
751      * @param l The listener to add.
752      *
753      */

754     public void addVetoableChangeListener(VetoableChangeListener JavaDoc l) {
755         vetoableChangeSupport.addVetoableChangeListener(l);
756     }
757
758     /** Removes a VetoableChangeListener from the listener list.
759      * @param l The listener to remove.
760      *
761      */

762     public void removeVetoableChangeListener(VetoableChangeListener JavaDoc l) {
763         vetoableChangeSupport.removeVetoableChangeListener(l);
764     }
765
766     /**
767      * @return
768      */

769     public Base getParent() {
770         return parent;
771     }
772
773     /** Retrieve the parser provided by the root DCB in this tree. Failing that,
774      * return the parser provided by the master root DCB of the entire configuration.
775      */

776     protected ConfigParser getParser() {
777         Base parent = getParent();
778         if(parent != null) {
779             return parent.getParser();
780         }
781
782         SunONEDeploymentConfiguration config = getConfig();
783         if(config != null) {
784             BaseRoot dcbRoot = config.getMasterDCBRoot();
785             if(dcbRoot != null) {
786                 return dcbRoot.getParser();
787             }
788         }
789
790         return null;
791     }
792
793     /** A DConfigBean may represent data that would go into multiple descriptor
794      * files. A DConfigBean may also expose properties of a super bean. These
795      * snippets are used to hold the schema2beans object and the name of the file
796      * that the bean will be part of. They are merged in Base.addToGraphs()
797      * to produce the deployment plan file.
798      *
799      * @return a collection of snippet objects for this bean. Null is not allowed.
800      */

801     abstract Collection JavaDoc getSnippets();
802
803     /** Loads the values of the DConfigBean properties from the deployment plan file
804      * that this bean's DeploymentConfiguration parent read. This method should be
805      * called by init. It is also called in the restore methods on
806      * DeploymentConfiguration.
807      *
808      * @param config The SunONEDeploymentConfig object that read in the deployment plan file
809      * @return true if a bean was found and loaded, false otherwise.
810      */

811     abstract boolean loadFromPlanFile(SunONEDeploymentConfiguration config);
812
813     /** This method operates recursively to perform a depth first search of the
814      * DConfigBean hierarchy, creating the corresponding schema2beans graph as
815      * it travels. Pieces of the graph can be merged as children of the tracking
816      * parent, or into other parts of a root found in the graph, or finally, into
817      * whole new roots that are added to the final map.
818      *
819      * @param map A map of file names to schema2beans object graphs
820      * @param bbCurrent The current tracking parent basebean
821      * @parem bbKey The map lookup key that matches the current tracking bean passed in
822      */

823     public void addToGraphs(Map JavaDoc map, CommonDDBean bbCurrent, String JavaDoc bbKey) {
824         jsr88Logger.entering(this.getClass().toString(), "addToGraphs"); // NOI18N
825

826         String JavaDoc uriText = getUriText();
827         Collection JavaDoc snippets = getSnippets();
828
829         boolean isFirst = true;
830         CommonDDBean newCurrentBean = null;
831         String JavaDoc newSnippetKey = "";
832
833         Iterator JavaDoc iter = snippets.iterator();
834         while(iter.hasNext()) {
835             try {
836                 CommonDDBean bean = null;
837                 Snippet s = (Snippet) iter.next();
838
839                 if(s.hasDDSnippet()) {
840                     String JavaDoc snippetKey = Utils.getFQNKey(uriText, s.getFileName());
841                     if(snippetKey.compareTo(bbKey) == 0) {
842                         // merge with current basebean
843
bean = s.mergeIntoRovingDD(bbCurrent);
844                     } else if(map.containsKey(snippetKey)) {
845                         // merge with root -- this option is unlikely to be used it means that the
846
// current snippet IS represented in existing graph AND the current roving
847
// bean is NOT in the same tree, so we must merge at root level with the root
848
// we found in the graph.
849
//
850
// !PW This option is now used by WebAppCache, a javabean that represents the
851
// cache portion of sun-web.xml and is owned/parented by WebAppRoot.
852
//
853
try {
854                             bean = s.mergeIntoRootDD((CommonDDBean) map.get(snippetKey));
855                         } catch(UnsupportedOperationException JavaDoc ex) {
856                             jsr88Logger.finest("Invalid Snippet: Snippet Class: " + s.getClass().getName());
857                             CommonDDBean parent = (CommonDDBean) map.get(snippetKey);
858                             jsr88Logger.finest("Parent Bean: " + ((parent != null) ? parent.getClass().getName() : "(null -- ack!)"));
859                             jsr88Logger.finest("Snippet Key: " + snippetKey);
860                             jsr88Logger.finest("Snippet Property Name: " + s.getPropertyName());
861                             throw ex;
862                         }
863                     } else {
864                         // create new basebean from root and add to graph
865
bean = s.getDDSnippet();
866
867                         // !PW FIXME Cmp SNIPPET is temporarily returning null here.
868
if(bean != null) {
869                             map.put(snippetKey, bean);
870                         }
871                     }
872
873                     if(isFirst) {
874                         // Save bean from first snippet for passing to children.
875
newCurrentBean = bean;
876                         newSnippetKey = snippetKey;
877                         isFirst = false;
878                     }
879                 }
880             } catch(Exception JavaDoc ex) {
881                 jsr88Logger.log(Level.SEVERE, "Base.newAddToGraph() -- exception processing bean", ex); // NOI18N
882
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
883             }
884         }
885
886         // Handle children before returning
887
//
888
Collection JavaDoc childList = getChildren();
889         iter = childList.iterator();
890         while(iter.hasNext()) {
891             Base childDCB = (Base) iter.next();
892             childDCB.addToGraphs(map, processParentBean(newCurrentBean, childDCB), newSnippetKey);
893         }
894
895         jsr88Logger.exiting(this.getClass().toString(), "addToGraphs"); // NOI18N
896
}
897
898     /** This method allows some customization of how parent basebeans are adjusted
899      * when the depthfirst search in addToGraphs is passing a parent basebean
900      * on to a child DConfigBean. In most cases, no adjustment is necessary.
901      * See BaseEjb.processParentBean for a case where it is.
902      */

903     protected CommonDDBean processParentBean(CommonDDBean bean, DConfigBean JavaDoc child) {
904         // Calculate what the parent S2B bean should be for this child and
905
// return that.
906
//
907
// Basic implementation assumes no translation is necessary
908
return bean;
909     }
910
911     /**
912      * @return
913      */

914     Collection JavaDoc getChildren() {
915         return children;
916     }
917
918     public String JavaDoc getUriText() {
919         if(parent != null) {
920             return parent.getUriText();
921         }
922
923         // This should never get executed actually, since this method is
924
// overridden in BaseRoot. But just in case...
925
return ""; // NOI18N
926
}
927
928     static private char XPATH_SEPCHAR = '/';
929
930     /** Holds value of property xpath. */
931     //private String xpath;
932

933     /** hack to clean up the J2EE 1.4 RI beta 1 getText() value on a DDBean.
934      * @param dDBean the bean that is having its text cleaned
935      */

936     static String JavaDoc cleanDDBeanText(DDBean JavaDoc dDBean) {
937         String JavaDoc candidate = null;
938
939         try {
940             if(dDBean == null) {
941                 return candidate;
942             }
943
944             candidate = dDBean.getText();
945             if (null == candidate || (candidate.length() == 0)) {
946                 return candidate;
947             }
948
949             if (!candidate.startsWith("<?xml")) { // NOI18N
950
return candidate;
951             }
952
953             String JavaDoc xpath = dDBean.getXpath();
954             if (null == xpath || (xpath.length() == 0)) {
955                 return candidate;
956             }
957
958             int lindex = xpath.lastIndexOf(XPATH_SEPCHAR);
959             if (lindex > -1) {
960                 lindex += 1;
961                 String JavaDoc finalEl = xpath.substring(lindex);
962                 finalEl = "<" + finalEl + ">"; // NOI18N
963
int elementPos = candidate.indexOf(finalEl);
964                 if (elementPos < 0) {
965                     return candidate;
966                 }
967                 String JavaDoc retVal = candidate.substring(elementPos + finalEl.length());
968                 if (retVal.length() < finalEl.length() + 1) {
969                     return retVal;
970                 }
971                 retVal = retVal.substring(0,retVal.length() - (finalEl.length()+2));
972                 return retVal;
973             }
974         } catch(RuntimeException JavaDoc ex) {
975             jsr88Logger.throwing("Base", "cleanDDBeanText", ex); // NOI18N
976
}
977
978         return candidate;
979     }
980
981     private DDBean JavaDoc secondary;
982     private Set JavaDoc children = new LinkedHashSet JavaDoc();
983
984     /**
985      * @param newKid
986      */

987     protected void addChild(DConfigBean JavaDoc bean) {
988         children.add(bean);
989     }
990
991     protected boolean removeChild(DConfigBean JavaDoc bean) {
992         return children.remove(bean);
993     }
994
995     /**
996      * @param secondary
997      */

998     void setSecondary(DDBean JavaDoc secondary) {
999         this.secondary = secondary;
1000    }
1001
1002    /**
1003     * @return
1004     */

1005    public SunONEDeploymentConfiguration getConfig() {
1006        if (null != parent) {
1007            return parent.getConfig();
1008        }
1009
1010        return null;
1011    }
1012
1013    /* ------------------------------------------------------------------------
1014     * Implementation of DConfigBeanUIFactory interface
1015     *
1016     * This interface allows DConfigBeanProperties object retrieval which is
1017     * primarily toallow UI customization beyond that provided by JSR-88 1.1 and
1018     * the Java Beans 1.01 specification.
1019     */

1020    /** Retrieve the DConfigBeanProperties object for this DConfigBean
1021     *
1022     * @param self Implementation artifact. Should be null or same as 'this'.
1023     * It is not used.
1024     * @return DConfigBeanProperties Object that provides the extra properties
1025     * needed for display.
1026     */

1027    public DConfigBeanProperties getUICustomization(DConfigBean JavaDoc self) {
1028        return new DConfigBeanProperties() {
1029            public String JavaDoc getDisplayName() {
1030                return Base.this.getDisplayName();
1031            }
1032
1033            public String JavaDoc getHelpId() {
1034                return Base.this.getHelpId();
1035            }
1036        };
1037    }
1038
1039    /** Getter for displayName property
1040     * @return String suitable for display
1041     */

1042    public String JavaDoc getDisplayName() {
1043        // This shows the name of the particular bean, if it has one. For example,
1044
// servlets, ejb's, modules inside EAR's, etc.
1045
//
1046
String JavaDoc name = getComponentName();
1047        Object JavaDoc [] args = new Object JavaDoc [1];
1048        args[0] = Utils.notEmpty(name) ? name : getDescriptorElement();
1049        String JavaDoc pattern = bundle.getString(isValid() ? "LBL_BeanDisplayName" : "LBL_BeanDisplayNameBroken");
1050        return MessageFormat.format(pattern, args);
1051    }
1052
1053    /** Getter for helpId property. Override this method to provide the correct
1054     * help context id for any specific DConfigBean.
1055     *
1056     * @return Help context ID for this DConfigBean
1057     */

1058        abstract public String JavaDoc getHelpId();
1059/* public String getHelpId() {
1060        // the default should be no help, not a debug message only targetted at us, the developer
1061                // of this plugin.
1062        //assert false : this.getClass().getName() + " does not override getHelpId!!!"; // NOI18N
1063        return "";
1064    }
1065*/

1066    /* ------------------------------------------------------------------------
1067     * DConfigBean caching support. Allows lookup of existing DCB's by their
1068     * associated DDBean as a key.
1069     */

1070
1071    /**
1072     * @param base
1073     */

1074    protected void putDCBInstance(Base base) {
1075        DDBean JavaDoc key = base.getDDBean();
1076        if(key != null) {
1077            SunONEDeploymentConfiguration config = getConfig();
1078            if(config != null) {
1079                Map JavaDoc cache = config.getDCBCache();
1080
1081                Object JavaDoc existingDCB = cache.get(key);
1082                if(existingDCB != null) {
1083// jsr88Logger.finest("DCBCache: Replacing existing DCB '" + existingDCB + "' with '" + base + "'"); // NOI18N
1084
} else {
1085// jsr88Logger.finest("DCBCache: Adding DCB to cache, ddbean key = '" + key.getXpath() + "'"); // NOI18N
1086
}
1087
1088                cache.put(key, base);
1089            } else {
1090// jsr88Logger.finest("DCBCache: Error: DCB '" + this + "' has null config so '" + base + "' cannot be cached"); // NOI18N
1091
}
1092        } else {
1093// jsr88Logger.finest("DCBCache: Error: DCB '" + base + "' has null DDBean"); // NOI18N
1094
}
1095    }
1096
1097    /**
1098     * @param key
1099     * @return
1100     */

1101    protected Base getDCBInstance(DDBean JavaDoc key) {
1102// jsr88Logger.finest("DCBCache: Looking for DCB to match ddbean key '" + key.getXpath() + "'");
1103

1104        Base result = null;
1105        SunONEDeploymentConfiguration config = getConfig();
1106
1107        if(config != null) {
1108            Map JavaDoc cache = config.getDCBCache();
1109            Object JavaDoc o = cache.get(key);
1110
1111            if(o != null) {
1112                if(o instanceof Base) {
1113                    result = (Base) o;
1114                } else {
1115// jsr88Logger.finest("DCBCache(get): Error: object matching DDBean key is wrong type: '" + o.getClass().getName() + "'"); // NOI18N
1116
}
1117            } else {
1118// jsr88Logger.finest("DCBCache: No DCB match for key: '" + key.getXpath() + "'"); // NOI18N
1119
}
1120        } else {
1121// jsr88Logger.finest("DCBCache(get): Error: DCB '" + this + "' has null config therefore no cache to search"); // NOI18N
1122
}
1123
1124        return result;
1125    }
1126
1127    /**
1128     * @param base
1129     * @return
1130     */

1131    protected Base removeDCBInstance(Base base) {
1132        return removeDCBInstance(base.getDDBean());
1133    }
1134
1135    /**
1136     * @param key
1137     * @return
1138     */

1139    protected Base removeDCBInstance(DDBean JavaDoc key) {
1140        Base result = null;
1141        SunONEDeploymentConfiguration config = getConfig();
1142
1143        if(config != null) {
1144            Map JavaDoc cache = config.getDCBCache();
1145            Object JavaDoc o = cache.remove(key);
1146
1147            if(o != null) {
1148                if(o instanceof Base) {
1149                    result = (Base) o;
1150                } else {
1151// jsr88Logger.finest("DCBCache: Error: object matching DDBean key is wrong type: '" + o.getClass().getName() + "'"); // NOI18N
1152
}
1153            }
1154        } else {
1155// jsr88Logger.finest("DCBCache(get): Error: DCB '" + this + "' has null config therefore no cache to search"); // NOI18N
1156
}
1157
1158        return result;
1159    }
1160
1161    /* ------------------------------------------------------------------------
1162     * Group child bean support. For any child beans that are stored as groups,
1163     * e.g. SecurityRoleMapping, ResourceEnvRef, etc., the parent owns the head
1164     * of the group. This support provides that storage, as well as a mechanism
1165     * for locating the head for a particular group (some parents have children
1166     * in more than one group, e.g. WarRoot has both ejbRef's and resRef's, both
1167     * of which are grouped.
1168     */

1169    /** ----------------------- Support used by parent DCB --------------------
1170     */

1171    /** dcbChildGroupMap is initally null because most beans will not even use
1172     * this system. Only DCB's that have linked groups of like child DCB's,
1173     * such as SecurityRoleMapping, ResRef, or EjbRef will use this capability.
1174     */

1175    private Map JavaDoc dcbChildGroupMap = null;
1176
1177    /**
1178     * @param dDBean
1179     * @return
1180     */

1181    protected Base getDCBGroup(DDBean JavaDoc dDBean) {
1182        Base dcbResult = null;
1183
1184        if(dcbChildGroupMap != null) {
1185            dcbResult = (Base) dcbChildGroupMap.get(dDBean.getXpath());
1186        }
1187
1188        return dcbResult;
1189    }
1190
1191    /**
1192     * @param dcb
1193     */

1194    protected void addDCBGroup(Base dcb) {
1195        if(dcbChildGroupMap == null) {
1196            dcbChildGroupMap = new HashMap JavaDoc(7);
1197        }
1198
1199        if(getDCBGroup(dcb.getDDBean()) == null) {
1200            dcbChildGroupMap.put(dcb.getDDBean().getXpath(), dcb);
1201        }
1202    }
1203
1204    /** ----------------------- Support used by child DCB --------------------
1205     */

1206    /** internal list of beans */
1207    private List JavaDoc groupDCBList = null;
1208    private Base dcbHead = null;
1209
1210    /** initializes a member of a bean group, making the bean the head (or
1211     * adding this bean to an existing group in the specified parent).
1212     * @param dDBean used to get the xpath that allows finding an existing
1213     * group in the parent, if any.
1214     * @param parent the parent of this bean, where we look to see if there
1215     * is an existing group
1216     */

1217    protected void initGroup(DDBean JavaDoc dDBean, Base parent) {
1218        if(parent != null) {
1219            Base dcb = parent.getDCBGroup(dDBean);
1220            if(dcb != null) {
1221                /* Head has already been created -- this is an additional bean
1222                 * of same type.
1223                 */

1224                dcbHead = dcb;
1225                dcbHead.addDCBToGroup(this);
1226            } else {
1227                /* Head is null, this is the first bean of it's type in for
1228                 * the given parent.
1229                 */

1230                dcbHead = this;
1231                addDCBToGroup(this);
1232
1233                parent.addDCBGroup(this);
1234            }
1235        }
1236    }
1237
1238    /** Adds beans to the list of like-grouped beans. Only the head bean in the
1239     * list will initialize and use this list. Other beans in the list will
1240     * have a reference to the head bean. If the head bean is null, the list
1241     * reference should also be null and that indicates this bean does not
1242     * support being grouped (though it may still be the parent of beans that
1243     * are grouped).
1244     * @param dcb DConfigBean to add to this group. Should only call this
1245     * method on the bean that is the head of a group (i.e. do not call it
1246     * on a member of a group that is not the head.)
1247     */

1248    private void addDCBToGroup(Base dcb) {
1249        if(groupDCBList == null) {
1250            groupDCBList = new ArrayList JavaDoc(10);
1251        }
1252
1253        groupDCBList.add(dcb);
1254    }
1255
1256    /** Retrieves the head bean of a bean group.
1257     * @return returns the head bean of bean group.
1258     */

1259    protected Base getDCBHead() {
1260        return dcbHead;
1261    }
1262
1263    /* ------------------------------------------------------------------------
1264     * Xpath to Factory mapping support
1265     */

1266    private static final java.util.Map JavaDoc defaultXPathToFactory = new java.util.HashMap JavaDoc();
1267
1268    /** Retrieve the XPathToFactory map for this DConfigBean. For Base, this is
1269     * the default map, which is empty.
1270     * @return
1271     */

1272    protected java.util.Map JavaDoc getXPathToFactoryMap() {
1273        return defaultXPathToFactory;
1274    }
1275
1276    private DCBFactoryMgr factoryMgrInstance = null;
1277
1278    /** Retrieve the factory manager for this DConfigBean. If one has not been
1279     * constructed yet, create it.
1280     * @return
1281     */

1282    DCBFactoryMgr getDCBFactoryMgr() {
1283        if(factoryMgrInstance == null) {
1284            factoryMgrInstance = new DCBFactoryMgr(getXPathToFactoryMap(), getDDBean().getXpath());
1285        }
1286
1287        return factoryMgrInstance;
1288    }
1289
1290    /* ------------------------------------------------------------------------
1291     * More persistence support
1292     */

1293
1294    /** Determine which file this bean is likely to go into. This is based on
1295     * the bean's DDBean "buddy".
1296     */

1297    protected String JavaDoc constructFileName() {
1298        String JavaDoc ddXpath = dDBean.getXpath();
1299        StringBuffer JavaDoc fname = new StringBuffer JavaDoc(32);
1300        fname.append("sun-"); // NOI18N
1301

1302        if(null != ddXpath) {
1303            if(ddXpath.startsWith("/ejb-jar")) { // NOI18N
1304
fname.append("ejb-jar"); // NOI18N
1305
} else if(ddXpath.startsWith("/web-app")) { // NOI18N
1306
fname.append("web"); // NOI18N
1307
} else if(ddXpath.startsWith("/application")) { // NOI18N
1308
if (ddXpath.indexOf("client") > -1 ) { // NOI18N
1309
fname.append("application-client"); // NOI18N
1310
} else {
1311                    fname.append("application"); // NOI18N
1312
}
1313            } else if(ddXpath.startsWith("/connector")) { // NOI18N
1314
fname.append("connector"); // NOI18N
1315
} else {
1316                String JavaDoc mess = MessageFormat.format(bundle.getString("ERR_InvalidXPathValueUsage"), // NOI18N
1317
new Object JavaDoc[] { ddXpath });
1318                throw new java.lang.IllegalStateException JavaDoc(mess);
1319            }
1320        } else {
1321            // this is bad
1322
throw new java.lang.IllegalStateException JavaDoc("null Xpath value"); // FIXME
1323
}
1324
1325        fname.append(".xml"); // NOI18N
1326
return fname.toString();
1327    }
1328
1329    /** This is a basic snippet and will be the base class for most if not all
1330     * snippet objects in the DCB hierarchy. The methods most likely to need
1331     * overriding are getDefaultSnippet(), hasDDSnippet() if the snippet in
1332     * question could be optional in it's entirety, and getPropertyName() if
1333     * the default merge code is being used.
1334     *
1335     * If custom merge is required, see the interface documentation in Snippet
1336     * for specifics on all of these methods.
1337     */

1338    abstract class DefaultSnippet implements Snippet {
1339
1340        public abstract CommonDDBean getDDSnippet();
1341
1342        public org.netbeans.modules.schema2beans.BaseBean getCmpDDSnippet() {
1343            return null;
1344        }
1345
1346        public boolean hasDDSnippet() {
1347            return true;
1348        }
1349
1350        public String JavaDoc getFileName() {
1351            return constructFileName();
1352        }
1353
1354        public CommonDDBean mergeIntoRootDD(CommonDDBean ddRoot) {
1355            throw new java.lang.UnsupportedOperationException JavaDoc();
1356        }
1357
1358        public CommonDDBean mergeIntoRovingDD(CommonDDBean ddParent) {
1359            CommonDDBean newBean = getDDSnippet();
1360            if(newBean != null) {
1361                if(ddParent != null) {
1362                    String JavaDoc propertyName = getPropertyName();
1363                    if(propertyName != null) {
1364                        ddParent.addValue(propertyName, newBean);
1365                    } else {
1366                        jsr88Logger.severe("No property name for " + Base.this.getClass()); // NOI18N
1367
}
1368                } else {
1369                    jsr88Logger.severe("mergeIntoRovingDD() called with null parent (called on root bean?)"); // NOI18N
1370
}
1371            } else {
1372                jsr88Logger.severe("No snippet to merge for " + Base.this.getClass()); // NOI18N
1373
}
1374            return newBean;
1375        }
1376
1377        public String JavaDoc getPropertyName() {
1378            return null;
1379        }
1380    }
1381
1382    protected static class NameBasedFinder implements ConfigFinder {
1383        private String JavaDoc propertyName;
1384        private String JavaDoc propertyValue;
1385        private Class JavaDoc beanType;
1386
1387        public NameBasedFinder(String JavaDoc propName, String JavaDoc propValue, Class JavaDoc type) {
1388            this.propertyName = propName;
1389            this.propertyValue = propValue;
1390            this.beanType = type;
1391        }
1392
1393        public Object JavaDoc find(Object JavaDoc obj) {
1394            Object JavaDoc result = null;
1395            CommonDDBean root = (CommonDDBean) obj;
1396            String JavaDoc[] props = root.findPropertyValue(propertyName, propertyValue);
1397
1398            for(int i = 0; i < props.length; i++) {
1399                CommonDDBean candidate = root.getPropertyParent(props[i]);
1400                if(beanType.isInstance(candidate)) {
1401                    result = candidate;
1402                    break;
1403                }
1404            }
1405
1406            return result;
1407        }
1408    }
1409}
1410
Popular Tags