Kaydet (Commit) f8803bd7 authored tarafından Duncan Foster's avatar Duncan Foster

#i22116# - Complete XPropertySet implementation

üst c37f4bb9
......@@ -3,9 +3,9 @@
#
# $RCSfile: build.xml,v $
#
# $Revision: 1.26 $
# $Revision: 1.27 $
#
# last change: $Author: dfoster $ $Date: 2003-11-03 16:07:05 $
# last change: $Author: dfoster $ $Date: 2003-11-04 17:45:27 $
#
# The Contents of this file are made available subject to the terms of
# either of the following licenses
......@@ -259,5 +259,5 @@
</target>
<!-- ========================= All In One Build ======================= -->
<target name="all" depends="clean,netbeans.jar,jar"/>
<target name="all" depends="clean,jar"/>
</project>
......@@ -2,9 +2,9 @@
*
* $RCSfile: ScriptContext.java,v $
*
* $Revision: 1.2 $
* $Revision: 1.3 $
*
* last change: $Author: toconnor $ $Date: 2003-10-29 15:01:13 $
* last change: $Author: dfoster $ $Date: 2003-11-04 17:45:27 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
......@@ -73,6 +73,9 @@ import com.sun.star.lang.WrappedTargetException;
import com.sun.star.lang.IllegalArgumentException;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.AnyConverter;
import com.sun.star.beans.PropertyAttribute;
import com.sun.star.lib.uno.helper.PropertySet;
import com.sun.star.uno.Type;
import java.util.HashMap;
......@@ -80,13 +83,14 @@ import drafts.com.sun.star.script.provider.XScriptContext;
import com.sun.star.script.framework.log.LogUtils;
/**
* Description of the Class
*
* @author Noel Power
* @created August 2, 2002
*/
public class ScriptContext implements XScriptContext, XPropertySet
public class ScriptContext extends PropertySet implements XScriptContext
{
/**
* Description of the Class
......@@ -98,33 +102,41 @@ public class ScriptContext implements XScriptContext, XPropertySet
public final static String HM_DOC_REF = "DocumentReference";
public final static String HM_DESKTOP = "Desktop";
public final static String HM_COMPONENT_CONTEXT = "ComponentContext";
private HashMap m_properties = new HashMap();
private final static String DOC_REF = "SCRIPTING_DOC_REF";
private final static String DOC_STORAGE_ID = "SCRIPTING_DOC_STORAGE_ID";
private final static String DOC_URI = "SCRIPTING_DOC_URI";
public XModel m_xModel = null;
public String m_sDocURI = null;
public XDesktop m_xDeskTop = null;
public Integer m_iStorageID = null;
public XComponentContext m_xComponentContext = null;
public ScriptContext( XComponentContext xmComponentContext,
XDesktop xDesktop, XPropertySet invocationCtxPropSet)
{
XModel xmDocRef = null;
this.m_xDeskTop = xDesktop;
this.m_xComponentContext = xmComponentContext;
try
{
xmDocRef = ( XModel ) UnoRuntime.queryInterface(
m_xModel = ( XModel ) UnoRuntime.queryInterface(
XModel.class,
invocationCtxPropSet.getPropertyValue( DOC_REF ) );
int iDocStorageID =
AnyConverter.toInt( invocationCtxPropSet.getPropertyValue(
DOC_STORAGE_ID ) );
String sDocUri = ( String )
m_iStorageID = new Integer ( AnyConverter.toInt( invocationCtxPropSet.getPropertyValue(
DOC_STORAGE_ID ) ) );
m_sDocURI = ( String )
invocationCtxPropSet.getPropertyValue( DOC_URI );
LogUtils.DEBUG( "DOC_REF query for URL = " + xmDocRef.getURL() );
LogUtils.DEBUG( "DOC_STORAGE_ID = " + iDocStorageID );
LogUtils.DEBUG( "DOC_URI query for URL = " + sDocUri );
LogUtils.DEBUG( "DOC_REF query for URL = " + m_xModel.getURL() );
LogUtils.DEBUG( "DOC_STORAGE_ID = " + m_iStorageID );
LogUtils.DEBUG( "DOC_URI query for URL = " + m_sDocURI );
m_properties.put( DOC_STORAGE_ID, new Integer( iDocStorageID ) );
m_properties.put( DOC_URI, sDocUri );
registerProperty( DOC_STORAGE_ID, new Type(Integer.class),
(short)(PropertyAttribute.MAYBEVOID | PropertyAttribute.TRANSIENT), "m_iStorageID");
registerProperty( DOC_URI, new Type(String.class),
(short)(PropertyAttribute.MAYBEVOID | PropertyAttribute.TRANSIENT), "m_sDocURI");
}
catch ( UnknownPropertyException upe )
{
......@@ -138,9 +150,12 @@ public class ScriptContext implements XScriptContext, XPropertySet
{
iae.printStackTrace();
}
m_properties.put( HM_DOC_REF, xmDocRef );
m_properties.put( HM_DESKTOP, xDesktop );
m_properties.put( HM_COMPONENT_CONTEXT, xmComponentContext );
registerProperty( HM_DOC_REF, new Type(XModel.class),
(short)(PropertyAttribute.MAYBEVOID | PropertyAttribute.TRANSIENT), "m_xModel");
registerProperty( HM_DESKTOP, new Type(XDesktop.class),
(short)(PropertyAttribute.MAYBEVOID | PropertyAttribute.TRANSIENT), "m_xDeskTop");
registerProperty( HM_COMPONENT_CONTEXT, new Type(XDesktop.class),
(short)(PropertyAttribute.MAYBEVOID | PropertyAttribute.TRANSIENT), "m_xComponentContext");
}
public static ScriptContext createContext(Object invocationCtx,
......@@ -177,7 +192,7 @@ public class ScriptContext implements XScriptContext, XPropertySet
*/
public XModel getDocument()
{
return ( XModel )m_properties.get( HM_DOC_REF );
return m_xModel;
}
/**
......@@ -188,7 +203,7 @@ public class ScriptContext implements XScriptContext, XPropertySet
*/
public XDesktop getDesktop()
{
return ( XDesktop )m_properties.get( HM_DESKTOP );
return m_xDeskTop;
}
/**
......@@ -199,132 +214,7 @@ public class ScriptContext implements XScriptContext, XPropertySet
*/
public XComponentContext getComponentContext()
{
return ( XComponentContext )m_properties.get( HM_COMPONENT_CONTEXT );
}
/** @returns
the <type>XPropertySetInfo</type> interface, which
describes all properties of the object which supplies this
interface.
@returns
<const>NULL</const> if the implementation cannot or will
not provide information about the properties; otherwise the
interface <type>XPropertySetInfo</type> is returned.
*/
public com.sun.star.beans.XPropertySetInfo getPropertySetInfo()
{
return null;
}
/** sets the value of the property with the specified name.
<p>If it is a bound property the value will be changed before
the change event is fired. If it is a constrained property
a vetoable event is fired before the property value can be
changed. </p>
@raises com::sun::star::beans::PropertyVetoException
if the property is read-only or vetoable
and one of the listeners throws this exception
because of an unaccepted new value.
*/
public void setPropertyValue( String aPropertyName,
java.lang.Object aValue )
throws UnknownPropertyException, PropertyVetoException,
com.sun.star.lang.IllegalArgumentException,
com.sun.star.lang.WrappedTargetException
{
throw new PropertyVetoException("No changes to ScriptContext allowed");
}
/** @returns
the value of the property with the specified name.
@param PropertyName
This parameter specifies the name of the property.
@throws UnknownPropertyException
if the property does not exist.
@throws com::sun::star::lang::WrappedTargetException
if the implementation has an internal reason for the exception.
In this case the original exception is wrapped into that
<type scope="com::sun::star::lang">WrappedTargetException</type>.
*/
public java.lang.Object getPropertyValue( String PropertyName )
throws UnknownPropertyException,
com.sun.star.lang.WrappedTargetException
{
if( !m_properties.containsKey( PropertyName ) )
{
throw new UnknownPropertyException( "No property called " + PropertyName + " in ScriptContext" );
}
return m_properties.get( PropertyName );
}
/** adds an <type>XPropertyChangeListener</type> to the specified property.
<p>An empty name ("") registers the listener to all bound
properties. If the property is not bound, the behavior is
not specified. </p>
@see removePropertyChangeListener
*/
public void addPropertyChangeListener( String aPropertyName,
XPropertyChangeListener xListener )
throws UnknownPropertyException,
com.sun.star.lang.WrappedTargetException
{
throw new RuntimeException("ScriptContext::addPropertyChangeListener not supported.");
}
/** removes an <type>XPropertyChangeListener</type> from
the listener list.
<p>It is a "noop" if the listener is not registered. </p>
@see addPropertyChangeListener
*/
public void removePropertyChangeListener( String aPropertyName,
XPropertyChangeListener aListener )
throws UnknownPropertyException,
com.sun.star.lang.WrappedTargetException
{
throw new RuntimeException("ScriptContext::removePropertyChangeListener not supported.");
}
/** adds an <type>XVetoableChangeListener</type> to the specified
property with the name PropertyName.
<p>An empty name ("") registers the listener to all
constrained properties. If the property is not constrained,
the behavior is not specified. </p>
@see removeVetoableChangeListener
*/
public void addVetoableChangeListener( String PropertyName,
XVetoableChangeListener aListener )
throws UnknownPropertyException,
com.sun.star.lang.WrappedTargetException
{
throw new RuntimeException("ScriptContext::addVetoableChangeListener not supported.");
}
/** removes an <type>XVetoableChangeListener</type> from the
listener list.
<p>It is a "noop" if the listener is not registered. </p>
@see addVetoableChangeListener
*/
public void removeVetoableChangeListener( String PropertyName,
XVetoableChangeListener aListener )
throws UnknownPropertyException,
com.sun.star.lang.WrappedTargetException
{
throw new RuntimeException("ScriptContext::removeVetoableChangeListener not supported.");
return m_xComponentContext;
}
}
......@@ -2,9 +2,9 @@
*
* $RCSfile: ScriptingContext.cxx,v $
*
* $Revision: 1.5 $
* $Revision: 1.6 $
*
* last change: $Author: dfoster $ $Date: 2002-10-23 14:13:25 $
* last change: $Author: dfoster $ $Date: 2003-11-04 17:45:28 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
......@@ -58,6 +58,8 @@
*
*
************************************************************************/
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <cppuhelper/implementationentry.hxx>
#include <cppuhelper/factory.hxx>
......@@ -69,7 +71,12 @@
using namespace com::sun::star;
using namespace com::sun::star::uno;
#define DOC_REF_PROPID 1
#define DOC_STORAGE_ID_PROPID 2
#define DOC_URI_PROPID 3
#define RESOLVED_STORAGE_ID_PROPID 4
#define SCRIPT_INFO_PROPID 5
#define SCRIPTINGCONTEXT_DEFAULT_ATTRIBS() beans::PropertyAttribute::TRANSIENT | beans::PropertyAttribute::MAYBEVOID
namespace func_provider
{
......@@ -77,7 +84,8 @@ namespace func_provider
// XScriptingContext implementation
//
//*************************************************************************
ScriptingContext::ScriptingContext( const Reference< XComponentContext > & xContext ) :
ScriptingContext::ScriptingContext( const Reference< XComponentContext > & xContext ) : //ScriptingContextImpl_BASE( GetMutex()),
OPropertyContainer( GetBroadcastHelper() ),
m_xContext( xContext )
{
OSL_TRACE( "< ScriptingContext ctor called >\n" );
......@@ -85,121 +93,55 @@ ScriptingContext::ScriptingContext( const Reference< XComponentContext > & xCont
validateXRef( m_xContext,
"ScriptingContext::ScriptingContext: No context available\n" );
//Setup internal hash map
Any nullAny;
scripting_constants::ScriptingConstantsPool& scriptingConstantsPool =
scripting_constants::ScriptingConstantsPool::instance();
m_propertyMap[ scriptingConstantsPool.DOC_REF ] = nullAny;
m_propertyMap[ scriptingConstantsPool.DOC_STORAGE_ID ] = nullAny;
m_propertyMap[ scriptingConstantsPool.DOC_URI ] = nullAny;
m_propertyMap[ scriptingConstantsPool.RESOLVED_STORAGE_ID ] = nullAny;
m_propertyMap[ scriptingConstantsPool.SCRIPT_INFO ] = nullAny;
registerPropertyNoMember( scriptingConstantsPool.DOC_REF, DOC_REF_PROPID, SCRIPTINGCONTEXT_DEFAULT_ATTRIBS(),::getCppuType( (const Reference< css::frame::XModel >* ) NULL ), NULL ) ;
registerPropertyNoMember( scriptingConstantsPool.DOC_STORAGE_ID, DOC_STORAGE_ID_PROPID, SCRIPTINGCONTEXT_DEFAULT_ATTRIBS(), ::getCppuType( (const sal_Int32* ) NULL ), NULL ) ;
registerPropertyNoMember( scriptingConstantsPool.DOC_URI, DOC_URI_PROPID, SCRIPTINGCONTEXT_DEFAULT_ATTRIBS(), ::getCppuType( (const ::rtl::OUString* ) NULL ), NULL ) ;
registerPropertyNoMember( scriptingConstantsPool.RESOLVED_STORAGE_ID, RESOLVED_STORAGE_ID_PROPID, SCRIPTINGCONTEXT_DEFAULT_ATTRIBS(), ::getCppuType( (const sal_Int32* ) NULL ), NULL );
registerPropertyNoMember( scriptingConstantsPool.SCRIPT_INFO, SCRIPT_INFO_PROPID, SCRIPTINGCONTEXT_DEFAULT_ATTRIBS(), ::getCppuType( (const sal_Int32* ) NULL ), NULL );
}
//*************************************************************************
bool ScriptingContext::validateKey( const ::rtl::OUString& key )
{
::osl::Guard< osl::Mutex > aGuard( m_mutex );
return ( m_propertyMap.find( key ) != m_propertyMap.end() );
}
//*************************************************************************
ScriptingContext::~ScriptingContext()
{
OSL_TRACE( "< ScriptingContext dtor called >\n" );
}
// -----------------------------------------------------------------------------
// OPropertySetHelper
// -----------------------------------------------------------------------------
//*************************************************************************
// XPropertySet implementation
//*************************************************************************
Reference< beans::XPropertySetInfo > SAL_CALL ScriptingContext::getPropertySetInfo( )
throw ( RuntimeException )
::cppu::IPropertyArrayHelper& ScriptingContext::getInfoHelper( )
{
return Reference< beans::XPropertySetInfo > (); // Not supported
return *getArrayHelper();
}
//*************************************************************************
void SAL_CALL ScriptingContext::setPropertyValue( const ::rtl::OUString& aPropertyName,
const Any& aValue )
throw ( beans::UnknownPropertyException, beans::PropertyVetoException,
lang::IllegalArgumentException, lang::WrappedTargetException,
RuntimeException )
{
if ( !validateKey( aPropertyName ) )
{
throw RuntimeException(
OUSTR( "ScriptingContext::setPropertyValue: invalid key" ),
Reference< XInterface >() );
}
::osl::Guard< osl::Mutex > aGuard( m_mutex );
m_propertyMap[ aPropertyName ] = aValue;
}
// -----------------------------------------------------------------------------
// OPropertyArrayUsageHelper
// -----------------------------------------------------------------------------
//*************************************************************************
Any SAL_CALL ScriptingContext::getPropertyValue( const ::rtl::OUString& PropertyName )
throw ( beans::UnknownPropertyException,
lang::WrappedTargetException, RuntimeException )
::cppu::IPropertyArrayHelper* ScriptingContext::createArrayHelper( ) const
{
if ( !validateKey( PropertyName ) )
{
throw RuntimeException(
OUSTR( "ScriptingContext::getPropertyValue: invalid key" ),
Reference< XInterface >() );
}
::osl::Guard< osl::Mutex > aGuard( m_mutex );
Any returnValue = m_propertyMap[ PropertyName ];
return returnValue;
}
//*************************************************************************
void SAL_CALL ScriptingContext::addPropertyChangeListener(
const ::rtl::OUString& aPropertyName,
const Reference< beans::XPropertyChangeListener >& xListener )
throw ( beans::UnknownPropertyException, lang::WrappedTargetException,
RuntimeException )
{
throw RuntimeException(
OUSTR( "ScriptingContext::addPropertyChangeListener: method not supported" ),
Reference< XInterface >() );
}
//*************************************************************************
void SAL_CALL ScriptingContext::removePropertyChangeListener(
const ::rtl::OUString& aPropertyName,
const Reference< beans::XPropertyChangeListener >& aListener )
throw ( beans::UnknownPropertyException, lang::WrappedTargetException,
RuntimeException )
{
throw RuntimeException(
OUSTR( "ScriptingContext::removePropertyChangeListener: method not supported" ),
Reference< XInterface >() );
Sequence< beans::Property > aProps;
describeProperties( aProps );
return new ::cppu::OPropertyArrayHelper( aProps );
}
// -----------------------------------------------------------------------------
// XPropertySet
// -----------------------------------------------------------------------------
//*************************************************************************
void SAL_CALL ScriptingContext::addVetoableChangeListener(
const ::rtl::OUString& PropertyName,
const Reference< beans::XVetoableChangeListener >& aListener )
throw ( beans::UnknownPropertyException, lang::WrappedTargetException,
RuntimeException )
Reference< beans::XPropertySetInfo > ScriptingContext::getPropertySetInfo( ) throw (RuntimeException)
{
throw RuntimeException(
OUSTR( "ScriptingContext::addVetoableChangeListener: method not supported" ),
Reference< XInterface >() );
Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
return xInfo;
}
// -----------------------------------------------------------------------------// XTypeProvider
// -----------------------------------------------------------------------------
IMPLEMENT_GET_IMPLEMENTATION_ID( ScriptingContext )
//*************************************************************************
void SAL_CALL ScriptingContext::removeVetoableChangeListener(
const ::rtl::OUString& PropertyName,
const Reference< beans::XVetoableChangeListener >& aListener )
throw ( beans::UnknownPropertyException, lang::WrappedTargetException,
RuntimeException )
css::uno::Sequence< css::uno::Type > SAL_CALL ScriptingContext::getTypes( ) throw (css::uno::RuntimeException)
{
throw RuntimeException(
OUSTR( "ScriptingContext::removeVetoableChangeListener: method not supported" ),
Reference< XInterface >() );
return OPropertyContainer::getTypes();
}
} // namespace func_provider
......@@ -2,9 +2,9 @@
*
* $RCSfile: ScriptingContext.hxx,v $
*
* $Revision: 1.4 $
* $Revision: 1.5 $
*
* last change: $Author: npower $ $Date: 2002-10-01 10:45:10 $
* last change: $Author: dfoster $ $Date: 2003-11-04 17:45:28 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
......@@ -62,82 +62,63 @@
#ifndef _FRAMEWORK_SCRIPT_PROTOCOLHANDLER_SCRIPTING_CONTEXT_HXX_
#define _FRAMEWORK_SCRIPT_PROTOCOLHANDLER_SCRIPTING_CONTEXT_HXX_
#include <hash_map>
#include <osl/mutex.hxx>
#include <rtl/ustring>
#include <cppuhelper/implbase1.hxx>
#include <comphelper/uno3.hxx>
#include <comphelper/propertycontainer.hxx>
#include <comphelper/proparrhlp.hxx>
#include <cppuhelper/implbase1.hxx>
#include <cppuhelper/weak.hxx>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/uno/RuntimeException.hpp>
#include <com/sun/star/uno/RuntimeException.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <comphelper/broadcasthelper.hxx>
namespace func_provider
{
// for simplification
#define css ::com::sun::star
#define dcsssf ::drafts::com::sun::star::script::framework
//Typedefs
//=============================================================================
typedef ::std::hash_map < ::rtl::OUString, css::uno::Any, ::rtl::OUStringHash,
::std::equal_to< ::rtl::OUString > > ScriptingConext_hash;
typedef ::std::vector< ::rtl::OUString > OUString_vec;
//typedef ::cppu::WeakImplHelper1< css::beans::XPropertySet > ScriptingContextImpl_BASE;
class ScriptingContext : public ::cppu::WeakImplHelper1< css::beans::XPropertySet >
class ScriptingContext : public ::comphelper::OMutexAndBroadcastHelper, public ::comphelper::OPropertyContainer,
public ::comphelper::OPropertyArrayUsageHelper< ScriptingContext >, public css::lang::XTypeProvider, public ::cppu::OWeakObject
{
public:
ScriptingContext( const css::uno::Reference< css::uno::XComponentContext > & xContext );
~ScriptingContext();
// XInterface
// XPropertySet implementation
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
getPropertySetInfo( )
throw ( css::uno::RuntimeException );
virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName,
const css::uno::Any& aValue )
throw ( css::beans::UnknownPropertyException,
css::beans::PropertyVetoException,
css::lang::IllegalArgumentException,
css::lang::WrappedTargetException,
css::uno::RuntimeException );
virtual css::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName )
throw ( css::beans::UnknownPropertyException,
css::lang::WrappedTargetException,
css::uno::RuntimeException );
virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName,
const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener )
throw ( css::beans::UnknownPropertyException,
css::lang::WrappedTargetException,
css::uno::RuntimeException );
virtual void SAL_CALL removePropertyChangeListener(
const ::rtl::OUString& aPropertyName,
const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener )
throw ( css::beans::UnknownPropertyException,
css::lang::WrappedTargetException,
css::uno::RuntimeException );
virtual void SAL_CALL addVetoableChangeListener(
const ::rtl::OUString& PropertyName,
const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener )
throw ( css::beans::UnknownPropertyException,
css::lang::WrappedTargetException,
css::uno::RuntimeException );
virtual void SAL_CALL removeVetoableChangeListener(
const ::rtl::OUString& PropertyName,
const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener )
throw ( css::beans::UnknownPropertyException,
css::lang::WrappedTargetException,
css::uno::RuntimeException );
css::uno::Any SAL_CALL queryInterface( const css::uno::Type& rType )
throw( css::uno::RuntimeException )
{
css::uno::Any aRet( OPropertySetHelper::queryInterface( rType ) );
return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
}
void SAL_CALL acquire() throw() { ::cppu::OWeakObject::acquire(); }
void SAL_CALL release() throw() { ::cppu::OWeakObject::release(); }
// XPropertySet
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( )
throw ( css::uno::RuntimeException );
//XTypeProvider
DECLARE_XTYPEPROVIDER( )
protected:
// OPropertySetHelper
virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper( );
// OPropertyArrayUsageHelper
virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const;
private:
// to obtain other services if needed
ScriptingConext_hash m_propertyMap;
css::uno::Reference< css::uno::XComponentContext > m_xContext;
osl::Mutex m_mutex;
// Private helper methods
bool validateKey( const ::rtl::OUString& key );
};
} // func_provider
......
......@@ -2,9 +2,9 @@
#
# $RCSfile: makefile.mk,v $
#
# $Revision: 1.2 $
# $Revision: 1.3 $
#
# last change: $Author: npower $ $Date: 2003-08-19 09:51:21 $
# last change: $Author: dfoster $ $Date: 2003-11-04 17:45:29 $
#
# The Contents of this file are made available subject to the terms of
# either of the following licenses
......@@ -87,6 +87,7 @@ SHL1IMPLIB= $(TARGET)
SHL1STDLIBS+=\
$(CPPULIB) \
$(CPPUHELPERLIB) \
$(COMPHELPERLIB) \
$(SALLIB)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment