root/OpenSceneGraph/trunk/src/osgDB/Registry.cpp @ 9884

Revision 9884, 69.2 kB (checked in by robert, 6 years ago)

From Stephan Huber,
"Attached you'll find a proposal for using different
protocols. The idea behind the new code is:

1.) plugins/apps register protocols which they can handle. This is done
via osgDB::Registry::registerProtocol(aProtocolName). Plugins register
supported protocols as usual via ReaderWriter::supportsProtocol(..), the
Registry is updated accordingly.

2.) osgDB::containsServerAddress checks first for an appearance of "://"
in the filename and then checks the protocol against the set of
registered protocols via Registry::isProtocolRegistered(aProtocollName)

3.) the other getServer*-functions changed as well, there's even a
getServerProtocol-function

With these changes filenames/Urls get routed to loaded plugins even with
different protocols than 'http'."

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