2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 // $TOG: MMDB_Factory.C /main/15 1998/04/17 11:42:43 mgreess $
25 # include "UAS_Exceptions.hh"
26 # include "MMDB_Factory.hh"
27 # include "UAS_Exceptions.hh"
28 # include "MMDB_EmbeddedObject.hh"
29 # include "MMDB_Library.hh"
30 # include "MMDB_BookCase.hh"
31 # include "MMDB_Section.hh"
32 # include "UAS_Collection.hh"
34 #include "Managers/CatMgr.hh"
35 #include "Registration.hh"
37 OLIAS_DB *MMDB_Factory::fOLIASDB = 0;
39 static MMDB_Factory the_mmdb_factory; // instantiation
41 MMDB_Factory::MMDB_Factory ()
43 UAS_Factory::register_factory("mmdb", this);
46 MMDB_Factory::~MMDB_Factory ()
49 UAS_Factory::unregister_factory("mmdb");
53 MMDB_Factory::olias_db () {
55 fOLIASDB = new OLIAS_DB ();
61 MMDB_Factory::createMMDB (const UAS_String &infoLibPath) {
64 // The MMDB leaks memory if we try to create an infolib
65 // with a bogus path. This routine is called often with
66 // infoLibPath == "", so we'll trap that case now
68 if (infoLibPath.length()) {
69 if (!olias_db().validInfoLibPath(infoLibPath)) {
72 (void) sprintf (buf, CATGETS(Set_UAS_MMDB, 2,
73 "Invalid Infolib path: %s"),
74 (char *) infoLibPath);
75 badPath.fErrorMsg = buf;
76 UAS_Common::send_message (badPath);
80 rval = new MMDB (infoLibPath);
81 fMMDBList.append (rval);
85 (void) sprintf (buf, CATGETS(Set_UAS_MMDB, 3,
86 "Ignoring invalid Infolib path: %s"),
87 (char *) infoLibPath);
88 UAS_ErrorMsg theError;
89 theError.fErrorMsg = buf;
90 UAS_Common::send_message (theError);
98 // check to make sure duplicate infolibs are not added.
99 // for a duplicate infolib, just return a pointer to
100 // the already-existing infolib.
101 // (Duplicate infolib means infolibs with the same lid (uid))
103 MMDB_Factory::getMMDB (const UAS_String &infoLibPath) {
105 UAS_String uid(fOLIASDB->getInfoLibUid((char*)infoLibPath));
106 for (i = 0; i < fMMDBList.numItems(); i ++) {
107 if (uid == fMMDBList[i]->infoLibUid())
110 for (i = 0; i < fDeadMMDBList.numItems(); i ++) {
111 if (uid == fDeadMMDBList[i]->infoLibUid())
112 return fDeadMMDBList[i];
114 return createMMDB (infoLibPath);
118 MMDB_Factory::resolveLocator (const UAS_String &loc,
120 info_base *&returnInfoBase) {
123 for (int i = 0; i < fMMDBList.numItems(); i ++) {
124 if (returnInfoBase = fMMDBList[i]->infolib()->
125 getInfobaseByComponent(loc, info_lib::LOC)) {
126 returnMMDB = fMMDBList[i];
133 MMDB_Factory::getMMDBFromObject (UAS_Pointer<UAS_Common> theDoc) {
134 if (theDoc->implementation_type() != "mmdb")
136 switch (theDoc->type()) {
138 MMDB_Library *l = (MMDB_Library *) ((UAS_Common *) theDoc);
142 MMDB_BookCase *c = (MMDB_BookCase *) ((UAS_Common *) theDoc);
147 MMDB_Section *s = (MMDB_Section *) ((UAS_Common *) theDoc);
155 UAS_Pointer<UAS_Common>
156 MMDB_Factory::create_object (const UAS_String &locator) {
158 curURL.locator (locator);
159 MMDB *theMMDB = getMMDB (curURL.fInfoLib);
160 info_base *theInfoBase = 0;
162 if (curURL.fLocator != "") {
163 resolveLocator (curURL.fLocator, theMMDB, theInfoBase);
165 throw (CASTEXCEPT Exception());
167 UAS_Pointer<UAS_Common> rval =
168 new MMDB_Section (*theMMDB, curURL.fLocator);
169 if (curURL.fType == "collection")
170 return new UAS_Collection (rval);
176 if (theMMDB && curURL.fLocator != "") {
177 UAS_Pointer<UAS_Common> rval =
178 new MMDB_Section (*theMMDB, curURL.fLocator);
179 if (curURL.fType == "collection")
180 return new UAS_Collection (rval);
182 } else if (theMMDB && curURL.fInfoBase != "") {
183 return new UAS_Collection(new MMDB_BookCase(*theMMDB,curURL.fInfoBase));
184 } else if (theMMDB && curURL.fInfoLib != "") {
185 return new UAS_Collection (new MMDB_Library(*theMMDB));
187 throw (CASTEXCEPT Exception());
191 UAS_Pointer<UAS_Common>
192 MMDB_Factory::create_relative_object (const UAS_String &locator,
193 UAS_Pointer<UAS_Common> theDoc) {
196 // First, try to get the object by using the current
197 // MMDB information library.
199 MMDB *theMMDB = getMMDBFromObject (theDoc);
201 info_base *ib = theMMDB->infolib()->
202 getInfobaseByComponent(locator, info_lib::LOC);
204 // need to pass precise id to the constructor
205 return new MMDB_Section (*theMMDB, locator);
210 // Couldn't find it in theDoc's infolib. Try all the infolibs
213 for (int i = 0; i < fMMDBList.numItems(); i ++) {
214 info_base *ib = fMMDBList[i]->infolib()->
215 getInfobaseByComponent(locator, info_lib::LOC);
217 // need to pass precise id to the constructor
218 return new MMDB_Section(*(fMMDBList[i]), locator);
222 return UAS_Pointer<UAS_Common>(NULL);
225 UAS_Pointer<UAS_EmbeddedObject>
226 MMDB_Factory::create_embedded_object (const UAS_String &locator) {
227 for (int i = 0; i < fMMDBList.numItems(); i ++) {
228 info_base *ib = fMMDBList[i]->infolib()->
229 getInfobaseByComponent(locator, info_lib::GRA);
231 return new MMDB_EmbeddedObject (*fMMDBList[i], ib, locator);
234 throw (CASTEXCEPT Exception());
237 UAS_Pointer<UAS_EmbeddedObject>
238 MMDB_Factory::create_relative_embedded_object (const UAS_String &locator,
239 UAS_Pointer<UAS_Common> theDoc) {
241 // First try resolving to theDoc's infolib
243 MMDB *theMMDB = getMMDBFromObject (theDoc);
245 info_base *ib = theMMDB->infolib()->
246 getInfobaseByComponent(locator, info_lib::GRA);
248 return new MMDB_EmbeddedObject (*theMMDB, ib, locator);
253 // Cross-infolib link. Iterate through the list of infolibs.
255 for (int i = 0; i < fMMDBList.numItems(); i ++) {
256 info_base *ib = fMMDBList[i]->infolib()->
257 getInfobaseByComponent(locator, info_lib::GRA);
259 return new MMDB_EmbeddedObject (*(fMMDBList[i]), ib, locator);
262 throw (CASTEXCEPT Exception());
266 MMDB_Factory::initializeFactory (UAS_List<UAS_String>& libs) {
268 // Take DTINFO_INFOLIB_PATH and split out the colon-separated
269 // paths. Create an MMDB object for each path and, if creation
270 // was successful, add it to our list of infolibs. Send messages
273 //char *libenv = getenv ("DTINFO_INFOLIB_PATH");
277 //UAS_String libstr (libenv);
278 //UAS_List<UAS_String> fields = libstr.splitFields (':');
279 //for (int i = 0; i < fields.length(); i ++) {
280 //(void) getMMDB (*(UAS_String*)fields[i]);
282 for (int i = 0; i < libs.length(); i ++) {
283 // If this call doesn't create a new MMDB, it sends
284 // an error message to the application.
285 (void) getMMDB (*(UAS_String*)libs[i]);
290 MMDB_Factory::finalizeFactory () {
291 while (fMMDBList.numItems() > 0) {
292 MMDB *dead = fMMDBList[0];
293 fMMDBList.remove(dead);
296 while (fDeadMMDBList.numItems() > 0) {
297 MMDB *deaddead = fDeadMMDBList[0];
298 fDeadMMDBList.remove(deaddead);
306 MMDB_Factory::rootLocators () {
308 // CHANGE THIS TO BE UAS_ObjList...
310 UAS_List<UAS_String> rval;
311 for (int i = 0; i < fMMDBList.numItems(); i ++) {
313 cur.fType = "collection";
314 cur.fInfoLib = fMMDBList[i]->infoLibPath();
315 rval.insert_item (new UAS_String (cur.locator()));
321 MMDB_Factory::destroy_root_object (UAS_Pointer<UAS_Common> theRoot) {
322 if (theRoot->implementation_type() != "mmdb" ||
323 theRoot->type() != UAS_LIBRARY)
324 throw(CASTEXCEPT Exception());
325 MMDB_Library *theLib = (MMDB_Library *) (UAS_Common *) theRoot;
326 MMDB *deadMMDB = &(theLib->mmdb());
328 for (i = 0; i < fMMDBList.numItems(); i ++)
329 if (fMMDBList[i] == deadMMDB)
331 if (i >= fMMDBList.numItems())
332 throw(CASTEXCEPT Exception());
334 // remove deadMMDB before sending msg because the user
335 // can possibly inquire mmdb list on the thread.
336 fMMDBList.remove (deadMMDB);
338 // Give the user a chance to blow away all objects associated
339 // with this library.
341 UAS_LibraryDestroyedMsg theMsg (theRoot);
342 UAS_Common::send_message (theMsg);
344 // Do the final damage.
349 MMDB_Factory::genInfolibName () {
350 static int counter = 0;
352 (void) sprintf (buf, CATGETS(Set_UAS_MMDB, 4, "DtMmdb Library %d"), ++counter);
353 return UAS_String (buf);
356 ///////////////////////////////////////////////////////////////////////////////
357 ///////////////////////////////////////////////////////////////////////////////
361 ///////////////////////////////////////////////////////////////////////////////
362 ///////////////////////////////////////////////////////////////////////////////
364 MMDB_URL::MMDB_URL () {
368 MMDB_URL::locator () {
369 UAS_String rval = "mmdb:";
371 if (fInfoLib != "") {
372 rval = rval + "INFOLIB=" + fInfoLib;
375 if (fInfoBase != "") {
378 rval = rval + "BOOKCASE=" + fInfoBase;
381 if (fLocator != "") {
384 rval = rval + "LOCATOR=" + fLocator;
388 fType = "collection"; // default value
392 rval = rval + "TYPE=" + fType;
399 MMDB_URL::installPair (const UAS_String &key, const UAS_String &value) {
400 if (key == "INFOLIB") {
402 } else if (key == "BOOKCASE") {
404 } else if (key == "TYPE") {
406 } else if (key == "LOCATOR") {
412 MMDB_URL::locator (const UAS_String &in) {
413 UAS_String access, rest;
414 in.split (':', access, rest);
415 UAS_List<UAS_String> pairs = rest.splitFields ('&');
416 for (int i = 0; i < pairs.length(); i ++) {
417 UAS_String key, value;
418 pairs[i]->split ('=', key, value);
419 installPair (key, value);