7 Extending Functionality

An extension class can be loaded by the Oracle Entitlements Server runtime environment to enhance core functionality. Extensions are bundled as Java Archive (JAR) files. This chapter contains the following sections on extensions that can be created.

7.1 Working With Attribute Retrievers

The Policy Information Point (PIP) is a system entity that acts as a source for attribute values. During runtime evaluation of a policy, Oracle Entitlements Server relies on an Attribute Retriever plug-in to get attribute values from one or more PIP information stores. These Attribute Retrievers allow policies to be data-driven in that the value of the attribute can impact the access decision. For example, if access to transfer money from a bank account is based on how much money is currently in the account, an Attribute Retriever can be used to get a value for the current balance. This infrastructure is highly extensible, allowing users to develop their own PIP plug-ins to retrieve information from many places - for example, from a file, a USB driver, or the internet.

The following sections have more information.

7.1.1 Understanding Attribute Retrievers

Oracle Entitlements Server uses predefined Attribute Retrievers to connect to Lightweight Directory Access Protocol (LDAP) data stores and relational database management systems (RDBMS). Custom Attribute Retrievers can be developed to get attribute values from other types of PIP data stores. A custom Attribute Retrievers can return values for one or many attributes.

Configuration information for Attribute Retrievers is defined in the jps-config.xml configuration file. Configuration of the Attribute Retriever within this file is dependent on whether it is predefined or custom.

  • For predefined Attribute Retrievers:

    • Configure information needed to connect to the data store as well as credential information.

    • Configure individual attribute values including attribute name, name of Attribute Retriever used, search query to retrieve the value (for example, SQL query if the PIP is a relational database or LDAP query if it's a directory), and any attribute value caching information).

    For detailed information on configuring predefined Attribute Retrievers, see the Oracle Fusion Middleware Administrator's Guide for Oracle Entitlements Server.

  • For custom Attribute Retrievers, configure information regarding the name of the class implementing the Attribute Retriever.

A given Attribute Retriever can return a single value or multiple values attribute.

Note:

See the Oracle Fusion Middleware Application Security Guide for more information on the jps-config.xml configuration file. Parameters specific to Oracle Entitlements Server are documented in the Oracle Fusion Middleware Administrator's Guide for Oracle Entitlements Server.

7.1.2 Creating Custom Attribute Retrievers

As described in Section 1.3.3, "Adding a Condition," a policy Condition is built using attributes or functions. If a dynamic attribute is used in a Condition, the attribute value can be passed in from the com.bea.security.AppContext interface or retrieved with either a predefined or custom Attribute Retriever. The following procedure documents the steps to create a custom Attribute Retriever.

  1. Implement the custom Attribute Retriever using the com.bea.security.providers.authorization.asi.AttributeRetrieverV2 interface.

    See Section 7.1.3, "Implementing Custom Attribute Retrievers" for more information.

  2. Create a JAR file.

  3. Add the JAR file to the appropriate classpath.

    • If connecting to a Java Security Module, add the JAR file to the application classpath.

    • If connecting to an RMI, Web Services or WebLogic Server Security Module, add the JAR file to the system classpath with the rest of the Security Module JAR files.

    It does not matter where the JAR is physically stored.

  4. Configure the Security Module to use the custom Attribute Retriever.

    Make sure the configuration specifies the fully-qualified location of the custom Attribute Retriever. For more information, see Oracle Fusion Middleware Administrator's Guide for Oracle Entitlements Server.

7.1.3 Implementing Custom Attribute Retrievers

A custom Attribute Retriever must implement the AttributeRetrieverV2 interface. Table 7-1 explains the methods available for this purpose.

Table 7-1 Methods in AttributeRetrieverV2 Interface

Method Description

getAttributeValue()

This method is called every time the value of a particular attribute is required. It returns the value of the named attribute and takes the following parameters:

  • Name defines the name of the attribute being retrieved.

  • RequestHandle is the interface that will retrieve values of other attributes (if required). It also allows the sharing of context – an arbitrary Object - between different attribute retrievers or custom functions.

  • Subject defines the user associated with the request.

  • Roles defines any role membership of the subject, or null if this is a role mapping call.

  • Resource defines the protected resource associated with the request.

  • contextHandler is the context associated with the request; this may be null if non-existent.

getHandledAttributeNames()

This method is called once, usually during loading of the attribute retriever. The method returns the list of attribute names for which the attribute retriever can return values.


In the simplest use case, an Attribute Retriever does not need additional information to get the value. For example, to get the time of day, getAttributeValue() calls a system function and returns the information. Another use case might find the Attribute Retriever needs additional information before it can return an attribute value. For example, the Attribute Retriever would have to know the user's identifier in order to get the location of the user. For this purpose, the Attribute Retriever is provided a RequestHandle interface to get the values for other attributes. In this example, the attribute retriever can use the RequestHandle interface to get the value of the built-in SYS_USER attribute which resolves to the identity of the current user.

Note:

Names of system attributes must be placed between percentage (%) signs as in %sys_user%.

The following sections contain more information on the attribute retrieval options.

7.1.3.1 Getting Attribute Values Directly

An implementation of AttributeRetrieverV2 can use the getAttributeValue() method to return the value of a named attribute. This method takes as input the name of the attribute whose value will be returned. Example 7-1 illustrates how getAttributeValue() might be used.

Example 7-1 Implementing getAttributeValue() Method

package oracle.security.oes.test;
 
import java.util.Map;
 
import javax.security.auth.Subject;
 
import weblogic.security.service.ContextHandler;
import weblogic.security.spi.Resource;
 
import com.bea.security.providers.authorization.asi.AttributeRetrieverV2;
import com.bea.security.providers.authorization.asi.ARME.evaluator.RequestHandle;
 
public class SimpleAttributeRetriever implements AttributeRetrieverV2 {
 
    public Object getAttributeValue(String name, RequestHandle requestHandle,
         Subject subject, Map roles, Resource resource, 
         ContextHandler contextHandler) {
       if (name == null) return null;
       return "static_value";
    }
 
    public String[] getHandledAttributeNames() {
       return new String[] {"static_attr"};
    }
 
}

MyAttributeRetrieverV2 is the implementation of AttributeRetrieverV2. The getHandledAttributeNames() method returns the names of attributes handled by this implementation. It may return at least one attribute name; an empty or null value indicates that the retriever will be called for any attribute. The values of the getAttributeValue() parameters are defined as:

  • name is the name of the attribute being retrieved.

  • requestHandle is the implementation of the interface that allows you to retrieve values of other attributes (if required). It also allows the sharing of context – an arbitrary Object - between different attribute retrievers or custom functions. It is passed to the function even if it is not used.

  • subject is the principal associated with the request.

  • roles defines the role membership of the associated principal. The object is a map where the key signifies the role name and the value is the role object.

  • resource is the protected resource associated with the request.

  • contextHandler defines the context associated with the request. It may be null if the context is non-existent.

7.1.3.2 Getting Attribute Values Using a Handle

In some cases, the Attribute Retriever might need to get an attribute for information before retrieving the attribute value it wants. For example, in order to get the location of a user, the attribute retriever would need the identifier of the user. By invoking the getAttribute() method in the RequestHandle interface, the Attribute Retriever is able to get the identifier and with it access to all of the user's information. The getAttribute() method returns the attribute name and value as a name-value pair in an AttributeElement object.

RequestHandle is the interface that allows you to retrieve values of other attributes if required. It also allows to share context – arbitrary Object - between different invocation of Attribute Retrievers and/or custom functions

Note:

The getAttribute() method is used to retrieve values for user and resource attributes. It should not be used to get values for dynamic or extension attributes.

Example 7-2 illustrates how getAttribute() might be used.

Example 7-2 Using getAttribute() Method

public Object getAttributeValue
   (String name, RequestHandle requestHandle, Subject subject, 
    Map roles, Resource resource, ContextHandler contextHandler) {

... ...
 
// retrieve sys_user built-in attribute 
   String user = null;
   try {
      AttributeElement element = requestHandle.getAttribute("sys_user", true);
          if (element != null) {
              user = (String)element.getValueAs(String.class);
            }
   } catch (Exception e) {
// ignore it
     }

... ...
}

The values of the getAttribute() parameters are defined as:

  • sys_user is the name of the attribute being retrieved.

  • true enables the attribute type check functionality. The value may be false to disable the type check.

7.1.4 Configuring Oracle Entitlements Server for Custom Attribute Retrievers

This section contains the procedure on how to configure Oracle Entitlements Server to recognize a custom attribute retriever. After implementing com.bea.security.providers.authorization.asi.AttributeRetrieverV2 (as discussed in Section 7.1.3, "Implementing Custom Attribute Retrievers"), compile the Java code, add the compiled class to the class path of the Security Module instance, and make the following changes to the jps-config.xml configuration file.

  1. Declare the PIP service provider in the <serviceProviders> section as illustrated in Example 7-3.

    Example 7-3 serviceProviders Section of jps-config.xml

    <serviceProviders>
       <serviceProvider 
          class="oracle.security.jps.az.internal.runtime.provider.
             PIPServiceProvider" name="pip.service.provider" type="PIP"/>
    </serviceProviders>
    
  2. Declare the PIP service instance in the <serviceInstances> section as illustrated in Example 7-4.

    Example 7-4 serviceProviders Section of jps-config.xml

    <serviceInstances>
       <serviceInstance name="pip.service.MyAttributeRetriever"
        provider="pip.service.provider">
          <property name="type" value="CUSTOM_PIP"/>
          <property name="application" value="testPIPBasedOnCustomPIP"/>
          <property name="description" value="MyAttributeRetriever"/>
          <property name="classnames" value="pips.MyDummyAttributeRetriever"/>
      </serviceInstance>
    </serviceInstances>
    

    Specify the properties as defined in the following table.

    Name Value
    Type The value should be CUSTOM_PIP
    Application The application in which the PIP instance takes effect
    Classnames The fully qualified class name of the custom PIP

  3. Declare the PIP service instance in the <jpsContext> section as illustrated in Example 7-5.

    Example 7-5 jpsContext Section of jps-config.xml

    <jpsContext name="default">
       <serviceInstanceRef ref="pip.service.MyAttributeRetriever"/>
    </jpsContext>
    

7.2 Developing Custom Functions

A function can be used in a policy Condition to perform some advanced operation. The function may have a number of parameters and can return any of the supported data types. Oracle Entitlements Server provides a number of predefined functions and, additionally, allows you to declare your own.

7.2.1 Implementing a Custom Function

The following procedure details the steps to take when implementing a custom function in your policy.

  1. Write the custom code for the function. See Example 7-6.

  2. Compile the Java code and create a jar file.Add the complied class to the class path.

  3. Restart the servers.

7.2.1.1 Step 1 Write the Custom Code

A custom function can be implemented as a method in a class that may contain one or more custom functions. You can choose any method name as long as the name matches the corresponding name referenced in the policy. Custom functions can be passed as arguments consisting of constants or names of other attributes (including dynamic attributes) or names of other functions. Since all evaluation functions share a common namespace, two functions cannot have the same name.

Example 7-6 illustrates how you might create a custom function.

Example 7-6 Sample Java Pseudo Code for a Custom Function

//Package declaration
package oracle.security.oes.extensions;
 
import java.util.Map;
 
 
import javax.security.auth.Subject;
 
import weblogic.security.service.ContextHandler;
import weblogic.security.spi.Resource;
 
import com.bea.security.providers.authorization.asi.ARME.evaluator.RequestHandle;
import com.wles.util.AttributeElement;
 
public class MyCustomFunction {
    
    /** 
     Named evaluation function. Additional authorization request data
     is made available to allow for more complex attribute evaluation.
     This method will be registered to an application and be invoked while 
     the policy contains a custom evaluation function with the name 
     "my_custom_function".
 
     @param requestHandle  an attributes container associated with the request, 
                           through which the function can get required attribute
                           value.
 
     @param args           an array of function arguments. Each element is either
                           <code>null</code> or a String
 
     @param subject        the subject associated with the request
 
     @param roles          the role membership map of the subject
                           key: role name.
                           value: role object <code>null</code> if function 
                           is called during role mapping
 
     @param resource       the resource associated with the request
 
     @param contextHandler the context associated with the request, may be
                           <code>null</code> if non-existent
 
     @return <Return_data_type> as the result of the function
 
     @throws Exception if the function cannot get required attribute value.
     */
    
public <Return_data_type> my_custom_function(RequestHandle requestHandle,
            Object[] args,
            Subject subject,
            Map roles,
            Resource resource,
            ContextHandler contextHandler) {
 
        // Check if we have a correct number of the input paramters
        if(args.length < <required_number_of_attributes> ||
                args[0] == null || args[1] == null) {
            // Incorrect number of arguments.
            // Such a policy is invalid and cannot be evaluated
               throw new RuntimeException
               ("Incorrect number of arguments provided to the function");
        }
 
        // Arguments for an evaluation function are attribute names.
        // If a string literal or a numeric value is used, then
        // it is passed in as value.  The only way to distinguish
        // values from names is to try to look up the attribute.
        // Evaluation function should not set any values.
        try {
 
              //The body of the custom function.
              //It should return the value of the type specified in the method
              //signature. 
                    
            } catch(Exception e) {
            
               //Catch the exception and throw with error message
               throw new RuntimeException(
                    "Detailed error message ...." + " Exception: " + e.getMessage());
        }
        
        return <return_data_type_value>;
    }
    
}

7.2.1.2 Step 2. Compile the Source Code and Include the Class in a JAR File

To compile the source code:

  1. Set JAVA_HOME and PATH based on your JVM location.

  2. Set your Classpath to include the OES jar file to be included in the compilation.

  3. Compile the code and create a JAR file called custom_funcs.jar.

7.2.1.3 Step 3. Add the Jar File to CLASSPATH of WebLogic Domain on which the Application is Deployed

To add a JAR file to the classpath:

  1. Make a copy of setDomainEnv.sh file.

  2. Add the Jar file to POST_CLASSPATH.

    POST_CLASSPATH="${POST_CLASSPATH}${CLASSPATHSEP}${ORACLE_HOME}/dist/custom_funcs.jar"export POST_CLASSPATH
    

7.2.1.4 Step 4. Restart the Servers

Restart the servers.

7.2.2 Using InspectableFunction For Metadata Information

An argument metadata interface is used to query for information about the arguments expected by a custom Oracle Entitlements Server function. (This includes information such as the number of arguments and their names and types.) Optionally, the InspectableFunction interface can be implemented for these argument queries. When adding a custom function based on this interface, the Administration Console calls the getArgMetadata method to return metadata describing the arguments, and verify the metadata that is expected by the custom function.

For each argument expected by the function starting with the first (argument 0), getArgMetadata must return metadata describing the argument. Once the Administration Console collects the metadata about each expected argument, it uses the interface methods getArgValue and isValidArgValue to automate the process of working with custom Oracle Entitlements Server functions.

  • Example 7-7 illustrates sample code for the getArgMetadata(String functionName) method.

  • Example 7-8 illustrates sample code for the getArgValues (String functionName, int argNumber, ArrayList<oracle.security.jps.service.policystore.info.DataType> prevArgValues) method.

  • Example 7-9 illustrates sample code for the isValidArgValue (String functionName, int argNumber, oracle.security.jps.service.policystore.info.DataType argValue, ArrayList<oracle.security.jps.service.policystore.info.DataType> prevArgValues) method.

Example 7-7 Sample Code for getArgMetadata() Method

package InspectableFunctionSample;
 
import com.bea.security.providers.authorization.asi.ARME.evaluator.RequestHandle;
import com.bea.security.providers.authorization.asi.InspectableFunction;
import java.io.PrintStream;
import java.util.*;
import javax.security.auth.Subject;
import oracle.security.jps.service.policystore.info.*;
import weblogic.security.service.ContextHandler;
import weblogic.security.spi.Resource;
 
/**
Custom OES function to validate an address. The number indicates the order used to emulate display and selection process.
arg[0]: country, arg[1]: city, arg[2]: street, arg[3]: house number, arg[4]: mailbox
entering previous values will help to provide options for late values
*/

public class Address
    implements InspectableFunction
{
 
    public Address()
    {
    }
 
    public boolean validateAddress(RequestHandle requestHandle, Object args[], 
     Subject subject, Map roles, Resource resource, ContextHandler contextHandler)
        throws RuntimeException
    {
        if(args.length != 5 || args[0] == null || args[1] == null || args[2] == null ||
         args[3] == null || args[4] == null)
        {
            throw new RuntimeException("Incorrect number of arguments in a function");
        } else
        {
            String country = args[0].toString();
            String city = args[1].toString();
            String street = args[2].toString();
            int house = Integer.parseInt(args[3].toString());
            boolean mailbox = Boolean.parseBoolean(args[4].toString());
            boolean result = country.compareToIgnoreCase("USA") == 0 &&
              city.compareToIgnoreCase("Boston") == 0 && street.compareToIgnoreCase
              ("Beacon Str") == 
                0 && house == 10 && mailbox;
            System.out.println((new StringBuilder()).append("Result =
             '").append(result).append("' for arguments Country =
             '").append(country).append("', City =
             '").append(city).append("', street = '").append(street).append
                ("', house
             '").append(house).append("', mailbox
             '").append(mailbox).append("'").toString());
            return result;
        }
    }
 
    public ArrayList getArgMetadata(String functionName)
    {
        if(functionName.compareToIgnoreCase("validateAddress") == 0)
        {
            ArrayList metdata = new ArrayList();
            metdata.add(new com.bea.security.providers.authorization.asi.InspectableFunction.ArgMetadata
  (0, "Country",
 OpssString.class, false, true, true));
            metdata.add(new
 com.bea.security.providers.authorization.asi.InspectableFunction.ArgMetadata(1, "City",
 OpssString.class, false, true, true));
            metdata.add(new com.bea.security.providers.authorization.asi.InspectableFunction.ArgMetadata(2, "Street",
 OpssString.class, false, true, true));
            metdata.add(new
 com.bea.security.providers.authorization.asi.InspectableFunction.ArgMetadata(3, "House",
 OpssInteger.class, true, false, false));
            metdata.add(new
 com.bea.security.providers.authorization.asi.InspectableFunction.ArgMetadata(4,
  "Mailbox",
 OpssBoolean.class, false, true, false));
            return metdata;
        } else
        {
            throw new RuntimeException("Invalid function name");
        }
    }
 
    public ArrayList getArgValues(String functionName, int argNumber, ArrayList
     prevArgValues)
        throws RuntimeException
    {
        ArrayList values = new ArrayList();
        if(functionName.compareToIgnoreCase("validateAddress") == 0)
        {
            if(argNumber == 0)
            {
                values.add(new OpssString("USA"));
                values.add(new OpssString("Canada"));
            } else
            if(argNumber == 1)
            {
                if(((DataType)prevArgValues.get(0)).toString().compareToIgnoreCase("USA") 
                 == 0)
                {
                    values.add(new OpssString("Boston"));
                    values.add(new OpssString("San Francisco"));
                } else
                if(((DataType)prevArgValues.get(0)).toString().compareToIgnoreCase("Canada")
                 == 0)
                {
                    values.add(new OpssString("Montreal"));
                    values.add(new OpssString("Toronto"));
                } else
                {
                    throw new RuntimeException("Invalid argument value");
                }
            } else
            if(argNumber == 2)
            {
                if(((DataType)prevArgValues.get(0)).toString().compareToIgnoreCase("USA") 
                 == 0)
                {
                    if(((DataType)prevArgValues.get(1)).toString().compareToIgnoreCase("Boston") == 0)
                    {
                        values.add(new OpssString("Beacon Str"));
                        values.add(new OpssString("Boylston Str"));
                    } else
                    if(((DataType)prevArgValues.get(1)).toString().compareToIgnoreCase
                     ("San Francisco") == 0)
                    {
                        values.add(new OpssString("Van Ness Str"));
                        values.add(new OpssString("Market Str"));
                    } else
                    {
                        throw new RuntimeException("Invalid USA city");
                    }
                } else
                if(((DataType)prevArgValues.get(0)).toString().compareToIgnoreCase("Canada")
                 == 0)
                {
                    if(((DataType)prevArgValues.get(1)).toString().compareToIgnoreCase("Montreal") == 0)
                    {
                        values.add(new OpssString("St. Laurent Str"));
                        values.add(new OpssString("St. Catherine Str"));
                    } else
                    if(((DataType)prevArgValues.get(1)).toString().compareToIgnoreCase("Toronto") == 0)
                    {
                        values.add(new OpssString("Queen Str"));
                        values.add(new OpssString("King Str"));
                    } else
                    {
                        throw new RuntimeException("Invalid Canada city");
                    }
                } else
                {
                    throw new RuntimeException("Invalid country");
                }
            } else
            if(argNumber == 3)
            {
                values.add(new OpssInteger(10));
                values.add(new OpssInteger(15));
            } else
            if(argNumber == 4)
            {
                values.add(new OpssBoolean(true));
                values.add(new OpssBoolean(false));
            } else
            {
                throw new RuntimeException("Invalid argument number");
            }
        } else
        {
            throw new RuntimeException("Invalid function name");
        }
        return values;
    }
 
    public boolean isValidArgValue(String functionName, int argNumber, DataType argValue,
     ArrayList prevArgValues)
        throws RuntimeException
    {
        if(functionName.compareToIgnoreCase("validateAddress") == 0)
        {
            if(argNumber == 0 && argValue.getClass() ==
             OpssString.class)
                return argValue.toString().compareToIgnoreCase("USA") == 0 ||
                 argValue.toString().compareToIgnoreCase("Canada") == 0;
            if(argNumber == 1 && argValue.getClass() == 
             OpssString.class)
            {
                if(((DataType)prevArgValues.get(0)).toString().compareToIgnoreCase("USA") 
                 == 0)
                    return argValue.toString().compareToIgnoreCase("Boston") == 0 ||
                     argValue.toString().compareToIgnoreCase("San Francisco") == 0;
                if(((DataType)prevArgValues.get(0)).toString().compareToIgnoreCase("Canada")
                  == 0)
                    return argValue.toString().compareToIgnoreCase("Montreal") == 0 ||
                     argValue.toString().compareToIgnoreCase("Toronto") == 0;
                else
                    throw new RuntimeException("Invalid country");
            }
            if(argNumber == 2 && argValue.getClass() ==
             OpssString.class)
            {
                if(((DataType)prevArgValues.get(0)).toString().compareToIgnoreCase("USA") ==
                 0)
                {
                    if(((DataType)prevArgValues.get(1)).toString().compareToIgnoreCase("Boston") == 0)
                        return argValue.toString().compareToIgnoreCase("Beacon Str") == 0 ||
                         argValue.toString().compareToIgnoreCase("Boylston Str") == 0;
                    if(((DataType)prevArgValues.get(1)).toString().compareToIgnoreCase
                     ("San Francisco") == 0)
                        return argValue.toString().compareToIgnoreCase("Van Ness Str") == 0
                         || argValue.toString().compareToIgnoreCase("Market Str") == 0;
                    else
                        throw new RuntimeException("Invalid USA city");
                }
                if(((DataType)prevArgValues.get(0)).toString().compareToIgnoreCase("Canada")
                 == 0)
                {
                    if(((DataType)prevArgValues.get(1)).toString().compareToIgnoreCase("Montreal") == 0)
                        return argValue.toString().compareToIgnoreCase("St. Laurent Str") ==
                         0 || argValue.toString().compareToIgnoreCase("St. Catherine Str") ==
                         0;
                    if(((DataType)prevArgValues.get(1)).toString().compareToIgnoreCase("Toronto") == 0)
                        return argValue.toString().compareToIgnoreCase("Queen Str") == 0 ||
                         argValue.toString().compareToIgnoreCase("King Str") == 0;
                    else
                        throw new RuntimeException("Invalid Canada city");
                } else
                {
                    throw new RuntimeException("Invalid country");
                }
            }
            if(argNumber == 3 && argValue.getClass() ==
             OpssInteger.class)
                return true;
            if(argNumber == 4 && argValue.getClass() ==
             OpssBoolean.class)
            {
                if(((OpssInteger)prevArgValues.get(3)).intValue() == 10)
                    return !((OpssBoolean)argValue).booleanValue();
                if(((OpssInteger)prevArgValues.get(3)).intValue() == 15)
                    return ((OpssBoolean)argValue).booleanValue();
                else
                    return false;
            } else
            {
                throw new RuntimeException("Invalid argument number or value type");
            }
        } else
        {
            throw new RuntimeException("Invalid function name");
        }
    }
 
    public static void main(String args[])
    {
        System.out.println("*** Inspecting function 'validateAddress' ***");
        ArrayList metadataList = OES_FUNCTION_CLASS.getArgMetadata("validateAddress");
        System.out.println((new StringBuilder()).append("\nNumber of arguments :
         ").append(metadataList.size()).toString());
        com.bea.security.providers.authorization.asi.InspectableFunction.ArgMetadata
          metadata;
        for(Iterator i$ = metadataList.iterator(); i$.hasNext(); System.out.println
         ((new StringBuilder()).append("Arg ").append(metadata.getArgNumber()).append(" :
           name = '").append(metadata.getArgName()).append("', class =
           '").append(metadata.getArgClass()).append("', manual entry =
           '").append(metadata.isArgAllowManualEntry()).append("', dependent =
           '").append(metadata.isArgDependent()).append("', clear dependent args =
           '").append(metadata.isArgOnChangeClearDependentArgs()).append("'").toString()))
            metadata =
 (com.bea.security.providers.authorization.asi.InspectableFunction.ArgMetadata)i$.next();
 
        System.out.println("\n*** Testing address selection for USA ***");
        ArrayList prevArgValuesUsa = new ArrayList();
        apm(0, prevArgValuesUsa, 0);
        apm(1, prevArgValuesUsa, 1);
        apm(2, prevArgValuesUsa, 0);
        apm(3, prevArgValuesUsa, 1);
        apm(4, prevArgValuesUsa, 0);
        System.out.println("\nFinal selection :");
        for(int i = 0; i < 5; i++)
            System.out.println((new StringBuilder()).append(" -
").append(((com.bea.security.providers.authorization.asi.InspectableFunction.ArgMetadata)
    metadataList.get(i)).getArgName()).append(" = ").append(((DataType)prevArgValuesUsa.get(i)).toString()).toString());
 
        System.out.println((new StringBuilder()).append("\nExpecting Not
Valid...").append(((com.bea.security.providers.authorization.asi.InspectableFunction.
  ArgMetadata)metadataList.get(1)).getArgName()).append(" '").append(CITY_NYC).append
  ("' is ").append(OES_FUNCTION_CLASS.isValidArgValue("validateAddress", 1, CITY_NYC,
    prevArgValuesUsa) ? "valid" : "not valid").append(" for address").toString());
        System.out.println((new StringBuilder()).append("\nExpecting
Valid...").append(((com.bea.security.providers.authorization.asi.InspectableFunction.
  ArgMetadata)metadataList.get(2)).getArgName()).append(" '").append
  (STREET_VANNESS).append("' is ").append(OES_FUNCTION_CLASS.isValidArgValue("validateAddress", 
  2, STREET_VANNESS, prevArgValuesUsa) ? "valid" : "not valid").append
    (" for address").toString());
        System.out.println((new StringBuilder()).append("\nExpecting Valid...").append
(((com.bea.security.providers.authorization.asi.InspectableFunction.ArgMetadata)
   metadataList.get(3)).getArgName()).append(" '").append(HOUSE_20).append
     ("' is ").append(OES_FUNCTION_CLASS.isValidArgValue("validateAddress", 3, HOUSE_20,
    prevArgValuesUsa) ? "valid" : "not valid").append(" for address").toString());
        System.out.println((new StringBuilder()).append("\nExpecting Not
Valid...").append(((com.bea.security.providers.authorization.asi.InspectableFunction.ArgMetadata)metadataList.get(4)).getArgName()).append(" '").append(MAILBOX_FALSE).append("' 
  is ").append(OES_FUNCTION_CLASS.isValidArgValue("validateAddress", 4, MAILBOX_FALSE,
    prevArgValuesUsa) ? "valid" : "not valid").append(" for address").toString());
        System.out.println("\n*** Testing address selection for Canada ***");
        ArrayList prevArgValuesCanada = new ArrayList();
        apm(0, prevArgValuesCanada, 1);
        apm(1, prevArgValuesCanada, 0);
        apm(2, prevArgValuesCanada, 1);
        apm(3, prevArgValuesCanada, 0);
        apm(4, prevArgValuesCanada, 1);
        System.out.println("\nFinal selection :");
        for(int i = 0; i < 5; i++)
            System.out.println((new StringBuilder()).append(" - ").append(((com.bea.security.providers.authorization.asi.InspectableFunction.ArgMetadata)metadataList.get(i)).getArgName()).append(" = ").append(((DataType)prevArgValuesCanada.get(i)).toString()).toString());
 
        System.out.println((new StringBuilder()).append("\nExpecting Valid...").append(((com.bea.security.providers.authorization.asi.InspectableFunction.ArgMetadata)metadataList.get(1)).getArgName()).append(" '").append(CITY_MONTREAL).append("' is ").append(OES_FUNCTION_CLASS.isValidArgValue("validateAddress", 1, CITY_MONTREAL, prevArgValuesCanada) ? "valid" : "not valid").append(" for address").toString());
        System.out.println((new StringBuilder()).append("\nExpecting Not Valid...").append(((com.bea.security.providers.authorization.asi.InspectableFunction.ArgMetadata)metadataList.get(2)).getArgName()).append(" '").append(STREET_SHERBROOKE).append("' is ").append(OES_FUNCTION_CLASS.isValidArgValue("validateAddress", 2, STREET_SHERBROOKE, prevArgValuesCanada) ? "valid" : "not valid").append(" for address").toString());
        System.out.println((new StringBuilder()).append("\nExpecting Valid...").append(((com.bea.security.providers.authorization.asi.InspectableFunction.ArgMetadata)metadataList.get(3)).getArgName()).append(" '").append(HOUSE_10).append("' is ").append(OES_FUNCTION_CLASS.isValidArgValue("validateAddress", 3, HOUSE_10, prevArgValuesCanada) ? "valid" : "not valid").append(" for address").toString());
        DataType mailbox_false1 = new OpssBoolean(false);
        System.out.println((new StringBuilder()).append("\nExpecting Valid...").append(((com.bea.security.providers.authorization.asi.InspectableFunction.ArgMetadata)metadataList.get(4)).getArgName()).append(" '").append(MAILBOX_FALSE).append("' is ").append(OES_FUNCTION_CLASS.isValidArgValue("validateAddress", 4, MAILBOX_FALSE, prevArgValuesCanada) ? "valid" : "not valid").append(" for address").toString());
    }
 
    private static void apm(int argnum, ArrayList prevArgValues, int selection)
    {
        ArrayList metadataList = OES_FUNCTION_CLASS.getArgMetadata("validateAddress");
        System.out.println((new StringBuilder()).append("\nGet values for argument '").append(((com.bea.security.providers.authorization.asi.InspectableFunction.ArgMetadata)metadataList.get(argnum)).getArgName()).append("'").toString());
        ArrayList argValues = OES_FUNCTION_CLASS.getArgValues("validateAddress", argnum, prevArgValues);
        DataType value;
        for(Iterator i$ = argValues.iterator(); i$.hasNext(); System.out.println((new StringBuilder()).append(" - ").append(value.toString()).toString()))
            value = (DataType)i$.next();
 
        System.out.println((new StringBuilder()).append("Selecting '").append(argValues.get(selection)).append("'").toString());
        prevArgValues.add(argValues.get(selection));
    }
 
    private static final String OES_FUNCTION = "validateAddress";
    private static final InspectableFunction OES_FUNCTION_CLASS = new Address();
    private static final int ADDRESS_COUNTRY = 0;
    private static final int ADDRESS_CITY = 1;
    private static final int ADDRESS_STREET = 2;
    private static final int ADDRESS_HOUSE = 3;
    private static final int ADDRESS_MAILBOX = 4;
    private static final int NUM_ARGUMENTS = 5;
    private static final DataType CITY_NYC = new OpssString("New York");
    private static final DataType CITY_MONTREAL = new OpssString("Montreal");
    private static final DataType STREET_VANNESS = new OpssString("Van Ness Str");
    private static final DataType STREET_SHERBROOKE = new OpssString("Sherbrooke");
    private static final DataType HOUSE_20 = new OpssInteger(20);
    private static final DataType HOUSE_10 = new OpssInteger(10);
    private static final DataType MAILBOX_FALSE = new OpssBoolean(false);
 
}

Example 7-8 Sample Code for getArgValues() Method

public ArrayList<oracle.security.jps.service.policystore.info.DataType> 
  getArgValues (String functionName, int argNumber, 
  ArrayList<oracle.security.jps.service.policystore.info.DataType> prevArgValues)
 
throws RuntimeException {
 
ArrayList<oracle.security.jps.service.policystore.info.DataType> values = 
  new ArrayList<oracle.security.jps.service.policystore.info.DataType>();
 
if (functionName.compareToIgnoreCase(Constants.GET_STRING_IDC_FUNC_NAME) == 0 ||
functionName.compareToIgnoreCase(Constants.GET_INTEGER_IDC_FUNC_NAME) == 0 ||
functionName.compareToIgnoreCase(Constants.GET_BOOLEAN_IDC_FUNC_NAME) == 0) 
{
  if (argNumber == Constants.GET_IDC_FUNC_ARGS.CLAIM_NAME.ordinal()) {
 
// return claims in the dictionary
 
Iterator<ClaimSchema> it = dictCtx.getDictionary().getClaimsForAllNamespaces();
 
while (it.hasNext()) {
 
if ((functionName.compareToIgnoreCase(Constants.GET_STRING_IDC_FUNC_NAME) == 
  0 && it.next().getType() == String.class) ||
 
(functionName.compareToIgnoreCase(Constants.GET_INTEGER_IDC_FUNC_NAME) == 
  0 && it.next().getType() == Integer.class) ||
 
(functionName.compareToIgnoreCase(Constants.GET_BOOLEAN_IDC_FUNC_NAME) == 
  0 && it.next().getType() == Boolean.class))
 
{                       
nameList.add (it.next().getUniqueName());
 
 }
 }
  Collections.sort(nameList);
  for (String name : nameList)
   values.add (new OpssString (name));
 
 } else {
 
 throw new RuntimeException ("Invalid argument number " + argNumber);
 
 }
 
 } else {
 
throw new RuntimeException ("Invalid function name " + functionName);
        } 
        return values;
    }

Example 7-9 Sample Code For isValidArgValue() Method

public boolean isValidArgValue (String functionName, int argNumber, oracle.security.jps.service.policystore.info.DataType argValue, ArrayList<oracle.security.jps.service.policystore.info.DataType> prevArgValues)
 
throws RuntimeException {
 
if (functionName.compareToIgnoreCase(Constants.GET_STRING_IDC_FUNC_NAME) == 0 ||
 
functionName.compareToIgnoreCase(Constants.GET_INTEGER_IDC_FUNC_NAME) == 0 ||
 
functionName.compareToIgnoreCase(Constants.GET_BOOLEAN_IDC_FUNC_NAME) == 0) {
 
if (argNumber == Constants.GET_IDC_FUNC_ARGS.CLAIM_NAME.ordinal()) 
  {
// is it a valid claim?
try {
ClaimSchema schema = dictCtx.getDictionary().getClaimSchema(argValue.toString());
return ((functionName.compareToIgnoreCase(Constants.GET_STRING_IDC_FUNC_NAME) 
  == 0 && schema.getType() == String.class) ||
 (functionName.compareToIgnoreCase(Constants.GET_INTEGER_IDC_FUNC_NAME) 
  == 0 && schema.getType() == Integer.class) ||
 (functionName.compareToIgnoreCase(Constants.GET_BOOLEAN_IDC_FUNC_NAME) 
  == 0 && schema.getType() == Boolean.class));
 
} catch (UnknownClaimException e) {
return false;
}
} else {
throw new RuntimeException ("Invalid argument number " + argNumber);
 
}
} else {
throw new RuntimeException ("Invalid function name " + functionName);
}
 
}