深入FDO----异常处理机制

FDO的所有异常类都继承自FdoException,但是在FDO 3.5之前FDO只提供了9个异常类,这些异常类的类图如92所示。

深入FDO----异常处理机制

92 FDO异常类类图

92可以看到,FDO的异常类并不是非常,FDO 3.5已经注意到了这个问题,而且提供了具体的解决方案,访问http://trac.osgeo.org/fdo/wiki/FDORfc37可以这个解决方案的具体细节。主要的改进有两点:

l 提供了更多的异常类。

l 为类FdoException增加了一个方法GetNativeErrorCode()用于返回数据源自身提供的错误码,这样用户可以通过错误码知道关于当前异常更加具体的信息。

class FdoException

{

virtual FdoInt64 GetNativeErrorCode();

}

以下是一个异常的捕获及处理的例子,需要注意的在捕获异常之后要记得调用异常类的Release()方法,否则会造成异常类实例的内存泄露。

try {

...

}

catch (FdoCommandException *ex){

//处理异常消息

...

ex->Release();

}

catch (FdoException *ex){

//处理异常消息

...

ex->Release();

}

Commands功能包一般会抛出FdoConnectionException类型的异常,Connections功能包一般会抛出FdoConnectionException类型的异常。但是在在某些情况下,一个FDO命令在FDO层面抛出一个FdoException,该命令将其捕获并且把它封装为FdoCommandException(或者对于模式命令则封装为FdoSchemaException)。这种情况下,一个异常就会返回多个异常消息。以下是处理一个异常中多个消息的例子:

catch ( FdoSchemaException* ex ) {

// 通过循环得到所有模式异常消息

FdoException* currE = ex;

while ( currE ) {

FdoStringP msg = currE->GetExceptionMessage();

wprintf ("FdoConnectionException: %s\n", msg);

currE = currE->GetCause();

}

ex->Release();

}

在捕获异常后要注意防止内存泄漏,以下便是这样一个当有异常发生时及时释放内存的例子。

FdoFeatureClass* pBase = NULL;

try {

pBase = myClass->GetBaseClass();

...

}

catch ( FdoException* e ) {

...

FDO_SAFE_RELEASE(pBase);

throw;

}

catch ( ...) {

...

FDO_SAFE_RELEASE(pBase);

throw;

}

更好的办法是通过使用FdoPtr来避免内存泄露,一旦使用了FdoPtr,就无需在捕获异常后显式地调用某些方法释放内存。

FdoPtr<FdoFeatureClass> pBase = myClass->GetBaseClass();

可见合理使用FdoPtr不仅可以避免内存泄漏,也可以使代码简洁明了。

异常消息是做过本地化的。在Windows环境下,本地化的字符串存放在资源专用的dll中,它们位于bin目录下,dll的名字以MessageMsg为后缀(不是扩展名);而在Linux中本地化的字符串存放在catalog中,catalog文件位于/usr/local/fdo-3.2.0/nls目录下,其命名都以.cat结尾,NLSNational Language Support的缩写。

Linux下需设置NLSPATH环境变量以使得应用程序在运行时可以找到消息的catalog,例如:export NLSPATH=/usr/local/fdo-3.2.0/nls/%N

Windows下,无需做任何设置,应用程序可以自动加载这些资源。

异常消息是经过索引的。当调用FdoException::NLSGetMessage时,需传入一个消息号码。用户也可以传入一个默认消息字符串,一旦不能找到资源文件,将返回该默认消息。如果用户既没有指定默认消息,又不能找到资源文件,将把消息号码作为异常消息返回。找不到资源文件的情况一般只会在Linux下没有设置NLSPATH环境变量时发生。