KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > module > core > MMBase


1 /*
2
3 This software is OSI Certified Open Source Software.
4 OSI Certified is a certification mark of the Open Source Initiative.
5
6 The license (Mozilla version 1.0) can be read at the MMBase site.
7 See http://www.MMBase.org/license
8
9 */

10 package org.mmbase.module.core;
11
12 import java.io.File JavaDoc;
13 import java.util.*;
14 import java.text.DateFormat JavaDoc;
15
16 import org.mmbase.core.event.*;
17 import org.mmbase.datatypes.DataTypes;
18 import org.mmbase.module.ProcessorModule;
19 import org.mmbase.module.SendMailInterface;
20 import org.mmbase.module.builders.DayMarkers;
21 import org.mmbase.module.builders.Versions;
22 import org.mmbase.module.corebuilders.*;
23 import org.mmbase.security.MMBaseCop;
24 import org.mmbase.storage.*;
25 import org.mmbase.storage.search.RelationStep;
26 import org.mmbase.model.*;
27 import org.mmbase.storage.search.SearchQueryHandler;
28 import org.mmbase.util.ResourceLoader;
29 import org.mmbase.util.logging.Logger;
30 import org.mmbase.util.logging.Logging;
31 import org.mmbase.util.platform.setUser;
32 import org.mmbase.util.xml.BuilderReader;
33 import org.mmbase.util.xml.BuilderWriter;
34 import org.mmbase.util.functions.*;
35 import org.xml.sax.SAXException JavaDoc;
36
37 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
38
39 /**
40  * The module which provides access to the MMBase storage defined
41  * by the provided name/setup.
42  * It holds the overal object cloud made up of builders, objects and relations and
43  * all the needed tools to use them.
44  *
45  * @author Daniel Ockeloen
46  * @author Pierre van Rooden
47  * @author Johannes Verelst
48  * @author Ernst Bunders
49  * @version $Id: MMBase.java,v 1.200.2.1 2006/09/10 17:04:36 nklasens Exp $
50  */

