KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > config > impl > ConfigContextImpl


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 package com.sun.enterprise.config.impl;
25
26 import java.io.File JavaDoc;
27 import java.io.FileOutputStream JavaDoc;
28 import java.io.FileWriter JavaDoc;
29 import java.io.FileInputStream JavaDoc;
30 import java.io.FileReader JavaDoc;
31 import java.io.ObjectInputStream JavaDoc;
32 import java.io.ObjectOutputStream JavaDoc;
33
34 import java.util.ArrayList JavaDoc;
35 import java.io.Serializable JavaDoc;
36 import java.util.Set JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.Enumeration JavaDoc;
39 import java.util.Vector JavaDoc;
40
41 import com.sun.enterprise.config.ConfigContext;
42 import com.sun.enterprise.config.ConfigAdd;
43 import com.sun.enterprise.config.ConfigChange;
44 import com.sun.enterprise.config.ConfigChangeFactory;
45 import com.sun.enterprise.config.ConfigDelete;
46 import com.sun.enterprise.config.ConfigSet;
47 import com.sun.enterprise.config.ConfigUpdate;
48 import com.sun.enterprise.config.ConfigBean;
49 import com.sun.enterprise.config.ConfigException;
50 import com.sun.enterprise.config.ConfigRuntimeException;
51 import com.sun.enterprise.config.StaleWriteConfigException;
52
53 import com.sun.enterprise.config.pluggable.ConfigBeanInterceptor;
54 import com.sun.enterprise.config.pluggable.ConfigEnvironment;
55 import com.sun.enterprise.config.pluggable.EnvironmentFactory;
56 import com.sun.enterprise.config.ConfigContextEventListener;
57 import com.sun.enterprise.config.ConfigContextEvent;
58 import com.sun.enterprise.config.ConfigBeansFactory;
59 import org.xml.sax.helpers.DefaultHandler JavaDoc;
60
61 import java.io.InputStream JavaDoc;
62
63 import org.netbeans.modules.schema2beans.BaseBean;
64
65 import java.util.logging.Logger JavaDoc;
66 import java.util.logging.Level JavaDoc;
67 //import com.sun.logging.LogDomains;
68

69 /**
70  * A configuration context represents a heirarchical view of the configuration
71  * attributes. It reads the configuration attributes from <i> domain.xml </i>
72  * The configuration context has a one-to-one realationship with
73  * a configuration file.
74  *
75  * There is no public constructor. Use ConfigFactory to construct ConfigContext.
76  * Once ConfigContext is created, then, it is tied to the configuration file forever.
77  *
78  * This object can be make readOnly and autoCommit during creation but these parameters
79  * cannot be changed once the object is created. Note that this object might be shared
80  * by number of threads.
81  *
82  * Here are some examples of code to illustrate lookup:
83  * 1. If you want to specifically locate a Node in the configuration:
84  * example: jms resource in server.xml
85  * <PRE>
86  * ConfigBean conBean =
87  * ctx.exactLookup("/server/resources/jms-resource[@name='jms1']");
88  * </PRE>
89  *
90  * Follow the syntax below for creating xpath expression for use in lookup/exactLookup. This is the only
91  * syntax supported.
92  * <PRE>
93  * expression := /tagName | /tagName/tagExpression
94  * tagExpression := tagName| tagName[@name='value'] | tagName/tagExpression | tagName[@name='value']/tagExpression
95  * </PRE>
96  *
97  */

