Solaris WBEM SDK Developer's Guide

Chapter 3 Writing a Client Program

This chapter explains how to use the Solaris WBEM SDK client APIs (javax.wbem.client) to write client programs, and includes the following topics:


Note -

For detailed information on the WBEM client APIs (javax.wbem.client), see file:/usr/sadm/lib/wbem/doc/index.html.


Overview

WBEM client applications use the javax.wbem.client APIs to manipulate Common Information Model (CIM) objects. A client application uses the CIM API to construct an object (for example, a class, instance, or namespace) and then initializes, or instantiates, that object. The application uses the client APIs to pass the object to the CIM Object Manager and request a WBEM operation, such as creating a CIM class, instance, or namespace.

Sequence of a Client Application

Client applications typically follow this sequence:

  1. Connect to the CIM Object Manager using CIMClient. A client application connects to the CIM Object Manager each time it needs to perform a WBEM operation, such as creating a CIM class or updating a CIM instance. See “Opening and Closing a Client Connection”.

  2. Use the client APIs to request operations and perform programming tasks. The application's feature set determines which operations it needs to request. The tasks that most programs perform include creating, deleting and updating instances; enumerating objects; calling methods; retrieving class definitions; and handling errors. Client programs can also create and delete classes, and create and delete namespaces, and use qualifiers. See “Performing Basic Client Operations”.

  3. Close the client connection to the CIM Object Manager using CIMClient, to free the server resources used by the client session. See “Opening and Closing a Client Connection”.

Opening and Closing a Client Connection

A client application must first establish a connection with the CIM Object Manager before it can perform WBEM operations such as adding, modifying, or deleting a CIM class, CIM instance, or CIM qualifier type. The client application and CIM Object Manager can run on the same host or on different hosts. In addition, multiple clients can establish connections to the same CIM Object Manager.

About Namespaces

When an application connects to the CIM Object Manager, it must also connect to a namespace, where all subsequent operations occur. A namespace is a directory-like structure that contains classes, instances, and qualifier types. The names of all objects within a namespace must be unique. When you install the Solaris WBEM SDK, four namespaces are created:

Opening a Client Connection

To open a client connection, you use the CIMClient class to connect to the CIM Object Manager. The CIMClient class takes four arguments:


Example 3-1 Connecting to the Root Account

In this example, the application connects to the CIM Object Manager running on the local host in the default namespace. The application creates a UserPrincipal object for the root account, which has read and write access to all CIM objects in the default namespace.

{
    ...

   /* Create a namespace object initialized with two null strings
   that specify the default host (the local host) and the default 
   namespace (root\cimv2).*/
 
    CIMNameSpace cns = new CIMNameSpace("", "");

    UserPrincipal up = new UserPrincipal("root");
    PasswordCredential pc = new PasswordCredential("root_password"); 
    /* Connect to the namespace as root with the root password. */
 
    CIMClient cc = new CIMClient(cns, up, pc);
    ...
}



Example 3-2 Connecting to a User Account

In this example, the application first creates an instance of a CIMNameSpace, UserPrincipal, and PasswordCredential object. Then, the application uses the CIMClient class to connect to the CIM Object Manager and pass the host name, namespace , user name, and password credential to the CIM Object Manager.

{
    ...
    /* Create a namespace object initialized with A 
    (name of namespace) on host happy.*/
    CIMNameSpace cns = new CIMNameSpace("happy", "A");
    UserPrincipal up = new UserPrincipal("Mary");
    PasswordCredential pc = new PasswordCredential("marys_password");
    CIMClient cc = new CIMClient(cns, up, pc);
    ...
    ...
} 



Example 3-3 Authenticating as an RBAC Role Identity

You use the SolarisUserPrincipal and SolarisPasswordCredential classes to authenticate a user's role identity. This example authenticates as Mary and assumes the role Admin.

