root/OpenSceneGraph/branches/osg-cocoa-dev/src/osgDB/Registry.cpp @ 9831

Revision 9831, 69.2 kB (checked in by shuber, 6 years ago)

* initial development of osgViewerCocoa
* initial import of imageio-plugin
* disabled quicktime-plugin for 64bit
* disabled GraphicsWindowCarbon? for 664bit

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <stdio.h>
15#include <string.h>
16
17#include <osg/Notify>
18#include <osg/Object>
19#include <osg/Image>
20#include <osg/Shader>
21#include <osg/Node>
22#include <osg/Group>
23#include <osg/Geode>
24#include <osg/ApplicationUsage>
25#include <osg/Version>
26#include <osg/Timer>
27
28#include <osgDB/Registry>
29#include <osgDB/FileUtils>
30#include <osgDB/FileNameUtils>
31#include <osgDB/fstream>
32#include <osgDB/Archive>
33
34#include <algorithm>
35#include <set>
36
37#include <stdlib.h>
38
39#if defined(__sgi)
40    #include <ctype.h>
41#elif defined(__GNUC__) || !defined(WIN32) || defined(__MWERKS__)
42    #include <cctype>
43    using std::tolower;
44#endif
45
46#ifdef OSG_DEBUG_POSTFIX
47    #define OSG_DEBUG_POSTFIX_WITH_QUOTES ADDQUOTES(OSG_DEBUG_POSTFIX)
48#else
49    #define OSG_DEBUG_POSTFIX_WITH_QUOTES "d"
50#endif
51
52using namespace osg;
53using namespace osgDB;
54
55#if !defined(WIN32) || defined(__CYGWIN__)
56static osg::ApplicationUsageProxy Registry_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH <path>[:path]..","Paths for locating datafiles");
57static osg::ApplicationUsageProxy Registry_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH <path>[:path]..","Paths for locating libraries/ plugins");
58#else
59static osg::ApplicationUsageProxy Registry_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH <path>[;path]..","Paths for locating datafiles");
60static osg::ApplicationUsageProxy Registry_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH <path>[;path]..","Paths for locating libraries/ plugins");
61#endif
62
63static osg::ApplicationUsageProxy Registry_e2(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_BUILD_KDTREES on/off","Enable/disable the automatic building of KdTrees for each loaded Geometry.");
64
65
66class Registry::AvailableReaderWriterIterator
67{
68public:
69    AvailableReaderWriterIterator(Registry::ReaderWriterList& rwList, OpenThreads::ReentrantMutex& pluginMutex):
70        _rwList(rwList),
71        _pluginMutex(pluginMutex) {}
72
73
74    ReaderWriter& operator * () { return *get(); }
75    ReaderWriter* operator -> () { return get(); }
76   
77    bool valid() { return get()!=0; }
78   
79    void operator ++()
80    {
81        _rwUsed.insert(get());
82    }
83   
84
85protected:
86
87    AvailableReaderWriterIterator& operator = (const AvailableReaderWriterIterator&) { return *this; }
88
89    Registry::ReaderWriterList&     _rwList;
90    OpenThreads::ReentrantMutex&    _pluginMutex;
91   
92    std::set<ReaderWriter*>         _rwUsed;
93
94    ReaderWriter* get()
95    {
96        OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
97        Registry::ReaderWriterList::iterator itr=_rwList.begin();
98        for(;itr!=_rwList.end();++itr)
99        {
100            if (_rwUsed.find(itr->get())==_rwUsed.end())
101            {
102                return itr->get();
103            }
104        }
105        return 0;
106    }
107
108};
109
110#if 0
111    // temporary test of autoregistering, not compiled by default.
112    enum Methods
113    {
114        SET_1,
115        SET_2,
116        END
117    };
118
119
120    typedef std::pair<Methods,std::string> MethodPair;
121
122    class Proxy
123    {
124    public:
125        Proxy(MethodPair* methods)
126        {
127            std::cout<<"methods "<<methods<<std::endl;
128            for(int i=0;methods[i].first!=END;++i)
129            {
130                std::cout<<"\t"<<methods[i].first<<"\t"<<methods[i].second<<std::endl;
131            }
132        }
133    };
134
135
136    static MethodPair methods[] =
137    {
138        MethodPair(SET_1,"SET_1"),
139        MethodPair(SET_2,"SET_2"),
140        MethodPair(END,"")
141    };
142
143    Proxy myproxy(methods);
144
145#endif
146
147void PrintFilePathList(std::ostream& stream,const FilePathList& filepath)
148{
149    for(FilePathList::const_iterator itr=filepath.begin();
150        itr!=filepath.end();
151        ++itr)
152    {
153        stream << "    "<< *itr<<std::endl;
154    }
155}
156
157Registry* Registry::instance(bool erase)
158{
159    static ref_ptr<Registry> s_registry = new Registry;
160    if (erase)
161    {   
162        s_registry->destruct();
163        s_registry = 0;
164    }
165    return s_registry.get(); // will return NULL on erase
166}
167
168
169// definition of the Registry
170Registry::Registry()
171{
172    // comment out because it was causing problems under OSX - causing it to crash osgconv when constructing ostream in osg::notify().
173    // notify(INFO) << "Constructing osg::Registry"<<std::endl;
174
175    _buildKdTreesHint = ReaderWriter::Options::NO_PREFERENCE;
176    _kdTreeBuilder = new osg::KdTreeBuilder;
177   
178    const char* kdtree_str = getenv("OSG_BUILD_KDTREES");
179    if (kdtree_str)
180    {
181        bool switchOff = (strcmp(kdtree_str, "off")==0 || strcmp(kdtree_str, "OFF")==0 || strcmp(kdtree_str, "Off")==0 );
182        if (switchOff) _buildKdTreesHint = ReaderWriter::Options::DO_NOT_BUILD_KDTREES;
183        else _buildKdTreesHint = ReaderWriter::Options::BUILD_KDTREES;
184    }
185
186    const char* fileCachePath = getenv("OSG_FILE_CACHE");
187    if (fileCachePath)
188    {
189        _fileCache = new FileCache(fileCachePath);   
190    }
191
192    _createNodeFromImage = false;
193    _openingLibrary = false;
194
195    // add default osga archive extension
196    _archiveExtList.push_back("osga");
197   
198    initFilePathLists();
199
200
201
202    // register file extension alias.
203    const char* flt_str = getenv("OSG_OPEN_FLIGHT_PLUGIN");
204    if (flt_str)
205    {
206        if (strcmp(flt_str, "new")==0)
207        {
208            addFileExtensionAlias("flt", "OpenFlight");
209        }
210    }
211    else
212    {
213    #ifndef COMPILE_WITH_OLD_OPENFLIGHT_PLUGIN_AS_DEFAULT
214        addFileExtensionAlias("flt", "OpenFlight");
215    #endif
216    }
217
218    addFileExtensionAlias("osgs", "osg");
219    addFileExtensionAlias("shadow""osgShadow");
220    addFileExtensionAlias("terrain", "osgTerrain");
221    addFileExtensionAlias("view""osgViewer");
222
223    addFileExtensionAlias("sgi""rgb");
224    addFileExtensionAlias("rgba", "rgb");
225    addFileExtensionAlias("int""rgb");
226    addFileExtensionAlias("inta", "rgb");
227    addFileExtensionAlias("bw",   "rgb");
228
229    addFileExtensionAlias("ivz",   "gz");
230    addFileExtensionAlias("ozg",   "gz");
231   
232    addFileExtensionAlias("mag",   "dicom");
233    addFileExtensionAlias("ph",   "dicom");
234    addFileExtensionAlias("ima",   "dicom");
235    addFileExtensionAlias("dcm",   "dicom");
236    addFileExtensionAlias("dic",   "dicom");
237
238    addFileExtensionAlias("gl",   "glsl");
239    addFileExtensionAlias("vert",   "glsl");
240    addFileExtensionAlias("frag",   "glsl");
241
242#if defined (__APPLE__) && (__LP64__)
243#undef DARWIN_QUICKTIME
244#define DARWIN_IMAGEIO 1
245#endif
246
247#if defined(DARWIN_IMAGEIO)
248    addFileExtensionAlias("jpg""imageio");
249    addFileExtensionAlias("jpe""imageio");
250    addFileExtensionAlias("jpeg", "imageio");
251    addFileExtensionAlias("tif""imageio");
252    addFileExtensionAlias("tiff", "imageio");
253    addFileExtensionAlias("gif""imageio");
254    addFileExtensionAlias("png""imageio");
255    addFileExtensionAlias("psd""imageio");
256    addFileExtensionAlias("tga""imageio");
257#endif
258
259#if defined(DARWIN_QUICKTIME)
260    addFileExtensionAlias("jpg""qt");
261    addFileExtensionAlias("jpe""qt");
262    addFileExtensionAlias("jpeg", "qt");
263    addFileExtensionAlias("tif""qt");
264    addFileExtensionAlias("tiff", "qt");
265    addFileExtensionAlias("gif""qt");
266    addFileExtensionAlias("png""qt");
267    addFileExtensionAlias("psd""qt");
268    addFileExtensionAlias("tga""qt");
269    addFileExtensionAlias("mov""qt");
270    addFileExtensionAlias("avi""qt");
271    addFileExtensionAlias("mpg""qt");
272    addFileExtensionAlias("flv""qt");
273    addFileExtensionAlias("mpv""qt");
274    addFileExtensionAlias("dv",   "qt");
275    addFileExtensionAlias("mp4""qt");
276    addFileExtensionAlias("m4v""qt");
277    addFileExtensionAlias("3gp""qt");
278    // Add QuickTime live support for OSX
279    addFileExtensionAlias("live", "qt");
280#else
281    addFileExtensionAlias("jpg""jpeg");
282    addFileExtensionAlias("jpe""jpeg");
283    addFileExtensionAlias("tif""tiff");
284
285    // really need to decide this at runtime...
286    #if defined(USE_XINE)
287        addFileExtensionAlias("mov""xine");
288        addFileExtensionAlias("mpg""xine");
289        addFileExtensionAlias("ogv""xine");
290        addFileExtensionAlias("mpv""xine");
291        addFileExtensionAlias("dv",   "xine");
292        addFileExtensionAlias("avi""xine");
293        addFileExtensionAlias("wmv""xine");
294        addFileExtensionAlias("flv""xine");
295    #endif
296
297    // support QuickTime for Windows
298    #if defined(USE_QUICKTIME)
299        addFileExtensionAlias("mov", "qt");
300        addFileExtensionAlias("live", "qt");
301        addFileExtensionAlias("mpg", "qt");
302        addFileExtensionAlias("avi", "qt");
303    #endif
304#endif
305
306    // remove geo to lwo alias as the new Carbon Graphics GEO format
307    // also uses the .geo. It is still possible to load light wave .geo
308    // files via loading the lwo plugin explicitly and then doing a readNodeFile.
309    //addFileExtensionAlias("geo",  "lwo");
310    addFileExtensionAlias("lw",   "lwo");
311
312    #if defined(USE_VRML)
313        addFileExtensionAlias("wrl",   "vrml");   
314    #elif defined(USE_INVENTOR)
315        addFileExtensionAlias("wrl",   "iv");
316    #endif
317   
318    // add alias for the text/freetype plugin.
319    addFileExtensionAlias("ttf",   "freetype");  // true type
320    addFileExtensionAlias("ttc",   "freetype");  // true type
321    addFileExtensionAlias("cid",   "freetype");  // Postscript CID-Fonts
322    addFileExtensionAlias("cff",   "freetype");  // OpenType
323    addFileExtensionAlias("cef",   "freetype");  // OpenType
324    addFileExtensionAlias("fon",   "freetype");  // Windows bitmap fonts
325    addFileExtensionAlias("fnt",   "freetype");    // Windows bitmap fonts
326   
327    // wont't add type1 and type2 until resolve extension collision with Performer binary and ascii files.
328    // addFileExtensionAlias("pfb",   "freetype");  // type1 binary
329    // addFileExtensionAlias("pfa",   "freetype");  // type2 ascii
330
331
332    // portable bitmap, greyscale and colour/pixmap image formats
333    addFileExtensionAlias("pbm", "pnm");
334    addFileExtensionAlias("pgm", "pnm");
335    addFileExtensionAlias("ppm", "pnm");
336       
337        // register http-protocol, so the curl can handle it, if necessary
338        registerProtocol("http");
339   
340}
341
342
343Registry::~Registry()
344{
345    destruct();
346}
347
348void Registry::destruct()
349{
350    // osg::notify(osg::NOTICE)<<"Registry::destruct()"<<std::endl;
351
352    // clean up the SharedStateManager
353    _sharedStateManager = 0;
354   
355
356    // clean up the FileCache
357    _fileCache = 0;
358   
359
360    // object cache clear needed here to prevent crash in unref() of
361    // the objects it contains when running the TXP plugin.
362    // Not sure why, but perhaps there is is something in a TXP plugin
363    // which deletes the data before its ref count hits zero, perhaps
364    // even some issue with objects be allocated by a plugin that is
365    // maintained after that plugin is deleted...  Robert Osfield, Jan 2004.
366    clearObjectCache();
367    clearArchiveCache();
368   
369
370    // unload all the plugin before we finally destruct.
371    closeAllLibraries();
372}
373
374#include <iostream>
375
376void Registry::initDataFilePathList()
377{
378    FilePathList filepath;
379    //
380    // set up data file paths
381    //
382    char *ptr;
383 
384    if( (ptr = getenv( "OSG_FILE_PATH" )) )
385    {
386        //notify(DEBUG_INFO) << "OSG_FILE_PATH("<<ptr<<")"<<std::endl;
387        convertStringPathIntoFilePathList(ptr, filepath);
388    }
389    else if( (ptr = getenv( "OSGFILEPATH" )) )
390    {
391        //notify(DEBUG_INFO) << "OSGFILEPATH("<<ptr<<")"<<std::endl;
392        convertStringPathIntoFilePathList(ptr, filepath);
393    }
394
395    osgDB::appendPlatformSpecificResourceFilePaths(filepath);
396    setDataFilePathList(filepath);
397   
398}
399
400void Registry::setDataFilePathList(const std::string& paths)
401{
402    _dataFilePath.clear();
403    convertStringPathIntoFilePathList(paths,_dataFilePath);
404}
405
406void Registry::setLibraryFilePathList(const std::string& paths) { _libraryFilePath.clear(); convertStringPathIntoFilePathList(paths,_libraryFilePath); }
407
408
409
410void Registry::initLibraryFilePathList()
411{
412    //
413    // set up library paths
414    //
415    char* ptr;
416    if( (ptr = getenv( "OSG_LIBRARY_PATH")) )
417    {
418        //notify(DEBUG_INFO) << "OSG_LIBRARY_PATH("<<ptr<<")"<<std::endl;
419        setLibraryFilePathList(ptr);
420    }
421    else if( (ptr = getenv( "OSG_LD_LIBRARY_PATH")) )
422    {
423        //notify(DEBUG_INFO) << "OSG_LD_LIBRARY_PATH("<<ptr<<")"<<std::endl;
424        setLibraryFilePathList(ptr);
425    }
426   
427    appendPlatformSpecificLibraryFilePaths(_libraryFilePath);
428
429}
430
431
432void Registry::readCommandLine(osg::ArgumentParser& arguments)
433{
434    // report the usage options.
435    if (arguments.getApplicationUsage())
436    {
437        arguments.getApplicationUsage()->addCommandLineOption("-l <library>","Load the plugin");
438        arguments.getApplicationUsage()->addCommandLineOption("-e <extension>","Load the plugin associated with handling files with specified extension");
439        arguments.getApplicationUsage()->addCommandLineOption("-O <option_string>","Provide an option string to reader/writers used to load databases");
440    }
441
442    std::string value;
443    while(arguments.read("-l",value))
444    {
445        loadLibrary(value);
446    }
447       
448    while(arguments.read("-e",value))
449    {
450        std::string libName = createLibraryNameForExtension(value);
451        loadLibrary(libName);
452    }
453
454    while(arguments.read("-O",value))
455    {
456        setOptions(new ReaderWriter::Options(value));
457    }
458}
459
460void Registry::addDotOsgWrapper(DotOsgWrapper* wrapper)
461{
462    if (wrapper==0L) return;
463
464    //notify(INFO) << "osg::Registry::addDotOsgWrapper("<<wrapper->getName()<<")"<< std::endl;
465    const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
466   
467    for(DotOsgWrapper::Associates::const_iterator itr=assoc.begin();
468                                                  itr!=assoc.end();
469                                                  ++itr)
470    {
471        //notify(INFO) << "    ("<<*itr<<")"<< std::endl;
472    }
473
474    const std::string& name = wrapper->getName();
475    const osg::Object* proto = wrapper->getPrototype();
476
477    _objectWrapperMap[name] = wrapper;
478    if (wrapper->getReadWriteMode()==DotOsgWrapper::READ_AND_WRITE) _classNameWrapperMap[name] = wrapper;
479   
480    if (proto)
481    {
482        std::string libraryName = proto->libraryName();
483        std::string compositeName = libraryName + "::" + name;
484
485        _objectWrapperMap[compositeName] = wrapper;
486        if (wrapper->getReadWriteMode()==DotOsgWrapper::READ_AND_WRITE) _classNameWrapperMap[compositeName] = wrapper;
487
488        if (dynamic_cast<const Image*>(proto))
489        {
490            _imageWrapperMap[name] = wrapper;
491            _imageWrapperMap[compositeName] = wrapper;
492        }
493        if (dynamic_cast<const Drawable*>(proto))
494        {
495              _drawableWrapperMap[name] = wrapper;
496              _drawableWrapperMap[compositeName] = wrapper;
497        }
498        if (dynamic_cast<const StateAttribute*>(proto))
499        {
500            _stateAttrWrapperMap[name] = wrapper;
501            _stateAttrWrapperMap[compositeName] = wrapper;
502        }
503        if (dynamic_cast<const Uniform*>(proto))
504        {
505            _uniformWrapperMap[name] = wrapper;
506            _uniformWrapperMap[compositeName] = wrapper;
507        }
508        if (dynamic_cast<const Node*>(proto))
509        {
510            _nodeWrapperMap[name] = wrapper;
511            _nodeWrapperMap[compositeName] = wrapper;
512        }
513        if (dynamic_cast<const Shader*>(proto))
514        {
515            _shaderWrapperMap[name] = wrapper;
516            _shaderWrapperMap[compositeName] = wrapper;
517        }
518
519
520    }
521}
522
523// need to change to delete all instances of wrapper, since we
524// now can have a wrapper entered twice with the addition of the
525// library::class composite name.
526void Registry::eraseWrapper(DotOsgWrapperMap& wrappermap,DotOsgWrapper* wrapper)
527{
528    typedef std::vector<DotOsgWrapperMap::iterator> EraseList;
529    EraseList eraseList;
530    for(DotOsgWrapperMap::iterator witr=wrappermap.begin();
531        witr!=wrappermap.end();
532        ++witr)
533    {
534        if (witr->second==wrapper) eraseList.push_back(witr);
535    }
536    for(EraseList::iterator eitr=eraseList.begin();
537        eitr!=eraseList.end();
538        ++eitr)
539    {
540        wrappermap.erase(*eitr);
541    }
542}
543
544void Registry::removeDotOsgWrapper(DotOsgWrapper* wrapper)
545{
546    if (wrapper==0L) return;
547
548    eraseWrapper(_objectWrapperMap,wrapper);
549    eraseWrapper(_classNameWrapperMap,wrapper);
550    eraseWrapper(_imageWrapperMap,wrapper);
551    eraseWrapper(_drawableWrapperMap,wrapper);
552    eraseWrapper(_uniformWrapperMap,wrapper);
553    eraseWrapper(_stateAttrWrapperMap,wrapper);
554    eraseWrapper(_nodeWrapperMap,wrapper);
555    eraseWrapper(_shaderWrapperMap,wrapper);
556}
557
558void Registry::addReaderWriter(ReaderWriter* rw)
559{
560    if (rw==0L) return;
561
562    // notify(INFO) << "osg::Registry::addReaderWriter("<<rw->className()<<")"<< std::endl;
563
564    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
565
566    _rwList.push_back(rw);
567
568}
569
570
571void Registry::removeReaderWriter(ReaderWriter* rw)
572{
573    if (rw==0L) return;
574
575//    notify(INFO) << "osg::Registry::removeReaderWriter();"<< std::endl;
576
577    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
578
579    ReaderWriterList::iterator rwitr = std::find(_rwList.begin(),_rwList.end(),rw);
580    if (rwitr!=_rwList.end())
581    {
582        _rwList.erase(rwitr);
583    }
584
585}
586
587
588void Registry::addFileExtensionAlias(const std::string mapExt, const std::string toExt)
589{
590    _extAliasMap[mapExt] = toExt;
591}
592
593bool Registry::readPluginAliasConfigurationFile( const std::string& file )
594{
595    std::string fileName = osgDB::findDataFile( file );
596    if (fileName.empty())
597    {
598        osg::notify( osg::WARN) << "Can't find plugin alias config file \"" << file << "\"." << std::endl;
599        return false;
600    }
601
602    osgDB::ifstream ifs;
603    ifs.open( fileName.c_str() );
604    if (!ifs.good())
605    {
606        osg::notify( osg::WARN) << "Can't open plugin alias config file \"" << fileName << "\"." << std::endl;
607        return false;
608    }
609
610    int lineNum( 0 );
611    while (ifs.good())
612    {
613        std::string raw;
614        ++lineNum;
615        std::getline( ifs, raw );
616        std::string ln = trim( raw );
617        if (ln.empty()) continue;
618        if (ln[0] == '#') continue;
619
620        std::string::size_type spIdx = ln.find_first_of( " \t" );
621        if (spIdx == ln.npos)
622        {
623            // mapExt and toExt must be on the same line, separated by a space.
624            osg::notify( osg::WARN) << file << ", line " << lineNum << ": Syntax error: missing space in \"" << raw << "\"." << std::endl;
625            continue;
626        }
627
628        const std::string mapExt = trim( ln.substr( 0, spIdx ) );
629        const std::string toExt = trim( ln.substr( spIdx+1 ) );
630        addFileExtensionAlias( mapExt, toExt );
631    }
632    return true;
633}
634
635std::string Registry::trim( const std::string& str )
636{
637    if (!str.size()) return str;
638    std::string::size_type first = str.find_first_not_of( " \t" );
639    std::string::size_type last = str.find_last_not_of( "  \t\r\n" );
640    if ((first==str.npos) || (last==str.npos)) return std::string( "" );
641    return str.substr( first, last-first+1 );
642}
643
644
645std::string Registry::createLibraryNameForFile(const std::string& fileName)
646{
647    return createLibraryNameForExtension(getFileExtension(fileName));
648}
649
650std::string Registry::createLibraryNameForExtension(const std::string& ext)
651{
652    std::string lowercase_ext;
653    for(std::string::const_iterator sitr=ext.begin();
654        sitr!=ext.end();
655        ++sitr)
656    {
657        lowercase_ext.push_back(tolower(*sitr));
658    }
659
660    ExtensionAliasMap::iterator itr=_extAliasMap.find(lowercase_ext);
661    if (itr!=_extAliasMap.end() && ext != itr->second) return createLibraryNameForExtension(itr->second);
662
663#ifdef OSG_JAVA_BUILD
664    static std::string prepend = std::string("osgPlugins-")+std::string(osgGetVersion())+std::string("/java");
665#elseif defined(__APPLE__)
666    // OSX is rather a mess in FileUtils.cpp w.r.t its appendPlatformSpecificLibraryFilePaths implementation
667    // as it hardwires the plugin name to PlugIns.  This *needs* fixing to use the naming convention as all
668    // other platforms.
669    static std::string prepend = "";
670#else
671    static std::string prepend = std::string("osgPlugins-")+std::string(osgGetVersion())+std::string("/");
672#endif
673
674#if defined(__CYGWIN__)
675    #ifdef _DEBUG
676        return prepend+"cygwin_"+"osgdb_"+lowercase_ext+OSG_DEBUG_POSTFIX_WITH_QUOTES+".dll";
677    #else
678        return prepend+"cygwin_"+"osgdb_"+lowercase_ext+".dll";
679    #endif
680#elif defined(__MINGW32__)
681    return prepend+"mingw_"+"osgdb_"+lowercase_ext+".dll";
682#elif defined(WIN32)
683    #ifdef _DEBUG
684        return prepend+"osgdb_"+lowercase_ext+ OSG_DEBUG_POSTFIX_WITH_QUOTES +".dll";
685    #else
686        return prepend+"osgdb_"+lowercase_ext+".dll";
687    #endif
688#elif macintosh
689    return prepend+"osgdb_"+lowercase_ext;
690#elif defined(__hpux__)
691    // why don't we use PLUGIN_EXT from the makefiles here?
692    return prepend+"osgdb_"+lowercase_ext+".sl";
693#else
694    #ifdef _DEBUG
695         return prepend+"osgdb_"+lowercase_ext+ OSG_DEBUG_POSTFIX_WITH_QUOTES + ".so";
696    #else
697         return prepend+"osgdb_"+lowercase_ext+".so";
698    #endif
699#endif
700
701}
702
703std::string Registry::createLibraryNameForNodeKit(const std::string& name)
704{
705#if defined(__CYGWIN__)
706    return "cyg"+name+".dll";
707#elif defined(__MINGW32__)
708    return "lib"+name+".dll";
709#elif defined(WIN32)
710    #ifdef _DEBUG
711        return name+OSG_DEBUG_POSTFIX_WITH_QUOTES +".dll";
712    #else
713        return name+".dll";
714    #endif
715#elif macintosh
716    return name;
717#elif defined(__hpux__)
718    // why don't we use PLUGIN_EXT from the makefiles here?
719    return "lib"+name+".sl";
720#else
721    #ifdef _DEBUG
722        return "lib"+name+OSG_DEBUG_POSTFIX_WITH_QUOTES +".so";
723    #else
724        return "lib"+name+".so";
725    #endif
726#endif
727}
728
729Registry::LoadStatus Registry::loadLibrary(const std::string& fileName)
730{
731    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
732
733    DynamicLibraryList::iterator ditr = getLibraryItr(fileName);
734    if (ditr!=_dlList.end()) return PREVIOUSLY_LOADED;
735
736    _openingLibrary=true;
737
738    DynamicLibrary* dl = DynamicLibrary::loadLibrary(fileName);
739    _openingLibrary=false;
740
741    if (dl)
742    {
743        _dlList.push_back(dl);
744        return LOADED;
745    }
746    return NOT_LOADED;
747}
748
749
750bool Registry::closeLibrary(const std::string& fileName)
751{
752    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
753    DynamicLibraryList::iterator ditr = getLibraryItr(fileName);
754    if (ditr!=_dlList.end())
755    {
756        _dlList.erase(ditr);
757        return true;
758    }
759    return false;
760}
761
762void Registry::closeAllLibraries()
763{
764    // osg::notify(osg::NOTICE)<<"Registry::closeAllLibraries()"<<std::endl;
765    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
766    _dlList.clear();
767}
768
769Registry::DynamicLibraryList::iterator Registry::getLibraryItr(const std::string& fileName)
770{
771    DynamicLibraryList::iterator ditr = _dlList.begin();
772    for(;ditr!=_dlList.end();++ditr)
773    {
774        if ((*ditr)->getName()==fileName) return ditr;
775    }
776    return _dlList.end();
777}
778
779DynamicLibrary* Registry::getLibrary(const std::string& fileName)
780{
781    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
782    DynamicLibraryList::iterator ditr = getLibraryItr(fileName);
783    if (ditr!=_dlList.end()) return ditr->get();
784    else return NULL;
785}
786
787ReaderWriter* Registry::getReaderWriterForExtension(const std::string& ext)
788{
789    // record the existing reader writer.
790    std::set<ReaderWriter*> rwOriginal;
791
792    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
793
794    // first attemt one of the installed loaders
795    for(ReaderWriterList::iterator itr=_rwList.begin();
796        itr!=_rwList.end();
797        ++itr)
798    {
799        rwOriginal.insert(itr->get());
800        if((*itr)->acceptsExtension(ext)) return (*itr).get();
801    }
802   
803    // now look for a plug-in to load the file.
804    std::string libraryName = createLibraryNameForExtension(ext);
805    notify(INFO) << "Now checking for plug-in "<<libraryName<< std::endl;
806    if (loadLibrary(libraryName)==LOADED)
807    {
808        for(ReaderWriterList::iterator itr=_rwList.begin();
809            itr!=_rwList.end();
810            ++itr)
811        {
812            if (rwOriginal.find(itr->get())==rwOriginal.end())
813            {
814                if((*itr)->acceptsExtension(ext)) return (*itr).get();
815            }
816        }
817    }
818
819    return NULL;
820
821}
822
823struct concrete_wrapper: basic_type_wrapper
824{
825    virtual ~concrete_wrapper() {}
826    concrete_wrapper(const osg::Object *myobj) : myobj_(myobj) {}
827    bool matches(const osg::Object *proto) const
828    {
829        return myobj_->isSameKindAs(proto);
830    }
831    const osg::Object *myobj_;
832};
833
834osg::Object* Registry::readObjectOfType(const osg::Object& compObj,Input& fr)
835{
836    return readObjectOfType(concrete_wrapper(&compObj), fr);
837}
838
839osg::Object* Registry::readObjectOfType(const basic_type_wrapper &btw,Input& fr)
840{
841    const char *str = fr[0].getStr();
842    if (str==NULL) return NULL;
843
844    if (fr[0].matchWord("Use"))
845    {
846        if (fr[1].isString())
847        {
848            Object* obj = fr.getObjectForUniqueID(fr[1].getStr());
849            if (obj && btw.matches(obj))
850            {
851                fr+=2;
852                return obj;
853            }
854        }
855        else return NULL;
856
857    }
858
859    std::string name = str;
860    DotOsgWrapperMap::iterator itr = _objectWrapperMap.find(name);
861    if (itr==_objectWrapperMap.end())
862    {
863        // not found so check if a library::class composite name.
864        std::string token = fr[0].getStr();
865        std::string::size_type posDoubleColon = token.rfind("::");
866        if (posDoubleColon != std::string::npos)
867        {
868            // we have a composite name so now strip off the library name
869            // are try to load it, and then retry the readObject to see
870            // if we can recognize the objects.
871            std::string libraryName = std::string(token,0,posDoubleColon);
872
873            // first try the standard nodekit library.
874            std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
875            if (loadLibrary(nodeKitLibraryName)==LOADED) return readObjectOfType(btw,fr);
876           
877            // otherwise try the osgdb_ plugin library.
878            std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
879            if (loadLibrary(pluginLibraryName)==LOADED) return readObjectOfType(btw,fr);
880        }
881    }
882    else if (fr[1].isOpenBracket())
883    {
884        DotOsgWrapper* wrapper = itr->second.get();
885        const osg::Object* proto = wrapper->getPrototype();
886        if (proto==NULL)
887        {
888            osg::notify(osg::WARN)<<"Token "<<fr[0].getStr()<<" read, but has no prototype, cannot load."<< std::endl;
889            return NULL;
890        }
891       
892        if (!btw.matches(proto))
893        {
894            return NULL;
895        }
896
897        // record the number of nested brackets move the input iterator
898        // over the name { tokens.
899        int entry = fr[0].getNoNestedBrackets();
900        fr+=2;
901
902        const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
903        osg::Object* obj = proto->cloneType();
904
905        while(!fr.eof() && fr[0].getNoNestedBrackets()>entry)
906        {
907            bool iteratorAdvanced = false;
908            if (fr[0].matchWord("UniqueID") && fr[1].isString())
909            {
910                fr.registerUniqueIDForObject(fr[1].getStr(),obj);
911                fr += 2;
912                iteratorAdvanced = true;
913            }
914
915            // read the local data by iterating through the associate
916            // list, mapping the associate names to DotOsgWrapper's which
917            // in turn have the appropriate functions.
918            for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin();
919                                                          aitr!=assoc.end();
920                                                          ++aitr)
921            {
922                DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr);
923                if (mitr==_objectWrapperMap.end())
924                {
925                    // not found so check if a library::class composite name.
926                    std::string token = *aitr;
927                    std::string::size_type posDoubleColon = token.rfind("::");
928                    if (posDoubleColon != std::string::npos)
929                    {
930                        // we have a composite name so now strip off the library name
931                        // and try to load it, and then retry the find to see
932                        // if we can recognize the objects.
933                        std::string libraryName = std::string(token,0,posDoubleColon);
934
935                        // first try the standard nodekit library.
936                        std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
937                        if (loadLibrary(nodeKitLibraryName)==LOADED)
938                        {
939                            mitr = _objectWrapperMap.find(*aitr);
940                            if (mitr==_objectWrapperMap.end())
941                            {
942                                // otherwise try the osgdb_ plugin library.
943                                std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
944                                if (loadLibrary(pluginLibraryName)==LOADED)
945                                {
946                                    mitr = _objectWrapperMap.find(*aitr);
947                                }
948                            }
949                        }
950                    }
951                }
952
953                if (mitr!=_objectWrapperMap.end())
954                {
955                    // get the function to read the data...
956                    DotOsgWrapper::ReadFunc rf = mitr->second->getReadFunc();
957                    if (rf && (*rf)(*obj,fr)) iteratorAdvanced = true;
958                }
959
960            }
961
962            if (!iteratorAdvanced) fr.advanceOverCurrentFieldOrBlock();
963        }
964        ++fr;                        // step over trailing '}'
965       
966        return obj;
967       
968    }
969    return 0L;
970}
971
972//
973// read object from input iterator.
974//
975osg::Object* Registry::readObject(DotOsgWrapperMap& dowMap,Input& fr)
976{
977    const char *str = fr[0].getStr();
978    if (str==NULL) return NULL;
979
980    std::string name = str;
981    DotOsgWrapperMap::iterator itr = dowMap.find(name);
982    if (itr==dowMap.end())
983    {
984        // not found so check if a library::class composite name.
985        std::string token = fr[0].getStr();
986        std::string::size_type posDoubleColon = token.rfind("::");
987        if (posDoubleColon != std::string::npos)
988        {
989            // we have a composite name so now strip off the library name
990            // are try to load it, and then retry the readObject to see
991            // if we can recognize the objects.
992       
993            std::string libraryName = std::string(token,0,posDoubleColon);
994
995            // first try the standard nodekit library.
996            std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
997            if (loadLibrary(nodeKitLibraryName)==LOADED) return readObject(dowMap,fr);
998           
999            // otherwise try the osgdb_ plugin library.
1000            std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
1001            if (loadLibrary(pluginLibraryName)==LOADED) return readObject(dowMap,fr);
1002        }
1003    }
1004    else if (fr[1].isOpenBracket())
1005    {
1006   
1007        DotOsgWrapper* wrapper = itr->second.get();
1008        const osg::Object* proto = wrapper->getPrototype();
1009        if (proto==NULL)
1010        {
1011            osg::notify(osg::WARN)<<"Token "<<fr[0].getStr()<<" read, but has no prototype, cannot load."<< std::endl;
1012            return NULL;
1013        }
1014
1015        // record the number of nested brackets move the input iterator
1016        // over the name { tokens.
1017        int entry = fr[0].getNoNestedBrackets();
1018        fr+=2;
1019
1020        const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
1021        osg::Object* obj = proto->cloneType();
1022
1023        while(!fr.eof() && fr[0].getNoNestedBrackets()>entry)
1024        {
1025            bool iteratorAdvanced = false;
1026            if (fr[0].matchWord("UniqueID") && fr[1].isString())
1027            {
1028                fr.registerUniqueIDForObject(fr[1].getStr(),obj);
1029                fr += 2;
1030                iteratorAdvanced = true;
1031            }
1032
1033            // read the local data by iterating through the associate
1034            // list, mapping the associate names to DotOsgWrapper's which
1035            // in turn have the appropriate functions.
1036            for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin();
1037                                                          aitr!=assoc.end();
1038                                                          ++aitr)
1039            {
1040                DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr);
1041                if (mitr==_objectWrapperMap.end())
1042                {
1043                    // not found so check if a library::class composite name.
1044                    std::string token = *aitr;
1045                    std::string::size_type posDoubleColon = token.rfind("::");
1046                    if (posDoubleColon != std::string::npos)
1047                    {
1048
1049                        // we have a composite name so now strip off the library name
1050                        // are try to load it, and then retry the find to see
1051                        // if we can recognize the objects.
1052
1053                        std::string libraryName = std::string(token,0,posDoubleColon);
1054
1055                        // first try the standard nodekit library.
1056                        std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
1057                        if (loadLibrary(nodeKitLibraryName)==LOADED)
1058                        {
1059                            mitr = _objectWrapperMap.find(*aitr);
1060                        }
1061
1062                        if (mitr==_objectWrapperMap.end())
1063                        {
1064                            // otherwise try the osgdb_ plugin library.
1065                            std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
1066                            if (loadLibrary(pluginLibraryName)==LOADED)
1067                            {
1068                                mitr = _objectWrapperMap.find(*aitr);
1069                            }
1070                        }
1071
1072                    }
1073                }
1074
1075                if (mitr!=_objectWrapperMap.end())
1076                {
1077                    // get the function to read the data...
1078                    DotOsgWrapper::ReadFunc rf = mitr->second->getReadFunc();
1079                    if (rf && (*rf)(*obj,fr)) iteratorAdvanced = true;
1080                }
1081
1082            }
1083
1084            if (!iteratorAdvanced) fr.advanceOverCurrentFieldOrBlock();
1085        }
1086        ++fr;                        // step over trailing '}'
1087       
1088        return obj;
1089       
1090    }
1091
1092    return 0L;
1093}
1094
1095//
1096// read object from input iterator.
1097//
1098Object* Registry::readObject(Input& fr)
1099{
1100    if (fr[0].matchWord("Use"))
1101    {
1102        if (fr[1].isString())
1103        {
1104            Object* obj = fr.getObjectForUniqueID(fr[1].getStr());
1105            if (obj) fr+=2;
1106            return obj;
1107        }
1108        else return NULL;
1109
1110    }
1111
1112    return readObject(_objectWrapperMap,fr);
1113}
1114
1115
1116//
1117// read image from input iterator.
1118//
1119Image* Registry::readImage(Input& fr)
1120{
1121    if (fr[0].matchWord("Use"))
1122    {
1123        if (fr[1].isString())
1124        {
1125            Image* image = dynamic_cast<Image*>(fr.getObjectForUniqueID(fr[1].getStr()));
1126            if (image) fr+=2;
1127            return image;
1128        }
1129        else return NULL;
1130
1131    }
1132
1133    osg::Object* obj = readObject(_imageWrapperMap,fr);
1134    osg::Image* image = dynamic_cast<Image*>(obj);
1135    if (image) return image;
1136    else if (obj) obj->unref();
1137   
1138    return NULL;
1139}
1140
1141
1142//
1143// read drawable from input iterator.
1144//
1145Drawable* Registry::readDrawable(Input& fr)
1146{
1147    if (fr[0].matchWord("Use"))
1148    {
1149        if (fr[1].isString())
1150        {
1151            Drawable* drawable = dynamic_cast<Drawable*>(fr.getObjectForUniqueID(fr[1].getStr()));
1152            if (drawable) fr+=2;
1153            return drawable;
1154        }
1155        else return NULL;
1156
1157    }
1158
1159    osg::Object* obj = readObject(_drawableWrapperMap,fr);
1160    osg::Drawable* drawable = dynamic_cast<Drawable*>(obj);
1161    if (drawable) return drawable;
1162    else if (obj) obj->unref();
1163   
1164    return NULL;
1165}
1166
1167//
1168// read drawable from input iterator.
1169//
1170StateAttribute* Registry::readStateAttribute(Input& fr)
1171{
1172
1173    if (fr[0].matchWord("Use"))
1174    {
1175        if (fr[1].isString())
1176        {
1177            StateAttribute* attribute = dynamic_cast<StateAttribute*>(fr.getObjectForUniqueID(fr[1].getStr()));
1178            if (attribute) fr+=2;
1179            return attribute;
1180        }
1181        else return NULL;
1182
1183    }
1184
1185    return dynamic_cast<StateAttribute*>(readObject(_stateAttrWrapperMap,fr));
1186}
1187
1188//
1189// read drawable from input iterator.
1190//
1191Uniform* Registry::readUniform(Input& fr)
1192{
1193
1194    if (fr[0].matchWord("Use"))
1195    {
1196        if (fr[1].isString())
1197        {
1198            Uniform* attribute = dynamic_cast<Uniform*>(fr.getObjectForUniqueID(fr[1].getStr()));
1199            if (attribute) fr+=2;
1200            return attribute;
1201        }
1202        else return NULL;
1203
1204    }
1205
1206    return dynamic_cast<Uniform*>(readObject(_uniformWrapperMap,fr));
1207}
1208
1209//
1210// read node from input iterator.
1211//
1212Node* Registry::readNode(Input& fr)
1213{
1214    if (fr[0].matchWord("Use"))
1215    {
1216        if (fr[1].isString())
1217        {
1218            Node* node = dynamic_cast<Node*>(fr.getObjectForUniqueID(fr[1].getStr()));
1219            if (node) fr+=2;
1220            return node;
1221        }
1222        else return NULL;
1223
1224    }
1225
1226    osg::Object* obj = readObject(_nodeWrapperMap,fr);
1227    osg::Node* node = dynamic_cast<Node*>(obj);
1228    if (node) return node;
1229    else if (obj) obj->unref();
1230   
1231    return NULL;
1232}
1233
1234//
1235// read image from input iterator.
1236//
1237Shader* Registry::readShader(Input& fr)
1238{
1239    if (fr[0].matchWord("Use"))
1240    {
1241        if (fr[1].isString())
1242        {
1243            Shader* shader = dynamic_cast<Shader*>(fr.getObjectForUniqueID(fr[1].getStr()));
1244            if (shader) fr+=2;
1245            return shader;
1246        }
1247        else return NULL;
1248
1249    }
1250
1251    osg::Object* obj = readObject(_shaderWrapperMap,fr);
1252    osg::Shader* shader = dynamic_cast<Shader*>(obj);
1253    if (shader) return shader;
1254    else if (obj) obj->unref();
1255   
1256    return NULL;
1257}
1258
1259//
1260// Write object to output
1261//
1262bool Registry::writeObject(const osg::Object& obj,Output& fw)
1263{
1264
1265    if (obj.referenceCount()>1)
1266    {
1267        std::string uniqueID;
1268        if (fw.getUniqueIDForObject(&obj,uniqueID))
1269        {
1270            fw.writeUseID( uniqueID );
1271            return true;
1272        }
1273    }
1274
1275    const std::string classname( obj.className() );
1276    const std::string libraryName( obj.libraryName() );
1277    const std::string compositeName( libraryName + "::" + classname );
1278
1279    // try composite name first
1280    DotOsgWrapperMap::iterator itr = _classNameWrapperMap.find(compositeName);
1281
1282    if (itr==_classNameWrapperMap.end())
1283    {
1284        // first try the standard nodekit library.
1285        std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
1286        if (loadLibrary(nodeKitLibraryName)==LOADED) return writeObject(obj,fw);
1287
1288        // otherwise try the osgdb_ plugin library.
1289        std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
1290        if (loadLibrary(pluginLibraryName)==LOADED) return writeObject(obj,fw);
1291
1292        // otherwise try simple class name
1293        if (itr == _classNameWrapperMap.end())
1294            itr = _classNameWrapperMap.find(classname);
1295    }
1296
1297    if (itr!=_classNameWrapperMap.end())
1298    {
1299        DotOsgWrapper* wrapper = itr->second.get();
1300        const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
1301
1302        if (libraryName=="osg")
1303        {
1304            // member of the core osg, so no need to have composite library::class name.
1305            fw.writeBeginObject( wrapper->getName() );
1306        }
1307        else
1308        {
1309            // member of the node kit so must use composite library::class name.
1310            std::string::size_type posDoubleColon = wrapper->getName().find("::");
1311            if (posDoubleColon != std::string::npos)
1312            {
1313                fw.writeBeginObject( wrapper->getName() );
1314            }
1315            else
1316            {
1317                fw.writeBeginObject( libraryName + "::" + wrapper->getName() );
1318            }
1319        }
1320        fw.moveIn();
1321
1322
1323        // write out the unique ID if required.
1324        if (obj.referenceCount()>1)
1325        {
1326            std::string uniqueID;
1327            fw.createUniqueIDForObject(&obj,uniqueID);
1328            fw.registerUniqueIDForObject(&obj,uniqueID);
1329            fw.writeUniqueID( uniqueID );
1330        }
1331
1332        // read the local data by iterating through the associate
1333        // list, mapping the associate names to DotOsgWrapper's which
1334        // in turn have the appropriate functions.
1335        for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin();
1336                                                      aitr!=assoc.end();
1337                                                      ++aitr)
1338        {
1339            DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr);
1340            if (mitr==_objectWrapperMap.end())
1341            {
1342                // not found so check if a library::class composite name.
1343                std::string token = *aitr;
1344                std::string::size_type posDoubleColon = token.rfind("::");
1345                if (posDoubleColon != std::string::npos)
1346                {
1347
1348                    // we have a composite name so now strip off the library name
1349                    // are try to load it, and then retry the find to see
1350                    // if we can recognize the objects.
1351
1352                    std::string libraryName = std::string(token,0,posDoubleColon);
1353
1354                    // first try the standard nodekit library.
1355                    std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
1356                    if (loadLibrary(nodeKitLibraryName)==LOADED)
1357                    {
1358                        mitr = _objectWrapperMap.find(*aitr);
1359                    }
1360
1361                    if (mitr==_objectWrapperMap.end())
1362                    {
1363                        // otherwise try the osgdb_ plugin library.
1364                        std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
1365                        if (loadLibrary(pluginLibraryName)==LOADED)
1366                        {
1367                            mitr = _objectWrapperMap.find(*aitr);
1368                        }
1369                    }
1370
1371                }
1372            }
1373            if (mitr!=_objectWrapperMap.end())
1374            {
1375                // get the function to read the data...
1376                DotOsgWrapper::WriteFunc wf = mitr->second->getWriteFunc();
1377                if (wf) (*wf)(obj,fw);
1378            }
1379
1380        }
1381
1382        fw.moveOut();
1383        fw.writeEndObject();
1384
1385        return true;
1386    }
1387   
1388    return false;
1389}
1390
1391
1392
1393struct Registry::ReadObjectFunctor : public Registry::ReadFunctor
1394{
1395    ReadObjectFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {}
1396
1397    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw) const { return rw.readObject(_filename, _options); }   
1398    virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validObject(); }
1399    virtual bool isValid(osg::Object* object) const { return object!=0;  }
1400};
1401
1402struct Registry::ReadImageFunctor : public Registry::ReadFunctor
1403{
1404    ReadImageFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {}
1405
1406    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw)const  { return rw.readImage(_filename, _options); }   
1407    virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validImage(); }
1408    virtual bool isValid(osg::Object* object) const { return dynamic_cast<osg::Image*>(object)!=0;  }
1409};
1410
1411struct Registry::ReadHeightFieldFunctor : public Registry::ReadFunctor
1412{
1413    ReadHeightFieldFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {}
1414
1415    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw) const { return rw.readHeightField(_filename, _options); }   
1416    virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validHeightField(); }
1417    virtual bool isValid(osg::Object* object) const { return dynamic_cast<osg::HeightField*>(object)!=0;  }
1418};
1419
1420struct Registry::ReadNodeFunctor : public Registry::ReadFunctor
1421{
1422    ReadNodeFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {}
1423
1424    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw) const { return rw.readNode(_filename, _options); }   
1425    virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validNode(); }
1426    virtual bool isValid(osg::Object* object) const { return dynamic_cast<osg::Node*>(object)!=0;  }
1427
1428};
1429
1430struct Registry::ReadArchiveFunctor : public Registry::ReadFunctor
1431{
1432    ReadArchiveFunctor(const std::string& filename, ReaderWriter::ArchiveStatus status, unsigned int indexBlockSizeHint, const ReaderWriter::Options* options):
1433        ReadFunctor(filename,options),
1434        _status(status),
1435        _indexBlockSizeHint(indexBlockSizeHint) {}
1436       
1437    ReaderWriter::ArchiveStatus _status;
1438    unsigned int _indexBlockSizeHint;
1439
1440    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw) const { return rw.openArchive(_filename, _status, _indexBlockSizeHint, _options); }
1441    virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validArchive(); }
1442    virtual bool isValid(osg::Object* object) const { return dynamic_cast<osgDB::Archive*>(object)!=0;  }
1443
1444};
1445
1446struct Registry::ReadShaderFunctor : public Registry::ReadFunctor
1447{
1448    ReadShaderFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {}
1449
1450    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw)const  { return rw.readShader(_filename, _options); }   
1451    virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validShader(); }
1452    virtual bool isValid(osg::Object* object) const { return dynamic_cast<osg::Shader*>(object)!=0;  }
1453};
1454
1455void Registry::addArchiveExtension(const std::string ext)
1456{
1457    for(ArchiveExtensionList::iterator aitr=_archiveExtList.begin();
1458        aitr!=_archiveExtList.end();
1459        ++aitr)
1460    {
1461        if ( (*aitr) == ext)   // extension already in archive extension list
1462            return;
1463    }
1464    _archiveExtList.push_back(ext);
1465}
1466
1467ReaderWriter::ReadResult Registry::read(const ReadFunctor& readFunctor)
1468{
1469    for(ArchiveExtensionList::iterator aitr=_archiveExtList.begin();
1470        aitr!=_archiveExtList.end();
1471        ++aitr)
1472    {
1473        std::string archiveExtension = "." + (*aitr);
1474
1475        std::string::size_type positionArchive = readFunctor._filename.find(archiveExtension+'/');
1476        if (positionArchive==std::string::npos) positionArchive = readFunctor._filename.find(archiveExtension+'\\');
1477        if (positionArchive!=std::string::npos)
1478        {
1479            std::string::size_type endArchive = positionArchive + archiveExtension.length();
1480            std::string archiveName( readFunctor._filename.substr(0,endArchive));
1481            std::string fileName(readFunctor._filename.substr(endArchive+1,std::string::npos));
1482            osg::notify(osg::INFO)<<"Contains archive : "<<readFunctor._filename<<std::endl;
1483            osg::notify(osg::INFO)<<"         archive : "<<archiveName<<std::endl;
1484            osg::notify(osg::INFO)<<"         filename : "<<fileName<<std::endl;
1485       
1486            ReaderWriter::ReadResult result = openArchiveImplementation(archiveName,ReaderWriter::READ, 4096, readFunctor._options);
1487       
1488            if (!result.validArchive()) return result;
1489
1490            osgDB::Archive* archive = result.getArchive();
1491       
1492            osg::ref_ptr<ReaderWriter::Options> options = new ReaderWriter::Options;
1493            options->setDatabasePath(archiveName);
1494
1495            return archive->readObject(fileName,options.get());
1496        }
1497    }
1498 
1499    // record the errors reported by readerwriters.
1500    typedef std::vector<ReaderWriter::ReadResult> Results;
1501    Results results;
1502
1503    // first attempt to load the file from existing ReaderWriter's
1504    AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
1505    for(;itr.valid();++itr)
1506    {
1507        ReaderWriter::ReadResult rr = readFunctor.doRead(*itr);
1508        if (readFunctor.isValid(rr)) return rr;
1509        else results.push_back(rr);
1510    }
1511
1512    if (!results.empty())
1513    {
1514        unsigned int num_FILE_NOT_HANDLED = 0;
1515        unsigned int num_FILE_NOT_FOUND = 0;
1516        unsigned int num_ERROR_IN_READING_FILE = 0;
1517
1518        Results::iterator ritr;
1519        for(ritr=results.begin();
1520            ritr!=results.end();
1521            ++ritr)
1522        {
1523            if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_HANDLED) ++num_FILE_NOT_HANDLED;
1524            else if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND) ++num_FILE_NOT_FOUND;
1525            else if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE) ++num_ERROR_IN_READING_FILE;
1526        }
1527       
1528        if (num_FILE_NOT_HANDLED!=results.size())
1529        {
1530            for(ritr=results.begin(); ritr!=results.end(); ++ritr)
1531            {
1532                if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE)
1533                {
1534                    // osg::notify(osg::NOTICE)<<"Warning: error reading file \""<<readFunctor._filename<<"\""<<std::endl;
1535                    return *ritr;
1536                }
1537            }
1538
1539            //If the filename is a URL, don't return FILE_NOT_FOUND until the CURL plugin is given a chance
1540            if (!osgDB::containsServerAddress(readFunctor._filename))
1541            {
1542                for(ritr=results.begin(); ritr!=results.end(); ++ritr)
1543                {
1544                    if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND)
1545                    {
1546                        //osg::notify(osg::NOTICE)<<"Warning: could not find file \""<<readFunctor._filename<<"\""<<std::endl;
1547                        return *ritr;
1548                    }
1549                }
1550            }
1551        }
1552    }
1553
1554    results.clear();
1555
1556    // now look for a plug-in to load the file.
1557    std::string libraryName = createLibraryNameForFile(readFunctor._filename);
1558    if (loadLibrary(libraryName)!=NOT_LOADED)
1559    {
1560        for(;itr.valid();++itr)
1561        {
1562            ReaderWriter::ReadResult rr = readFunctor.doRead(*itr);
1563            if (readFunctor.isValid(rr)) return rr;
1564            else results.push_back(rr);
1565        }
1566    }
1567
1568    //If the filename contains a server address and wasn't loaded by any of the plugins, try to use the CURL plugin
1569    //to download the file and use the stream reading functionality of the plugins to load the file
1570    if (containsServerAddress(readFunctor._filename))
1571    {
1572        ReaderWriter* rw = getReaderWriterForExtension("curl");
1573        if (rw)
1574        {
1575            return readFunctor.doRead(*rw);
1576        }
1577        else
1578        {
1579            return  ReaderWriter::ReadResult("Warning: Could not find the .curl plugin to read from server.");
1580        }
1581    }
1582   
1583    if (!results.empty())
1584    {
1585        unsigned int num_FILE_NOT_HANDLED = 0;
1586        unsigned int num_FILE_NOT_FOUND = 0;
1587        unsigned int num_ERROR_IN_READING_FILE = 0;
1588
1589        Results::iterator ritr;
1590        for(ritr=results.begin();
1591            ritr!=results.end();
1592            ++ritr)
1593        {
1594            if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_HANDLED) ++num_FILE_NOT_HANDLED;
1595            else if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND) ++num_FILE_NOT_FOUND;
1596            else if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE) ++num_ERROR_IN_READING_FILE;
1597        }
1598       
1599        if (num_FILE_NOT_HANDLED!=results.size())
1600        {
1601            for(ritr=results.begin(); ritr!=results.end(); ++ritr)
1602            {
1603                if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE)
1604                {
1605                    // osg::notify(osg::NOTICE)<<"Warning: error reading file \""<<readFunctor._filename<<"\""<<std::endl;
1606                    return *ritr;
1607                }
1608            }
1609
1610            for(ritr=results.begin(); ritr!=results.end(); ++ritr)
1611            {
1612                if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND)
1613                {
1614                    // osg::notify(osg::NOTICE)<<"Warning: could not find file \""<<readFunctor._filename<<"\""<<std::endl;
1615                    return *ritr;
1616                }
1617            }
1618        }
1619    }
1620    else
1621    {
1622        return ReaderWriter::ReadResult("Warning: Could not find plugin to read objects from file \""+readFunctor._filename+"\".");
1623    }
1624
1625    return results.front();
1626}
1627
1628ReaderWriter::ReadResult Registry::readImplementation(const ReadFunctor& readFunctor, bool useObjectCache)
1629{
1630    std::string file(readFunctor._filename);
1631
1632    if (useObjectCache)
1633    {
1634        // search for entry in the object cache.
1635        {
1636            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
1637            ObjectCache::iterator oitr=_objectCache.find(file);
1638            if (oitr!=_objectCache.end())
1639            {
1640                notify(INFO)<<"returning cached instanced of "<<file<<std::endl;
1641                if (readFunctor.isValid(oitr->second.first.get())) return ReaderWriter::ReadResult(oitr->second.first.get(), ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE);
1642                else return ReaderWriter::ReadResult("Error file does not contain an osg::Object");
1643            }
1644        }
1645       
1646        ReaderWriter::ReadResult rr = read(readFunctor);
1647        if (rr.validObject())
1648        {
1649            // update cache with new entry.
1650            notify(INFO)<<"Adding to object cache "<<file<<std::endl;
1651            addEntryToObjectCache(file,rr.getObject());
1652        }
1653        else
1654        {
1655            notify(INFO)<<"No valid object found for "<<file<<std::endl;
1656        }
1657
1658        return rr;
1659
1660    }
1661    else
1662    {
1663        ObjectCache tmpObjectCache;
1664       
1665        {
1666            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
1667            tmpObjectCache.swap(_objectCache);
1668        }
1669       
1670        ReaderWriter::ReadResult rr = read(readFunctor);
1671
1672        {
1673            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
1674            tmpObjectCache.swap(_objectCache);
1675        }
1676       
1677        return rr;
1678    }
1679}
1680
1681
1682ReaderWriter::ReadResult Registry::openArchiveImplementation(const std::string& fileName, ReaderWriter::ArchiveStatus status, unsigned int indexBlockSizeHint, const ReaderWriter::Options* options)
1683{
1684    osgDB::Archive* archive = getFromArchiveCache(fileName);
1685    if (archive) return archive;
1686
1687    ReaderWriter::ReadResult result = readImplementation(ReadArchiveFunctor(fileName, status, indexBlockSizeHint, options),false);
1688
1689    // default to using caching archive if no options structure provided, but if options are provided use archives
1690    // only if supplied.
1691    if (result.validArchive() &&
1692        (!options || (options->getObjectCacheHint() & ReaderWriter::Options::CACHE_ARCHIVES)) )
1693    {
1694        addToArchiveCache(fileName,result.getArchive());
1695    }
1696    return result;
1697}
1698
1699
1700ReaderWriter::ReadResult Registry::readObjectImplementation(const std::string& fileName,const ReaderWriter::Options* options)
1701{
1702    return readImplementation(ReadObjectFunctor(fileName, options),
1703                              options ? (options->getObjectCacheHint()&ReaderWriter::Options::CACHE_OBJECTS)!=0: false);
1704}
1705
1706ReaderWriter::WriteResult Registry::writeObjectImplementation(const Object& obj,const std::string& fileName,const ReaderWriter::Options* options)
1707{
1708    // record the errors reported by readerwriters.
1709    typedef std::vector<ReaderWriter::WriteResult> Results;
1710    Results results;
1711
1712    // first attempt to load the file from existing ReaderWriter's
1713    AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
1714    for(;itr.valid();++itr)
1715    {
1716        ReaderWriter::WriteResult rr = itr->writeObject(obj,fileName,options);
1717        if (rr.success()) return rr;
1718        else results.push_back(rr);
1719    }
1720
1721    // now look for a plug-in to save the file.
1722    std::string libraryName = createLibraryNameForFile(fileName);
1723    if (loadLibrary(libraryName)==LOADED)
1724    {
1725        for(;itr.valid();++itr)
1726        {
1727            ReaderWriter::WriteResult rr = itr->writeObject(obj,fileName,options);
1728            if (rr.success()) return rr;
1729            else results.push_back(rr);
1730        }
1731    }
1732
1733    if (results.empty())
1734    {
1735        return ReaderWriter::WriteResult("Warning: Could not find plugin to write objects to file \""+fileName+"\".");
1736    }
1737
1738    if (results.front().message().empty())
1739    {
1740        switch(results.front().status())
1741        {
1742            case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): results.front().message() = "Warning: Write to \""+fileName+"\" not supported."; break;
1743            case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): results.front().message() = "Warning: Error in writing to \""+fileName+"\"."; break;
1744            default: break;
1745        }
1746    }
1747
1748    return results.front();
1749}
1750
1751
1752
1753ReaderWriter::ReadResult Registry::readImageImplementation(const std::string& fileName,const ReaderWriter::Options* options)
1754{
1755    return readImplementation(ReadImageFunctor(fileName, options),
1756                              options ? (options->getObjectCacheHint()&ReaderWriter::Options::CACHE_IMAGES)!=0: false);
1757}
1758
1759ReaderWriter::WriteResult Registry::writeImageImplementation(const Image& image,const std::string& fileName,const ReaderWriter::Options* options)
1760{
1761    // record the errors reported by readerwriters.
1762    typedef std::vector<ReaderWriter::WriteResult> Results;
1763    Results results;
1764
1765    // first attempt to load the file from existing ReaderWriter's
1766    AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
1767    for(;itr.valid();++itr)
1768    {
1769        ReaderWriter::WriteResult rr = itr->writeImage(image,fileName,options);
1770        if (rr.success()) return rr;
1771        else results.push_back(rr);
1772    }
1773
1774    results.clear();
1775
1776    // now look for a plug-in to save the file.
1777    std::string libraryName = createLibraryNameForFile(fileName);
1778    if (loadLibrary(libraryName)==LOADED)
1779    {
1780        for(;itr.valid();++itr)
1781        {
1782            ReaderWriter::WriteResult rr = itr->writeImage(image,fileName,options);
1783            if (rr.success()) return rr;
1784            else results.push_back(rr);
1785        }
1786    }
1787
1788    if (results.empty())
1789    {
1790        return ReaderWriter::WriteResult("Warning: Could not find plugin to write image to file \""+fileName+"\".");
1791    }
1792   
1793    if (results.front().message().empty())
1794    {
1795        switch(results.front().status())
1796        {
1797            case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): results.front().message() = "Warning: Write to \""+fileName+"\" not supported."; break;
1798            case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): results.front().message() = "Warning: Error in writing to \""+fileName+"\"."; break;
1799            default: break;
1800        }
1801    }
1802
1803    return results.front();
1804}
1805
1806
1807ReaderWriter::ReadResult Registry::readHeightFieldImplementation(const std::string& fileName,const ReaderWriter::Options* options)
1808{
1809    return readImplementation(ReadHeightFieldFunctor(fileName, options),
1810                              options ? (options->getObjectCacheHint()&ReaderWriter::Options::CACHE_HEIGHTFIELDS)!=0: false);
1811}
1812
1813ReaderWriter::WriteResult Registry::writeHeightFieldImplementation(const HeightField& HeightField,const std::string& fileName,const ReaderWriter::Options* options)
1814{
1815    // record the errors reported by readerwriters.
1816    typedef std::vector<ReaderWriter::WriteResult> Results;
1817    Results results;
1818
1819    // first attempt to load the file from existing ReaderWriter's
1820    AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
1821    for(;itr.valid();++itr)
1822    {
1823        ReaderWriter::WriteResult rr = itr->writeHeightField(HeightField,fileName,options);
1824        if (rr.success()) return rr;
1825        else results.push_back(rr);
1826    }
1827
1828    results.clear();
1829
1830    // now look for a plug-in to save the file.
1831    std::string libraryName = createLibraryNameForFile(fileName);
1832    if (loadLibrary(libraryName)==LOADED)
1833    {
1834        for(;itr.valid();++itr)
1835        {
1836            ReaderWriter::WriteResult rr = itr->writeHeightField(HeightField,fileName,options);
1837            if (rr.success()) return rr;
1838            else results.push_back(rr);
1839        }
1840    }
1841
1842    if (results.empty())
1843    {
1844        return ReaderWriter::WriteResult("Warning: Could not find plugin to write HeightField to file \""+fileName+"\".");
1845    }
1846
1847    if (results.front().message().empty())
1848    {
1849        switch(results.front().status())
1850        {
1851            case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): results.front().message() = "Warning: Write to \""+fileName+"\" not supported."; break;
1852            case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): results.front().message() = "Warning: Error in writing to \""+fileName+"\"."; break;
1853            default: break;
1854        }
1855    }
1856   
1857    return results.front();
1858}
1859
1860
1861ReaderWriter::ReadResult Registry::readNodeImplementation(const std::string& fileName,const ReaderWriter::Options* options)
1862{
1863#if 0
1864
1865    osg::Timer_t startTick = osg::Timer::instance()->tick();
1866    ReaderWriter::ReadResult result = readImplementation(ReadNodeFunctor(fileName, options),
1867                              options ? (options->getObjectCacheHint()&ReaderWriter::Options::CACHE_NODES)!=0: false);
1868    osg::Timer_t endTick = osg::Timer::instance()->tick();
1869    osg::notify(osg::NOTICE)<<"time to load "<<fileName<<" "<<osg::Timer::instance()->delta_m(startTick, endTick)<<"ms"<<std::endl;
1870    return result;
1871
1872#else
1873
1874    return readImplementation(ReadNodeFunctor(fileName, options),
1875                              options ? (options->getObjectCacheHint()&ReaderWriter::Options::CACHE_NODES)!=0: false);
1876                             
1877#endif
1878}
1879
1880ReaderWriter::WriteResult Registry::writeNodeImplementation(const Node& node,const std::string& fileName,const ReaderWriter::Options* options)
1881{
1882    // record the errors reported by readerwriters.
1883    typedef std::vector<ReaderWriter::WriteResult> Results;
1884    Results results;
1885
1886    // first attempt to write the file from existing ReaderWriter's
1887    AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
1888    for(;itr.valid();++itr)
1889    {
1890        ReaderWriter::WriteResult rr = itr->writeNode(node,fileName,options);
1891        if (rr.success()) return rr;
1892        else results.push_back(rr);
1893    }
1894
1895    results.clear();
1896
1897    // now look for a plug-in to save the file.
1898    std::string libraryName = createLibraryNameForFile(fileName);
1899
1900
1901    if (loadLibrary(libraryName)==LOADED)
1902    {
1903        for(;itr.valid();++itr)
1904        {
1905            ReaderWriter::WriteResult rr = itr->writeNode(node,fileName,options);
1906   
1907            if (rr.success()) return rr;
1908            else results.push_back(rr);
1909        }
1910    }
1911
1912    if (results.empty())
1913    {
1914        return ReaderWriter::WriteResult("Warning: Could not find plugin to write nodes to file \""+fileName+"\".");
1915    }
1916
1917    if (results.front().message().empty())
1918    {
1919        switch(results.front().status())
1920        {
1921            case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): results.front().message() = "Warning: Write to \""+fileName+"\" not supported."; break;
1922            case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): results.front().message() = "Warning: Error in writing to \""+fileName+"\"."; break;
1923            default: break;
1924        }
1925    }
1926
1927    return results.front();
1928}
1929
1930ReaderWriter::ReadResult Registry::readShaderImplementation(const std::string& fileName,const ReaderWriter::Options* options)
1931{
1932    return readImplementation(ReadShaderFunctor(fileName, options),
1933                              options ? (options->getObjectCacheHint()&ReaderWriter::Options::CACHE_SHADERS)!=0: false);
1934}
1935
1936ReaderWriter::WriteResult Registry::writeShaderImplementation(const Shader& shader,const std::string& fileName,const ReaderWriter::Options* options)
1937{
1938    // record the errors reported by readerwriters.
1939    typedef std::vector<ReaderWriter::WriteResult> Results;
1940    Results results;
1941
1942    // first attempt to load the file from existing ReaderWriter's
1943    AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
1944    for(;itr.valid();++itr)
1945    {
1946        ReaderWriter::WriteResult rr = itr->writeShader(shader,fileName,options);
1947        if (rr.success()) return rr;
1948        else results.push_back(rr);
1949    }
1950
1951    results.clear();
1952
1953    // now look for a plug-in to save the file.
1954    std::string libraryName = createLibraryNameForFile(fileName);
1955    if (loadLibrary(libraryName)==LOADED)
1956    {
1957        for(;itr.valid();++itr)
1958        {
1959            ReaderWriter::WriteResult rr = itr->writeShader(shader,fileName,options);
1960            if (rr.success()) return rr;
1961            else results.push_back(rr);
1962        }
1963    }
1964
1965    if (results.empty())
1966    {
1967        return ReaderWriter::WriteResult("Warning: Could not find plugin to write shader to file \""+fileName+"\".");
1968    }
1969   
1970    if (results.front().message().empty())
1971    {
1972        switch(results.front().status())
1973        {
1974            case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): results.front().message() = "Warning: Write to \""+fileName+"\" not supported."; break;
1975            case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): results.front().message() = "Warning: Error in writing to \""+fileName+"\"."; break;
1976            default: break;
1977        }
1978    }
1979
1980    return results.front();
1981}
1982
1983void Registry::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp)
1984{
1985    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
1986    _objectCache[filename]=ObjectTimeStampPair(object,timestamp);
1987}
1988osg::Object* Registry::getFromObjectCache(const std::string& fileName)
1989{
1990    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
1991    ObjectCache::iterator itr = _objectCache.find(fileName);
1992    if (itr!=_objectCache.end()) return itr->second.first.get();
1993    else return 0;
1994}
1995
1996void Registry::updateTimeStampOfObjectsInCacheWithExternalReferences(double currentTime)
1997{
1998    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
1999
2000    // look for objects with external references and update their time stamp.
2001    for(ObjectCache::iterator itr=_objectCache.begin();
2002        itr!=_objectCache.end();
2003        ++itr)
2004    {
2005        // if ref count is greater the 1 the object has an external reference.
2006        if (itr->second.first->referenceCount()>1)
2007        {
2008            // so update it time stamp.
2009            itr->second.second = currentTime;
2010        }
2011    }
2012}
2013
2014void Registry::removeExpiredObjectsInCache(double expiryTime)
2015{
2016    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
2017
2018    typedef std::vector<std::string> ObjectsToRemove;
2019    ObjectsToRemove objectsToRemove;
2020
2021    // first collect all the expired entries in the ObjectToRemove list.
2022    for(ObjectCache::iterator oitr=_objectCache.begin();
2023        oitr!=_objectCache.end();
2024        ++oitr)
2025    {
2026        if (oitr->second.second<=expiryTime)
2027        {
2028            // record the filename of the entry to use as key for deleting
2029            // afterwards/
2030            objectsToRemove.push_back(oitr->first);
2031        }
2032    }
2033   
2034    // remove the entries from the _objectCaache.
2035    for(ObjectsToRemove::iterator ritr=objectsToRemove.begin();
2036        ritr!=objectsToRemove.end();
2037        ++ritr)
2038    {
2039        // std::cout<<"Removing from Registry object cache '"<<*ritr<<"'"<<std::endl;
2040        _objectCache.erase(*ritr);
2041    }
2042       
2043}
2044
2045void Registry::clearObjectCache()
2046{
2047    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
2048    _objectCache.clear();
2049}
2050
2051void Registry::addToArchiveCache(const std::string& fileName, osgDB::Archive* archive)
2052{
2053    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_archiveCacheMutex);
2054    _archiveCache[fileName] = archive;
2055}
2056
2057/** Remove archive from cache.*/
2058void Registry::removeFromArchiveCache(const std::string& fileName)
2059{
2060    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_archiveCacheMutex);
2061    ArchiveCache::iterator itr = _archiveCache.find(fileName);
2062    if (itr!=_archiveCache.end())
2063    {
2064        _archiveCache.erase(itr);
2065    }
2066}
2067
2068osgDB::Archive* Registry::getFromArchiveCache(const std::string& fileName)
2069{
2070    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_archiveCacheMutex);
2071    ArchiveCache::iterator itr = _archiveCache.find(fileName);
2072    if (itr!=_archiveCache.end()) return itr->second.get();
2073    else return 0;
2074}
2075
2076void Registry::clearArchiveCache()
2077{
2078    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_archiveCacheMutex);
2079    _archiveCache.clear();
2080}
2081
2082void Registry::releaseGLObjects(osg::State* state)
2083{
2084    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
2085
2086    for(ObjectCache::iterator itr = _objectCache.begin();
2087        itr != _objectCache.end();
2088        ++itr)
2089    {
2090        osg::Object* object = itr->second.first.get();
2091        object->releaseGLObjects(state);
2092    }
2093}
2094
2095SharedStateManager* Registry::getOrCreateSharedStateManager()
2096{
2097    if (!_sharedStateManager) _sharedStateManager = new SharedStateManager;
2098   
2099    return _sharedStateManager.get();
2100}
2101
2102
2103void Registry::registerProtocol(const std::string& protocol)
2104
2105        _registeredProtocols.insert( convertToLowerCase(protocol) );
2106}
2107               
2108bool Registry::isProtocolRegistered(const std::string& protocol)
2109{
2110        return (_registeredProtocols.find( convertToLowerCase(protocol) ) != _registeredProtocols.end());
2111}
Note: See TracBrowser for help on using the browser.