KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jcorporate > expresso > core > dbobj > Schema


1 /* ====================================================================
2  * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
3  *
4  * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The end-user documentation included with the redistribution,
19  * if any, must include the following acknowledgment:
20  * "This product includes software developed by Jcorporate Ltd.
21  * (http://www.jcorporate.com/)."
22  * Alternately, this acknowledgment may appear in the software itself,
23  * if and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. "Jcorporate" and product names such as "Expresso" must
26  * not be used to endorse or promote products derived from this
27  * software without prior written permission. For written permission,
28  * please contact info@jcorporate.com.
29  *
30  * 5. Products derived from this software may not be called "Expresso",
31  * or other Jcorporate product names; nor may "Expresso" or other
32  * Jcorporate product names appear in their name, without prior
33  * written permission of Jcorporate Ltd.
34  *
35  * 6. No product derived from this software may compete in the same
36  * market space, i.e. framework, without prior written permission
37  * of Jcorporate Ltd. For written permission, please contact
38  * partners@jcorporate.com.
39  *
40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43  * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
44  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
46  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
47  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
48  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This software consists of voluntary contributions made by many
55  * individuals on behalf of the Jcorporate Ltd. Contributions back
56  * to the project(s) are encouraged when you make modifications.
57  * Please send them to support@jcorporate.com. For more information
58  * on Jcorporate Ltd. and its products, please see
59  * <http://www.jcorporate.com/>.
60  *
61  * Portions of this software are based upon other open source
62  * products and are subject to their respective licenses.
63  */

64
65 package com.jcorporate.expresso.core.dbobj;
66
67 import com.jcorporate.expresso.core.controller.Controller;
68 import com.jcorporate.expresso.core.controller.ControllerException;
69 import com.jcorporate.expresso.core.db.DBException;
70 import com.jcorporate.expresso.core.i18n.Messages;
71 import com.jcorporate.expresso.core.job.Job;
72 import com.jcorporate.expresso.core.misc.ConfigContext;
73 import com.jcorporate.expresso.core.misc.ConfigManager;
74 import com.jcorporate.expresso.core.misc.ConfigSetupDefault;
75 import com.jcorporate.expresso.core.misc.StringUtil;
76 import com.jcorporate.expresso.core.servlet.StdServlet;
77 import com.jcorporate.expresso.ext.report.ExpressoReport;
78 import com.jcorporate.expresso.kernel.ComponentLifecycle;
79 import com.jcorporate.expresso.kernel.Configuration;
80 import com.jcorporate.expresso.kernel.ContainerComponentBase;
81 import com.jcorporate.expresso.kernel.InstallLog;
82 import com.jcorporate.expresso.kernel.exception.ConfigurationException;
83 import com.jcorporate.expresso.kernel.management.ExpressoRuntimeMap;
84 import com.jcorporate.expresso.kernel.util.ClassLocator;
85 import com.jcorporate.expresso.kernel.util.FastStringBuffer;
86 import com.jcorporate.expresso.services.controller.RegistrationFactory;
87 import com.jcorporate.expresso.services.dbobj.Setup;
88 import org.apache.log4j.Logger;
89
90 import java.net.URL JavaDoc;
91 import java.util.Collections JavaDoc;
92 import java.util.Enumeration JavaDoc;
93 import java.util.HashMap JavaDoc;
94 import java.util.Hashtable JavaDoc;
95 import java.util.Iterator JavaDoc;
96 import java.util.Map JavaDoc;
97 import java.util.StringTokenizer JavaDoc;
98 import java.util.Vector JavaDoc;
99
100
101 /**
102  * <p/>
103  * A Schema contains a collection of DBObjects, Controllers, Jobs, and MessageBundles
104  * allowing them to be created all at once,
105  * dropped at once, and reported on as a group
106  * A schema also contains (optional) a list of ReportPage objects
107  * that make up the standard reports for a package
108  * </p>
109  * <p>You create your own schema as the hub of your Expresso-based component.
110  * To do this, derive your own class from Schema, override the abstract members
111  * to give your component a name, component code, etc. And then in the constructor
112  * of the schema, you add the various components such as DBOBjects to your schema.
113  * </p>
114  *
115  * @author Michael Nash
116  */