51 public class MMBase extends ProcessorModule {
52
53
54     /**
55      * State of MMBase after shutdown
56      * @since MMBase-1.7
57      */

58     private static final int STATE_SHUT_DOWN = -3;
59
60     /**
61      * State of MMBase before the beginning of startup
62      * @since MMBase-1.6
63      */

64     private static final int STATE_START_UP = -2;
65
66     /**
67      * State of MMBase
68      * @since MMBase-1.8
69      */

70     private static final int STATE_STARTED_INIT = -1;
71     /**
72      * State of MMBase before builders are loaded
73      * @since MMBase-1.6
74      */

75     private static final int STATE_LOAD = 0;
76     /**
77      * State of MMBase before builders are initialized
78      * @since MMBase-1.6
79      */

80     private static final int STATE_INITIALIZE = 1;
81     /**
82      * State of MMBase after startup is completed
83      * @since MMBase-1.6
84      */

85     private static final int STATE_UP = 2;
86
87     // logging
88
private static final Logger log = Logging.getLoggerInstance(MMBase.class);
89
90
91     /**
92      * Reference to the MMBase singleton. Used for quick reference by getMMBase();
93      */

94     private static MMBase mmbaseroot = null;
95
96     /**
97      * Time in seconds, when mmbase was started.
98      * @since MMBase-1.7
99      */

100     public static final int startTime = (int) (System.currentTimeMillis() / 1000);
101
102     /**
103      * The (base)path to the builder configuration files
104      */

105     private static ResourceLoader builderLoader = ResourceLoader.getConfigurationRoot().getChildResourceLoader("builders");
106
107     /**
108      * Base name for the storage to be accessed using this instance of MMBase.
109      * Retrieved from the mmbaseroot module configuration setUser
110      * If not specified the default is "def1"
111      * Should be made private and accessed instead using getBaseName()
112      * @scope private
113      */

114     public String JavaDoc baseName = "def1";
115
116     /**
117      * Reference to the TypeDef builder.
118      */

119     private TypeDef typeDef;
120     /**
121      * Reference to the RelDef builder.
122      */

123     private RelDef relDef;
124     /**
125      * Reference to the OALias builder.
126      */

127     private OAlias oAlias;
128     /**
129      * Reference to the InsRel builder.
130      */

131     private InsRel insRel;
132     /**
133      * Reference to the TypeRel builder.
134      */

135     private TypeRel typeRel;
136
137     /**
138      * The table that contains all loaded builders. Includes virtual builders.
139      * A collection of builders from this map can be accessed by calling {@link #getBuilders}
140      */

141     private Map mmobjs = new ConcurrentHashMap();
142
143     private CloudModel cloudModel;
144
145     /**
146      * Determines whether MMBase is in development mode.
147      * @see #inDevelopment()
148      * @since MMBase-1.8.1
149      */

150     private boolean inDevelopment = false;
151
152     /**
153      * Name of the machine used in the mmbase cluster.
154      * it is used for the mmservers objects. Make sure that this is different
155      * for each node in your cluster. This is not the machines dns name
156      * (as defined by host as name or ip number).
157      */

158     private String JavaDoc machineName = "unknown";
159
160     /**
161      * The host or ip number of the machine this module is
162      * running on. Its important that this name is set correctly because it is
163      * used for communication between mmbase nodes and external devices
164      */

165     private String JavaDoc host = "unknown";
166
167     /**
168      * Authorisation type. Access using getAuthType()
169      */

170     private String JavaDoc authtype = "none";
171
172     /**
173      * The storage manager factory to use. Retrieve using getStorageManagerFactory();
174      */

175     private StorageManagerFactory storageManagerFactory = null;
176
177     /**
178      * Reference to the Root builder (the most basic builder, aka 'object').
179      * This can be null (does not exist) in older systems
180      */

181     private MMObjectBuilder rootBuilder;
182
183     /**
184      * Base url for the location of the DTDs. obtained using getDTDBase()
185      * @deprecated
186      */

187     private String JavaDoc dtdbase = "http://www.mmbase.org";
188
189     /**
190      * our securityManager (MMBaseCop)
191      */

192     private MMBaseCop mmbaseCop = null;
193
194     /**
195      * Reference to the cluster builder, a virtual builder used to perform
196      * multilevel searches.
197      * @see ClusterBuilder
198      */

199     private ClusterBuilder clusterBuilder;
200
201     /**
202      * Currently used locale. Access using getLocale()
203      */

204     private Locale locale = Locale.ENGLISH;
205
206     private TimeZone timeZone = TimeZone.getDefault();
207
208     /**
209      * Currently used encoding. Access using getEncoding(). This
210      * default to ISO-8859-1 as long as support for other encodings is
211      * not thoroughly tested. In the feature we will probably switch
212      * to UTF-8.
213      *
214      * @since MMBase-1.6
215      */

216     private String JavaDoc encoding = "ISO-8859-1";
217
218     /**
219      * MMbase 'up state. Access using getState()
220      *
221      * @since MMBase-1.6
222      */

223     private int mmbaseState = STATE_START_UP;
224
225     /**
226      * The table that indexes builders being loaded.
227      * This map does not actually contian builders - it merely contains
228      * a reference that the builder is in the process of being loaded.
229      * The map is used to prevent circular references when extending builders.
230      *
231      * @since MMBase-1.6
232      */

233     private Set loading = new HashSet();
234
235
236     /**
237      * Constructor to create the MMBase root module.
238      */

239     public MMBase() {
240         if (mmbaseroot != null) log.error("Tried to instantiate a second MMBase");
241         log.debug("MMBase constructed");
242     }
243
244     /**
245      * Initalizes the MMBase module. Evaluates the parameters loaded from the configuration file.
246      * Sets parameters (authorisation, language), loads the builders, and starts MultiCasting.
247      */

248     public synchronized void init() {
249         if (mmbaseState >= STATE_STARTED_INIT) {
250             log.debug("Already initing");
251             return;
252         }
253         log.service("Init of " + org.mmbase.Version.get() + " (" + this + ")");
254
255         mmbaseState = STATE_STARTED_INIT;
256
257         // Set the mmbaseroot singleton var
258
// This prevents recursion if MMBase.getMMBase() is called while
259
// this method is run
260
mmbaseroot = this;
261
262         loadInitParameters("mmbase/mmbaseroot");
263
264         // is there a basename defined in MMBASE.properties ?
265
String JavaDoc tmp = getInitParameter("BASENAME");
266         if (tmp != null) {
267             // yes then replace the default name (def1)
268
baseName = tmp;
269         } else {
270             log.info("init(): No name defined for mmbase using default (def1)");
271         }
272
273         tmp = getInitParameter("AUTHTYPE");
274         if (tmp != null && !tmp.equals("")) {
275             authtype = tmp;
276         }
277
278         tmp = getInitParameter("TIMEZONE");
279         if (tmp != null && !tmp.equals("")) {
280             timeZone = TimeZone.getTimeZone(tmp);
281         }
282         DateFormat JavaDoc format = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.US);
283         format.setTimeZone(timeZone);
284         log.info("MMBase Time zone : " + timeZone.getDisplayName(Locale.US) + " (it's now " + format.format(new Date()) + ")");
285         org.mmbase.util.dateparser.DateParser.setDefault(timeZone);
286
287         tmp = getInitParameter("LANGUAGE");
288         if (tmp != null && !tmp.equals("")) {
289             locale = new Locale(tmp, "");
290         }
291         log.info("MMBase default locale : " + locale);
292         org.mmbase.util.LocalizedString.setDefault(locale);
293
294         tmp = getInitParameter("DEVELOPMENT");
295         if (tmp != null && !tmp.equals("")) {
296             inDevelopment = "true".equals(tmp);
297         }
298
299         tmp = getInitParameter("ENCODING");
300         if (tmp != null && !tmp.equals("")) {
301             encoding = tmp;
302         }
303
304         tmp = getInitParameter("DTDBASE");
305         if (tmp != null && !tmp.equals("")) {
306             dtdbase = tmp;
307         }
308
309         // default locale has to be known before initializing datatypes:
310
DataTypes.initialize();
311
312         // default machine name is the local host name plus context-path.
313
// We suppose that that is sufficiently unique in most cases
314
try {
315             host = java.net.InetAddress.getLocalHost().getHostName();
316             machineName = host + MMBaseContext.getHtmlRootUrlPath();
317         } catch (java.net.UnknownHostException JavaDoc uhe) {
318             machineName = "UNKNOWN";
319             host = machineName;
320         }
321
322         tmp = getInitParameter("HOST");
323         if (tmp != null && !tmp.equals("")) {
324             host = tmp;
325         }
326
327         String JavaDoc machineNameParam = getInitParameter("MACHINENAME");
328         if (machineNameParam != null) {
329             // try to incorporate the hostname (if needed)
330
int pos = machineNameParam.indexOf("${HOST}");
331             if (pos != -1) {
332                 machineNameParam =
333                     machineNameParam.substring(0, pos) +
334                     machineName + machineNameParam.substring(pos + 7);
335             }
336             // you may also try to incorporate the username in the machine name
337
pos = machineNameParam.indexOf("${USER}");
338             if (pos != -1) {
339                 machineNameParam = machineNameParam.substring(0, pos) + System.getProperty("user.name") + machineNameParam.substring(pos + 7);
340             }
341             machineName = machineNameParam;
342         }
343         log.service("MMBase machine name used for clustering: '" + machineName + "'");
344         Logging.setMachineName(machineName);
345
346         log.service("Initializing storage");
347         initializeStorage();
348
349         mmbaseState = STATE_LOAD;
350
351
352         log.debug("Loading builders:");
353
354     cloudModel = ModelsManager.addModel("default","default.xml");
355
356         loadBuilders();
357
358         if(Thread.currentThread().isInterrupted()) {
359             log.info("Interrupted");
360             return;
361         }
362
363         mmbaseState = STATE_INITIALIZE;
364
365
366         log.debug("Checking MMBase");
367         if (!checkMMBase()) {
368             // there is no base defined yet, create the core objects
369
createMMBase();
370         }
371
372         log.service("Initializing builders:");
373         initBuilders();
374
375         EventManager.getInstance().addEventListener(org.mmbase.cache.NodeCache.getCache());
376
377         log.debug("Objects started");
378
379         String JavaDoc writerpath = getInitParameter("XMLBUILDERWRITERDIR");
380         if (writerpath != null && !writerpath.equals("")) {
381             Iterator t = mmobjs.values().iterator();
382             while (t.hasNext()) {
383                 MMObjectBuilder builder = (MMObjectBuilder)t.next();
384                 if (!builder.isVirtual()) {
385                     String JavaDoc name = builder.getTableName();
386                     log.debug("WRITING BUILDER FILE =" + writerpath + File.separator + name);
387                     try {
388                         BuilderWriter builderOut = new BuilderWriter(builder);
389                         builderOut.setIncludeComments(false);
390                         builderOut.setExpandBuilder(false);
391                         builderOut.writeToFile(writerpath + File.separator + builder.getTableName() + ".xml");
392                     } catch (Exception JavaDoc ex) {
393                         log.error(Logging.stackTrace(ex));
394                     }
395                 }
396             }
397         }
398         if(Thread.currentThread().isInterrupted()) {
399             log.info("Interrupted");
400             return;
401         }
402
403         // try to load security...
404
try {
405             mmbaseCop = new MMBaseCop();
406         } catch (Exception JavaDoc e) {
407             log.fatal("Error loading the mmbase cop: " + e.getMessage());
408             log.error(Logging.stackTrace(e));
409             log.error("MMBase will continue without security.");
410             log.error("All future security invocations will fail.");
411         }
412
413         typeRel.readCache();
414
415         // signal that MMBase is up and running
416
mmbaseState = STATE_UP;
417         log.info("MMBase is up and running");
418         checkUserLevel();
419
420     }
421
422     // javadoc inherited
423
protected void shutdown() {
424         mmbaseState = STATE_SHUT_DOWN;
425
426         // there all over the place static references to mmbasroot are maintained, which I cannot
427
// change presently. so let's clean up mmbaseroot itself as well as possible...
428
typeDef = null;
429         relDef = null;
430         oAlias = null;
431         insRel = null;
432         typeRel = null;
433         mmobjs.clear(); mmobjs = null;
434         cloudModel = null;
435         storageManagerFactory = null;
436         rootBuilder = null;
437         mmbaseCop = null;
438         clusterBuilder = null;
439         mmbaseroot = null;
440     }
441
442     /**
443      * @since MMBase-1.7
444      */

