[
https://issues.apache.org/jira/browse/AXISCPP-970?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
nadir amra updated AXISCPP-970:
-------------------------------
Description:
[Introduction]:
Maybe you have known that, the axis-c-1.5final's "nillable" dealing is
completely wrong.
I found that axis-c-1.6beta has taken some improvement on this area, it's good.
But after really verify axis-c-1.6beta, I found axis-c-1.6beta seems has NOT
resolved the old nillable issue correctly.
At first, the design of "nillable" is too strange and hard-for-maintain in
axis-c-1.6beta.
The W3C's standard set default of "nillable" to "false", but axis-c-1.6beta set
it's default to "true" in related constructor.
Anyway, if axis-c-1.6beta can deal with "nillable" carefully & correctly in
inner logic, there will has no problem.
But after verify, I found that axis-c-1.6beta seems does not deal with
"nillable" correctly in case of minOccurs="0".
This problem occurred in nearly all XSD types.
The below is a sample which has been verified by me, which indicate that
axis-c-1.6beta has problem to deal with "nillable" in case of minOccurs="0".
[Error Statement]:
The below is a piece of WSDL which used by me:
... ...
<xs:element name="TestingResponse">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="testcase"
type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
... ...
I created server code by axis-c-1.6beta on this WSDL, wrote the related code
logic(demo purpose only) inside server module like the below:
xsd__string_Array * MyTesting::Testing(xsd__string Value0,xsd__string
Value1,xsd__string Value2)
{
//<mxiong debug 2006/5/19
xsd__string_Array* pIDs = new xsd__string_Array();
xsd__string* p = new xsd__string[3];
p[0] = strdup("");
p[1] = strdup("");
p[2] = strdup("2");
pIDs->set(p,3);
return pIDs;
//>mxiong debug 2006/5/19
}
I build my server module and run, ***TESTING IT BY A CLIENT APPLICATION WHICH
SPEAK THE SAME WSDL***, the response looks like this:
... ...
<TestingResponse xmlns="... ...">;
<testcase xsi:nil="true"></testcase>
<testcase xsi:nil="true"></testcase>
<testcase>2</testcase>
</TestingResponse>
... ...
You can found that the response xsi:nil="true" is wrong.(because my schema does
not allow xsi:nil="true", my schema means xsi:nil="false" indeed for it's the
default setting according to W3C's standard )
That will cause my client application to decline the response since it does not
follow contracted schema.
[My Solution]:
After analyzing and debug to axis-c-1.6beta code, I modified
soap/xsd/String.cpp, it became OK.
The correct response looks like the below:
... ...
<TestingResponse xmlns="... ...">;
<testcase></testcase>
<testcase></testcase>
<testcase>2</testcase>
</TestingResponse>
... ...
Thus my client application can accept the response correctly and succeed to
complete the whole session.
My detail modification is like the below:
String::String(const xsd__string value)
{
#ifdef ENABLE_AXISTRACE
if (axiscpp::AxisTrace::isTraceOn())
axiscpp::AxisTrace::traceEntry("String", "String", this, 1,
TRACETYPE_STRING, 0, ((void*)&value)); /* AUTOINSERTED TRACE */
#endif
//<mxiong debug 2006/5/19
// if (value)
// {
setNil(false);
serialize(value);
// }
//>mxiong debug 2006/5/19
{
#ifdef ENABLE_AXISTRACE
if (axiscpp::AxisTrace::isTraceOn())
axiscpp::AxisTrace::traceExit("String", "String", this, 0); /* AUTOINSERTED
TRACE */
#endif
return;
}
}
AxisChar* String::serialize(const xsd__string value) throw (AxisSoapException)
{
#ifdef ENABLE_AXISTRACE
if (axiscpp::AxisTrace::isTraceOn())
axiscpp::AxisTrace::traceEntry("String", "serialize", this, 1,
TRACETYPE_STRING, 0, ((void*)&value)); /* AUTOINSERTED TRACE */
#endif
MinLength* minLength= getMinLength();
//<mxiong debug 2006/5/19
unsigned int nLen = 0;
//>mxiong debug 2006/5/19
if (minLength->isSet())
{
//<mxiong debug 2006/5/19
if (NULL != value)
{
nLen = strlen(value);
}
if (nLen < (unsigned int) minLength->getMinLength())
//>mxiong debug 2006/5/19
// if (strlen(value) < (unsigned int) minLength->getMinLength())
{
AxisString exceptionMessage =
"Length of value to be serialized is shorter than MinLength
specified for this type. Minlength = ";
AxisChar* length = new AxisChar[10];
sprintf(length, "%d", minLength->getMinLength());
exceptionMessage += length;
exceptionMessage += ", Length of value = ";
sprintf(length, "%d", strlen(value));
exceptionMessage += length;
exceptionMessage += ".";
delete [] length;
throw AxisSoapException(CLIENT_SOAP_SOAP_CONTENT_ERROR,
const_cast<AxisChar*>(exceptionMessage.c_str()));
}
}
delete minLength;
MaxLength* maxLength = getMaxLength();
if (maxLength->isSet())
{
//<mxiong debug 2006/5/19
// if (strlen(value) > (unsigned int) maxLength->getMaxLength())
if (nLen > (unsigned int) maxLength->getMaxLength())
//>mxiong debug 2006/5/19
{
AxisString exceptionMessage =
"Length of value to be serialized is longer than MaxLength
specified for this type. Maxlength = ";
AxisChar* length = new AxisChar[10];
sprintf(length, "%d", maxLength->getMaxLength());
exceptionMessage += length;
exceptionMessage += ", Length of value = ";
sprintf(length, "%d", strlen(value));
exceptionMessage += length;
exceptionMessage += ".";
delete [] length;
throw AxisSoapException(CLIENT_SOAP_SOAP_CONTENT_ERROR,
const_cast<AxisChar*>(exceptionMessage.c_str()));
}
}
delete maxLength;
Length* length = getLength();
if (length->isSet())
{
//<mxiong debug 2006/5/19
if (nLen != (unsigned int) length->getLength())
//>mxiong debug 2006/5/19
// if (strlen(value) != (unsigned int) length->getLength())
{
AxisString exceptionMessage =
"Length of value to be serialized is not the same as Length
specified for this type. Length = ";
AxisChar* lengthAsString = new AxisChar[10];
sprintf(lengthAsString, "%d", length->getLength());
exceptionMessage += lengthAsString;
exceptionMessage += ", Length of value = ";
sprintf(lengthAsString, "%d", strlen(value));
exceptionMessage += lengthAsString;
exceptionMessage += ".";
delete [] lengthAsString;
throw AxisSoapException(CLIENT_SOAP_SOAP_CONTENT_ERROR,
const_cast<AxisChar*>(exceptionMessage.c_str()));
}
}
delete length;
//<mxiong debug 2006/5/19
AxisString valueAsString;
if (NULL != value)
{
valueAsString = value;
} else
{
valueAsString = "";
}
//>mxiong debug 2006/5/19
// AxisString valueAsString = value;
AxisChar* serializedValue = (AxisChar*)
replaceReservedCharacters(valueAsString).c_str();
IAnySimpleType::serialize(serializedValue);
{
#ifdef ENABLE_AXISTRACE
AxisChar* traceRet = (m_Buf);
if (axiscpp::AxisTrace::isTraceOn())
axiscpp::AxisTrace::traceExit("String", "serialize", this, 0,
TRACETYPE_STRING, 0, ((void*)&traceRet)); /* AUTOINSERTED TRACE */
return traceRet;
#else
return m_Buf;
#endif
}
}
So I think axis-c-1.6beta has bug in dealing with "nillable" for nearly all the
XSD types, especially for String type(but not only for String type, but also
other types) as my sample indicated.
[My Suggestion]
Would you like to give it a careful check to correct this problem in
axis-c-1.6beta?
My code modification may be regarded as a candicate solution for you to resolve
this problem, but I think there may has some better detail design for
axis-c-1.6beta on "nillable" area.
was:
[Introduction]:
Maybe you have known that, the axis-c-1.5final's "nillable" dealing is
completely wrong.
I found that axis-c-1.6beta has taken some improvement on this area, it's good.
But after really verify axis-c-1.6beta, I found axis-c-1.6beta seems has NOT
resolved the old nillable issue correctly.
At first, the design of "nillable" is too strange and hard-for-maintain in
axis-c-1.6beta.
The W3C's standard set default of "nillable" to "false", but axis-c-1.6beta set
it's default to "true" in related constructor.
Anyway, if axis-c-1.6beta can deal with "nillable" carefully & correctly in
inner logic, there will has no problem.
But after verify, I found that axis-c-1.6beta seems does not deal with
"nillable" correctly in case of minOccurs="0".
This problem occurred in nearly all XSD types.
The below is a sample which has been verified by me, which indicate that
axis-c-1.6beta has problem to deal with "nillable" in case of minOccurs="0".
[Error Statement]:
The below is a piece of WSDL which used by me:
... ...
<xs:element name="TestingResponse">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="testcase"
type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
... ...
When I create server code by axis-c-1.6beta on this WSDL, build it and run, the
response looks like this:
<TestingResponse xmlns="... ...">;
<testcase xsi:nil="true"></testcase>
<testcase xsi:nil="true"></testcase>
<testcase xsi:nil="true"></testcase>
</TestingResponse>
I wrote the related code logic(demo purpose only) in server module is like the
below:
xsd__string_Array * MyTesting::Testing(xsd__string Value0,xsd__string
Value1,xsd__string Value2)
{
//<mxiong debug 2006/5/19
xsd__string_Array* pIDs = new xsd__string_Array();
xsd__string* p = new xsd__string[3];
p[0] = strdup("");
p[1] = strdup("");
p[2] = strdup("");
pIDs->set(p,3);
return pIDs;
//>mxiong debug 2006/5/19
}
You can found that the response xsi:nil="true" is wrong.
That will cause my client application rejecting to accept this response for it
does not follow contracted schema.
[My Solution]:
After analyzing and debug to axis-c-1.6beta code, I modified
soap/xsd/String.cpp, it became OK.
My modification is like the below:
String::String(const xsd__string value)
{
#ifdef ENABLE_AXISTRACE
if (axiscpp::AxisTrace::isTraceOn())
axiscpp::AxisTrace::traceEntry("String", "String",
this, 1,
TRACETYPE_STRING, 0, ((void*)&value));
/* AUTOINSERTED TRACE */
#endif
//<mxiong debug 2006/5/19
// if (value)
// {
setNil(false);
serialize(value);
// }
//>mxiong debug 2006/5/19
{
#ifdef ENABLE_AXISTRACE
if (axiscpp::AxisTrace::isTraceOn())
axiscpp::AxisTrace::traceExit("String",
"String", this, 0); /* AUTOINSERTED TRACE */
#endif
return;
}
}
AxisChar* String::serialize(const xsd__string value) throw (AxisSoapException)
{
#ifdef ENABLE_AXISTRACE
if (axiscpp::AxisTrace::isTraceOn())
axiscpp::AxisTrace::traceEntry("String", "serialize",
this, 1,
TRACETYPE_STRING, 0, ((void*)&value));
/* AUTOINSERTED TRACE */
#endif
MinLength* minLength= getMinLength();
//<mxiong debug 2006/5/19
unsigned int nLen = 0;
//>mxiong debug 2006/5/19
if (minLength->isSet())
{
//<mxiong debug 2006/5/19
if (NULL != value)
{
nLen = strlen(value);
}
if (nLen < (unsigned int) minLength->getMinLength())
//>mxiong debug 2006/5/19
// if (strlen(value) < (unsigned int) minLength->getMinLength())
{
AxisString exceptionMessage =
"Length of value to be serialized is shorter than MinLength
specified for this type. Minlength = ";
AxisChar* length = new AxisChar[10];
sprintf(length, "%d", minLength->getMinLength());
exceptionMessage += length;
exceptionMessage += ", Length of value = ";
sprintf(length, "%d", strlen(value));
exceptionMessage += length;
exceptionMessage += ".";
delete [] length;
throw AxisSoapException(CLIENT_SOAP_SOAP_CONTENT_ERROR,
const_cast<AxisChar*>(exceptionMessage.c_str()));
}
}
delete minLength;
MaxLength* maxLength = getMaxLength();
if (maxLength->isSet())
{
//<mxiong debug 2006/5/19
// if (strlen(value) > (unsigned int) maxLength->getMaxLength())
if (nLen > (unsigned int) maxLength->getMaxLength())
//>mxiong debug 2006/5/19
{
AxisString exceptionMessage =
"Length of value to be serialized is longer than MaxLength
specified for this type. Maxlength = ";
AxisChar* length = new AxisChar[10];
sprintf(length, "%d", maxLength->getMaxLength());
exceptionMessage += length;
exceptionMessage += ", Length of value = ";
sprintf(length, "%d", strlen(value));
exceptionMessage += length;
exceptionMessage += ".";
delete [] length;
throw AxisSoapException(CLIENT_SOAP_SOAP_CONTENT_ERROR,
const_cast<AxisChar*>(exceptionMessage.c_str()));
}
}
delete maxLength;
Length* length = getLength();
if (length->isSet())
{
//<mxiong debug 2006/5/19
if (nLen != (unsigned int) length->getLength())
//>mxiong debug 2006/5/19
// if (strlen(value) != (unsigned int) length->getLength())
{
AxisString exceptionMessage =
"Length of value to be serialized is not the same as Length
specified for this type. Length = ";
AxisChar* lengthAsString = new AxisChar[10];
sprintf(lengthAsString, "%d", length->getLength());
exceptionMessage += lengthAsString;
exceptionMessage += ", Length of value = ";
sprintf(lengthAsString, "%d", strlen(value));
exceptionMessage += lengthAsString;
exceptionMessage += ".";
delete [] lengthAsString;
throw AxisSoapException(CLIENT_SOAP_SOAP_CONTENT_ERROR,
const_cast<AxisChar*>(exceptionMessage.c_str()));
}
}
delete length;
//<mxiong debug 2006/5/19
AxisString valueAsString;
if (NULL != value)
{
valueAsString = value;
} else
{
valueAsString = "";
}
//>mxiong debug 2006/5/19
// AxisString valueAsString = value;
AxisChar* serializedValue = (AxisChar*)
replaceReservedCharacters(valueAsString).c_str();
IAnySimpleType::serialize(serializedValue);
{
#ifdef ENABLE_AXISTRACE
AxisChar* traceRet = (m_Buf);
if (axiscpp::AxisTrace::isTraceOn())
axiscpp::AxisTrace::traceExit("String",
"serialize", this, 0,
TRACETYPE_STRING, 0,
((void*)&traceRet)); /* AUTOINSERTED TRACE */
return traceRet;
#else
return m_Buf;
#endif
}
}
So I think axis-c-1.6beta has bug in dealing with "nillable" for nearly any XSD
types, especially for String type as my sample indicated.
[Suggestion]
Would you like to give it a careful check to correct this problem in
axis-c-1.6beta?
My modification may be regarded as a candicate solution for you to resolve this
problem, but I wish maybe a better detail design for axis-c-1.6beta on
"nillable" area may be better.
> axis-c engine: nillable problem: when minOccurs="0" and nillable="false", the
> serailization does NOT follow W3C schema standard
> -------------------------------------------------------------------------------------------------------------------------------
>
> Key: AXISCPP-970
> URL: https://issues.apache.org/jira/browse/AXISCPP-970
> Project: Axis-C++
> Issue Type: Bug
> Components: Serialization, Server - Apache module, Server - Engine,
> SOAP, XSD Types
> Affects Versions: 1.6 Beta
> Environment: Platform:
> Linux fedora 3.0
> Axis version:
> Server-side Axis C++ 1.6Beta
> XML Parser Lib:
> xersesc 2.6
> WSDL2ws tool by using axis java 1.3
> Client-side version Axis java 1.3
> Http Server Version:
> Apache 2.0.53
> Tomcat 2.0.58
> Reporter: Michael Xiong
> Priority: Critical
>
> [Introduction]:
> Maybe you have known that, the axis-c-1.5final's "nillable" dealing is
> completely wrong.
> I found that axis-c-1.6beta has taken some improvement on this area, it's
> good.
> But after really verify axis-c-1.6beta, I found axis-c-1.6beta seems has NOT
> resolved the old nillable issue correctly.
> At first, the design of "nillable" is too strange and hard-for-maintain in
> axis-c-1.6beta.
> The W3C's standard set default of "nillable" to "false", but axis-c-1.6beta
> set it's default to "true" in related constructor.
> Anyway, if axis-c-1.6beta can deal with "nillable" carefully & correctly in
> inner logic, there will has no problem.
> But after verify, I found that axis-c-1.6beta seems does not deal with
> "nillable" correctly in case of minOccurs="0".
> This problem occurred in nearly all XSD types.
> The below is a sample which has been verified by me, which indicate that
> axis-c-1.6beta has problem to deal with "nillable" in case of minOccurs="0".
> [Error Statement]:
> The below is a piece of WSDL which used by me:
> ... ...
> <xs:element name="TestingResponse">
> <xs:complexType>
> <xs:sequence>
> <xs:element minOccurs="0" maxOccurs="unbounded" name="testcase"
> type="xs:string"/>
> </xs:sequence>
> </xs:complexType>
> </xs:element>
> ... ...
> I created server code by axis-c-1.6beta on this WSDL, wrote the related code
> logic(demo purpose only) inside server module like the below:
> xsd__string_Array * MyTesting::Testing(xsd__string Value0,xsd__string
> Value1,xsd__string Value2)
> {
> //<mxiong debug 2006/5/19
> xsd__string_Array* pIDs = new xsd__string_Array();
> xsd__string* p = new xsd__string[3];
> p[0] = strdup("");
> p[1] = strdup("");
> p[2] = strdup("2");
> pIDs->set(p,3);
> return pIDs;
> //>mxiong debug 2006/5/19
> }
> I build my server module and run, ***TESTING IT BY A CLIENT APPLICATION WHICH
> SPEAK THE SAME WSDL***, the response looks like this:
> ... ...
> <TestingResponse xmlns="... ...">;
> <testcase xsi:nil="true"></testcase>
> <testcase xsi:nil="true"></testcase>
> <testcase>2</testcase>
> </TestingResponse>
> ... ...
> You can found that the response xsi:nil="true" is wrong.(because my schema
> does not allow xsi:nil="true", my schema means xsi:nil="false" indeed for
> it's the default setting according to W3C's standard )
> That will cause my client application to decline the response since it does
> not follow contracted schema.
> [My Solution]:
> After analyzing and debug to axis-c-1.6beta code, I modified
> soap/xsd/String.cpp, it became OK.
> The correct response looks like the below:
> ... ...
> <TestingResponse xmlns="... ...">;
> <testcase></testcase>
> <testcase></testcase>
> <testcase>2</testcase>
> </TestingResponse>
> ... ...
> Thus my client application can accept the response correctly and succeed to
> complete the whole session.
> My detail modification is like the below:
> String::String(const xsd__string value)
> {
> #ifdef ENABLE_AXISTRACE
> if (axiscpp::AxisTrace::isTraceOn())
> axiscpp::AxisTrace::traceEntry("String", "String", this, 1,
> TRACETYPE_STRING, 0, ((void*)&value)); /* AUTOINSERTED TRACE */
> #endif
> //<mxiong debug 2006/5/19
> // if (value)
> // {
> setNil(false);
> serialize(value);
> // }
> //>mxiong debug 2006/5/19
> {
> #ifdef ENABLE_AXISTRACE
> if (axiscpp::AxisTrace::isTraceOn())
> axiscpp::AxisTrace::traceExit("String", "String", this, 0); /* AUTOINSERTED
> TRACE */
> #endif
> return;
> }
> }
> AxisChar* String::serialize(const xsd__string value) throw (AxisSoapException)
> {
> #ifdef ENABLE_AXISTRACE
> if (axiscpp::AxisTrace::isTraceOn())
> axiscpp::AxisTrace::traceEntry("String", "serialize", this, 1,
> TRACETYPE_STRING, 0, ((void*)&value)); /* AUTOINSERTED TRACE */
> #endif
> MinLength* minLength= getMinLength();
> //<mxiong debug 2006/5/19
> unsigned int nLen = 0;
> //>mxiong debug 2006/5/19
> if (minLength->isSet())
> {
> //<mxiong debug 2006/5/19
> if (NULL != value)
> {
> nLen = strlen(value);
> }
> if (nLen < (unsigned int) minLength->getMinLength())
> //>mxiong debug 2006/5/19
> // if (strlen(value) < (unsigned int) minLength->getMinLength())
> {
> AxisString exceptionMessage =
> "Length of value to be serialized is shorter than MinLength
> specified for this type. Minlength = ";
> AxisChar* length = new AxisChar[10];
> sprintf(length, "%d", minLength->getMinLength());
> exceptionMessage += length;
> exceptionMessage += ", Length of value = ";
> sprintf(length, "%d", strlen(value));
> exceptionMessage += length;
> exceptionMessage += ".";
> delete [] length;
>
> throw AxisSoapException(CLIENT_SOAP_SOAP_CONTENT_ERROR,
> const_cast<AxisChar*>(exceptionMessage.c_str()));
> }
> }
> delete minLength;
>
> MaxLength* maxLength = getMaxLength();
> if (maxLength->isSet())
> {
> //<mxiong debug 2006/5/19
> // if (strlen(value) > (unsigned int) maxLength->getMaxLength())
> if (nLen > (unsigned int) maxLength->getMaxLength())
> //>mxiong debug 2006/5/19
> {
> AxisString exceptionMessage =
> "Length of value to be serialized is longer than MaxLength
> specified for this type. Maxlength = ";
> AxisChar* length = new AxisChar[10];
> sprintf(length, "%d", maxLength->getMaxLength());
> exceptionMessage += length;
> exceptionMessage += ", Length of value = ";
> sprintf(length, "%d", strlen(value));
> exceptionMessage += length;
> exceptionMessage += ".";
> delete [] length;
>
> throw AxisSoapException(CLIENT_SOAP_SOAP_CONTENT_ERROR,
> const_cast<AxisChar*>(exceptionMessage.c_str()));
> }
> }
> delete maxLength;
> Length* length = getLength();
> if (length->isSet())
> {
> //<mxiong debug 2006/5/19
> if (nLen != (unsigned int) length->getLength())
> //>mxiong debug 2006/5/19
> // if (strlen(value) != (unsigned int) length->getLength())
> {
> AxisString exceptionMessage =
> "Length of value to be serialized is not the same as Length
> specified for this type. Length = ";
> AxisChar* lengthAsString = new AxisChar[10];
> sprintf(lengthAsString, "%d", length->getLength());
> exceptionMessage += lengthAsString;
> exceptionMessage += ", Length of value = ";
> sprintf(lengthAsString, "%d", strlen(value));
> exceptionMessage += lengthAsString;
> exceptionMessage += ".";
> delete [] lengthAsString;
>
> throw AxisSoapException(CLIENT_SOAP_SOAP_CONTENT_ERROR,
> const_cast<AxisChar*>(exceptionMessage.c_str()));
> }
> }
> delete length;
> //<mxiong debug 2006/5/19
> AxisString valueAsString;
> if (NULL != value)
> {
> valueAsString = value;
> } else
> {
> valueAsString = "";
> }
> //>mxiong debug 2006/5/19
> // AxisString valueAsString = value;
> AxisChar* serializedValue = (AxisChar*)
> replaceReservedCharacters(valueAsString).c_str();
> IAnySimpleType::serialize(serializedValue);
> {
> #ifdef ENABLE_AXISTRACE
> AxisChar* traceRet = (m_Buf);
> if (axiscpp::AxisTrace::isTraceOn())
> axiscpp::AxisTrace::traceExit("String", "serialize", this, 0,
> TRACETYPE_STRING, 0, ((void*)&traceRet)); /* AUTOINSERTED TRACE */
> return traceRet;
> #else
> return m_Buf;
> #endif
> }
> }
> So I think axis-c-1.6beta has bug in dealing with "nillable" for nearly all
> the XSD types, especially for String type(but not only for String type, but
> also other types) as my sample indicated.
> [My Suggestion]
> Would you like to give it a careful check to correct this problem in
> axis-c-1.6beta?
> My code modification may be regarded as a candicate solution for you to
> resolve this problem, but I think there may has some better detail design for
> axis-c-1.6beta on "nillable" area.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]