117 public abstract class Schema extends ContainerComponentBase implements ComponentLifecycle, RegistrationFactory {
118
119     private static Logger log = Logger.getLogger(Schema.class);
120
121     private static Map schemaDefinitions = Collections.synchronizedMap(new HashMap JavaDoc(5));
122
123
124     /**
125      * These are the current setup values for this schema.
126      */

127     private Map setupValue = new HashMap JavaDoc();
128
129     /**
130      * This are setup values that are defined as default values.
131      */

132     private Map defaultSetupValues = new HashMap JavaDoc();
133
134     /**
135      * dbKey is used to indicate that this schema is actually being applied to
136      * other than the default database. Null indicates it's being applied to the
137      * default
138      * database
139      */

140     private String JavaDoc dbKey = "";
141
142
143     /**
144      * Return the component code, or the directory under the 'expresso' directory
145      * that the component is set into.
146      */

147     private String JavaDoc defaultComponentCode = "";
148
149     /**
150      * Retrieve a default description of the schema.
151      */

152     private String JavaDoc defaultDescription = "No Description Provided";
153
154     /**
155      * Used to store an instance of this Schema class to prevent a new instance
156      * being instantiated for access to the messages bundle
157      */

158     private static Schema myInstance = null;
159
160
161     /**
162      * The path to the message Bundle
163      */

164     private String JavaDoc messageBundlePath = "";
165     private int mUserID;
166
167
168     /**
169      * Constructor
170      */

171     public Schema() {
172
173         //
174
//Put per-instance initializations before this line.
175
//
176
if (schemaDefinitions.containsKey(this.getClass().getName())) {
177             //Data already initialized
178
return;
179         }
180
181         if (myInstance == null) {
182             myInstance = this;
183         }
184
185         schemaDefinitions.put(this.getClass().getName(), new SchemaDefinition());
186
187
188     } /* Schema() */
189
190     /**
191      * Method to add a dbobject to the list of dbobjects in this schema
192      *
193      * @param dbobjectClass the class name of the DBObject that you want to add.
194      */

195     protected synchronized void addDBObject(String JavaDoc dbobjectClass) {
196         addDBObject(dbobjectClass, null, "default");
197     } /* addDBObject(String) */
198
199     /**
200      * New method of adding a dbobject to the specified category. Call by
201      * writing:
202      *
203      * @param c the class name of the DBObject that you want to add.
204      * @param categoryName the category to which this controller belongs.
205      */

206     protected synchronized void addDBObject(Class JavaDoc c, String JavaDoc categoryName) {
207         addDBObject(c.getName(), null, categoryName);
208     }
209
210     /**
211      * New method of adding a dbobject to the default category. Call by
212      * writing:
213      * <code>addController(&quot;your.class.here.<b>class</b>&quot;);
214      *
215      * @param c the class of the controller that you want to add. If you mis-type
216      * your controller name, the compiler will catch it at compile time.
217      */

218     protected synchronized void addDBObject(Class JavaDoc c) {
219         addDBObject(c.getName(), null, "default");
220     }
221
222
223     /**
224      * Method to add a dbobject to the list of dbobjects in this schema
225      * for a named dbother location in the default category. Please note that
226      * otherdb tables are not created on a DBCreate run.
227      *
228      * @param dbobjectClass the name of the database object class to use
229      * @param otherDBName The dbcontext to use for this dataobject.
230      */

231     protected synchronized void addDBObject(String JavaDoc dbobjectClass,
232                                             String JavaDoc otherDBName) {
233         addDBObject(dbobjectClass, otherDBName, "default");
234     }
235
236     /**
237      * Method to add a dbobject to the list of dbobjects in this schema
238      * for a named dbother location and named category.
239      *
240      * @param dbobjectClass The name of the dbobject to add to the schema.
241      * @param otherDBName The dbcontext to use for this dataobject.
242      * @param categoryName the navigation category to use for this database object
243      */

244     protected synchronized void addDBObject(String JavaDoc dbobjectClass,
245                                             String JavaDoc otherDBName,
246                                             String JavaDoc categoryName) {
247         StringUtil.assertNotBlank(dbobjectClass,
248                 "DB Object class name may not " +
249                 " be null or blank here");
250         SchemaDefinition sd = getDef();
251         sd.addMember(dbobjectClass);
252
253         if (otherDBName != null) {
254             sd.addDBObjectMap(dbobjectClass, otherDBName);
255         }
256
257     } /* addDBObject(String, String, String) */
258
259
260     /**
261      * Add a controller to the default category
262      *
263      * @param controllerName the String name of the controller to add to the
264      * schema
265      */

266     protected synchronized void addController(String JavaDoc controllerName) {
267         addController(controllerName, "default");
268     }
269
270     /**
271      * New method of adding a controller to the default category. Call by
272      * writing:
273      * <code>addController(&quot;your.class.here.<b>class</b>&quot;);
274      *
275      * @param c the class of the controller that you want to add. If you mis-type
276      * your controller name, the compiler will catch it at compile time.
277      */

278     protected synchronized void addController(Class JavaDoc c) {
279         addController(c.getName());
280     }
281
282     /**
283      * New method to add controller objects to the list of controllers
284      * in this Schema object. We no longer add the object itself (as this
285      * is not very efficient, to say the least) we only store the *name*
286      * of the controller.
287      *
288      * @param controllerName The class name of the controller object
289      * @param categoryName The category to which this controller belongs
290      */

291     protected synchronized void addController(String JavaDoc controllerName,
292                                               String JavaDoc categoryName) {
293         SchemaDefinition sd = getDef();
294         sd.addController(controllerName);
295     } /*addController(String) */
296
297     /**
298      * New method of adding a controller to the default category. Call by
299      * writing:
300      * <code>addController(&quot;your.class.here.<b>class</b>&quot;);
301      *
302      * @param c the class of the controller that you want to add. If you mis-type
303      * your controller name, the compiler will catch it at compile time.
304      * @param categoryName the category to which this controller belongs.
305      */

306     protected synchronized void addController(Class JavaDoc c, String JavaDoc categoryName) {
307         addController(c.getName(), categoryName);
308     }
309
310     /**
311      * Add a new report page to the schema.
312      *
313      * @param reportClass the class of the report. Usually obtained by typing
314      * out the class name and adding &quot;.class&quot; at the end. Example:
315      * <code>com.jcorporate.ext.report.DownloadUsers<b>.class</b></code>
316      */

317     public synchronized void addReportPage(Class JavaDoc reportClass) {
318         addReportPage(reportClass.getName());
319     }
320
321     /**
322      * Add a new ReportPage to the default category
323      *
324      * @param reportClassName The class name of a "ReportPage" object that is
325      * part of this schema
326      */

327     public synchronized void addReportPage(String JavaDoc reportClassName) {
328         StringUtil.assertNotBlank(reportClassName,
329                 "Blank report class name not allowed here");
330         SchemaDefinition sd = getDef();
331         sd.addReport(reportClassName);
332     }
333
334     /**
335      * Add a new Job object to this schema
336      *
337      * @param oneJob New job object to add as a member to this
338      * schema
339      * @throws DBException If the object cannot be added
340      * @deprecated See the addJob(Class) method instead since Expresso 5.6
341      */

342     public synchronized void add(Job oneJob)
343             throws DBException {
344         getDef().addJob(oneJob.getClass().getName());
345     } /* add(Job) */
346
347     /**
348      * method of adding a job to the specified category. Call by
349      * writing:
350      * <code>addController(&quot;your.class.here.<b>class</b>&quot;);
351      *
352      * @param c the class of the controller that you want to add. If you mis-type
353      * your controller name, the compiler will catch it at compile time.
354      */

355     protected synchronized void addJob(Class JavaDoc c) {
356         getDef().addJob(c.getName());
357     }
358
359     /**
360      * New method of adding a servlet to the specified category. Call by
361      * writing:
362      * <code>addController(&quot;your.class.here.<b>class</b>&quot;);
363      *
364      * @param c the class of the controller that you want to add. If you mis-type
365      * your controller name, the compiler will catch it at compile time.
366      */

367     protected synchronized void addServlet(Class JavaDoc c) {
368         getDef().addServlet(c.getName());
369     }
370
371     /**
372      * Add a new setup value to this schema
373      *
374      * @param schemaClass Class name of this schema
375      * @param setupCode Code of the new setup value
376      * @param descrip A description of the new setup value
377      * @param defaultValue A default value for the new setup value
378      * @throws DBException If the value cannot be added to the setup table
379      * @see #addSetup
380      * @deprecated since 3/04; use addSetup() instead
381      */

382     public synchronized void add(String JavaDoc schemaClass, String JavaDoc setupCode,
383                                  String JavaDoc descrip, String JavaDoc defaultValue)
384             throws DBException {
385         addSetup(schemaClass, setupCode, descrip, defaultValue);
386     }
387
388     /**
389      * Add a new setup value to the named schema; will not change value if one already exists in Setup table
390      *
391      * @param schemaClass Class name of this schema
392      * @param setupCode Code of the new setup value
393      * @param descrip A description of the new setup value
394      * @param defaultValue A default value for the new setup value
395      * @throws DBException If the value cannot be added to the setup table
396      */

397     public synchronized void addSetup(String JavaDoc schemaClass, String JavaDoc setupCode,
398                                       String JavaDoc descrip, String JavaDoc defaultValue)
399             throws DBException {
400
401         FastStringBuffer fsb = FastStringBuffer.getInstance();
402         try {
403             fsb.append(schemaClass);
404             fsb.append("|");
405             fsb.append(setupCode);
406             fsb.append("|");
407             fsb.append(descrip);
408             fsb.append("|");
409             fsb.append(defaultValue);
410
411             getDef().addConfigValue(fsb.toString());
412         } finally {
413             fsb.release();
414         }
415
416         this.defaultSetupValues.put(setupCode, defaultValue);
417
418     }
419
420     /**
421      * Add a new setup value to this schema for THIS schema; will not change value if one already exists in Setup table
422      *
423      * @param setupCode Code of the new setup value
424      * @param descrip A description of the new setup value
425      * @param defaultValue A default value for the new setup value
426      * @throws DBException If the value cannot be added to the setup table
427      */

428     public synchronized void addSetup(String JavaDoc setupCode,
429                                       String JavaDoc descrip, String JavaDoc defaultValue)
430             throws DBException {
431         addSetup(getClass().getName(), setupCode, descrip, defaultValue);
432     }
433
434     /**
435      * Return the list of configuration values required by this schema
436      *
437      * @return Vector A vector of setup/configuration values for this schema
438      */

439     public synchronized Vector JavaDoc getConfig() {
440         Vector JavaDoc newConfig = new Vector JavaDoc();
441         String JavaDoc oneHolder = null;
442
443         for (Iterator JavaDoc e = getDef().getConfigValues(); e.hasNext();) {
444             oneHolder = (String JavaDoc) e.next();
445
446             StringTokenizer JavaDoc stk = new StringTokenizer JavaDoc(oneHolder, "|");
447
448             try {
449                 Setup oneSetup = new Setup(SecuredDBObject.SYSTEM_ACCOUNT);
450                 oneSetup.setField("SchemaClass", stk.nextToken());
451                 oneSetup.setField("SetupCode", stk.nextToken());
452                 oneSetup.setField("Descrip", stk.nextToken());
453
454                 //Setup value for many places is blank.
455
if (stk.hasMoreTokens()) {
456                     oneSetup.setField("SetupValue", stk.nextToken());
457                 }
458
459                 newConfig.addElement(oneSetup);
460             } catch (Exception JavaDoc ee) {
461                 log.error("Error parsing setup value: " + oneHolder, ee);
462             }
463         } /* for */
464
465
466         return newConfig;
467     } /* getConfig() */
468
469     /**
470      * Return a list of the Controller objects that are members of this
471      * schema. Controllers are instantiated if not already cached. However, since ControllerFactory caches
472      * the instances, performance of calls after the initial call is faster
473      *
474      * @return java.util.List of Controller objects that belong to this schema
475      */

476     public java.util.List JavaDoc getControllerList() {
477         java.util.List JavaDoc theControllers = new java.util.ArrayList JavaDoc(4);
478         String JavaDoc oneControllerName = null;
479         Controller oneController = null;
480
481         for (Iterator JavaDoc ee = getDef().getControllers(); ee.hasNext();) {
482             oneControllerName = (String JavaDoc) ee.next();
483
484             try {
485                 oneController = ConfigManager.getControllerFactory().getController(oneControllerName);
486                 theControllers.add(oneController);
487             } catch (Exception JavaDoc e) {
488                 log.error("Unable to instantiate controller '" +
489                         oneControllerName + "'", e);
490             }
491         } /* for each controller listed */
492
493
494         return theControllers;
495
496     }
497
498     /**
499      * Returns the default component code for this schema. Useful for automated
500      * component testing/installation
501      *
502      * @return the component code string as defined by the derived schema class
503      */

504     public String JavaDoc getDefaultComponentCode() {
505         return this.defaultComponentCode;
506     }
507
508
509     /**
510      * Returns the default description for this schema. Useful for automated
511      * component testing/installation
512      *
513      * @return the component friendly name as defined by the derived schema class
514      */

515     public String JavaDoc getDefaultDescription() {
516         return this.defaultDescription;
517     }
518
519     /**
520      * Return the name of the context/database connection that this schema is being
521      * applied to. If none is set, then we are applying to the "default"
522      * database/context.
523      *
524      * @return the database context that this Schema object is associated with.
525      * @deprecated Use getDataContext() instead. Since v.5.5
526      */

527     public synchronized String JavaDoc getDBName() {
528         if (StringUtil.notNull(dbKey).equals("")) {
529             return "default";
530         }
531
532         return dbKey;
533     } /* getDBName() */
534
535
536     /**
537      * Return the name of the context/database connection
538      * that this schema is being
539      * applied to. If none is set, then we are applying to the "default"
540      * database/context.
541      *
542      * @return the database context that this Schema object
543      * is associated with.
544      * @since Expresso 5.6
545      */

546     public synchronized String JavaDoc getDataContext() {
547         if (StringUtil.notNull(dbKey).equals("")) {
548             return "default";
549         }
550
551         return dbKey;
552     } /* getDBName() */
553
554
555     /**
556      * @return an an instance of this schema instance.
557      */

558     public static Schema getInstance() {
559         return myInstance;
560     } /* getInstance() */
561
562     /**
563      * Return an enumeration of the jobs that are members of this schema
564      *
565      * @return Enumeration List of Transaction objects that belong to
566      * this schema
567      */

568     public Enumeration JavaDoc getJobs() {
569         Vector JavaDoc theJobs = new Vector JavaDoc();
570         String JavaDoc oneJobName = null;
571
572         for (Iterator JavaDoc ee = getDef().getJobs(); ee.hasNext();) {
573             oneJobName = (String JavaDoc) ee.next();
574
575             try {
576                 Class JavaDoc clazz = ClassLocator.loadClass(oneJobName);
577                 Job oneJob = (Job) clazz.newInstance();
578                 theJobs.addElement(oneJob);
579             } catch (Exception JavaDoc e) {
580                 log.error("Unable to instantiate job '" + oneJobName +
581                         "' belonging to schema '" + getClass().getName() +
582                         "'", e);
583             }
584         } /* for each job listed */
585
586
587         return theJobs.elements();
588     } /* getJobs() */
589
590     /**
591      * Return an enumeration of the database objects that belong to this schema
592      *
593      * @return Enumeration List of DBObject objects that belong to this schema
594      */

595     public Enumeration JavaDoc getMembers() {
596         Vector JavaDoc theDBObjects = new Vector JavaDoc();
597         String JavaDoc oneDBObjectName = null;
598         DBObject oneDBObject = null;
599
600         boolean threadLoader = false;
601
602         if (this.getClass().getClassLoader() != null) {
603             threadLoader = true;
604         }
605
606         for (Iterator JavaDoc ee = getDef().getMembers(); ee.hasNext();) {
607             oneDBObjectName = (String JavaDoc) ee.next();
608
609             try {
610                 oneDBObject = null;
611                 Class JavaDoc clazz = null;
612                 if (threadLoader == true) {
613                     clazz = this.getClass().getClassLoader().loadClass(oneDBObjectName);
614                 } else {
615                     clazz = ClassLocator.loadClass(oneDBObjectName);
616                 }
617                 oneDBObject = (DBObject) clazz.newInstance();
618             } catch (Exception JavaDoc e) {
619                 log.error("Unable to instantiate dbobject '" +
620                         oneDBObjectName + "'", e);
621             }
622
623
624             if (oneDBObject != null) {
625
626                 if (getDataContext() != null) {
627                     try {
628                         oneDBObject.setDBName(getDataContext());
629                     } catch (DBException e) {
630                         log.error("cannot set data context: ", e);
631                     }
632                 }
633
634                 // we are creating an object from a no-arg constuctor, without even
635
// knowing another dbobject which has context. we have the DBName, above,
636
// but for SecuredDBObjects, we need the requesting UID. Since dealing
637
// with a schema is a privileged procedure, we have little choice but
638
// to assume superuser privileges unless we have other information.
639
// NB: we are actually concerned with RowSecuredDBObject because the default
640
// constructor for SecuredDBObject already assumes superuser privileges,
641
// while the default constructor for RowSecuredDBObject does the opposite,
642
// (more securely) assuming that without any other information, we give
643
// NO permissions. Anyway, creating the schema is one of the first
644
// behaviors of an application, so we have to make some assumptions here.
645

646                 if (oneDBObject instanceof SecuredDBObject) {
647                     if (getRequestingUser() != 0) {
648                         ((SecuredDBObject) oneDBObject).setRequestingUid(getRequestingUser());
649                     } else {
650                         ((SecuredDBObject) oneDBObject).setRequestingUid(SecuredDBObject.SYSTEM_ACCOUNT);
651                     }
652                 }
653
654                 theDBObjects.addElement(oneDBObject);
655             } // we created oneDBObject
656
} /* for each dbobject listed */
657
658
659         return theDBObjects.elements();
660     } /* getMembers() */
661
662     /**
663      * Return the path, relative to the classpath, of the MessageBundle file for
664      * this schema. For example, the Expresso schema
665      * (com.jcorporate.expresso.core.ExpressoSchema) returns
666      * "com/jcorporate/expresso/core", as this is where it's message files are
667      * stored.
668      *
669      * @return A String describing the location of the MessageBundle Path
670      */

671     public String JavaDoc getMessageBundlePath() {
672         return this.messageBundlePath;
673     }
674
675     /**
676      * Return the list of ExpressoReport objects that are required by this schema.
677      *
678      * @return Vector A list of <code>ExpressoReport</code> objects that are standard reports
679      * in this schema.
680      */

681     public synchronized Vector JavaDoc getReports() {
682         Vector JavaDoc theReports = new Vector JavaDoc();
683         String JavaDoc oneReportName = null;
684         ExpressoReport oneReport = null;
685
686         for (Iterator JavaDoc ee = getDef().getReports(); ee.hasNext();) {
687             oneReportName = (String JavaDoc) ee.next();
688
689             try {
690                 Class JavaDoc clazz = ClassLocator.loadClass(oneReportName);
691                 oneReport = (ExpressoReport) clazz.newInstance();
692             } catch (Exception JavaDoc e) {
693                 log.error("Unable to instantiate Expresso Report '" +
694                         oneReportName + "'", e);
695             }
696
697             theReports.addElement(oneReport);
698         } /* for each servlet listed */
699
700
701         return theReports;
702     } /* getReports() */
703
704     /**
705      * Return an enumeration of the servlets that are members of this schema
706      *
707      * @return Enumeration List of StdServlet objects that belong to
708      * this schema
709      */

710     public Enumeration JavaDoc getServlets() {
711         Vector JavaDoc theServlets = new Vector JavaDoc();
712         String JavaDoc oneServletName = null;
713         StdServlet oneServlet = null;
714
715         for (Iterator JavaDoc ee = getDef().getServlets(); ee.hasNext();) {
716             oneServletName = (String JavaDoc) ee.next();
717
718             try {
719                 Class JavaDoc clazz = ClassLocator.loadClass(oneServletName);
720                 oneServlet = (StdServlet) clazz.newInstance();
721                 theServlets.addElement(oneServlet);
722             } catch (Exception JavaDoc e) {
723                 log.error("Unable to instantiate servlet '" + oneServletName +
724                         "'", e);
725             }
726         } /* for each servlet listed */
727
728
729         return theServlets.elements();
730     } /* getServlets() */
731
732     /**
733      * Return the value if this property is defined in the properties file for
734      * this config key.
735      *
736      * @param paramName Property Name
737      * @param defaultValue value if property is not defined
738      * @return String Value of this property in the property file for this DB
739      * config.
740      */

741     protected String JavaDoc getSetupDefault(String JavaDoc paramName, String JavaDoc defaultValue) {
742         try {
743             ConfigContext myContext = ConfigManager.getContext(getDataContext());
744             ConfigSetupDefault oneValue = null;
745
746             for (Enumeration JavaDoc sv = myContext.getSetupDefaults().elements();
747                  sv.hasMoreElements();) {
748                 oneValue = (ConfigSetupDefault) sv.nextElement();
749
750                 if (oneValue.getName().equals(paramName)) {
751                     return oneValue.getValue();
752                 }
753             }
754         } catch (com.jcorporate.expresso.core.misc.ConfigurationException ce) {
755             log.error(ce);
756         }
757
758         return defaultValue;
759     } /* getSetupDefault(String, String) */
760
761     /**
762      * Return a single transaction as the "starting point" for this application.
763      * Each Schema object may define such a transaction, and the appropriate
764      * application can then be invoked from that point
765      *
766      * @return a Controller Instance of the starting controller point.
767      */

768     public Controller getStartController() {
769         return null;
770     } /* getStartController() */
771
772     /**
773      * Retrieve one of the Setup values for the schema.
774      *
775      * @param key The setup value key
776      * @return java.lang.String the value of the setup value. May be null;
777      */

778     public String JavaDoc getSetupValue(String JavaDoc key) {
779         return (String JavaDoc) setupValue.get(key);
780     }
781
782     /**
783      * Sets the setup values for the given key
784      *
785      * @param key The name of the setup value.
786      * @param value the Value of the setup value.
787      */

788     public void setSetupValue(String JavaDoc key, String JavaDoc value) {
789         setupValue.put(key, value);
790     }
791
792     /**
793      * preferable way of performaing other setup. Utilizes the context independant
794      * logging system.
795      *
796      * @param installLog the InstallLog implementation that the setup process
797      * will log progress to.
798      * @param dataContext he database context to execute this process against.
799      * @throws DBException If there's a database communication error
800      */

801     public synchronized void otherSetup(InstallLog installLog, String JavaDoc dataContext)
802             throws DBException {
803     }
804
805
806     /**
807      * Perform any additional setup/intialize functions required
808      * by this schema. This is where applications can set up default
809      * values for lookup tables, reference values, etc.
810      * Subclass does not extend this method if it is not needed.
811      *
812      * @param dbName The database context to execute this process against.
813      * @throws DBException If there's a database communication error
814      * @deprecated 5.5+; 10/04. use otherSetup(log, dbcontext) instead
815      */

816     public synchronized void otherSetup(String JavaDoc dbName)
817             throws DBException {
818
819     } /* otherSetup(String) */
820
821
822     /**
823      * Set the database name/context for this schema. If setDBName is not called,
824      * the "default" db name and context is used.
825      *
826      * @param newOther The name of the context or database to use
827      * @throws DBException If there's a problem switching to the database context.
828      * @deprecated Since Expresso 5.6 Use setDataContext(String) instead.
829      */

830     public synchronized void setDBName(String JavaDoc newOther)
831             throws DBException {
832         setDataContext(newOther);
833     } /* setDBName(String) */
834
835     /**
836      * Set the database name/context for this schema. If setDBName is not called,
837      * the "default" db name and context is used.
838      *
839      * @param newOther The name of the context or database to use
840      * @throws DBException If there's a problem switching to the database context.
841      */

842     public synchronized void setDataContext(String JavaDoc newOther)
843             throws DBException {
844         dbKey = newOther;
845     }
846
847     /**
848      * Go through each DBobject in the schema and call populateDefaultValues.<p>
849      * See: @see com.jcorporate.expresso.core.dbobj.DBObject.populateDefaultValues
850      *
851      * @param dbName The name of the database to set this up on.
852      */

853     public synchronized void setupDefaultValues(String JavaDoc dbName) {
854         try {
855             setupDefaultValuesWithException(dbName);
856         } catch (DBException de) {
857             log.error("Unable to populate table with default values", de);
858         }
859     } /* setupDefaultValues(String) */
860
861     /**
862      * Go through each DBobject and each Controller in the schema and call default-populate methods.<p>
863      * See: @see com.jcorporate.expresso.core.dbobj.DBObject.populateDefaultValues
864      * See: @see com.jcorporate.expresso.core.controller.Controller.setupDefaultValues
865      *
866      * @param dbName The name of the database to set this up on.
867      * @throws DBException if a database exception occurs
868      */

869     public synchronized void setupDefaultValuesWithException(String JavaDoc dbName)
870             throws DBException {
871
872         if (ExpressoRuntimeMap.getDefaultRuntime() != null) {
873             log.warn("Setup Values no longer apply in the Expresso Runtime context." +
874                     " please add them to your Metadata for various values instead");
875         }
876
877         DBObject oneMember = null;
878
879         for (Enumeration JavaDoc e = getMembers(); e.hasMoreElements();) {
880             oneMember = (DBObject) e.nextElement();
881             if (log.isInfoEnabled()) {
882                 log.info("Populating table " + oneMember.getDataContext());
883             }
884             oneMember.setDataContext(dbName);
885             oneMember.populateDefaultValues();
886         }
887
888         Controller oneController = null;
889
890         for (Iterator JavaDoc e = this.getControllerList().iterator(); e.hasNext();) {
891             oneController = (Controller) e.next();
892             if (log.isInfoEnabled()) {
893                 log.info("Populating Default Controller Data " +
894                         oneController.getClass().getName());
895             }
896             oneController.setupDefaultValues(dbName);
897         }
898
899         populateSchemaData(dbName);
900     } /* setupDefaultValues(String) */
901
902
903     /**
904      * Allow populations of sample data where all tables must be set up first.
905      *
906      * @param dbName The name to add the data to
907      * see com.jcorporate.eforum.ForumSchema#populateSchemaData for example.
908      * @throws DBException if an error occurs while populating the table.
909      */

910     public synchronized void populateSchemaData(String JavaDoc dbName)
911             throws DBException {
912     }
913
914
915     /**
916      * Return the list of Junit tests in this application
917      *
918      * @return An Enumeration of all tests for this schema
919      * @deprecated Since Expresso 5.6 Tests have been separated from
920      * the main code base.
921      */

922     public Enumeration JavaDoc getTests() {
923         Vector JavaDoc v = new Vector JavaDoc();
924         for (Iterator JavaDoc i = getDef().getTests(); i.hasNext();) {
925             v.add(i.next());
926         }
927         return v.elements();
928     } /* getTests() */
929
930     /**
931      * Utility function to get the SchemaDefinitions
932      *
933      * @return the SchemaDefinition class associated with this schema type.
934      */

935     private SchemaDefinition getDef() {
936         return (SchemaDefinition) schemaDefinitions.get(this.getClass().getName());
937     }
938
939     /**
940      * Retrieves the DBObject Map for table creation.
941      *
942      * @return java.util.Hashtable
943      */

944     public Hashtable JavaDoc getDBObjMap() {
945         return getDef().getDbobjMap();
946     }
947
948     /**
949      * Get the i18N'ized string for this schema
950      *
951      * @param stringCode The string code to find in the messages bundle.
952      * @return The Mapped String
953      */

954     protected String JavaDoc getString(String JavaDoc stringCode) {
955         Object JavaDoc[] args = {};
956         String JavaDoc language = null;
957         String JavaDoc country = null;
958
959         try {
960             ConfigContext myContext = ConfigManager.getContext(getDataContext());
961             language = myContext.getLanguage();
962             country = myContext.getCountry();
963         } catch (com.jcorporate.expresso.core.misc.ConfigurationException ce) {
964             language = "en";
965             country = "US";
966         }
967
968         return Messages.getStringByPath(getMessageBundlePath(), language,
969                 country, stringCode, args);
970     } /* getString(String) */
971
972     /**
973      * <p>Method to return the current version number of an application Schema.
974      * Individual Schema objects may override this method if they define a version,
975      * then other dependant applications can use that information to make sure
976      * that the current version dependancies are met.</p>
977      * <p>How to define your own version string:</p>
978      * <p>The format is: MajorVersion.MinorVersion.Release-EA Release Number<p>
979      * <p>MajorVerseion,MinorVersion, and Release represent the typical: 1.0.1
980      * type of version formatting. -EAReleaseNumber is also a number but is optional
981      * if you do not wish to use a EA number if the version number.</p>
982      * <p><b>Examples</b><p>
983      * <ul>
984      * <li>1.0.1 : First Major Version with a bugfix release.</li>
985      * <li>2.2.2-2: Second Major Version, Second Minor Version, Second Bugfix release
986      * and it is currently considered ea-2</li>
987      * </ul>
988      *
989      * @return the Version you define for your system.
990      */

991     public String JavaDoc getVersion() {
992         if (this.getMetaData() != null) {
993             return this.getMetaData().getVersionNumber();
994         } else {
995             return "No Version Defined";
996         }
997     }
998
999     /**
1000     * Method for a schema to define a dependance on another schema
1001     * with a particular version - e.g. if eContent requires
1002     * expresso 3.11, it can call this method to ensure that's the version it's
1003     * being run with
1004     *
1005     * @param versionString String the string version this requires.
1006     * @param schemaClassName the class name to check against.
1007     * @throws DBException if an error occurs locating the appropriate schema
1008     * class
1009     */

1010    protected void requiresVersion(String JavaDoc versionString,
1011                                   String JavaDoc schemaClassName)
1012            throws DBException {
1013        Schema otherSchema = instantiate(schemaClassName);
1014
1015        if (otherSchema.getVersion().equals(versionString)) {
1016            return;
1017        }
1018        /* If the two versions are convertable to numbers, see if the */
1019        /* available version is greater than the required version - */
1020        /* if so, just log a warning */
1021        try {
1022            String JavaDoc foundVersionString = otherSchema.getVersion();
1023            String JavaDoc requiredVersionString = versionString;
1024
1025            StringTokenizer JavaDoc stok1 = new StringTokenizer JavaDoc(foundVersionString, ".");
1026            StringTokenizer JavaDoc stok2 = new StringTokenizer JavaDoc(requiredVersionString, ".");
1027
1028            if (stok1.hasMoreTokens() && stok2.hasMoreTokens()) {
1029                int foundVersionNumbers[] = {0, 0, 0, 0};
1030                int requiredVersionNumbers[] = {0, 0, 0, 0};
1031                try {
1032                    parseVersionString(stok1, foundVersionNumbers);
1033                    parseVersionString(stok2, requiredVersionNumbers);
1034
1035                    if (foundVersionNumbers[0] == requiredVersionNumbers[0]) {
1036                        if (foundVersionNumbers[1] == requiredVersionNumbers[1]) {
1037                            if (foundVersionNumbers[2] > requiredVersionNumbers[2]) {
1038                                return;
1039                            } else {
1040                                if (log.isInfoEnabled()) {
1041                                    log.info("Schema '" + getClass().getName() +
1042                                            "', version " + getVersion() +
1043                                            " requires version " + versionString +
1044                                            " of schema '" + schemaClassName +
1045                                            "', but version " + otherSchema.getVersion() +
1046                                            " was found instead. You might encounter " +
1047                                            "some problems because of bugs being fixed. " +
1048                                            "It is recommended that you upgrade to the required version");
1049                                }
1050                                return;
1051
1052                            }
1053
1054                        } else {
1055                            log.warn("Schema '" + getClass().getName() +
1056                                    "', version " + getVersion() +
1057                                    " requires version " + versionString +
1058                                    " of schema '" + schemaClassName +
1059                                    "', but version " + otherSchema.getVersion() +
1060                                    " was found instead. You may encounter " +
1061                                    "some problems because of the minor version differences.");
1062                            return;
1063                        }
1064
1065                    } else {
1066                        log.error("Schema '" + getClass().getName() +
1067                                "', version " + getVersion() +
1068                                " requires version " + versionString +
1069                                " of schema '" + schemaClassName +
1070                                "', but version " + otherSchema.getVersion() +
1071                                " was found instead. You may encounter " +
1072                                "serious problems because of the major version differences.");
1073                        return;
1074                    }
1075                } catch (NumberFormatException JavaDoc ex) {
1076                    log.error("Schema '" + getClass().getName() +
1077                            "', version " + getVersion() +
1078                            " requires version " + versionString +
1079                            " of schema '" + schemaClassName +
1080                            "', but version " + otherSchema.getVersion() +
1081                            " was found instead.");
1082                    return;
1083                }
1084            } else {
1085                if (stok1.hasMoreTokens()) {
1086                    log.warn("Unable to find version information for :" +
1087                            schemaClassName);
1088                } else {
1089                    log.warn("Unable to find version information for :" +
1090                            this.getClass().getName());
1091                }
1092
1093                return;
1094            }
1095        } catch (Exception JavaDoc ne) {
1096            log.warn("Unable to convert version numbers to strings");
1097        }
1098
1099        log.error("Schema '" + getClass().getName() +
1100                "', version " + getVersion() +
1101                " requires version " + versionString +
1102                " of schema '" + schemaClassName +
1103                "', but version " + otherSchema.getVersion() +
1104                " was found instead.");
1105    } /* requiresVersion */
1106
1107    /**
1108     * Used by requiresVersion to parse the version number into an integer array
1109     * that is easy to analyze
1110     *
1111     * @param tokenizer a tokenizer with comma's and parsing the string.
1112     * @param parsedNumbers an array of 4 integers.
1113     * @throws NumberFormatException if there's an error parsing the values.
1114     */

1115    private void parseVersionString(StringTokenizer JavaDoc tokenizer, int parsedNumbers[])
1116            throws NumberFormatException JavaDoc {
1117        int index = 0;
1118        while (tokenizer.hasMoreTokens()) {
1119            String JavaDoc temp = tokenizer.nextToken();
1120            if (temp.indexOf("-") > 0 && index == 2) {
1121                StringTokenizer JavaDoc releaseTokenizer = new StringTokenizer JavaDoc(temp, "-");
1122                String JavaDoc buildNum = releaseTokenizer.nextToken();
1123                String JavaDoc eaNum = releaseTokenizer.nextToken();
1124                parsedNumbers[index] = Integer.parseInt(buildNum);
1125                index++;
1126                parsedNumbers[index] = Integer.parseInt(eaNum);
1127                index++;
1128            } else {
1129                parsedNumbers[index] = Integer.parseInt(temp);
1130            }
1131            index++;
1132
1133            if (index >= 4) {
1134                return;
1135            }
1136        }
1137
1138    }
1139
1140
1141    /**
1142     * Convenience method to create a Schema object from it's name
1143     *
1144     * @param className The ClassName to instantiate
1145     * @return A newly initialized Schema Object
1146     * @throws DBException if there's an instantiation problem
1147     */

1148    public static Schema instantiate(String JavaDoc className)
1149            throws DBException {
1150        StringUtil.assertNotBlank(className,
1151                "Schema class name " +
1152                " may not be blank or null here");
1153
1154        try {
1155
1156            Class JavaDoc c = ClassLocator.loadClass(className);
1157            return (Schema) c.newInstance();
1158        } catch (ClassNotFoundException JavaDoc cn) {
1159            throw new DBException("Schema object '" + className +
1160                    "' not found", cn);
1161        } catch (InstantiationException JavaDoc ie) {
1162            throw new DBException("Schema object '" + className +
1163                    "' cannot be instantiated", ie);
1164        } catch (IllegalAccessException JavaDoc iae) {
1165            throw new DBException("llegal access loading " +
1166                    "Schema object '" + className + "'. " +
1167                    "Your schema must have a default public constructor", iae);
1168        } catch (java.lang.Throwable JavaDoc t) {
1169            t.printStackTrace();
1170            throw new DBException("Error instantiating schema: " + className + ".", t);
1171
1172        }
1173    }
1174
1175    /**
1176     * Base metadata location. All schemas have the same component metadata,
1177     * unless you want to specify your own. In which case, you'll want to
1178     * override based upon your own information.
1179     *
1180     * @return java.net.URL
1181     */

1182    public URL JavaDoc getMetadataLocation() {
1183        return Schema.class.getResource("Schema.xml");
1184    }
1185
1186    /**
1187     * Initialize Lifecycle event. Provide quick initialization
1188     */

1189    public void initialize() {
1190        this.dbKey = this.getParent().getMetaData().getName();
1191    }
1192
1193    /**
1194     * Provide Configurations
1195     *
1196     * @param newConfig the new configuration object
1197     */

1198    public void configure(Configuration newConfig) throws ConfigurationException {
1199        this.setupValue = newConfig.getMappedProperties("SetupValue");
1200
1201        //
1202
//We have to merge the saved setup values with these ones.
1203
//
1204
for (Iterator JavaDoc i = this.defaultSetupValues.keySet().iterator(); i.hasNext();) {
1205            String JavaDoc key = (String JavaDoc) i.next();
1206            if (!setupValue.containsKey(key)) {
1207                setupValue.put(key, defaultSetupValues.get(key));
1208            }
1209        }
1210
1211        this.defaultComponentCode = (String JavaDoc) newConfig.get("DefaultComponentCode");
1212        this.defaultDescription = (String JavaDoc) newConfig.get("DefaultDescription");
1213        this.messageBundlePath = (String JavaDoc) newConfig.get("MessageBundlePath");
1214    }
1215
1216
1217    /**
1218     * Reconfigure Lifecycle Event. Nullify values and restart.
1219     *
1220     * @param newConfig The new Configuration
1221     */

1222    public void reconfigure(Configuration newConfig) throws ConfigurationException {
1223        synchronized (Schema.class) {
1224            this.setupValue = null;
1225            this.defaultComponentCode = null;
1226            this.defaultDescription = null;
1227            this.messageBundlePath = null;
1228            configure(newConfig);
1229        }
1230    }
1231
1232    public void destroy() {
1233// schemaDefinitions.remove(this.getClass().getName());
1234
}
1235
1236    /**
1237     * Retrieve the login controller for your schema. The default implementation
1238     * checks the ClassHandler section and returns it or the default (SimpleLogin)
1239     * if there is none defined in the ClassHandlers. Override for your own apps
1240     * to have custom and multiple logins and registration controllers.
1241     *
1242     * @return Controller Instance
1243     * @throws ControllerException if there is an error instantiating the controller
1244     */

1245    public Controller getLoginController() throws ControllerException {
1246        String JavaDoc className = ConfigManager.getClassHandler(com.jcorporate
1247                .expresso.services.controller.LoginController.CLASS_HANDLER_NAME);
1248        if (className == null || className.length() == 0) {
1249            className = com.jcorporate.expresso.services.controller
1250                    .LoginController.DEFAULT_CLASS_NAME;
1251        }
1252
1253        return ConfigManager.getControllerFactory().getController(className);
1254    }
1255
1256    /**
1257     * Retrieve the registration controller. The default version checks the
1258     * classhandlers section in the expresso-config.xml file and returns what's
1259     * appropriate there or SimpleRegistration if none is defined.
1260     *
1261     * @return a controller instance for Registration
1262     * @throws ControllerException if there is an error instantiating the controller
1263     */

1264    public Controller getRegistrationController() throws ControllerException {
1265        String JavaDoc className = ConfigManager.getClassHandler("registration");
1266        if (className == null || className.length() == 0) {
1267            className = com.jcorporate.expresso.services
1268
                    .controller.SimpleRegistration.class.getName();
1269        }
1270
1271        return ConfigManager.getControllerFactory().getController(className);
1272    } /* instantiate(String) */
1273
1274    /**
1275     * Set the user ID of requester.
1276     *
1277     * @param uid ID of requesting user
1278     */

1279    public void setRequestingUser(int uid) {
1280        mUserID = uid;
1281    }
1282
1283    /**
1284     * Retrieve the UID of requesting user.
1285     *
1286     * @return UID of requesting user, if known. otherwise, returns 0
1287     */

1288    public int getRequestingUser() {
1289        return mUserID;
1290    }
1291
1292    /**
1293     * Checks if a particular dbobject resides in a given schema.
1294     *
1295     * @param dbObject the object to check against.
1296     * @return true if this schema contains this object
1297     */

1298    public boolean contains(DBObject dbObject) {
1299        SchemaDefinition def = getDef();
1300        return def.contains(dbObject);
1301    }
1302
1303
1304} /* Schema */
1305
Popular Tags