445     public boolean isShutdown() {
446         return mmbaseState == STATE_SHUT_DOWN;
447     }
448    
449     /**
450      * Returns <code>true</code> when MMBase is in development mode.
451      * This can be used to determine behavior with regards to common errors,
452      * such as whether or not to throw an exception when a non-existing field
453      * in a buidler is referenced.
454      * The value for this property ('true' or 'false') can be set in the "development"
455      * property in the mmbaseroot.xml configuration file.
456      * The default value is <code>false</code>.
457      * @since MMBase-1.8.1
458      */

459     public boolean inDevelopment() {
460         return inDevelopment;
461     }
462
463     /**
464      * Checks whether the storage to be used exists.
465      * The system determines whether the object table exists
466      * for the baseName provided in the configuration file.
467      * @return <code>true</code> if the storage exists and is accessible, <code>false</code> otherwise.
468      */

469     boolean checkMMBase() {
470         return getStorageManager().exists();
471     }
472
473     /**
474      * Create a new MMBase persistent storage instance.
475      * The storage instance created is based on the baseName provided in the configuration file.
476      * This call automatically creates an object table.
477      * The fields in the table are either specified in an object builder xml,
478      * or from a default setup existing of a number field and a owner field.
479      * Note: If specified, the object builder is instantiated and its table created, but
480      * the builder is not registered in the TypeDef builder, as this builder does not exist yet.
481      * Registration happens when the other builders are registered.
482      * @return <code>true</code> if the storage was succesfully created, otherwise a runtime exception is thrown
483      * (shouldn't it return <code>false</code> instead?)
484      */

485     boolean createMMBase() {
486         log.debug(" creating new multimedia base : " + baseName);
487         getStorageManager().create();
488         return true;
489     }
490
491     /**
492      * Determines whether a builder is in the process of being loaded,
493      * but not yet finished. Needed to track down circular references.
494      * @return true if the builder is being loaded
495      *
496      * @since MMBase-1.6
497      */

498     private boolean builderLoading(String JavaDoc name) {
499         return loading.contains(name);
500     }
501
502     /**
503      * Retrieves a specified builder.
504      * If the builder is not loaded, but the system is in the 'startup' state
505      * (i.e. it is in the process of loading builders), an attempt is made to
506      * directly load the builder.
507      * This allows for dependencies between builders to exist (i.e. inheritance).
508      * When circular reference occurs between two loading buidlers, an exception is thrown.
509      *
510      * @since MMBase-1.6
511      * @param name The name of the builder to retrieve
512      * @return a <code>MMObjectBuilder</code> for the specified builder
513      * @throws CircularReferenceException when circular reference is detected
514      * @throws BuilderConfigurationException if the builder config file does not exist
515      */

516     public MMObjectBuilder getBuilder(String JavaDoc name) throws CircularReferenceException {
517         MMObjectBuilder builder = getMMObject(name);
518         if (builder == null && (mmbaseState == STATE_LOAD)) {
519             // MM: odd way to check this. Could it not be done a bit more explicitely?
520
if (builderLoading(name)) {
521                 throw new CircularReferenceException("Circular reference to builder with name '" + name + "': currently loading " + loading);
522             }
523             builder = loadBuilder(name);
524         }
525         return builder;
526     }
527
528     public String JavaDoc getBuilderNameForNode(final int number) {
529         int nodeType = getMMBase().getStorageManager().getNodeType(number);
530         if (nodeType < 0) {
531             // the node does not exists, which according to javadoc should return null
532
throw new StorageNotFoundException("Cannot determine node type of node with number =" + number);
533         }
534         // if the type is not for the current builder, determine the real builder
535
return getTypeDef().getValue(nodeType);
536     }
537     
538     public MMObjectBuilder getBuilderForNode(final int number) {
539         String JavaDoc builderName = getBuilderNameForNode(number);
540         MMObjectBuilder nodeBuilder = null;
541         if (builderName == null) {
542             log.error("The nodetype name of node #" + number + " could not be found '");
543         }
544         else {
545             nodeBuilder = getBuilder(builderName);
546             if (nodeBuilder == null) {
547                 log.warn("Node #" + number + "'s builder " + builderName + " is not loaded, taking 'object'.");
548                 nodeBuilder = getBuilder("object");
549             }
550         }
551         return nodeBuilder;
552     }
553     
554     /**
555      * @since MMBase-1.8
556      */

557     public MMObjectBuilder addBuilder(String JavaDoc name, MMObjectBuilder bul) {
558         return (MMObjectBuilder) mmobjs.put(name, bul);
559     }
560
561     /**
562      * Retrieves a specified builder.
563      * Note: may get deprecated in the future - use getBuilder instead.
564      * @param name The name of the builder to retrieve
565      * @return a <code>MMObjectBuilder</code> if found, <code>null</code> otherwise
566      */

567     public MMObjectBuilder getMMObject(String JavaDoc name) {
568         if (name == null) throw new RuntimeException JavaDoc("Cannot get builder with name 'NULL' in " + machineName);
569         Object JavaDoc o = mmobjs.get(name);
570         if (o == null) {
571             log.trace("MMObject " + name + " could not be found"); // can happen...
572
}
573         return (MMObjectBuilder) o;
574     }
575
576     /**
577      * Retrieves the MMBase module('mmbaseroot').
578      * @return the active MMBase module
579      */

