BundleMetadata const& BundleLoader::loadLibrary( string const& path )
	{
		if ( isLibraryLoaded( path ) )
		{
			BundleInfoConstIterator it = m_LoadedBundles.find( path );
			return it->second.metainfo->getBundleData();
		}

		typedef void ( *MetainfoFunc )( bundle::BundleMetainfo &info );

		Poco::SharedLibrary *lib;
		try
		{
			lib = new Poco::SharedLibrary( path );
		}
		catch ( Poco::Exception &e )
		{
			ostringstream msg;
			msg << e.what() << " " << e.message() << " lib could not be loaded";
			throw NotFoundException( msg.str() );
		}

		Metainfo *info = new Metainfo();

		if ( lib->hasSymbol( "getBundleMetainfo" ) )
		{
			try
			{
				BundleInfo bundleInfo;
				MetainfoFunc func = ( MetainfoFunc ) lib->getSymbol( "getBundleMetainfo" );

				bundle::BundleMetainfo metainfo( *info );
				func( metainfo );
				bundleInfo.library = lib;
				bundleInfo.metainfo = info;

				bundleInfo.metainfo->setInstallDirectory( path );
				bundleInfo.metainfo->cleanup();

				m_LoadedBundles.insert( make_pair( path, bundleInfo ) );
			}
			catch ( Exception &e )
			{
				delete lib;
				delete info;
				throw e;
			}
			BundleMetadata const& meta = info->getBundleData();
			if ( meta.getName() == "undefined" )
			{
				ostringstream msg;
				msg << "bundle " << meta.getInstallDirectory() << " does not define a name";
				throw NotFoundException( msg.str() );
			}

			return meta;
		}
		else
		{
			delete lib;
			delete info;

			ostringstream msg;
			msg << "shared library " << path << " does not contain metadata";
			throw NotFoundException( msg.str() );
		}
	}