{
...
CIMNameSpaceRole cns = new CIMNameSpace("happy", "A");
SolarisUserPrincipal sup = new SolarisUserRolePrincipal("Mary", "Admin");
SolarisPswdCredential spc = new
        SolarisPswdCredential("marys_password", "admins_password");
CIMClient cc = new CIMClient(cns, sup, spc);


Closing a Client Connection

Use the close method of the CIMClient class to close a client connection and free the server resources used by the session.


Example 3-4 Closing a Client Connection

This example closes a client connection. The instance variable cc represents the client connection.

...
cc.close();
...

Performing Basic Client Operations

This section describes how to use the the javax.wbem.client APIs to request operations and perform common programming tasks.

Creating an Instance

Use the newInstance method to create an instance of an existing class. If the existing class has a key property, the application must set the key property to a unique value. As an option, an instance can define additional qualifiers that are not defined for the class. These qualifiers can be defined for the instance or for a particular property of the instance and do not need to appear in the class declaration.

Applications can use the getQualifiers method to get the set of qualifiers defined for a class.


Example 3-5 Creating an Instance

This example uses the newInstance method to create a Java class representing a CIM instance, for example, a Solaris package, from the Solaris_Package class.

...
{ 
/*Connect to the CIM Object Manager in the root\cimv2 
namespace on the local host. Specify the username and password of an 
account that has write permission to the objects in the 
root\cimv2 namespace. */
 
    UserPrincipal up = new UserPrincipal("root");
    PasswordCredential pc = new PasswordCredential("root_password"); 
    /* Connect to the namespace as root with the root password. */
 
    CIMClient cc = new CIMClient(cns, up, pc);
...
 
// Get the Solaris_Package class
cimclass = cc.getClass(new CIMObjectPath("Solaris_Package"),  
                                          true, true, true, null);
 
/* Create a new instance of the Solaris_Package 
 class populated with the default values for properties. If the provider
 for the class does not specify default values, the values of the 
 properties will be null and must be explicitly set. */
 
 CIMInstance ci = cc.createInstance (new CIMObjectPath("Solaris_Package"), 
 ci);
}
... 


Deleting an Instance

Use the deleteInstance method to delete an instance.


Example 3-6 Deleting Instances

The following example connects the client application to the CIM Object Manager, uses CIMObjectPath to construct an object containing the CIM object path of the object to be deleted, enumerateInstance to get the instance and all instances of its subclasses, and deleteInstance to delete each instance.

 
import java.rmi.*;
import java.util.Enumeration;

import javax.wbem.cim.CIMClass;
import javax.wbem.cim.CIMException;
import javax.wbem.cim.CIMInstance;
import javax.wbem.cim.CIMNameSpace;
import javax.wbem.cim.CIMObjectPath;

import javax.wbem.client.CIMClient;
import javax.wbem.client.PasswordCredential;
import javax.wbem.client.UserPrincipal;

/** 
 * Returns all instances of the specified class.
 * This example takes five arguments: hostname (args[0]), username
 * (args[1]), password (args[2]) namespace (args[3] and classname (args[4]) 
 * It will delete all instances of the specified classname.  The specified 
 * username must have write permissions to the specified namespace  
 */
public class DeleteInstances {
    public static void main(String args[]) throws CIMException {
        CIMClient cc = null;
        // if not five arguments, show usage and exit
        if (args.length != 5) {
           System.out.println("Usage: DeleteInstances host username " +
                              "password namespace classname ");
           System.exit(1);
           }
       try {
          // args[0] contains the hostname and args[3] contains the 
          // namespace.  We create a CIMNameSpace (cns) pointing to 
          // the specified namespace on the specified host
          CIMNameSpace cns = new CIMNameSpace(args[0], args[3]);

         // args[1] and args[2] contain the username and password.
         // We create a UserPrincipal (up) using the username and
         // a PasswordCredential using the password.
         UserPrincipal up = new UserPrincipal(args[1]);
         PasswordCredential pc = new PasswordCredential(args[2]);

        // Connect to the CIM Object Manager and pass it the
        // CIMNameSpace, UserPrincipal and PasswordCredential objects
        // we created. 
        cc = new CIMClient(cns, up, pc);

        // Get the class name (args[4]) and create a CIMObjectPath
        CIMObjectPath cop = new CIMObjectPath(args[4]);

        // Get an enumeration of all the instance object paths of the
        // class and all subclasses of the class.  An instance object 
        // path is a reference used by the CIM object manager to 
        // locate the instance
        Enumeration e = cc.enumerateInstanceNames(cop);


        // Iterate through the instance object paths in the enumeration.
        // Construct an object to store the object path of each 
        // enumerated instance, print the instance and then delete it 
        while (e.hasMoreElements()) {
           CIMObjectPath  op = (CIMObjectPath)e.nextElement();
           System.out.println(op);
           cc.deleteInstance(op);
        } // end while 
  } catch (Exception e) {
       // is we have an exception, catch it and print it out.
       System.out.println("Exception: "+e);
  } // end catch

 // close session.
 if (cc != null) {
     cc.close();
       }
    }
}


Getting and Setting Instances

Client applications commonly use the getInstance method to retrieve CIM instances from the CIM Object Manager. When an instance of a class is created, it inherits the properties of the class it is derived from and all parent classes in its class hierarchy. The getInstance method takes the Boolean argument localOnly.

Use the setInstance method to update an existing instance.


Example 3-7 Getting and Setting Instances

The following example gets instances of an object path in an enumeration, updates the property value of b to 10 in each instance, and passes the updated instances to the CIM Object Manager.

...
{
    // Create an object path, an object that contains the CIM name for 
    // "myclass"
    CIMObjectPath cop = new CIMObjectPath("myclass"); 

    /* Get instances for each instance object path in an enumeration, 
    update the property value of b to 10 in each instance, and pass the 
    updated instance to the CIM Object Manager. */
    
    while(e.hasMoreElements()) {
           CIMInstance ci = cc.getInstance((CIMObjectPath)(e.nextElement
                                          ()),true, true, true, null);
           ci.setProperty("b", new CIMValue(new Integer(10)));
           cc.setInstance(new CIMObjectPath(),ci);
           }
}
...


Getting and Setting Properties

A CIM property is a value that describes the characteristic of a CIM class. Properties can be thought of as a pair of functions, one that gets the property value and one that sets the property value.


Example 3-8 Getting a Property

The following example uses enumerateInstanceNames to return the names of all instances of the Solaris processor, getProperty to get the value of the current clockspeed for each instance, and println to print the current clockspeed values.

...
{
/* Create an object (CIMObjectPath) to store the name of the
Solaris_Processor class. */ 
 
CIMObjectPath cop = new CIMObjectPath("Solaris_Processor"); 
 
/* The CIM Object Manager returns an enumeration containing the names 
of instances of the Solaris_Processor class. */
 
Enumeration e = cc.enumerateInstanceNames(cop); 
 
/* Iterate through the enumeration of instance object paths.
Use the getProperty method to get the current clockspeed
value for each Solaris processor. */
 
while(e.hasMoreElements()) {
        CIMValue cv = cc.getProperty(e.nextElement(CIMObjectPath), 
                                     "CurrentClockSpeed");
        System.out.println(cv);
}
...
}
 



Example 3-9 Setting a Property

The following example sets the initial shell value for all Solaris_UserTemplate instances. This code segment uses enumerateInstanceNames to get the names of all instances of the Solaris_User Template, and setProperty to set the value of the initial shell for each instance.

...
{
    /* Create an object (CIMObjectPath) to store the name of the
    Solaris_Processor class. */ 
 
    CIMObjectPath cop = new CIMObjectPath("Solaris_UserTemplate"); 
 
    /* The CIM Object Manager returns an enumeration containing the names 
    of instances of the Solaris_UserTemplate class and
    all its subclasses. */
 
    Enumeration e = cc.enumerateInstanceNames(cop); 
 
    /* Iterate through the enumeration of instance object paths.
    Use the setProperty method to set the initial shell
    value to /usr/bin/sh for each Solaris_UserTemplate instance. */
 
   for (; e.hasMoreElements(); cc.setProperty(e.nextElement(), 
        "/usr/bin/sh", new CIMValue(new Integer(500))));
 
...
}
 


Enumerating Objects

An enumeration is a collection of objects that can be retrieved one at a time. You can enumerate classes, class names, instances, instance names, and namespaces. The results of an enumeration depend on the method and the arguments used, as shown in the following table.

Enumerating Objects

Table 3-1 Enumerating Objects

Method 

No args 

deep

localOnly

enumerateClasses

Returns the contents of the class specified in path.

If true: Returns the contents of the subclasses of the specified class, but does not return the class itself.

If true: Returns only non-inherited properties and methods of the specified class.

If false: Returns the contents of the direct subclasses of the specified class.

If false: Returns all properties of the specified class.

enumerateInstances

Returns the instances of the class specified in path.

If true: Returns the instances of the specified class and its subclasseses.

If true: Returns only non-inherited properties of the instances of the specified class.

If false: Returns the instances of the specified class and its subclasses. The properties of the subclasses are filtered out.

If false: Returns all properties of the instances of the specified class.

enumerateClassNames 

Returns the names of the class specified in path.

If true: Returns the names of all classes derived from the specified class.

N/A 

If false: Returns only the names of the first level children of the specified class.

N/A 

enumerateInstanceNames 

Returns the names of the instances of the class specified in path.

N/A 

N/A 

N/A 

N/A 

enumNameSpace 

Returns a list of the namespaces within the namespace specified in path

If true: Returns the entire hierarchy of namespaces under the specified namespace.

N/A 

If false: Returns only the first level children of the specified namespace.

N/A 


Example 3-10 Enumerating Classes

The following example program returns the contents of a class and its subclasses.

...
{
    /* Creates a CIMObjectPath object and initializes it 
    with the name of the CIM class to be enumerated (myclass). */
     
    CIMObjectPath cop = new CIMObjectPath(myclass); 
     
    /* This enumeration contains the classes and subclasses
    in the enumerated class (deep=true). This enumeration
    returns only the non-inherited methods and properties 
    for each class and subclass (localOnly is true).*/
 
    Enumeration e = cc.enumerateClasses(cop, true, true);  
}
...


Example 3-11 Enumerating Classes and Instances

The following example program performs a deep and shallow (deep=false) enumeration of classes and instances. The localOnly flag returns the contents of the classes and instances instead of the names of the classes and instances.

import java.rmi.*;
import java.util.Enumeration;

import javax.wbem.client.CIMClient;
import javax.wbem.cim.CIMClass;
import javax.wbem.cim.CIMException;
import javax.wbem.cim.CIMInstance;
import javax.wbem.cim.CIMNameSpace;
import javax.wbem.cim.CIMObjectPath;

import javax.wbem.client.UserPrincipal;
import javax.wbem.client.PasswordCredential;


/** 
 * This example enumerates classes and instances. It does deep and 
 * shallow enumerations on a class that is passed from the command line
 */
public class ClientEnum {

    public static void main(String args[]) throws CIMException {
        CIMClient cc = null;
        CIMObjectPath cop = null;
        if (args.length < 4) {
            System.out.println("Usage: ClientEnum host user passwd " + 
                               "classname");
            System.exit(1);
   }
   try {
       CIMNameSpace cns = new CIMNameSpace(args[0]);
       UserPrincipal up = new UserPrincipal(args[1]);
       PasswordCredential pc = new PasswordCredential(args[2]);
       cc = new CIMClient(cns, up, pc);


       // Get the class name from the command line    
       cop = new CIMObjectPath(args[3]);    
       // Do a deep enumeration of the class
       Enumeration e = cc.enumerateClasses(cop, true, true, true, 
                                           true);
       // Will print out all the subclasses of the class.
       while (e.hasMoreElements()) {
           System.out.println(e.nextElement());
       }
       System.out.println("+++++");
       // Do a shallow enumeration of the class
       e = cc.enumerateClasses(cop, false, true, true, true);
       // Will print out the first level subclasses.
       while (e.hasMoreElements()) {
           System.out.println(e.nextElement());
       }
       System.out.println("+++++");
       // Do a deep enumeration of the instances of the class
       e = cc.enumerateInstances(cop, false, true, true, true, null);
       // Will print out all the instances of the class and its 
       // subclasses.
       while (e.hasMoreElements()) {
           System.out.println(e.nextElement());
       }
       System.out.println("+++++");
       // Do a shallow enumeration of the instances of the class
       e = cc.enumerateInstances(cop, false, false, true, true, null);
       // Will print out all the instances of the class.
       while (e.hasMoreElements()) {
           System.out.println(e.nextElement());
       }
       System.out.println("+++++");

       e = cc.enumerateInstanceNames(cop);
       while (e.hasMoreElements()) {
           System.out.println(e.nextElement());
       }
       System.out.println("+++++");

       e = cc.enumerateInstanceNames(cop);
       while (e.hasMoreElements()) {
           CIMObjectPath opInstance = (CIMObjectPath)e.nextElement();
           CIMInstance ci = cc.getInstance(opInstance, false, 
                                           true, true, null);
           System.out.println(ci); 
       }
       System.out.println("+++++");

  }
  catch (Exception e) {
      System.out.println("Exception: "+e);
  }

 // close session.
 if (cc != null) {
     cc.close();
  }
 }
}


Example 3-12 Enumerating Class Names

The following example program returns a list of class names and subclass names.

...
{
    /* Creates a CIMObjectPath object and initializes it 
    with the name of the CIM class to be enumerated (myclass). */
    CIMObjectPath cop = new CIMObjectPath(myclass); 
    
    /* This enumeration contains the names of the classes and subclasses
    in the enumerated class. */
    Enumeration e = cc.enumerateClassNames(cop, true);
}
... 



Example 3-13 Enumerating Namespaces

This example program uses the enumNameSpace method in the CIMClient class to print the names of the namespace and all the namespaces contained within the namespace.

 
import java.rmi.*;
import java.util.Enumeration;

import javax.wbem.cim.CIMClass;
import javax.wbem.cim.CIMException;
import javax.wbem.cim.CIMInstance;
import javax.wbem.cim.CIMNameSpace;
import javax.wbem.cim.CIMObjectPath;

import javax.wbem.client.CIMClient;
import javax.wbem.client.PasswordCredential;
import javax.wbem.client.UserPrincipal;


/** 
 *
 */
public class EnumNameSpace {
    public static void main(String args[]) throws CIMException {
        CIMClient cc = null;
        // if not four arguments, show usage and exit
        if (args.length < 4) {
            System.out.println("Usage: EnumNameSpace host username " +
                               "password namespace");
            System.exit(1);
            }
        try {
            // args[0] contains the hostname. We create a CIMNameSpace 
            // (cns) pointing to the specified namespace on the 
            // specified host
            CIMNameSpace cns = new CIMNameSpace(args[0], "");

           // args[1] and args[2] contain the username and password.
           // We create a UserPrincipal (up) using the username and
           // a PasswordCredential using the password.
           UserPrincipal up = new UserPrincipal(args[1]);
           PasswordCredential pc = new PasswordCredential(args[2]);

           // Connect to the CIM Object Manager and pass it the
           // CIMNameSpace, UserPrincipal and PasswordCredential objects
           // we created. 
           cc = new CIMClient(cns, up, pc);

           // Use the namespace (args[3]) to create a CIMObjectPath
           CIMObjectPath cop = new CIMObjectPath("", args[3]);

           // Enumerate the namespace
           Enumeration e = cc.enumNameSpace(cop);
           while (e.hasMoreElements()) {
               System.out.println((CIMObjectPath)e.nextElement());
           } // end while 

           } catch (Exception e) {
              // is we have an exception, catch it and print it out.
              System.out.println("Exception: "+ e);
           } // end catch

          // close session.
          if (cc != null) {
              cc.close();
        }
    }
}


Creating Associations

An association describes a relationship between two or more managed resources such as a computer and its hard disk. This relationship is abstracted in an association class, which is a special type of class that contains an association qualifier. You can add or change an association class without affecting the objects themselves.

Figure 3-1 TeacherStudent Association 1

Diagram shows that in TeacherStudent Association 1, the Teacher Teaches the Student and that the Student is Taught By the Teacher.

Figure 3–1 shows two classes, Teacher and Student. Both classes are linked by the TeacherStudent association. The TeacherStudent association has two references:

About The Association Methods

The association methods in CIMClient return information about the relationships between classes and instances. These methods are described in the following table.

Table 3-2 Association Methods

Method 

Description 

associators

Gets the CIM classes or instances that are associated with the specified CIM class or instance. 

associatorNames

Gets the names of the CIM classes or instances that are associated with the specified CIM class or instance. 

references

Gets the association classes or instances that refer to the specified CIM class or instance, respectively. 

referenceNames

Gets the names of the association classes or instances that refer to the specified CIM classes or instances, respectively. 

These methods take one required argument, CIMObjectPath, which is the name of a source CIM class or CIM instance whose associations, associated classes, or instances you want to return. If the CIM Object Manager does not find any associations, associated classes, or instances, it does not return anything.

Figure 3-2 TeacherStudent Association 2

Diagram shows that Math Teacher and Art Teacher are subclasses of Teacher, and that Teacher 1, Teacher 2, and Student 1 are class instances.

In Figure 3–2, the associators and associatorNames methods return information about the classes associated with the Teacher and Student classes. The references and referenceNames methods return information about the associations between the Teacher and Student classes.

Table 3-3 TeacherStudent Methods

Example 

Output 

Description 

associators(Teacher, null, null, null, null, false, false, null)

Student class

Returns associated classes.Student is linked to Teacher by the TeacherStudent association.

associators(MathTeacher, null, null, null, null,,false, false, null)

Student

Returns associated classes. Teacher is linked to Student by the TeacherStudent association. MathTeacher and ArtTeacher inherit the TeacherStudent association from Teacher.

associatorNames(Teacher, null, null, null, null)

Name of the Student class

Returns the names of the associated classes. Student is linked to Teacher by the TeacherStudentassociation.

references(Student, null, null. false, false, null)

TeacherStudent

Returns the associations in which Student participates.

references(Teacher, null, null. false, false, null)

TeacherStudent

Returns the associations in which Teacher participates.

references(Teacher, null, null, false, false, null)

TeacherStudent

Returns the associations in which Teacher participates.

referenceNames(Teacher, null, null)

The name of the TeacherStudent class.

Returns the names of the associations in which Teacher participates.

referenceNames(Teacher, null, null)

The name of the TeacherStudent class.

Returns the names of the associations in which Teacher participates.


Note -

The associatorNames and referenceNames methods do not take the arguments includeQualifiers, includeClassOrigin, and propertyList because these arguments are irrelevant to a method that returns only the names of instances or classes, not their entire contents.


Passing a Class to the Association Methods

To specify the name of a class, you specify its model path. The model path includes the class's namespace, class name, and keys. A key is a property or set of properties that uniquely identify managed resource. Key properties are marked with the key qualifier. This model path:

\\myserver\\root\cimv2\Solaris_ComputerSystem.Name=
mycomputer: CreationClassName=Solaris_ComputerSystem

Specifies the following:

Passing Instances to the Association Methods

You use the enumerateInstances method to return all instances of a given class, and a loop structure to iterate through the instances. In the loop, you can pass each instance to an association method.


Example 3-14 Passing Instances

This example enumerates the instances in the op class and its subclasses, uses a while loop to cast each instance to a CIMObjectPath (op), and passes each instance as the first argument to the associators method.

 {
    ...
    Enumeration e = cc.enumerateInstances(op, true);
    while (e.hasMoreElements()) {
        op = (CIMObjectPath)e.nextElement();
        Enumeration e1 = cc.associators(op, null, null, 
                null, null, false, false, null);
    ...
    }           

Using Optional Arguments with the Association Methods

You can use the optional arguments with the association methods to filter the classes and instances that are returned. Each optional parameter value passes its results to the next parameter for filtering until all parameters have been processed.

You can pass values for any one or a combination of the optional parameters. You must enter a value or null for each parameter. The assocClass, resultClass, role, and resultRole parameters filter the classes and instances that are returned. Only the classes and instances that match the values specified for these parameters are returned. The includeQualifiers, includeClassOrigin, and propertyList parameters filter the information that are included in the classes and instances that are returned.

Calling Methods

You use the invokeMethod interface to call a method in a class supported by a provider. To retrieve the signature of a method, an application must first get the definition of the class to which the method belongs. The invokeMethod method returns a CIMValue. The return value is null when the method you invoke does not define a return value.

The invokeMethod interface takes four arguments, as described in the following table.

Table 3-4 invokeMethod Parameters

Parameter 

Data Type 

Description 

name

CIMObjectPath 

The name of the instance on which the method must be invoked 

methodName

String 

The name of the method to call 

inParams

Vector 

Input parameters to pass to the method 

outParams

Vector 

Output parameters to get from the method 


Example 3-15 Calling a Method

This example gets the instances of the CIM_Service class (services that manage device or software features) and uses the invokeMethod method to stop each service.

{
    ...
    /* Pass the CIM Object Path of the CIM_Service class 
    to the CIM Object Manager. We want to invoke a method defined in
    this class. */ 
     
    CIMObjectPath op = new CIMObjectPath("CIM_Service"); 
     
    /* The CIM Object Manager returns an enumeration of instance
    object paths, the names of instances of the CIM_Service 
    class. */
     
    Enumeration e = cc.enumerateInstanceNames (op, true); 
     
    /* Iterate through the enumeration of instance object paths */
     
    while(e.hasMoreElements()) {
                // Get the instance
                CIMObjectPath op = (CIMObjectPath) e.nextElement();
                //Invoke the Stop Service method to stop the CIM services.
                cc.invokeMethod("StopService", null, null);
              }
}
 


Retrieving Class Definitions

The getClass method gets a CIM class. When a class is created, it inherits the methods and properties of the class from which it is derived, and all parent classes in the class hierarchy. The getClass method takes the localOnly Boolean argument.


Example 3-16 Retrieving a Class Definition

This example uses the following methods to retrieve a class definition:

import java.rmi.*;
import javax.wbem.client.CIMClient;
import javax.wbem.cim.CIMInstance;
import javax.wbem.cim.CIMValue;
import javax.wbem.cim.CIMProperty;
import javax.wbem.cim.CIMNameSpace;
import javax.wbem.cim.CIMObjectPath;
import javax.wbem.cim.CIMClass;
import javax.wbem.cim.CIMException;
import java.util.Enumeration;
/**
 * Gets the class specified in the command line. Works in the default
 * namespace root\cimv2.
 */
public class GetClass {
    public static void main(String args[]) throws CIMException {
      CIMClient cc = null;
      try {
         CIMNameSpace cns = new CIMNameSpace(args[0]);
         UserPrincipal up = new UserPrincipal("root");
         PasswordCredential pc = new PasswordCredential("root_password");
         cc = new CIMClient(cns);
         CIMObjectPath cop = new CIMObjectPath(args[1]);
             // Returns only the methods and properties that 
             // are local to the specified class (localOnly is true).
         cc.getClass(cop, true);
      } catch (Exception e) {
         System.out.println("Exception: "+e);
      }
      if(cc != null) {
         cc.close();
        }
    }
}


Handling Exceptions

Each CIMClient method throws a CIMException, or error condition. The CIM Object Manager uses Java exception handling and creates a hierarchy of WBEM-specific exceptions. The CIMException class is the base class for CIM exceptions. All other CIM exception classes extend from the CIMException class.

Each class of CIM exceptions defines a particular type of error condition that the API code handles. CIMException has methods to retrieve error codes and parameters relating to the exception. Refer to file:/usr/sadm/lib/wbem/doc/index.html for more information on the CIMException class.

Creating a Namespace

The Solaris WBEM SDK installation compiles the standard CIM Managed Object Format (MOF) files into the default namespaces. If you create a new namespace, you must compile the appropriate CIM .mof files into the new namespace before you create objects in that namespace. For example, if you plan to create classes that use the standard CIM elements, compile the CIM Core Schema into the namespace. If you plan to create classes that extend the CIM Application Schema, compile the CIM Application into the namespace.


Example 3-17 Creating a Namespace

This example uses a two-step process to create a namespace within an existing namespace:

  1. When the namespace is created, the CIMNameSpace method constructs a namespace object that contains the parameters to be passed to the CIM Object Manager.

  2. The CIMClient class connects to the CIM Object Manager and passes the namespace object. The CIM Object Manager creates the namespace, using the parameters contained in the namespace object.

{
    ...
    /* Creates a namespace object on the client, which stores parameters 
    passed to it from the command line. args[0] contains the host 
    name (for example, myhost); args[1] contains the 
    parent namespace (for example, the toplevel directory.) */
     
    CIMNameSpace cns = new CIMNameSpace (args[0], args[1]); 

    UserPrincipal up = new UserPrincipal("root");
    PasswordCredential pc = new PasswordCredential("root_password"); 
     
    /* Connects to the CIM Object Manager and passes it three parameters:
    the namespace object (cns), which contains the host name (args[0]) and
    parent namespace name (args[1]), a user name string (args[3]), and a
    password string (args[4]). */
     
    CIMClient cc = new CIMClient (cns, up, pc);
     
    /* Passes to the CIM Object Manager another namespace object that 
    contains a null string (host name) and args[2], the name of a 
    child namespace (for example, secondlevel). */
     
    CIMNameSpace cop = new CIMNameSpace("", args[2]);
    
    /* Creates a new namespace by the name passed in as args[2] under the
    toplevel namespace on myhost./*
     
    cc.createNameSpace(cop);
    ...
} 


Deleting a Namespace

Use the deleteNameSpace method to delete a namespace.

Creating a Base Class


Note -

You can also create a base class using the MOF language. If you are familiar with MOF syntax, use a text editor to create a MOF file and then use the MOF Compiler to compile the file into Java classes. See Chapter 2, Creating JavaBeans Using the MOF Compiler.


Use the CIMClass class to create a Java class representing a CIM class. To declare the most basic class, you need only specify the class name and a key property or an abstract qualifier. However, most classes include properties that describe the data of the class. To declare a property, include the property's data type, name, and an optional default value. The property data type must be an instance of CIMDataType.

A property can have a key qualifier, which identifies it as a key property. A key property uniquely defines the instances of the class. Only keyed classes can have instances. Therefore, if you do not define a key property in a class, the class can only be used as an abstract class. If you define a key property in a class in a new namespace, you must first compile the core MOF files into the namespace. The core MOF files contain the declarations of the standard CIM qualifiers, such as the key qualifier.

Class definitions can be more complicated, including such features as aliases, qualifiers, and qualifier flavors.

Deleting a Class

Use the CIMClient deleteClass method to delete a class. Deleting a class removes the class and throws a CIMException.


Note -

You must first remove any existing subclasses or instances before deleting a base class.



Example 3-18 Deleting a Class

This example uses the deleteClass method to delete a class in the default namespace root\cimv2. This program takes four required string arguments (hostname, classname, username, and password). The user running this program must specify the username and password for an account that has write permission to the root\cimv2 namespace.

 
import javax.wbem.cim.CIMClass;
import javax.wbem.cim.CIMException;
import javax.wbem.cim.CIMNameSpace;
import javax.wbem.cim.CIMObjectPath;
import javax.wbem.client.CIMClient;
import javax.wbem.client.UserPrincipal;
import javax.wbem.client.PasswordCredential;

import java.rmi.*;
import java.util.Enumeration;

/**
 * Deletes the class specified in the command line. Works in the default
 * namespace root/cimv2.
 */
public class DeleteClass {
    public static void main(String args[]) throws CIMException {
       CIMClient cc = null;
       // if not four arguments, show usage and exit
       if (args.length != 4) {
           System.out.println("Usage: DeleteClass host className " +
                              "username password"); 
           System.exit(1);
       }
       try {
          // args[0] contains the hostname. We create a CIMNameSpace 
          // (cns) pointing to the default namespace on the specified host
          CIMNameSpace cns = new CIMNameSpace(args[0]);

          // args[2] and args[3] contain the username and password.
          // We create a UserPrincipal (up) using the username and
          // a PasswordCredential using the password.
          UserPrincipal up = new UserPrincipal(args[2]);
          PasswordCredential pc = new PasswordCredential(args[3]);

          cc = new CIMClient(cns, up, pc);

          // Get the class name (args[4]) and create a CIMObjectPath
          CIMObjectPath cop = new CIMObjectPath(args[1]);
          // delete the class
          cc.deleteClass(cop);
   }
   catch (Exception e) {
          System.out.println("Exception: "+e);
   }
   if (cc != null) {
       cc.close();
       }
    }
}

Setting Access Control

You can set access control on a per-user or namespace basis. The following access control classes are stored in the root\security namespace:

You can set access control for individual users to the CIM objects within a namespace by creating an instance of the Solaris_UserACL class and then changing the access rights for that instance. Similarly, you can set access control for a namespace by creating an instance of the Solaris_NameSpaceACL class and then using the createInstance method to set the access rights for that instance.

An effective way to combine the use of these two classes is to use the Solaris_NameSpaceACL class first, to restrict access to all users to the objects in a namespace. Then, you can use the Solaris_UserACL class to grant selected users access to the namespace.

The Solaris_UserAcl Class

The Solaris_UserAcl class extends the Solaris_Acl base class, from which it inherits the string property capability with a default value of r (read only). You can set the capability property to any one of the following values for access privileges.

Access Right 

Description 

r

Read 

rw

Read and Write 

w

Write 

none 

No access 

The Solaris_UserAcl class defines the following key properties. Only one instance of the namespace and user name ACL pair can exist in a namespace.

Property 

Data Type 

Purpose 

nspace

string

Identifies the namespace to which the ACL applies.

username

string

Identifies the user to which the ACL applies.

To Set Access Control for a User
  1. Create an instance of the Solaris_UserAcl class. For example:

    ... 
    /* Create a namespace object initialized with root\security
    (name of namespace) on the local host. */
    
    CIMNameSpace cns = new CIMNameSpace("", "root\security");
    
    // Connect to the root\security namespace as root. 
    cc = new CIMClient(cns, user, user_passwd);
    
    // Get the Solaris_UserAcl class 
    cimclass = cc.getClass(new CIMObjectPath("Solaris_UserAcl");
    
    // Create a new instance of the Solaris_UserAcl
    class ci = cimclass.newInstance();
    ...

  2. Set the capability property to the desired access rights. For example:

    ...
    /* Change the access rights (capability) to read/write for user Guest
    on objects in the root\molly namespace.*/
    ci.setProperty("capability", new CIMValue(new String("rw")); 
    ci.setProperty("nspace", new CIMValue(new String("root\molly")); 
    ci.setProperty("username", new CIMValue(new String("guest"));
    ...

  3. Update the instance. For example:

    ...
    // Pass the updated instance to the CIM Object Manager 
    cc.createInstance(new CIMObjectPath(), ci);
    ...  

The Solaris_NamespaceAcl Class

The Solaris_NamespaceAcl extends the Solaris_Acl base class, from which it inherits the string property capability with a default value r (read-only for all users). The Solaris_NamespaceAcl class defines this key property.

Property 

Data Type 

Purpose 

nspace

string

Identifies the namespace to which the access control list applies. Only one instance of the namespace ACL can exist in a namespace.

To Set Access Control for a Namespace
  1. Create an instance of the Solaris_namespaceAcl class. For example:

    ...
    /* Create a namespace object initialized with root\security  
    (name of namespace) on the local host. */   
    CIMNameSpace cns = new CIMNameSpace("", "root\security"); 
    
    // Connect to the root\security namespace as root. 
    cc = new CIMClient(cns, user, user_passwd);
    
    // Get the Solaris_namespaceAcl class 
    cimclass = cc.getClass(new CIMObjectPath("Solaris_namespaceAcl");
    
    // Create a new instance of the Solaris_namespaceAcl 
    class ci = cimclass.newInstance();
    ...

  2. Set the capability property to the desired access rights. For example:

    ...
    /* Change the access rights (capability) to read/write 
    to the root\molly namespace. */
    ci.setProperty("capability", new CIMValue(new String("rw")); 
    ci.setProperty("nspace", new CIMValue(new String("root\molly"));
    ...

  3. Update the instance. For example:

    // Pass the updated instance to the CIM Object Manager 
    cc.createInstance(new CIMObjectPath(), ci);  

Working with Qualifiers and Qualifier Types

A CIM qualifier is an element that characterizes a CIM class, instance, property, method, or parameter. Qualifiers have the following attributes:

In MOF syntax, each CIM qualifier must have a CIM qualifier type defined. Qualifiers do not have a scope attribute, which indicates the CIM elements that can use the qualifier. You can only define scope in the qualifier type declaration. You cannot change scope in a qualifier.

The following sample code shows the MOF syntax for a CIM qualifier type declaration. This statement defines a qualifier type named key, with a Boolean data type (default value false), which can describe only a property and a reference to an object. The DisableOverride flavor means that key qualifiers cannot change their value.

Qualifier Key : boolean = false, Scope(property, reference), 
                    Flavor(DisableOverride);

The following sample code shows the MOF syntax for a CIM qualifier. In this sample MOF file, key and description are qualifiers for the property a. The property data type is an integer with the property name a.

{
[key, Description("test")]
int a;
};

Getting and Setting CIM Qualifiers

A qualifier flavor is a flag that governs the use of a qualifier. Flavors describe rules that specify whether a qualifier can be propagated to derived classes and instances and whether or not a derived class or instance can override the qualifier's original value.


Example 3-19 Setting CIM Qualifiers

This example sets a list of CIM qualifiers for a new class to the qualifiers in its superclass.

{

 try {
     cimSuperClass = cimClient.getClass(new CIMObjectPath(scName));
        Vector v = new Vector();
        for (Enumeration e = cimSuperClass.getQualifiers().elements();
                         e.hasMoreElements();) { 
CIMQualifier qual = (CIMQualifier)((CIMQualifier)e.nextElement()).clone();
        v.addElement(qual);
        }
        cimClass.setQualifiers(v); 
 } catch (CIMException exc) {
          return;
        }
    }
}
...


Batching Client Requests

You can batch multiple CIMClient API calls into a single remote call to reduce the delay introduced by multiple remote message exchanges. You use an instance of the BatchCIMClient class to build the list of operations that you want to execute in a batch request. Then use the performBatchOperations method of the CIMClient class to send the list of operations to the CIM Object Manager.


Note -

A batch operation does not imply a single transaction. Each operation is independent of the other operations included in the batch and has no dependencies on the success or failure of the preceding operations.


The BatchCIMClient class contains methods that enable you to perform the same CIM operations as in non-batch mode. These methods are similar to CIMClient methods except that the BatchCIMClient methods do not return the same types as their equivalents in the CIMClient class because the values are returned as a list after the batch operation is complete. The methods return an integer operation ID which you can use to get the result of the operation later. As methods of BatchCIMClient are invoked, the BatchCIMClient object builds a list of CIMOperationobjects that will be executed later.

When the client executes the batch operation list by invoking CIMClient's performBatchOperations method, a BatchResult object is returned that contains the results of the batch operation. Clients can then pass the operation ID to the getResult method of the BatchResult class to get the results of the operations. If an operation on the list generates an exception, an exception object is embedded in the BatchResult object. When you invoke the getResult method with the ID of the operation that failed, the exception is thrown by the getResult method.


Example 3-20 Batching Example

The following example shows how you can use the batching API to perform multiple operations in one remote call. In this example, three operations - enumerateInstanceNames, getClass, and enumerateInstances are performed as a single batch operation.

import java.util.Enumeration;
import java.util.ArrayList;
import java.util.Vector;
import java.lang.String;

import javax.wbem.cim.*;
import javax.wbem.client.*;
import javax.wbem.client.UserPrincipal;
import javax.wbem.client.PasswordCredential;


public class TestBatch {
    public static void main(String args[]) throws CIMException {
	       CIMClient cc = null;
	       CIMObjectPath cop = null;
	       String protocol = CIMClient.CIM_RMI;
	       if (args.length < 4) {
	           System.out.println("Usage: TestBatch host user passwd 
                                classname " + "[rmi|http]");
	           System.exit(1);
	           }
	       try {
	           CIMNameSpace cns = new CIMNameSpace(args[0]);

	           UserPrincipal up = new UserPrincipal(args[1]);
	           PasswordCredential pc = new PasswordCredential(args[2]);
	           if (args.length == 5 && args[4].equalsIgnoreCase("http")) {
	    	           protocol = CIMClient.CIM_XML;
	           }
	           cc = new CIMClient(cns, up, pc, protocol);

	           CIMObjectPath op = new CIMObjectPath(args[3]);

	           BatchCIMClient bc = new BatchCIMClient();
	           int[] ids = new int[3];

	           ids[0] = bc.enumerateInstanceNames(op);
	           ids[1] = bc.getClass(op, false, true, true, null);
	           ids[2] = bc.enumerateInstances(op, true, false, false, 
                                           false, null);

	           BatchResult br = cc.performBatchOperations(bc);

            Enumeration instanceNames = (Enumeration)br.getResult
                                        (ids[0]);
	           CIMClass cl = (CIMClass)br.getResult(ids[1]);
	           Enumeration instances = (Enumeration)br.getResult(ids[2]);

	           while (instanceNames.hasMoreElements()) {
	               System.out.println((CIMObjectPath)instanceNames.
                                    nextElement());
	           }

	           System.out.println(cl.toMOF());

	           while (instances.hasMoreElements()) {
	               System.out.println((CIMInstance)instances.
                                    nextElement());
	           }

	       }
	       catch (Exception e) {
	           e.printStackTrace();
	           System.out.println("Exception: "+e);
	       }

	       // close session.
	       if (cc != null) {
	           cc.close();
	       }
    }
}

Handling CIM Events


Note -

For in-depth information on CIM Indications and how they are used to communicate occurrences of events, see the Distributed Management Task Force (DMTF) Event white paper at http://www.dmtf.org/education/whitepapers.php.


An event is a real world occurrence. An indication is an object that communicates the occurrence of an event. In the Common Information Model, indications are published—not events. Providers generate an indication when an event takes place.

An indication may have zero or more triggers, which are recognitions of changes in state. WBEM does not have an explicit object representing a trigger. Instead, a trigger is implied by the following:


For example, when a service terminates and a trigger is engaged, this event results in an indication that serves as notification that the service has terminated.


You can view the related CIM event classes in the Solaris WBEM Services schema at /usr/sadm/lib/wbem/doc/mofhtml/index.html. The class is structured as follows:

Table 3-5 CIM_Indication Class Structure

Root Class 

Superclass 

Subclass 

CIM_Indication

CIM_ClassIndication

CIM_ClassCreation , CIM_ClassDeletion, CIM_ClassModification

 

CIM_InstIndication

CIM_InstCreation, CIM_InstDeletion, CIM_InstMethodCall, CIM_InstModification, CIM_InstRead

 

CIM_ProcessIndication

CIM_AlertIndication, CIM_AlertInstIndication, CIM_ThresholdIndication, CIM_SNMPTrapIndication

About Indications

CIM events can be classified as either life cycle or process. A life cycle event is a built-in CIM event that occurs in response to a change to data in which a class is created, modified, or deleted, or a class instance is created, modified, deleted, read, or has a method invocation. A process event is a user-defined event that is not described by a life cycle event.

Event providers generate indications in response to requests made by the CIM Object Manager. The CIM Object Manager analyzes subscription requests and uses the EventProvider and/or the CIMIndicationProvider interface to contact the provider, requesting that it generate the appropriate indications. When the provider generates the indication, the CIM Object Manager routes the indication to the destinations specified by the CIM_IndicationHandler instances. These instances are created by the subscribers.

Event providers are located in the same manner as instance providers. In the case of subscriptions pertaining to instance life cycle indication (subclasses of CIM_InstIndication), once the CIM Object Manager determines the classes covered by the subscription, it contacts the instance providers for those classes. For process indications, the CIM Object Manager contacts the appropriate provider using the Provider qualifier.

The CIM Object Manager and the CIM Object Manager Repository handle indications under the following circumstances:

In these cases, the provider does not generate indications or implement the EventProvider interface. In addition, the provider can delegate event generation responsibilities to the CIM Object Manager. The CIM Object Manager invokes enumerateInstances on the providers and compares snapshots of previous states to current states to determine if instances have been created, modified, or deleted.


Note -

In most cases, providers should handle their own indications since polling carries a high overhead. In order to generate indications, the provider itself must poll. In this case, the provider can delegate the task to the CIM Object Manager.


If a provider implements the EventProvider interface, the CIM Object Manager invokes the methods in the interface and takes actions according to the responses. When the CIM Object Manager determines that a particular provider must participate in a subscription request, the methods are invoked in the following order:

  1. mustPoll - Invoked by the CIM Object Manager for CIM_InstCreation, CIM_InstDeletion, and CIM_InstModification to determine if the provider wants the CIM Object Manager to poll. If the provider does not implement the EventProvider interface, the CIM Object Manager assumes polling by default.

  2. authorizeFilter - If the provider implements the Authorizable interface, this method is invoked by the CIM Object Manager to determine if the subscription is authorized. The provider can make the determination based on the user ID of the owner of the indication handler—the user who receives the indications—or based on the user ID of the user who created the subscription.

    If the provider does not implement the Authorizable interface, the CIM Object Manager performs the default read authorization check for the namespace.

    If the provider does not implement the EventProvider interface and the CIM Object Manager tries to poll, the authorization succeeds if enumerateInstances succeeds on the provider.

  3. activateFilter - Invoked by the CIM Object Manager when the authorization succeeds and the provider does not want to be polled.

  4. deActivateFilter - Called when a subscription is removed either by the subscriber or the CIM Object Manager; for example, if the destination handler malfunctions.

About Subscriptions

A client application can subscribe to be notified of CIM events. A subscription is a declaration of interest in one or more streams of indications. Currently, providers cannot subscribe for event indications.

An application that subscribes for indications of CIM events describes the following:

The occurrence of an event is represented as an instance of one of the subclasses of the CIM_Indication class. An indication is generated only when a client subscribes to the event.

To Create a Subscription

An application can create one or more event filters with one or more event handlers. Event indications are not delivered until the application creates the event subscription.

  1. Create an instance of CIM_Listener. See Adding a CIM Listener..

  2. Create an instance of CIM_IndicationFilter. See Creating an Event Filter.

  3. Create an instance of CIM_IndicationHandler. See Creating an Event Handler.

  4. Bind the to the CIM_IndicationFilter to the CIM_IndicationHandler. See Binding an Event Filter to an Event Handler.

Adding a CIM Listener

To receive indications of CIM events, first add an instance of CIMListener to CIMClient, by invoking the addCIMListener method on CIMClient.


Note -

The CIMListener interface must implement the indicationOccured method, which takes the argument CIMEvent. This method is invoked when an indication is available for delivery.



Example 3-21 Adding a CIM Listener

// Connect to the CIM Object Manager
cc = new CIMClient();

// Register the CIM Listener
cc.addCIMListener(
new CIMListener() {
    public void indicationOccured(CIMEvent e) {
    }
});


Creating an Event Filter

Event filters describe the types of events to be delivered and the conditions under which they are delivered. To create an event filter, create an instance of the CIM_IndicationFilter class and define values for its properties. Each event filter works only on events that belong to the namespace to which the filter belongs.

The CIM_IndicationFilter class has string properties that you can set to uniquely identify the filter, specify a query string, and specify the query language that parses the query string. Currently, only the WBEM Query Language (WQL) is supported.

Table 3-6 CIM_IndicationFilter Properties

Property 

Description 

Required/Optional 

SystemCreationClassName

The name of the system on which the creation class for the filter resides or to which it applies. 

Optional. The value is decided by the CIM Object Manager. 

SystemName

The name of the system on which the filter resides or to which it applies. 

Optional. The default for this key property is the name of the system on which the CIM Object Manager is running. 

CreationClassName

The name of the class or subclass used to create the filter.  

Optional. The CIM Object Manager assigns CIM_IndicationFilter as the default for this key property.

Name

The unique name of the filter. 

Optional. The CIM Object Manager assigns a unique name. 

SourceNamespace

The path to a local namespace where the CIM indications originate. 

Optional. The default is null. 

Query

A query expression that defines the conditions under which indications are generated. Currently, only Level 1 WBEM Query Language (WQL) expressions are supported. To learn more about WQL query expressions, see Chapter 5, Writing WBEM Queries.

Required. 

QueryLanguage

The language in which the query is expressed. 

Required. The default is WQL (WBEM Query Language). 

To Create an Event Filter
  1. Create an instance of the CIM_IndicationFilter class:

    CIMClass cimfilter = cc.getClass
            (new CIMObjectPath(“CIM_IndicationFilter”),
             true, true, true, null);
    CIMInstance ci = cimfilter.newInstance();

  2. Specify the name of the event filter:

    Name = “filter_all_new_solarisdiskdrives”

  3. Create a WQL string to identify that event indications to return:

    String filterString = “SELECT * 
            FROM CIM_InstCreation WHERE sourceInstance 
            ISA Solaris_DiskDrive”;

  4. Set property values in the cimfilter instance to identify the name of the filter, the filter string to select CIM events, and the query language (WQL) to parse the query string.

    ci.setProperty(“Name”, new 
            CIMValue("filter_all_new_solarisdiskdrives”));
    ci.setProperty("Query", new CIMValue(filterString));
    ci.setProperty("QueryLanguage", new CIMValue("WQL");)

  5. Create an instance of the cimfilter instance called filter and store it in the CIM Object Manager Repository:

    CIMObjectPath filter = cc.createInstance(new
                                                   CIMObjectPath(), ci);


Example 3-22 Creating an Event Filter

CIMClass cimfilter = cc.getClass(new CIMObjectPath
                                (“CIM_IndicationFilter”), true);
CIMInstance ci = cimfilter.newInstance();
//Assuming that the test_a class exists in the namespace
String filterString = "select * from CIM_InstCreation where sourceInstance 
                       isa test_a"

ci.setProperty("query", new CIMValue(filterString));
CIMObjectPath filter = cc.createInstance(newCIMObjectPath(), ci);


Creating an Event Handler

An event handler is an instance of a CIM_IndicationHandler class. You set the properties in an instance of the CIM_IndicationHandler class to uniquely name the handler and identify the UID of its owner. The CIM Event MOF defines a CIM_IndicationHandlerCIMXML class for describing the destination for indications to be delivered to client applications using the HTTP protocol. The Solaris Event MOF extends the CIM_IndicationHandler class by creating the Solaris_JAVAXRMIDelivery class to handle delivery of indications of CIM events to client applications using the RMI protocol. RMI clients must instantiate the Solaris_JAVAXRMIDelivery class to set up an RMI delivery location.

Table 3-7 CIM_IndicationHandler Properties

Property 

Description 

Required/Optional 

SystemCreationClassName 

The name of the system on which the creation class for the handler resides or to which it applies. 

 Optional. Completed by the CIM Object Manager.

SystemName 

The name of the system on which the handler resides or to which it applies. 

Optional. The default value for this key property is the name of the system on which the CIM Object Manager is running. 

CreationClassName 

The class or subclass used to create the handler. 

Optional. The CIM Object Manager assigns the appropriate class name as the default for this key property. 

Name 

The unique name of the handler. 

Optional. The client application must assign a unique name. 

Owner 

The name of the entity that created or maintains this handler. The provider can check this value to determine whether or not to authorize a handler to receive an indication. 

Optional. The default value is the Solaris user name of the user creating the instance. 


Example 3-23 Creating an Event Handler

// Create an instance of the Solaris_JAVAXRMIDelivery class or get
// the appropriate instance of the handler.
CIMInstance ci = cc.getIndicationHandler(null);

//Create a new instance (delivery) from
//the rmidelivery instance.
CIMObjectPath delivery = cc.createInstance(new CIMObjectPath(), ci);


Binding an Event Filter to an Event Handler

You bind an event filter to an event handler by creating an instance of the CIM_IndicationSubscription class. When you create an indication of this class, indications for the events specified by the event filter are delivered.

The following example creates a subscription (filterdelivery) and defines the filter property to the filter object path created in “To Create an Event Filter”, and defines the handler property to the delivery object path created in Example 3–23.


Example 3-24 Binding an Event Filter to an Event Handler

CIMClass filterdelivery = cc.getClass(new 
        CIMObjectPath(“CIM_IndicationSubscription”), 
        true, true, true, null);
ci = filterdelivery.newInstance():

//Create a property called filter that refers to the filter instance.
ci.setProperty("filter", new CIMValue(filter));

//Create a property called handler that refers to the delivery instance.
ci.setProperty("handler", new CIMValue(delivery));

CIMObjectPath indsub = cc.createInstance(new CIMObjectPath(), ci);


Reading and Writing Log Messages

The Solaris MOFs include logging classes. Clients can create and read log records using these classes to record errors, warnings, and informational messages. For example, a log message can indicate when a system cannot access a serial port, when a system successfully mounts a file system, or when the number of processes that are running on a system exceeds the allowed number.

The underlying providers for the logging classes can forward logging requests to the syslog daemon, the default logging system in the Solaris operating environment. See syslogd(1M).

About Log Files

WBEM log messages are stored in individual log files in the /var/sadm/wbem/log directory. The names of the log files, the directory in which the log files are stored, the log file size limit, the number of log files to store, and whether to forward messages to syslogd(1M) are properties that you manipulate with the singleton instance of the Solaris_LogServiceProperties class.

The format of each log entry is defined by the Solaris_LogEntry class, which is a subclass of CIM_LogRecord. You can find Solaris_LogEntry in Solaris_Device1.0.mof, and CIM_LogRecord in CIM_Device26.mof.

A log message includes the following elements:

Table 3-8 Log Message Elements

Element 

Description 

Category

Type of message – application, system, or security 

Severity

Severity of the condition – warning or error 

Application

Name of the application (or the provider) that is writing the log message 

User

Name of the user who was using the application when the log message was generated 

Client Machine

Name and IP address of the system that the user was on when the log message was generated 

Server Machine

Name of the system on which the incident that generated the log message occurred 

Summary Message

Descriptive summary of the incident 

Detailed Message

Detailed description of the incident 

Data

Contextual information that provides a better understanding of the incident 

SyslogFlag

Boolean flag that specifies whether or not to send the message to syslogd(1M)


Example 3-25 Creating an Instance of Solaris_LogEntry

This example creates an instance of Solaris_LogEntryand sets the instance.

public class CreateLog {
    public static void main(String args[]) throws CIMException {

        // Display usage statement if insufficient command line
        // arguments are passed.
        if (args.length < 3) {
            System.out.println("Usage: CreateLog host username password 
                               " + "[rmi|http]"); 
            System.exit(1);
        }

        String protocol = CIMClient.CIM_RMI;
        CIMClient cc = null;
        CIMObjectPath cop = null;
        BufferedReader d = new BufferedReader(new InputStreamReader
                                             (System.in));

        String input_line = "";

        // Query user for number of records that need to be created.
        System.out.print("How many log records do you want to write? ");
        int num_recs = 0;

        try {
                num_recs = Integer.parseInt(d.readLine());
        } catch (Exception ex) {
                ex.printStackTrace();
                System.exit(1);
        }

        // Over-arching try-catch block
        try {
            CIMNameSpace cns = new CIMNameSpace(args[0]);
            UserPrincipal up = new UserPrincipal(args[1]);
            PasswordCredential pc = new PasswordCredential(args[2]);

            // Set up the transport protocol - set by default to RMI.
            if (args.length == 4 && args[3].equalsIgnoreCase("http")) {
                protocol = CIMClient.CIM_XML;
            }

            cc = new CIMClient(cns, up, pc, protocol);

                Vector keys = new Vector();
                CIMProperty logsvcKey = null;


                // Prompt user for relevant info needed to create the
                // log record.

                System.out.println("Please enter the record Category: ");
                System.out.println("\t(0)application, (1)security, 
                                                      (2)system");
                logsvcKey = new CIMProperty("category");
                input_line = d.readLine();
                logsvcKey.setValue(new CIMValue(Integer.valueOf
                                               (input_line)));
                keys.addElement(logsvcKey);
                System.out.println("Please enter the record Severity:");
                System.out.println("\t(0)Informational, (1)Warning, 
                                                        (2)Error");
                logsvcKey = new CIMProperty("severity");
                input_line = d.readLine();
                logsvcKey.setValue(new CIMValue(Integer.valueOf
                                  (input_line)));
                keys.addElement(logsvcKey);
                logsvcKey = new CIMProperty("Source");
                System.out.println("Please enter Application Name:");
                logsvcKey.setValue(new CIMValue(d.readLine()));
                keys.addElement(logsvcKey);
                logsvcKey = new CIMProperty("SummaryMessage");
                System.out.println("Please enter a summary message:");
                logsvcKey.setValue(new CIMValue(d.readLine()));
                keys.addElement(logsvcKey);
                logsvcKey = new CIMProperty("DetailedMessage");
                System.out.println("Please enter a detailed message:");
                logsvcKey.setValue(new CIMValue(d.readLine()));
                keys.addElement(logsvcKey);
                logsvcKey = new CIMProperty("RecordData");
                logsvcKey.setValue(
                        new CIMValue("0xfe 0x45 0xae 0xda random data"));
                keys.addElement(logsvcKey);
                logsvcKey = new CIMProperty("SyslogFlag");
                logsvcKey.setValue(new CIMValue(new Boolean(true)));
                keys.addElement(logsvcKey);
                CIMObjectPath logreccop = 
                        new CIMObjectPath("Solaris_LogEntry", keys);
                CIMClass logClass = cc.getClass(logreccop);
                CIMInstance ci = logClass.newInstance();
                ci.setClassName("Solaris_LogEntry");
                ci.setProperties(keys);
                // System.out.println(ci.toString());

                // Create as many instances of the record as requested.
                for (int i = 0; i < num_recs; i++) {
                        cc.createInstance(logreccop, ci);
                }
        } catch (Exception e) {
            System.out.println("Exception: "+e);
                e.printStackTrace();
        }

        // close session.
        if (cc != null) {
            cc.close();
        }
    }
}


Example 3-26 Displaying a List of Log Records

This example displays a list of log records.

 public class ReadLog {
    public static void main(String args[]) throws CIMException {

        String protocol = CIMClient.CIM_RMI;

        // Display usage statement if insufficient command line
        // arguments are passed.
        if (args.length < 3) {
            System.out.println("Usage: ReadLog host username password " +
                               "[rmi|http]"); 
            System.exit(1);
        }

        CIMClient cc = null;
        CIMObjectPath cop = null;
        CIMObjectPath serviceObjPath = null;
        Vector inVec = new Vector();
        Vector outVec = new Vector();

        // Over-arching try-catch block
        try {
            CIMNameSpace cns = new CIMNameSpace(args[0]);
            UserPrincipal up = new UserPrincipal(args[1]);
            PasswordCredential pc = new PasswordCredential(args[2]);

            // Set up the transport protocol - set by default to RMI.
            if (args.length == 4 && args[3].equalsIgnoreCase("http")) {
                protocol = CIMClient.CIM_XML;
            }

            cc = new CIMClient(cns, up, pc, protocol);

            cop = new CIMObjectPath("Solaris_LogEntry");

            // Enumerate the list of instances of class Solaris_LogEntry
            Enumeration e = cc.enumerateInstances(cop, true, false,
                                                false, false, null);

            // iterate over the list and print out each property.
            for (; e.hasMoreElements(); ) {
                System.out.println("---------------------------------");
                CIMInstance ci = (CIMInstance)e.nextElement();
                System.out.println("Log filename : " + 
                    ((String)ci.getProperty("LogName").getValue().
                                                       getValue()));
                int categ = 
    (((Integer)ci.getProperty("Category").getValue().getValue()).
       intValue());
                if (categ == 0)
                    System.out.println("Category : Application Log");
                else if (categ == 1)
                    System.out.println("Category : Security Log");
                else if (categ == 2)
                    System.out.println("Category : System Log");
                int severity = 
    (((Integer)ci.getProperty("Severity").getValue().getValue()).
       intValue());
                if (severity == 0)
                    System.out.println("Severity : Informational");
                else if (severity == 1)
                    System.out.println("Severity : Warning Log!");
                else if (severity == 2)
                    System.out.println("Severity : Error!!");
                System.out.println("Log Record written by :" + 
    ((String)ci.getProperty("Source").getValue().getValue()));
                System.out.println("User : " + 
    ((String)ci.getProperty("UserName").getValue().getValue()));
                System.out.println("Client Machine : " + 
    ((String)ci.getProperty("ClientMachineName").getValue().getValue()));
                System.out.println("Server Machine : " + 
    ((String)ci.getProperty("ServerMachineName").getValue().getValue()));
                System.out.println("Summary Message : " + 
    ((String)ci.getProperty("SummaryMessage").getValue().getValue()));
                System.out.println("Detailed Message : " + 
    ((String)ci.getProperty("DetailedMessage").getValue().getValue()));
                System.out.println("Additional data : " + 
    ((String)ci.getProperty("RecordData").getValue().getValue()));
                boolean syslogflag =
((Boolean)ci.getProperty("SyslogFlag").getValue().getValue()).
  booleanValue();
                if (syslogflag == true) {
                    System.out.println("Record was written to syslog");
                } else {
                    System.out.println("Record was not written to syslog");
                }
                System.out.println("---------------------------------");
            }
        } catch (Exception e) {
            System.out.println("Exception: "+e);
            e.printStackTrace();
        }

        // close session.
        if (cc != null) {
            cc.close();
        }
    }
}