580     public static MMBase getMMBase() {
581         if (mmbaseroot == null) {
582             synchronized(builderLoader) { // make sure only one mmbaseroot is instantiated (synchronized on random static member...)
583
mmbaseroot = (MMBase) getModule("mmbaseroot");
584                 if (mmbaseroot == null) {
585                     log.fatal("The mmbaseroot module could not be found. Perhaps 'mmbaseroot.xml' is missing?");
586                 }
587                 mmbaseroot.startModule();
588             }
589         }
590         return mmbaseroot;
591     }
592
593     /**
594      * Retrieves the loaded security manager(MMBaseCop).
595      * @return the loaded security manager(MMBaseCop)
596      */

597     public MMBaseCop getMMBaseCop() {
598         return mmbaseCop;
599     }
600
601     /**
602      * Retrieves the loaded builders.
603      * @deprecated use {@link #getBuilders()}
604      * @return an <code>Enumeration</code> listing the loaded builders
605      */

606     public Enumeration getMMObjects() {
607         return Collections.enumeration(mmobjs.values());
608     }
609
610     /**
611      * Retrieves a Collection of loaded builders.
612      */

613     public Collection getBuilders() {
614         return mmobjs.values();
615     }
616
617     /**
618      * Returns a reference to the InsRel builder.
619      * @return the <code>InsRel</code> builder if defined, <code>null</code> otherwise
620      */

621     public InsRel getInsRel() {
622         return insRel;
623     }
624
625     /**
626      * Returns a reference to the RelDef builder.
627      * @return the <code>RelDef</code> builder if defined, <code>null</code> otherwise
628      */

629     public RelDef getRelDef() {
630         return relDef;
631     }
632
633     /**
634      * Returns a reference to the TypeDef builder.
635      * @return the <code>TypeDef</code> builder if defined, <code>null</code> otherwise
636      */

637     public TypeDef getTypeDef() {
638         return typeDef;
639     }
640
641     /**
642      * Returns a reference to the TypeRel builder.
643      * @return the <code>TypeRel</code> builder if defined, <code>null</code> otherwise
644      */

645     public TypeRel getTypeRel() {
646         return typeRel;
647     }
648
649     /**
650      * Returns a reference to the OAlias builder.
651      * @return the <code>OAlias</code> builder if defined, <code>null</code> otherwise
652      */

653     public OAlias getOAlias() {
654         return oAlias;
655     }
656
657     /**
658      * Returns a reference to the Object builder.
659      * The Object builder is the builder from which all other builders eventually extend.
660      * @return the <code>Object</code> builder.
661      * @since MMBase-1.6
662      */

663     public MMObjectBuilder getRootBuilder() {
664         if (rootBuilder == null) {
665             rootBuilder = loadBuilder("object");
666         }
667         return rootBuilder;
668     }
669
670     /**
671      * Returns the otype of the Object builder, or -1 if it is not known.
672      * The Object builder is the builder from which all other builders eventually extend.
673      * @since MMBase-1.6
674      */

675     public int getRootType() {
676         if (rootBuilder == null) {
677             return -1;
678         } else {
679             return rootBuilder.getNumber();
680         }
681     }
682
683     /**
684      * Returns a reference to the cluster builder, a virtual builder used to
685      * perform multilevel searches.
686      *
687      * @return The cluster builder.
688      * @see ClusterBuilder
689      */

690     public ClusterBuilder getClusterBuilder() {
691         assertUp();
692         return clusterBuilder;
693     }
694
695     /**
696      * Locks until init of mmbase is finished.
697      * @since MMBase-1.7
698      */

699     protected void assertUp() {
700         if (! getState()) {
701             synchronized(this) {
702                 // lock until up. (Init is synchronized on this too)
703
}
704         }
705     }
706
707     /**
708      * Retrieves the storage base name
709      * @return the base name as a <code>String</code>
710      */

711     public String JavaDoc getBaseName() {
712         return baseName;
713     }
714
715     /**
716      * Performs periodic maintenance.
717      */

718     public void maintainance() {
719         DayMarkers dayMarkers = (DayMarkers)getMMObject("daymarks");
720         if (dayMarkers != null) {
721             dayMarkers.probe();
722         } else {
723             log.error("Can't access builder : daymarks");
724         }
725     }
726
727     /**
728      * Converts a vector containing nodes to a hashmap,
729      * using a specified (unique) integer field as the hash key.
730      * @param se The vector containing the nodes
731      * @param mapper the name of the (integer) field that determines the hash key, i.e. "number"
732      * @return the node list mapped to a <code>Hashtable</code>
733      */

734     public Hashtable getSearchHash(Vector se, String JavaDoc mapper) {
735         Hashtable results = new Hashtable();
736         Enumeration t = se.elements();
737         MMObjectNode node;
738         while (t.hasMoreElements()) {
739             node = (MMObjectNode)t.nextElement();
740             results.put(new Integer JavaDoc(node.getIntValue(mapper)), node);
741         }
742         return results;
743     }
744
745     /**
746      * Converts a vector containing nodes to a comma seperated list of values,
747      * obtained from a specified integer field.
748      * @param se The vector containing the nodes
749      * @param mapper the name of the (integer) field whose value to include in the list
750      * @return a parenthised, comma-seperated list of values, as a <code>String</code>
751      */

752     public String JavaDoc getWhereList(Vector se, String JavaDoc mapper) {
753         if (se == null)
754             return null;
755         StringBuffer JavaDoc inlist = new StringBuffer JavaDoc();
756         inlist.append(" (");
757         Enumeration t = se.elements();
758         MMObjectNode node;
759         while (t.hasMoreElements()) {
760             node = (MMObjectNode)t.nextElement();
761             inlist.append(node.getIntValue(mapper) + ",");
762         }
763         if (inlist.length() >= 1)
764             inlist.setLength(inlist.length() - 1);
765         inlist.append(") ");
766         return inlist.toString();
767     }
768
769     /**
770      * Retrieves a reference to the sendmail module.
771      * @deprecated use getModule("sendmail") instead
772      * SendMail will become a separate application.
773      * In MMBase 1.8. this method will be removed
774      * @return a <code>SendMailInterface</code> object if the module was loaded, <code>null</code> otherwise.
775      */

776     public SendMailInterface getSendMail() {
777         return (SendMailInterface)getModule("sendmail");
778     }
779
780     /**
781      * Retrieves the machine name.
782      * This value is set using the configuration file.
783      * @return the machine name as a <code>String</code>
784      */

785     public String JavaDoc getMachineName() {
786         return machineName;
787     }
788
789     /**
790      * Retrieves the host name or ip number
791      * This value is set using the configuration file.
792      * @return the host name as a <code>String</code>
793      */