98 public class ConfigContextImpl implements
99                                 ConfigContext,
100                                 DefaultConstants,
101                                 Serializable JavaDoc,
102                                 Cloneable JavaDoc {
103     
104         //For storing ChangeEvent Listeners
105
transient protected Vector JavaDoc listeners = null;
106         
107         private ConfigBean server;
108         protected String JavaDoc xmlUrl;
109         
110         //will be used to keep track of manual changes
111
transient private long lastModified = UNINITIALIZED_LAST_MODIFIED;
112         
113         // FIXME: also set xml doc readonly.
114
private boolean readOnly = false; // FIXME: implement this
115
private boolean autoCommit = false; //FIXME: implement this
116
private Class JavaDoc rootClass;
117         private boolean isAdministered = false; // Handle properly. FIXME TODO
118
private DefaultHandler JavaDoc defaultHandler = null;
119         private boolean resolvePath = true;
120        
121         private transient ConfigBeanInterceptor configBeanInterceptor =
122             EnvironmentFactory.getEnvironmentFactory().
123                 getConfigEnvironment().getConfigBeanInterceptor();
124
125         /**
126          * used for checking lastModifiedTimestamps in configBeans
127          * Note that it is transient. we do not want the clone
128          * to have it enabled by default
129          */

130         transient private boolean _lastModifiedCheck = false;
131         
132         transient private ArrayList JavaDoc configChangeList = new ArrayList JavaDoc();
133         
134         public ArrayList JavaDoc getConfigChangeList() {
135             return configChangeList;
136         }
137         
138         public boolean isAdministered() {
139             return isAdministered;
140         }
141         
142         public void setIsAdministered(boolean value) {
143             isAdministered = value;
144         }
145         
146         // also called by refresh()
147
public synchronized void resetConfigChangeList() {
148             configChangeList = new ArrayList JavaDoc();
149             clearPersistentConfigChanges();
150             
151             //FIXME
152
isAdministered = true;
153         }
154            
155         public synchronized ConfigChange addToConfigChangeList(String JavaDoc xpath, String JavaDoc attrName, String JavaDoc oldValue, String JavaDoc newValue) {
156             //find xpath and add. else create new obj.
157
if(!isAdministered) return null;
158             
159             ConfigChange cChange = null;
160             
161             try {
162                 if(oldValue == null && newValue == null) return null;
163                 if(oldValue != null && oldValue.equals(newValue)) return null;
164                 
165                 boolean found = false;
166                 for(int i=0;i<configChangeList.size();i++) {
167                     if(((ConfigChange)configChangeList.get(i)).getConfigChangeType().equals(ConfigChange.TYPE_UPDATE)
168                                     && ((ConfigUpdate)configChangeList.get(i)).getXPath().equals(xpath)) {
169                         ((ConfigUpdate)configChangeList.get(i)).addChangedAttribute(attrName, oldValue, newValue);
170                         //_logger.log(Level.INFO,"config.change_added");
171
persistConfigChanges();
172                         found = true;
173                         break;
174                     }
175                 }
176                 if(!found) {
177                     cChange = ConfigChangeFactory.createConfigUpdate
178                                         (xpath,
179                                         attrName,
180                                         oldValue,
181                                         newValue);
182                     configChangeList.add(cChange);
183                     persistConfigChanges();
184                     //_logger.log(Level.INFO,"config.create_config_ch_obj",xpath);
185
}
186             } catch (Throwable JavaDoc t) {
187                 //_logger.log(Level.WARNING,"config.add_config_change_exception",t);
188
}
189            return cChange;
190         }
191         
192        /**
193          * Package private constructor. Not to be called by clients.
194          *
195          * @param xmlUrl
196          * @param readOnly
197         * @deprecated
198          */

199         public ConfigContextImpl(String JavaDoc xmlUrl, boolean readOnly, boolean autoCommit, Class JavaDoc rootClass, DefaultHandler JavaDoc dh) // throws ConfigException
200
{
201             this.xmlUrl = xmlUrl;
202             this.readOnly = readOnly;
203             //FIXME: use dom readonly
204
/* if(readOnly) {
205                 ((ElementNode)this.serverInstanceDocument.getDocumentElement()).setReadOnly(true);
206             }
207             */

208             this.autoCommit = autoCommit;
209             this.rootClass = rootClass;
210             this.defaultHandler = dh;
211     }
212         
213         /**
214          * Package private constructor. Not to be called by clients.
215          *
216          * @param xmlUrl
217          * @param readOnly
218          * @param resolvePath
219          *
220          * @deprecated
221          */

222         public ConfigContextImpl(String JavaDoc xmlUrl, boolean readOnly, boolean autoCommit,
223                 Class JavaDoc rootClass, DefaultHandler JavaDoc dh, boolean resolvePath) // throws ConfigException
224
{
225             this.xmlUrl = xmlUrl;
226             this.readOnly = readOnly;
227             //FIXME: use dom readonly
228
/* if(readOnly) {
229                 ((ElementNode)this.serverInstanceDocument.getDocumentElement()).setReadOnly(true);
230             }
231             */

232             this.autoCommit = autoCommit;
233             this.rootClass = rootClass;
234             this.defaultHandler = dh;
235             this.resolvePath = resolvePath;
236     }
237         
238         public ConfigContextImpl(ConfigEnvironment ce) {
239             try {
240             this.xmlUrl = ce.getUrl();
241             this.readOnly = ce.isReadOnly();
242             //FIXME: use dom readonly
243
/* if(readOnly) {
244                 ((ElementNode)this.serverInstanceDocument.getDocumentElement()).setReadOnly(true);
245             }
246             */

247             this.autoCommit = ce.isAutoCommitOn();
248             this.rootClass = Class.forName(ce.getRootClass());
249             this.defaultHandler =
250                 (DefaultHandler JavaDoc) Class.forName(ce.getHandler()).newInstance();
251             this.configBeanInterceptor = ce.getConfigBeanInterceptor();
252             } catch (Exception JavaDoc e) {
253                 throw new ConfigRuntimeException("err_creating_ctx", e);
254             }
255             
256         }
257         public synchronized ConfigBean getRootConfigBean() throws ConfigException {
258             if(server == null) {
259                 refresh();
260             }
261             return server;
262         }
263                 
264         /**
265          * @deprecated use getUrl()
266          */

267         String JavaDoc getXmlUrl() {
268             return this.xmlUrl;
269         }
270         
271         /**
272          * Retrieves the named object. The parameter passed is a <a href = http://www.w3.org/TR/xpath>
273          * XPath version 1.0</a>
274          * used as the path notation for navigating the hierarchical structure. Only the AbsoluteLocationPath
275          * and Relative LocationPath elements are used.
276          * The code below returns a ConfigBeam representing an application with appId="app1"
277          * <PRE>
278          * ConfigBean cn = conCtx.exactLookup(ServerXPathHelper.getAppIdXpathExpression("app1"));
279          * </PRE>
280          * @return a ConfigBean representing a node in the tree.
281          *
282          * @param xpath
283          * @throws ConfigException
284          */

285     public ConfigBean exactLookup(String JavaDoc xpath) throws ConfigException
286     {
287             if(server == null) {
288                 refresh();
289             }
290             return ConfigBeansFactory.getConfigBeanByXPath(this,xpath);
291     }
292         
293         /*
294          * Not Yet Implemented
295          */

296         public ConfigBean[] lookup(String JavaDoc xpath) throws ConfigException
297         {
298             // FIXME NYI
299
return null;
300         }
301         
302         private void assertReadOnly() throws ConfigException {
303             if(readOnly) {
304                 throw new ConfigException("Read only: you cannot write " + toString() );
305             }
306         }
307
308     /**
309          * saves all the changes in ConfigContext to storage
310          * Throws ConfigException if there is any problem writing to storage.
311          * or the file has been modified after last read.
312          * However, if overwrite is true, then it overwrites any manual changes
313          * on disk
314          */

315         public synchronized void flush(boolean overwrite) throws ConfigException {
316             if(!overwrite && isFileChangedExternally()) {
317                 throw new StaleWriteConfigException
318                     ("ConfigContext Flush failed: File Changed Externally");
319             }
320             
321             // <addition> srini@sun.com server.xml verifier
322
//preChange(ConfigContextEvent.PRE_FLUSH_CHANGE);
323
ConfigContextEvent ccce = new ConfigContextEvent(this,ConfigContextEvent.PRE_FLUSH_CHANGE);
324             preChange(ccce);
325             // </addition> server.xml verifier
326

327             try {
328                 FileOutputStream JavaDoc fos = new FileOutputStream JavaDoc(this.xmlUrl);
329                 server.write(fos);
330             } catch(Exception JavaDoc e) {
331                 throw new ConfigException("Error Flushing ConfigContext " + toString());
332             }
333             initLastModified();
334             // <addition> srini@sun.com
335
//postChange(ConfigContextEvent.POST_FLUSH_CHANGE);
336
ccce = new ConfigContextEvent(this,ConfigContextEvent.POST_FLUSH_CHANGE);
337             postChange(ccce);
338             // </addition> server.xml verifier
339

340             //FIXME: should I not write out persistentConfigChanges now??
341
}
342         
343     /**
344          * is equivalent to flush(true)
345          */

346         public void flush() throws ConfigException {
347             flush(true);
348         }
349         
350
351         /** discards all the changes and reloads the xml from storage based on the force flag
352          * @param force forces a reload from disk even if dirty bit is not set
353          */

354         public synchronized void refresh(boolean force) throws ConfigException {
355             try {
356                 if(!force && isChanged()) {
357                     throw new ConfigException
358                         ("ConfigContext has changed in Memory. cannot refresh " + toString());
359                 }
360                 
361                 FileInputStream JavaDoc in = new FileInputStream JavaDoc(this.xmlUrl);
362                 if(this.defaultHandler != null) {
363                     server = (ConfigBean) BaseBean.createGraph(
364                                 rootClass,
365                                 in,
366                                 true,
367                                 this.defaultHandler,
368                                 this.defaultHandler);
369                 } else {
370                     server = (ConfigBean) BaseBean.createGraph(rootClass, in, true);
371                 }
372                  
373                 initConfigChanges(); // not reset. load it up.
374

375                 initLastModified();
376                 
377                 //setXpath for the tree of readwrite mode
378
if(INITIALIZE_XPATH) {
379                     if(!this.readOnly) {
380                         setXPathInAllBeans();
381                     }
382                 }
383                 setIsAdministered(true);
384                 server.setInterceptor(this.configBeanInterceptor);
385             } catch (Exception JavaDoc e) {
386                 throw new ConfigException("Error refreshing ConfigContext:" + this.xmlUrl, e);
387             }
388         }
389         
390         /**
391          * sets xpath in all beans
392          */

393         public void setXPathInAllBeans() throws ConfigException {
394             if(this.readOnly) return;
395             
396             ConfigBean cb = this.getRootConfigBean();
397             //set ctx and xpath
398
//_logger.fine("Setting xpath for the whole tree");
399
setXPathInTree(cb,"");
400             //_logger.fine("Finished setting xpath for the whole tree");
401
}
402         
403         /**
404          * recursive method
405          */

406         private void setXPathInTree(ConfigBean cb, String JavaDoc parentXpath) {
407             cb.setConfigContext(this);
408             String JavaDoc xp = cb.getAbsoluteXPath(parentXpath);
409             //_logger.finer(" " + cb.name() + " " + xp);
410
cb.setXPath(xp);
411             
412             //if cb is leaf. return.
413
ConfigBean[] chChildArr = cb.getAllChildBeans();
414             if(chChildArr == null || chChildArr.length <= 0) return;
415             for(int i = 0; i<chChildArr.length; i++) {
416                 if(chChildArr[i] == null) continue;
417                 //_logger.finest("Child " + chChildArr[i].name());
418
try {
419                     setXPathInTree(chChildArr[i], cb.getXPath());
420                 } catch(Throwable JavaDoc t) {
421                     //ignore this node and its children and continue with rest
422
//_logger.fine("Error: Cannot setXpath for " + chChildArr[i].name());
423
//_logger.fine("Error: Xpath is " + cb.getXPath());
424
//_logger.fine("Error: Exception is: " + t.getMessage());
425
//_logger.fine("Error: Continuing with rest of settings");
426
}
427                 
428             }
429         }
430       
431        /**
432         * recursive method that cleansup the config context and allows better memory model
433         * This should be called when we know that the tree in this context is used in future
434         */

435        public void cleanup() {
436             //set ctx and xpath
437
//_logger.fine("Cleaning up config context");
438
if(server != null)
439                 cleanup(server);
440             //_logger.fine("Finished setting xpath for the whole tree");
441
server = null;
442       }
443
444       private void cleanup(ConfigBean cb) {
445             cb.cleanup();
446             //_logger.finer(" " + cb.name() + " cleaned up");
447

448             //if cb is leaf. return.
449
ConfigBean[] chChildArr = cb.getAllChildBeans();
450             if(chChildArr == null || chChildArr.length <= 0) return;
451             for(int i = 0; i<chChildArr.length; i++) {
452                 if(chChildArr[i] == null) continue;
453                 //_logger.finest("Child " + chChildArr[i].name());
454
try {
455                     cleanup(chChildArr[i]);
456                 } catch(Throwable JavaDoc t) {
457                     //ignore this node and its children and continue with rest
458
//_logger.fine("Warning: Cannot cleanup configbean " + chChildArr[i].name());
459
//_logger.fine("Warning: Exception is: " + t.getMessage());
460
//_logger.fine("Warning: Continuing with rest of settings");
461
}
462             }
463        }
464
465         /** discards all the changes and reloads the xml from storage if dirty flag is true
466          */

467         public void refresh() throws ConfigException {
468            refresh(true);
469         }
470         
471         public Object JavaDoc clone() {
472             ConfigContextImpl ctxClone =
473                 new ConfigContextImpl(this.xmlUrl, false, false, this.rootClass, this.defaultHandler);
474             ctxClone.configBeanInterceptor = getConfigBeanInterceptor();
475             /*
476                 server is initialized on refresh(). What if someone calls clone()
477                 before server is initialized.
478              */

479             if (server != null) {
480                 ConfigBean rootClone = (ConfigBean)this.server.clone();
481                 ctxClone.setRootConfigBean(rootClone);
482                 rootClone.setConfigContext(ctxClone);
483                 rootClone.setInterceptor(ctxClone.configBeanInterceptor);
484                 try {
485                         ((ConfigContextImpl)ctxClone).setXPathInAllBeans();
486                 } catch (Exception JavaDoc e) {
487                     //ignore
488
}
489             }
490             ctxClone.setIsAdministered(true);
491             
492             return ctxClone;
493         }
494         
495         void setRootConfigBean(ConfigBean c) {
496             this.server = c;
497         }
498                
499         /**
500          * for add
501          */

502         public synchronized ConfigChange addToConfigChangeList(
503                     String JavaDoc parentXpath,
504                     String JavaDoc childXpath,
505                     String JavaDoc name,
506                     ConfigBean cb) {
507             //adds
508
if(!isAdministered) return null;
509             
510             ConfigChange cChange = ConfigChangeFactory.createConfigAdd
511                                         (parentXpath, childXpath, name, cb);
512             
513             configChangeList.add(cChange);
514             persistConfigChanges();
515             return cChange;
516         }
517         
518         public synchronized ConfigChange addToConfigChangeList(String JavaDoc xpath) {
519             if(!isAdministered) return null;
520             
521             ConfigChange cChange = null;
522             if(!removeOtherConfigChanges(xpath)) {
523                 cChange = ConfigChangeFactory.createConfigDelete(xpath);
524                 configChangeList.add(cChange);
525             }
526
527             persistConfigChanges();
528             return cChange;
529         }
530
531         /*
532          * returns true if there is config add
533          * so , we do not need to add config delete
534          */

535         private boolean removeOtherConfigChanges(String JavaDoc xpath) {
536         boolean ret = false;
537             try {
538                 //Bug# 4884726 Begin
539
final Iterator JavaDoc it = configChangeList.iterator();
540                 while (it.hasNext()) {
541                     final ConfigChange cc = (ConfigChange)it.next();
542                     if(xpath.indexOf(cc.getXPath()) >= 0) {
543                 if(cc instanceof ConfigAdd)
544                 ret = true;
545                         it.remove();
546                     }
547                 }
548                 //Bug# 4884726 End
549
} catch (Throwable JavaDoc t) {
550         //_logger.log(Level.WARNING,"config.remove_config_change_exception",t);
551
}
552             return ret;
553         }
554         
555         public synchronized ConfigChange addToConfigChangeList(String JavaDoc parentXpath, String JavaDoc name, Object JavaDoc cb, Object JavaDoc[] cbArray) {
556             if(!isAdministered) return null;
557             
558             ConfigChange cChange = ConfigChangeFactory.createConfigSet(
559                                 parentXpath,
560                                 name,
561                                 cb,
562                                 cbArray);
563             configChangeList.add(cChange);
564             persistConfigChanges();
565             return cChange;
566         }
567
568         public synchronized void removeConfigChange(ConfigChange change) {
569             if (!isAdministered) return;
570
571             int ndx = configChangeList.indexOf(change);
572             if (ndx != -1) {
573                 configChangeList.remove(ndx);
574             }
575             persistConfigChanges();
576         }
577
578         public synchronized void updateFromConfigChange(ConfigChange configChange) throws ConfigException {
579             if(configChange == null) return;
580             
581             //disable configChangeList while updating.
582
//otherwise, we get unnecessary changes in the list.
583
boolean tmpAdministered = isAdministered;
584             isAdministered = false;
585             
586             if(configChange.getConfigChangeType().equals(ConfigChange.TYPE_ADD))
587                 updateFromConfigAdd((ConfigAdd)configChange);
588             else if(configChange.getConfigChangeType().equals(ConfigChange.TYPE_UPDATE))
589                 updateFromConfigUpdate((ConfigUpdate)configChange);
590             else if(configChange.getConfigChangeType().equals(ConfigChange.TYPE_DELETE))
591                 updateFromConfigDelete((ConfigDelete)configChange);
592             else if(configChange.getConfigChangeType().equals(ConfigChange.TYPE_SET))
593                 updateFromConfigSet((ConfigSet)configChange);
594             
595             //enable if needed.
596
isAdministered = tmpAdministered;
597         }
598         
599         private void updateFromConfigAdd(ConfigAdd configChange) throws ConfigException {
600             ConfigBean parent = ConfigBeansFactory.getConfigBeanByXPath(this,configChange.getParentXPath());
601             if(parent == null)
602                 throw new ConfigException("updateFromConfigAdd: Cannot find parent");
603             
604             ConfigBean rootBean = configChange.getConfigBean();
605             if(rootBean == null)
606                 throw new ConfigException("updateFromConfigAdd: Cannot find root bean");
607             
608             ConfigBean childBean = ConfigBeansFactory.getConfigBeanByXPath(rootBean, configChange.getXPath());
609             
610             if(childBean == null)
611                 throw new ConfigException("updateFromConfigAdd: Cannot find childBean");
612             
613             //lastModified Check
614
if(isLastModifiedCheckEnabled()) {
615                 validateLastModified(parent, configChange);
616             }
617             
618             childBean = (ConfigBean)childBean.clone();
619             //System.out.println("++++++++++before add +++++++++++++++");
620
//System.out.println("this childBean:");
621
//System.out.println(childBean.dumpBeanNode());
622
//System.out.println("++++++++++++++++++++++++++++++++");
623
//System.out.println(childBean.dumpDomNode());
624
//System.out.println("++++++++++before add +++++++++++++++");
625

626             parent.addValue(configChange.getName(), childBean);
627             //System.out.println("++++++++++after add +++++++++++++++");
628
//System.out.println("this configcontxt:");
629
//this.getRootConfigBean().dumpXml();
630
//System.out.println("++++++++++after add +++++++++++++++");
631
}
632
633         private void updateFromConfigSet(ConfigSet configChange) throws ConfigException {
634             ConfigBean parent = ConfigBeansFactory.getConfigBeanByXPath(this,configChange.getParentXPath());
635             
636             if(parent == null)
637                 throw new ConfigException("updateFromConfigSet: Cannot update. Could not get parent");
638             Object JavaDoc child = configChange.getConfigBean();
639             
640             //lastModified Check
641
if(isLastModifiedCheckEnabled()) {
642                 validateLastModified(parent, configChange);
643             }
644             
645             if(child != null) {
646                 parent.setValue(configChange.getName(), child);
647             } else { //it is an array
648
Object JavaDoc[] childArray = configChange.getConfigBeanArray();
649                 parent.setValue(configChange.getName(), childArray);
650             }
651         }
652
653         private void updateFromConfigUpdate(ConfigUpdate configChange) throws ConfigException {
654             //set all the attributes
655
//System.out.println("configchange is:" + configChange);
656
//System.out.println("++++++++++++++++++++++++++++");
657
//System.out.println("this configcontext:" + this);
658
//System.out.println("++++++++++++++++++++++++++++");
659
ConfigBean b = ConfigBeansFactory.getConfigBeanByXPath(this,configChange.getXPath());
660         //_logger.log(Level.FINE,"xpath="+ configChange.getXPath());
661
if(b == null)
662                 throw new ConfigException("updateFromConfigUpdate:Could not find ConfigBean to update");
663             
664             //lastModified Check
665
if(isLastModifiedCheckEnabled()) {
666                 validateLastModified(b, configChange);
667             }
668             
669             Set JavaDoc s = configChange.getAttributeSet();
670             for (Iterator JavaDoc i = s.iterator();i.hasNext();) {
671                 String JavaDoc name = (String JavaDoc) i.next();
672                 b.setAttributeValue(name, configChange.getNewValue(name));
673             }
674         }
675         
676         private void updateFromConfigDelete(ConfigDelete configChange) throws ConfigException {
677             //delete
678
String JavaDoc xpath = configChange.getXPath();
679             ConfigBean child = ConfigBeansFactory.getConfigBeanByXPath(this,xpath);
680             if(child != null) {
681                 //throw new ConfigException("Child not found:" + xpath);
682
ConfigBean parent = (ConfigBean) child.parent();
683             
684             //lastModified Check
685
if(isLastModifiedCheckEnabled()) {
686                 validateLastModified(parent, configChange);
687             }
688             
689             parent.removeChild(child);
690             }
691         }
692         
693         /**
694          * get all the important attributes of this configcontext as a String
695          * Each attribute is separated by a comma
696          * @return String representation of this configContext
697          */

698         public String JavaDoc toString() {
699             return "com.sun.enterprise.config.ConfigContext: Url=" + this.xmlUrl
700                         + ", ReadOnly=" + this.readOnly
701                         + ", ResolvePath=" + (resolvePath)
702                         + ", LastModified Timestamp=" + this.lastModified
703                         + ", isChanged=" + this.isChanged()
704                         + ", Autocommit=" + this.autoCommit
705                         + ", isConfigBeanNull=" + (server==null);
706         }
707         
708         /** get the ConfigBean information as a String
709          * String is in a schema2beans proprietory format
710          * Note that this method is not exposed in ConfigContext.
711          * @return String representation of config bean. return "null bean" if
712          * there is no associated config bean
713          */

714         public String JavaDoc configBeanToString() {
715             if(server == null) return "null bean";
716             return this.server.dumpBeanNode();
717         }
718         
719         
720          /**
721          * Get the Value of an attribute with One call
722          * This equivalent of doing an exactLookup to get a bean
723          * and then a getAttributeValue on that bean
724          *
725          */

726         public String JavaDoc getAttributeValue(String JavaDoc xpath, String JavaDoc attributeName) {
727             ConfigBean c = null;
728             try {
729                 c = this.exactLookup(xpath);
730             } catch(Exception JavaDoc e) {}
731             
732             if(c!= null) {
733                 if(!isResolvingPaths()) {
734                     return c.getRawAttributeValue(attributeName);
735                 } else {
736                     return c.getAttributeValue(attributeName);
737                 }
738             }
739             
740             return null;
741         }
742         
743         /**
744          * similar to getAttributeValue but returns a boolean
745          */

746         public boolean getBooleanAttributeValue(String JavaDoc xpath, String JavaDoc attributeName) {
747             String JavaDoc ret = getAttributeValue(xpath, attributeName);
748             if(ret == null) return false;
749             
750             if (ret.equals("true"))
751                 return true;
752
753             return false;
754         }
755         
756         public boolean isChanged() {
757             if(configChangeList == null || configChangeList.size() ==0)
758                 return false;
759             return true;
760         }
761         
762         /**
763          *
764          */

765         private long getLastModified() {
766             long ts = INVALID_LAST_MODIFIED;
767             try {
768                 File JavaDoc f = new File JavaDoc(this.xmlUrl);
769                 ts = f.lastModified();
770             } catch(Exception JavaDoc e) {
771                 //ignore
772
}
773             return ts;
774         }
775         
776         /**
777          * checks if file has changed externally after the config context
778          * last updated the file
779          */

780         public boolean isFileChangedExternally() {
781             if(getLastModified() == this.lastModified)
782                 return false;
783             return true;
784         }
785                 
786         /**
787          * init to be called from constructor
788          */

789         private void initLastModified() {
790             this.lastModified = getLastModified();
791         }
792         
793         public boolean equals(Object JavaDoc obj) {
794             try {
795                 if(this.getRootConfigBean().equals(((ConfigContext)obj).getRootConfigBean())) {
796                     return true;
797                 }
798             } catch(Throwable JavaDoc t) {
799                 //ignore
800
}
801             return false;
802         }
803         
804         public int hashCode() {
805             try {
806                 return this.getRootConfigBean().hashCode();
807             } catch(Throwable JavaDoc t) {
808                 //ignore
809
}
810            return super.hashCode();
811         }
812         
813                
814         private String JavaDoc getConfigChangeUrl() {
815             return this.xmlUrl + ".changes";
816         }
817         
818         private void persistConfigChanges() {
819             
820             //We donot need to write if persistent
821
//config changes are not required
822
if(!LOAD_PERSISTENT_CONFIG_CHANGES) return;
823             
824             FileOutputStream JavaDoc ostream = null;
825             ObjectOutputStream JavaDoc p = null;
826             try {
827                 ostream = new FileOutputStream JavaDoc(getConfigChangeUrl());
828                 p = new ObjectOutputStream JavaDoc(ostream);
829                 p.writeObject(this.configChangeList);
830                 p.flush();
831             } catch(Throwable JavaDoc t) {
832                 //ignore.
833
} finally {
834                 try {
835                     p.close();
836                     ostream.close();
837                 } catch(Exception JavaDoc e){}
838             }
839             
840         }
841         
842         private void initConfigChanges() {
843             if(!LOAD_PERSISTENT_CONFIG_CHANGES) return;
844             
845             FileInputStream JavaDoc istream = null;
846             try {
847                 istream = new FileInputStream JavaDoc(getConfigChangeUrl());
848                 ObjectInputStream JavaDoc p = new ObjectInputStream JavaDoc(istream);
849
850                 this.configChangeList = (ArrayList JavaDoc)p.readObject();
851
852             } catch(Throwable JavaDoc t) {
853                 //ignore.
854
} finally {
855                 try {
856                     istream.close();
857                 } catch(Exception JavaDoc e){}
858             }
859             
860         }
861         
862         private void clearPersistentConfigChanges() {
863              if(!LOAD_PERSISTENT_CONFIG_CHANGES) return;
864              
865             //remove change file on disk
866
try {
867                 File JavaDoc f = new File JavaDoc(getConfigChangeUrl());
868                 f.delete();
869             } catch(Throwable JavaDoc t) {
870                 //ignore.
871
}
872         }
873         
874                /*
875          * Add Notification Listener
876          */

877         public void addConfigContextEventListener(ConfigContextEventListener ccel) {
878             if (listeners==null)
879                 listeners = new Vector JavaDoc();
880             listeners.addElement(ccel);
881         }
882         
883         /*
884          * remove
885          */

886         public void removeConfigContextEventListener(ConfigContextEventListener ccel) {
887              if (listeners==null)
888                 listeners = new Vector JavaDoc();
889             listeners.removeElement(ccel);
890         }
891     
892         
893     private static final String JavaDoc PRE_CHANGE = "PRE_CHANGE";
894     private static final String JavaDoc POST_CHANGE = "POST_CHANGE";
895     
896     /**
897      * Notify all my listeners that I will change!
898      *
899      */

900     
901     // <addition> srini@sun.com server.xml verifier
902
//public void preChange(String type) {
903
public void preChange(ConfigContextEvent ccce) {
904         //change(PRE_CHANGE, type);
905
change(PRE_CHANGE, ccce);
906     }
907     
908     //public void postChange(String type) {
909
public void postChange(ConfigContextEvent ccce) {
910         //change(POST_CHANGE, type);
911
change(POST_CHANGE, ccce);
912     }
913     
914     //private void change(String when, String type) {
915
private void change(String JavaDoc when, ConfigContextEvent ne) {
916         if (listeners==null)
917             return;
918         
919         //ConfigContextEvent ne = new ConfigContextEvent(this, type);
920
String JavaDoc type = ne.getType();
921         
922         Vector JavaDoc listenersClone = null;
923         synchronized (listeners) {
924             listenersClone = (Vector JavaDoc) listeners.clone();
925         }
926         for (Enumeration JavaDoc e = listenersClone.elements(); e.hasMoreElements();) {
927             ConfigContextEventListener nl = (ConfigContextEventListener) e.nextElement();
928             if(when.equals(PRE_CHANGE)) {
929                 /*
930                 if(type.equals(ConfigContextEvent.PRE_ACCESS) || type.equals(ConfigContextEvent.POST_ACCESS))
931                     nl.preAccessNotification(ne);
932                 else
933                  */

934                     nl.preChangeNotification(ne);
935             } else {
936                 /*
937                 if(type.equals(ConfigContextEvent.PRE_ACCESS) || type.equals(ConfigContextEvent.POST_ACCESS))
938                     nl.postAccessNotification(ne);
939                 else
940                  */

941                     nl.postChangeNotification(ne);
942             }
943         }
944     }
945     
946     /**
947      * Returns boolean true is this is the config context for admin.
948      */

949     public boolean isResolvingPaths() {
950         return this.resolvePath;
951     }
952     
953     // </addition> server.xml verifier
954

955     /**
956      * This method is used to activate the lastModified checking for a configContext
957      * If activated, configbeans will carry a lastmodified timestamp in every bean.
958      * This time is also carried onto the configChangeList and also to clones. When
959      * configContext.updateFromConfigChangeList is called, the timestamp is first checked
960      * to see if the bean has not changed since the clone and then the update is made.
961      * If a modification to the bean is detected, a staleWriteConfigException is thrown.
962      *
963      * @param value boolean to enable/disable
964      * @return boolean previous value that was set (not the changed value)
965      */

966     public synchronized boolean enableLastModifiedCheck(boolean value) {
967         boolean prev = _lastModifiedCheck;
968         _lastModifiedCheck = value;
969         return prev;
970     }
971     
972     public boolean isLastModifiedCheckEnabled() {
973         return _lastModifiedCheck;
974     }
975     
976     /**
977      * throws StaleWriteConfigException if lastmodified is initialized
978      * and there is any modifications
979      */

980     private void validateLastModified(ConfigBean cb, ConfigChange cc)
981                                        throws StaleWriteConfigException {
982                                            
983         if(cb == null || cc == null) return;
984         
985         long beanLM = cb.getThisLastModified();
986         if(beanLM == -1) return; // not initialized. so, don't validate
987

988         long ccLM = cc.getGlobalLastModified();
989         if(ccLM == -1) return; // not initialized. so, don't validate
990

991         if (beanLM == ccLM) return; // okay.
992

993         throw new StaleWriteConfigException("validateLastModified failed for cb=" + cb);
994     }
995     
996     public synchronized ArrayList JavaDoc updateFromConfigChange(ArrayList JavaDoc configChangeList)
997                                                                 throws ConfigException {
998         
999         ArrayList JavaDoc errList = new ArrayList JavaDoc();
1000        if (configChangeList == null || configChangeList.size() == 0) return errList;
1001        
1002        validateAllLastModified(configChangeList);
1003        
1004        boolean prev = enableLastModifiedCheck(false);
1005        try {
1006            for(int i = 0 ; i < configChangeList.size(); i++ ) {
1007                ConfigChange cc = (ConfigChange) configChangeList.get(i);
1008                try {
1009                    updateFromConfigChange(cc);
1010                } catch (Exception JavaDoc e) {
1011                    errList.add(cc);
1012                }
1013            }
1014    // save the context. TBD
1015
} finally {
1016            enableLastModifiedCheck(prev);
1017        }
1018        return errList;
1019    }
1020    
1021    private void validateAllLastModified(ArrayList JavaDoc arr) throws StaleWriteConfigException {
1022        if(arr == null || arr.size() == 0) return;
1023        
1024        for(int i = 0 ; i < arr.size(); i++ ) {
1025           ConfigChange cc = (ConfigChange) arr.get(i);
1026           validateLastModified(cc);
1027        }
1028    }
1029    
1030    private void validateLastModified(ConfigChange cc) throws StaleWriteConfigException {
1031        ConfigBean bean = getConfigBeanFromConfigChange(cc);
1032        validateLastModified(bean, cc);
1033    }
1034    
1035    private ConfigBean getConfigBeanFromConfigChange(ConfigChange configChange) {
1036        ConfigBean result = null;
1037        try {
1038            if(configChange.getConfigChangeType().equals(ConfigChange.TYPE_UPDATE)) {
1039                result = ConfigBeansFactory.getConfigBeanByXPath(this,configChange.getXPath());
1040            } else if (configChange.getConfigChangeType().equals(ConfigChange.TYPE_DELETE)) {
1041                String JavaDoc xpath = configChange.getXPath();
1042                ConfigBean child = ConfigBeansFactory.getConfigBeanByXPath(this,xpath);
1043                if(child != null) {
1044                    result = (ConfigBean) child.parent();
1045                }
1046            } else { // add/set
1047
result = ConfigBeansFactory.getConfigBeanByXPath(this, configChange.getParentXPath());
1048            }
1049        } catch (ConfigException ce) {
1050            //ignore
1051
}
1052        return result;
1053    }
1054    
1055    public String JavaDoc getUrl() {
1056         return this.xmlUrl;
1057    }
1058
1059    public ConfigBeanInterceptor getConfigBeanInterceptor() {
1060        ConfigBeanInterceptor cbiClone = null;
1061        if (null != configBeanInterceptor) {
1062            cbiClone = (ConfigBeanInterceptor)configBeanInterceptor.clone();
1063        }
1064        return cbiClone;
1065    }
1066}
1067
Popular Tags