794     public String JavaDoc getHost() {
795         return host;
796     }
797
798     /**
799      * Adds a remote observer to a specified builder.
800      * The observer is notified whenever an object of that builder is changed, added, or removed.
801      * @return <code>true</code> if adding the observer succeeded, <code>false</code> otherwise.
802      */

803     public boolean addRemoteObserver(String JavaDoc type, MMBaseObserver obs) {
804         MMObjectBuilder builder = getMMObject(type);
805         if (builder != null) {
806             return builder.addRemoteObserver(obs);
807         } else {
808             log.error("addRemoteObserver(): ERROR: Can't find builder : " + type);
809             return false;
810         }
811     }
812
813     /**
814      * Adds a local observer to a specified builder.
815      * The observer is notified whenever an object of that builder is changed, added, or removed.
816      * @return <code>true</code> if adding the observer succeeded, <code>false</code> otherwise.
817      */

818     public boolean addLocalObserver(String JavaDoc type, MMBaseObserver obs) {
819         MMObjectBuilder builder = getMMObject(type);
820         if (builder != null) {
821             return builder.addLocalObserver(obs);
822         } else {
823             log.error("addLocalObserver(): ERROR: Can't find builder : " + type);
824             return false;
825         }
826     }
827
828     /**
829      * Returns the number of marked days from a specified daycount (?)
830      * @deprecated SCAN related, should not be in this module.
831      */

832     public String JavaDoc doGetAgeMarker(StringTokenizer tok) {
833         if (tok.hasMoreTokens()) {
834             String JavaDoc age = tok.nextToken();
835             try {
836                 int agenr = Integer.parseInt(age);
837                 int agecount = ((DayMarkers)getMMObject("daymarks")).getDayCountAge(agenr);
838                 return "" + agecount;
839             } catch (Exception JavaDoc e) {
840                 log.debug(" Not a valid AGE");
841                 return "No valid age given";
842             }
843         } else {
844             return "No age given";
845         }
846     }
847
848     /**
849      * Retrieves an unique key to use for a new node's number.
850      * Calls the storage to request the key. <code>Sychronized</code> so the same number cannot be dealt out to different nodes.
851      * Does possibly not work well with multiple mmbase systems that work on the same database.
852      * @return the new unique key as an <code>int</code> value
853      * @deprecated use getStorageManager().createKey()
854      */

855     public synchronized int getDBKey() {
856         return getStorageManager().createKey();
857     }
858
859     /**
860      * Loads a core Builder.
861      * If the builder does not exist, an exception is thrown.
862      * @since MMBase-1.6
863      * @param name the name of the builder to load
864      * @return the builder
865      * @throws BuilderConfigurationException if the builder config file does not exist or is inactive
866      */

867     private MMObjectBuilder loadCoreBuilder(String JavaDoc name) {
868         MMObjectBuilder builder = loadBuilder(name);
869         if (builder == null) {
870             throw new BuilderConfigurationException("The core builder " + name + " is mandatory but inactive.");
871         } else {
872             log.debug("Loaded core builder " + builder + " with otype " + builder.getNumber());
873             return builder;
874         }
875     }
876
877
878     /**
879      *@since MMBase-1.7
880      */

881     private void loadBuilders() {
882         // first load the core builders
883
// remarks:
884
// - If nodescaches inactive, in init of typerel reldef nodes are created wich uses InsRel.getNumber(), so typerel must be started after insrel and reldef. (bug #6237)
885

886         getRootBuilder(); // loads object.xml if present.
887

888         typeDef = (TypeDef) loadCoreBuilder("typedef");
889         relDef = (RelDef) loadCoreBuilder("reldef");
890         insRel = (InsRel) loadCoreBuilder("insrel");
891         typeRel = (TypeRel) loadCoreBuilder("typerel");
892
893
894         try {
895             oAlias = (OAlias)loadBuilder("oalias");
896         } catch (BuilderConfigurationException e) {
897             // OALias builder was not defined -
898
// builder is optional, so this is not an error
899
}
900
901
902         Set builders = getBuilderLoader().getResourcePaths(ResourceLoader.XML_PATTERN, true/* recursive*/);
903
904         log.info("Loading builders: " + builders);
905         Iterator i = builders.iterator();
906         while (i.hasNext()) {
907             if (Thread.currentThread().isInterrupted()) {
908                 return;
909             }
910             String JavaDoc builderXml = (String JavaDoc) i.next();
911             String JavaDoc resourceName = ResourceLoader.getName(builderXml);
912             String JavaDoc resourceDirectory = ResourceLoader.getDirectory(builderXml) + "/";
913             loadBuilderFromXML(resourceName, resourceDirectory);
914         if (cloudModel != null) {
915                 cloudModel.addBuilder(resourceName,"builders/" + resourceDirectory + resourceName + ".xml");
916             }
917         }
918
919         log.debug("Starting Cluster Builder");
920         clusterBuilder = new ClusterBuilder(this);
921     }
922
923 // private void initClustering(){
924
// String clusterClass = getInitParameter("CLUSTERING");
925
// if (clusterClass != null) {
926
// log.debug("Starting ClusterManager: " + clusterClass);
927
//
928
// Class newclass;
929
// try {
930
// newclass = Class.forName(clusterClass);
931
// clusterManager = (ClusterManager) newclass.newInstance();
932
// } catch (Exception e) {
933
// log.error("Failed to start MMBaseChangeInterface: " + e.getMessage());
934
// clusterManager = null;
935
// }
936
// } else {
937
// log.debug("Not starting a ClusterManager");
938
// }
939
// }
940

941     /**
942      * Initializes the builders, using the builder xml files in the config directory
943      * @return Always <code>true</code>
944      */

945     boolean initBuilders() {
946
947         typeDef.init();
948
949         // first initialize versions, if available (table must exist for quereis to succeed)
950
log.debug("Versions:");
951         Versions versions = (Versions)getMMObject("versions");
952         if (versions != null) {
953             versions.init();
954         }
955
956         relDef.init();
957         insRel.init();
958         typeRel.init();
959
960
961         log.debug("mmobjects, inits");
962         Iterator bi = mmobjs.entrySet().iterator();
963         while (bi.hasNext()) {
964             Map.Entry me = (Map.Entry)bi.next();
965             MMObjectBuilder builder = (MMObjectBuilder)me.getValue();
966             log.debug("init " + builder);
967             try {
968                 initBuilder(builder);
969             } catch (BuilderConfigurationException e) {
970                 // something bad with this builder or its parents - remove it
971
log.error("Removed builder " + builder.getTableName() + " from the builderlist, as it cannot be initialized.");
972                 bi.remove();
973             } catch (Exception JavaDoc ex) {
974                 log.error("Something went wrong while initializing builder " + builder.getTableName());
975                 log.info("This builder will be removed from active builder list");
976                 log.error(Logging.stackTrace(ex));
977                 bi.remove();
978             }
979         }
980
981         log.debug("**** end of initBuilders");
982         return true;
983     }
984
985     /**
986      * inits a builder
987      * @param builder The builder which has to be initialized
988      */

989     public void initBuilder(MMObjectBuilder builder) {
990         if (!builder.isVirtual()) {
991             builder.init();
992             typeDef.loadTypeDef(builder.getTableName());
993             Versions versions = (Versions)getMMObject("versions");
994             if (versions != null && versions.created()) {
995                 checkBuilderVersion(builder.getTableName(), versions);
996             }
997         }
998     }
999
1000    /**
1001     * Unloads a builders from MMBase. After this, the builder is gone
1002     * @param builder the builder which has to be unloaded
1003     */

1004    public void unloadBuilder(MMObjectBuilder builder) {
1005        if (mmobjs.remove(builder.getTableName()) == null) {
1006            throw new RuntimeException JavaDoc("builder with name: " + builder.getTableName() + " could not be unloaded, since it was not loaded.");
1007        }
1008        if (!builder.isVirtual()) {
1009            typeDef.unloadTypeDef(builder.getTableName());
1010            log.info("unloaded builder with name:" + builder.getTableName());
1011        } else {
1012            log.info("unloaded virtual builder with name:" + builder.getTableName());
1013        }
1014    }
1015
1016
1017    /**
1018     * @since MMBase-1.8
1019     */

1020    public ResourceLoader getBuilderLoader() {
1021        return MMBase.builderLoader;
1022    }
1023
1024    /**
1025     * @since MMBase-1.8
1026     */

1027    public BuilderReader getBuilderReader(String JavaDoc builderName) {
1028        try {
1029            java.net.URL JavaDoc url = getBuilderLoader().getResource(builderName + ".xml");
1030            if (url == null) return null;
1031            org.w3c.dom.Document JavaDoc doc = ResourceLoader.getDocument(url, true, BuilderReader.class);
1032            BuilderReader r = new BuilderReader(doc, this);
1033            r.setSystemId(url.toString());
1034            return r;
1035        } catch (SAXException JavaDoc se) {
1036            log.error(se);
1037            return null;
1038        } catch (java.io.IOException JavaDoc ioe) {
1039            log.error(ioe);
1040            return null;
1041        }
1042    }
1043
1044    /**
1045     * Locate one specific builder withing the main builder config path, including sub-paths.
1046     * If the builder already exists, the existing object is returned instead.
1047     * If the builder cannot be found in this path, a BuilderConfigurationException is thrown.
1048     * @since MMBase-1.6
1049     * @param builderName name of the builder to initialize
1050     * @return the initialized builder object, or null if the builder could not be created (i.e. is inactive).
1051     * @throws BuilderConfigurationException if the builder config file does not exist
1052     */

1053    synchronized MMObjectBuilder loadBuilder(String JavaDoc builderName) { // synchronized to make sure that storage initialized only once
1054
return loadBuilder(builderName, "");
1055    }
1056
1057    /**
1058     * Locate one specific builder within a given path, relative to the main builder config path, including sub-paths.
1059     * Return the actual path.
1060     * @param builderName name of the builder to find
1061     * @param path the path to start searching. The path need be closed with a '/ character
1062     * @return the file path to the builder xml, or null if the builder could not be created (i.e. is inactive).
1063     * @throws BuilderConfigurationException if the builder config file does not exist
1064     * @todo The second argument (and perhaps the whole function) is silly, only exists because this
1065     * function used to be implemented recursively (now delegated to ResourceLoader).
1066     */

1067    public String JavaDoc getBuilderPath(String JavaDoc builderName, String JavaDoc path) {
1068        Set builders = getBuilderLoader().getResourcePaths(java.util.regex.Pattern.compile(path + ResourceLoader.XML_PATTERN.pattern()), true /*recursive*/);
1069        Iterator i = builders.iterator();
1070        if (log.isDebugEnabled()) {
1071            log.debug("Found builder " + builders + " from " + getBuilderLoader() + " searching for " + builderName);
1072        }
1073        String JavaDoc xml = builderName + ".xml";
1074        while (i.hasNext()) {
1075            String JavaDoc builderXml = (String JavaDoc) i.next();
1076            if (builderXml.equals(xml)) {
1077                return "";
1078            } else if (builderXml.endsWith("/" + xml)) {
1079                return builderXml.substring(0, builderXml.length() - xml.length());
1080            }
1081        }
1082        return null;
1083    }
1084
1085
1086
1087    /**
1088     * Locate one specific builder within a given path, relative to the main builder config path, including sub-paths.
1089     * If the builder already exists, the existing object is returned instead.
1090     * @param builderName name of the builder to initialize
1091     * @param ipath the path to start searching. The path need be closed with a File.seperator character.
1092     * @return the initialized builder object, or null if the builder could not be created (i.e. is inactive).
1093     * @throws BuilderConfigurationException if the builder config file does not exist
1094     */

1095    MMObjectBuilder loadBuilder(String JavaDoc builderName, String JavaDoc ipath) {
1096        MMObjectBuilder builder = getMMObject(builderName);
1097        if (builder != null) {
1098            log.debug("Builder '" + builderName + "' is already loaded");
1099            return builder;
1100        }
1101        String JavaDoc path = getBuilderPath(builderName, ipath);
1102        if (path != null) {
1103        if (cloudModel != null) {
1104                cloudModel.addBuilder(builderName,path+builderName+".xml");
1105            }
1106            return loadBuilderFromXML(builderName, path);
1107        } else {
1108            log.error("Cannot find specified builder " + builderName);
1109            throw new BuilderConfigurationException("Cannot find specified builder " + builderName);
1110        }
1111    }
1112
1113    /**
1114     * Create a new builder object using a xml configfile located in a given path relative to the main builder config path,
1115     * and return the builder object.
1116     * If the builder already exists, the existing object is returned instead.
1117     * Note that the builder's init() method is NOT called (since some builders need other builders in memory when their init() is called,
1118     * this method is called seperately after all builders are loaded).
1119     * @deprecation-used uses deprecated builder methods, contains commented-out code
1120     * @param builderName name of the builder to initialize
1121     * @param ipath the path to start searching. The path need be closed with a '/' character.
1122     * @return the loaded builder object.
1123     */

1124    public MMObjectBuilder loadBuilderFromXML(String JavaDoc builderName, String JavaDoc ipath) {
1125        MMObjectBuilder builder = getMMObject(builderName);
1126        if (builder != null) {
1127            log.debug("Builder '" + builderName + "' is already loaded");
1128            return builder;
1129        }
1130
1131        try {
1132            // register the loading of this builder
1133
loading.add(builderName);
1134            BuilderReader parser = getBuilderReader(ipath + builderName);
1135            if (parser == null) return null;
1136            String JavaDoc status = parser.getStatus();
1137            if (status.equals("active")) {
1138                log.service("Starting builder: " + builderName);
1139                Class JavaDoc newclass;
1140                try {
1141                    String JavaDoc classname = parser.getClassName();
1142                    newclass = Class.forName(classname);
1143                } catch (ClassNotFoundException JavaDoc cnfe) {
1144                    MMObjectBuilder p = parser.getParentBuilder();
1145                    if(p != null) {
1146                        newclass = p.getClass();
1147                    } else {
1148                        newclass = MMObjectBuilder.class;
1149                    }
1150                    log.error(cnfe.toString() + " (for " + parser.getClassName() + ") Falling back to " + newclass.getName());
1151                }
1152                builder = (MMObjectBuilder)newclass.newInstance();
1153
1154                addBuilder(builderName, builder);
1155
1156                builder.setXMLPath(ipath);
1157                builder.setMMBase(this);
1158                builder.setTableName(builderName);
1159
1160                // register the parent builder, if applicable
1161
MMObjectBuilder parent = parser.getParentBuilder();
1162                if (parent != null) {
1163                    builder.setParentBuilder(parent);
1164                } else if ((builder instanceof InsRel) && !builderName.equals("insrel")) {
1165                    builder.setParentBuilder(getInsRel());
1166                } else if (!builderName.equals("object")) {
1167                    builder.setParentBuilder(getRootBuilder());
1168                }
1169
1170                Hashtable descriptions = parser.getDescriptions();
1171                builder.setDescriptions(descriptions);
1172                String JavaDoc desc = (String JavaDoc)descriptions.get(locale.getLanguage());
1173                // XXX" set description by builder?
1174
builder.setDescription(desc);
1175                builder.setSingularNames(parser.getSingularNames());
1176                builder.setPluralNames(parser.getPluralNames());
1177                builder.setVersion(parser.getVersion());
1178                builder.setMaintainer(parser.getMaintainer());
1179                builder.setSearchAge("" + parser.getSearchAge());
1180                builder.setInitParameters(parser.getProperties());
1181                parser.getDataTypes(builder.getDataTypeCollector());
1182                builder.setFields(parser.getFields(builder, builder.getDataTypeCollector()));
1183                builder.getStorageConnector().addIndices(parser.getIndices(builder));
1184                Iterator f = parser.getFunctions().iterator();
1185                while (f.hasNext()) {
1186                    Function func = (Function) f.next();
1187                    builder.addFunction(func);
1188                    log.service("Added " + func + " to " + builder);
1189                }
1190                if (parent != null) {
1191                    Iterator i = parent.getFunctions().iterator();
1192                    while (i.hasNext()) {
1193                        Function parentFunction = (Function) i.next();
1194                        if (builder.getFunction(parentFunction.getName()) == null) {
1195                            builder.addFunction(parentFunction);
1196                        }
1197                    }
1198                }
1199            }
1200        } catch (Throwable JavaDoc e) { // what kind of exceptions are these?
1201
loading.remove(builderName);
1202            log.error(Logging.stackTrace(e));
1203            return null;
1204        }
1205        loading.remove(builderName);
1206        return builder;
1207    }
1208
1209    /**
1210     * Retrieves the DTD base url.
1211     * This value is set using the configuration file.
1212     * @deprecated keesj: This method is not used. Document type definitions
1213     * should contain a fully qualified url.
1214     * I think the author was thinking of a dtdpath wich makes sence
1215     * @return the dtd base as a <code>String</code>
1216     */

1217    public String JavaDoc getDTDBase() {
1218        return dtdbase;
1219    }
1220
1221    /**
1222     * Loads either the storage manager factory or the appropriate support class using the configuration parameters.
1223     * @since MMBase-1.7
1224     */

1225    protected void initializeStorage() {
1226        if (storageManagerFactory != null) return; // initialized allready
1227
try {
1228            storageManagerFactory = StorageManagerFactory.newInstance(this);
1229            // print information about storage
1230
log.info("Using class: '" + storageManagerFactory.getClass().getName() + "'.");
1231        } catch (StorageException se) {
1232            log.error(se.getMessage());
1233            throw new StorageError();
1234        }
1235    }
1236
1237    /**
1238     * Returns StorageManagerFactory class used to access the storage configuration.
1239     * @since MMBase-1.7
1240     * @return a StorageManagerFactory class, or <code>null</code> if not configured
1241     */

1242    public StorageManagerFactory getStorageManagerFactory() {
1243        return storageManagerFactory;
1244    }
1245
1246    /**
1247     * Returns a StorageManager to access the storage.. Equal to getStorageManagerFactory().getStorageManager().
1248     * @since MMBase-1.7
1249     * @return a StorageManager class
1250     * @throws StorageException if no storage manager could be instantiated
1251     */

1252    public StorageManager getStorageManager() throws StorageException {
1253        if (storageManagerFactory == null) {
1254            throw new StorageConfigurationException("Storage manager factory not configured.");
1255        } else {
1256            return storageManagerFactory.getStorageManager();
1257        }
1258    }
1259
1260    /**
1261     * Returns a SearchQueryHandler to access the storage.. Equal to getStorageManagerFactory().getSearchQueryHandler().
1262     * @since MMBase-1.8
1263     * @return a StorageManager class
1264     * @throws StorageException if no storage manager could be instantiated
1265     */

1266    public SearchQueryHandler getSearchQueryHandler() throws StorageException {
1267        if (storageManagerFactory == null) {
1268            throw new StorageConfigurationException("Storage manager factory not configured.");
1269        } else {
1270            return storageManagerFactory.getSearchQueryHandler();
1271        }
1272    }
1273
1274    /**
1275     * Loads a Node again, using its 'right' parent.
1276     * Reloading may retrieve extra fields if the original node was not loaded accurately.
1277     * @deprecated Not necessary in most cases, with the possible exception of lists obtained from InsRel.
1278     * However, in the later case using this method is probably too costly.
1279     */

1280    public MMObjectNode castNode(MMObjectNode node) {
1281        /* fake because solved
1282         */

1283        int otype = node.getOType();
1284        String JavaDoc ename = typeDef.getValue(otype);
1285        if (ename == null) {
1286            return null;
1287        }
1288        MMObjectBuilder res = getMMObject(ename);
1289        return res.getNode(node.getNumber());
1290    }
1291
1292    /**
1293     * Retrieves the autorisation type.
1294     * This value is set using the configuration file.
1295     * Examples are 'none' or 'basic'.
1296     * @return a <code>String</code> identifying the type
1297     */

1298    public String JavaDoc getAuthType() {
1299        return authtype;
1300    }
1301
1302    /**
1303     * Retrieves the current language.
1304     * This value is set using the configuration file.
1305     * Examples are 'en' or 'nl'.
1306     * @return the language as a <code>String</code>
1307     */

1308    public String JavaDoc getLanguage() {
1309        return locale.getLanguage();
1310    }
1311
1312    /**
1313     * Retrieves the current locale.
1314     * @since MMBase-1.8
1315     */

1316    public Locale getLocale() {
1317        return locale;
1318    }
1319
1320    /**
1321     * Retrieves the timezone asociated with this MMBase's 'DateTime' objects. MMBase stores dates
1322     * in storage as 'Date' but without time-zone information, and therefore to a certain
1323     * degree open to interpretation.
1324     *
1325     * Together with this timezone the times can be defined absoletely (that is, of course, relative
1326     * to the time frame of out planet).
1327     (
1328     * @since MMBase-1.8
1329     */

1330    public TimeZone getTimeZone() {
1331        return timeZone;
1332    }
1333
1334
1335    /**
1336     * Retrieves the encoding.
1337     * This value is set using the configuration file.
1338     * Examples are 'UTF-8' (default) or 'ISO-8859-1'.
1339     *
1340     * @return the coding as a <code>String</code>
1341     * @since MMBase-1.6
1342     */

1343    public String JavaDoc getEncoding() {
1344        return encoding;
1345    }
1346
1347    /**
1348     * Retrieves whether this mmbase module is running.
1349     * @return <code>true</code> if the module has been initialized and all builders loaded, <code>false</code> otherwise.
1350     */

1351    public boolean getState() {
1352        return mmbaseState == STATE_UP;
1353    }
1354
1355    /**
1356     * Checks and switches the user/grouplevel in which MMBase runs.
1357     * The userlevel is set using the -Dmmbase:userlevel=user:group commandline parameter.
1358     * Should probably be changed to <code>private</code>.
1359     */

1360    public void checkUserLevel() {
1361        String JavaDoc level = System.getProperty("mmbase.userlevel");
1362        if (level != null) {
1363            log.info("CheckUserLevel -> mmmbase.userlevel=" + System.getProperty("mmbase.userlevel"));
1364            int pos = level.indexOf(':');
1365            if (pos != -1) {
1366                String JavaDoc user = level.substring(0, pos);
1367                String JavaDoc group = level.substring(pos + 1);
1368                setUser setuser = new setUser();
1369                setuser.setUserGroup(user, group);
1370            } else {
1371                log.info("CheckUserLevel -> mmmbase.userlevel= not defined as user:group");
1372            }
1373        }
1374    }
1375
1376    /**
1377     * Checks the builder version and, if needed, updates the version table.
1378     * Queries the xml files instead of the builder itself (?)
1379     * @return Returns <code>true</code> if the builder XML could be read, <code>false</code> otherwise.
1380     */

1381    private boolean checkBuilderVersion(String JavaDoc builderName, Versions ver) {
1382
1383        MMObjectBuilder tmp = (MMObjectBuilder) mmobjs.get(builderName);
1384
1385        if (tmp == null) {
1386            return false;
1387        }
1388
1389        if (tmp != null) {
1390            int version = tmp.getVersion();
1391            String JavaDoc maintainer = tmp.getMaintainer();
1392
1393            int installedversion = ver.getInstalledVersion(builderName, "builder");
1394            if (installedversion == -1 || version > installedversion) {
1395                ver.setInstalledVersion(builderName, "builder", maintainer, version);
1396            }
1397        }
1398        return true;
1399    }
1400
1401    /**
1402     * This is a conveniance method to help you register listeners to node and
1403     * relation events. Becouse they are now separate listeners the method accepts
1404     * an object that may have implemented either NodeEvent
1405     * or RelationEvent. This method checks and registers accordingly. <br/>
1406     * the purpose of this method is that a straight node or relation event listeren
1407     * will listen to any node or relation event. This method will wrap your event
1408     * listener to make shure only the requested event types are forwarded.
1409     * @see TypedRelationEventListenerWrapper
1410     * @see TypedNodeEventListenerWrapper
1411     * @see NodeEventListener
1412     * @see RelationEventListener
1413     * @param builder should be a valid builder name, the type for which you want to
1414     * receive events
1415     * @param listener some object implementing NodeEventListener, RelationEventListener,
1416     * or both
1417     * @since MMBase-1.8
1418     */

1419    public void addNodeRelatedEventsListener(String JavaDoc builder, org.mmbase.core.event.EventListener listener) {
1420        MMObjectBuilder b = getBuilder(builder);
1421        if(b != null){
1422            if(listener instanceof NodeEventListener){
1423                TypedNodeEventListenerWrapper tnelr = new TypedNodeEventListenerWrapper(b, (NodeEventListener)listener, true);
1424                EventManager.getInstance().addEventListener(tnelr);
1425            }
1426            if(listener instanceof RelationEventListener){
1427                TypedRelationEventListenerWrapper trelr = new TypedRelationEventListenerWrapper(b, (RelationEventListener)listener, RelationStep.DIRECTIONS_BOTH, true);
1428                EventManager.getInstance().addEventListener(trelr);
1429            }
1430        }
1431    }
1432
1433    /**
1434     * @see MMBase#addNodeRelatedEventsListener
1435     * @param builder
1436     * @param listener
1437     * @since MMBase-1.8
1438     */

1439    public void removeNodeRelatedEventsListener(String JavaDoc builder, org.mmbase.core.event.EventListener listener) {
1440        MMObjectBuilder b = getBuilder(builder);
1441        if(b != null){
1442            if(listener instanceof NodeEventListener){
1443                TypedNodeEventListenerWrapper tnelr = new TypedNodeEventListenerWrapper(b, (NodeEventListener)listener, true);
1444                EventManager.getInstance().removeEventListener(tnelr);
1445            }
1446            if(listener instanceof RelationEventListener){
1447                TypedRelationEventListenerWrapper trelr= new TypedRelationEventListenerWrapper(b, (RelationEventListener)listener, RelationStep.DIRECTIONS_BOTH, true);
1448                EventManager.getInstance().removeEventListener(trelr);
1449
1450            }
1451        }
1452    }
1453
1454
1455}
1456
Popular Tags