Saturday Dec 08, 2007

Bye Bye


Good bye to SUN.

I wish good luck to SUN microsystems.

Monday Aug 27, 2007

openInstaller provides a way to declare platform specific config attributes

openInstaller has a way to provide the platform specific value in declarative way.
User need not to write java code to specify platform specific config attribute value.


Following is an example.
e.g


In this example we have config attribute "InstallHome",Here we show the way to specify
platform specific value for property "installhome".


<prop name=InstallHome>
<!-- applies to all other Unix -->
<value osType="Unix">/opt/sun/wbsvr7</value>
<!-- applies to all Solaris -->
<value osType="Unix" osName="SunOS">/opt/SUNWwbsvr7</value>
<!-- applies to all Solaris 10-->
<value osType="Unix" osName="SunOS" osVers="5.10">/opt/SUNWwbsvr7/s10</value>
<!-- applies only to Solaris 11 x86_64 -->
<value osType="Unix" osName="SunOS" osVers="5.11" osArch="x86_64">/opt/SUNWwbsvr7/s11/x64</value>
<!-- applies to all Linux -->
<value osType="Unix" osName="Linux">/opt/sun/linuxwb7</value>
<!-- applies to windows -->
<value osType="Windows">C:\\\\WebServer7</value>
</prop>


So in above example you can see we are declaring, for solaris, most generic to more
specific platform value,also this example contains value for Linux and Windows platform too.


If Installer runs on windows or Linux platform it pickus up windows or Linux value specified.
If openInstaller runs on Solaris, as you are seeing we have different value for solaris,
Installer picks up most specific value.So if installer runs on solaris version 11
with Arch 64, It will pick up "/opt/SUNWwbsvr7/s11/x64" value.


If it run on anyother UNIX flavour platform, Installer picks up "/opt/sun/wbsvr7" value.


Thats it for now.


Keep watching for more openInstaller feature,You can try openInstaller from http://openinstaller.org/.
Also you can login to IRC channel #openInstaller to get any openInstaller support.

Sunday Jul 08, 2007

Proxy pattern, Java and protection proxy

Proxy pattern is very important in developer world. That can be used in many real scenario. This pattern is useful when we want to have access control to object by creating protection proxy.Now we will see the scenario where we can use proxy pattern and we will use java to implement it.Lets say we have two employee SunA and SunB.Employee has two attributes name and grade. In Manager and employee scenario, one employee can set its own name, but he cant set another employee name,Similarly one employee cant set its own grade ,but He can set another employee grade.
How we are going to achieve this access control ?????


Proxy pattern and java is going to help to resolve this problem.So here we are going to create two proxy objects,one for accessing its own object and second for accessing another object, Because Java creates the proxy class for us,we need a way to tell the proxy class what to do. We cant put the access control code in to the Proxy class,So if can't put the code in Proxy class , where do we put it ?? In InvocationHandler.The job of the InvocationHandler is to respond to any method call on the proxy.
I am going to give a try to explain this by code samples.


First we will create the Employee interface:
Employee.java


package proxypattern;


public interface Employee {
    public String getName();
    public int getGrade();
    public void setName(String aName);
    public void setGrade(int aGrade);


}


Implementation of this :
EmployeeImpl.java


package proxypattern;


public class EmployeeImpl implements Employee{
private String gName;
private int gGrade;
    public EmployeeImpl() {
    }
    public String getName(){
        return gName;
    }
    public int getGrade(){
        return gGrade;
    }
    public void setName(String aName){
        gName = aName;
       
    }
    public void setGrade(int aGrade){
        gGrade = aGrade;
    }


}


Next step is we will create two InvocationHandler. InvocationHandlers implements the behaviour of the proxy. Java takes care of creating the actual proxy class and object,We need to supply handler that know what to do when a method is called on it.


FirstInvocationHandler.java
package proxypattern;


import java.lang.reflect.\*;


public class FirstInvocationHandler implements InvocationHandler {
Employee gEmployee;
    public FirstInvocationHandler(Employee aEmployee) {
        gEmployee = aEmployee;
    }
    public Object invoke(Object aProxy, Method aMethod, Object aArgs[])
                  throws IllegalAccessException {
        try{
            if(aMethod.getName().startsWith("get")){
                return aMethod.invoke(gEmployee, aArgs);
            }
            else if (aMethod.getName().equals("setGrade")){
                throw new IllegalAccessException();
            }
            else if (aMethod.getName().startsWith("set")){
                return aMethod.invoke(gEmployee, aArgs);
            }
        }catch (InvocationTargetException aEx){
            aEx.printStackTrace();
        }
        return null;
    }


}



SecondInvocationHandler.java
package proxypattern;
import java.lang.reflect.\*;


public class SecondInvocationHandler implements InvocationHandler {


  Employee gEmployee;
    public SecondInvocationHandler(Employee aEmployee) {
        gEmployee = aEmployee;
    }
    public Object invoke(Object aProxy, Method aMethod, Object aArgs[])
                  throws IllegalAccessException {
        try{
            if(aMethod.getName().startsWith("get")){
                return aMethod.invoke(gEmployee, aArgs);
            }
            else if (aMethod.getName().equals("setName")){
                throw new IllegalAccessException();
               
            }
            else if (aMethod.getName().startsWith("set")){
                return aMethod.invoke(gEmployee, aArgs);
               
            }
        }catch (InvocationTargetException aEx){
            aEx.printStackTrace();
        }
        return null;
    }


}



So Above we have created two invocation handler to deal with two different proxies.You can see that we need to implement only invoke method of InvocationHandler interface,invoke method has parameter proxy object that will invoke this handler,method object that was invoked and args that is arguments to method.This InvocationHandler makes call on real object as per condition defined.


Next we will see how to get the Proxy objects.


Employee getFirstProxy(Employee aEmployee){
        return (Employee)Proxy.newProxyInstance(
                aEmployee.getClass().getClassLoader(),
                aEmployee.getClass().getInterfaces(),
                new FirstInvocationHandler(aEmployee));
    }



Employee getSecondProxy(Employee bEmployee) {
        return (Employee)Proxy.newProxyInstance(
                bEmployee.getClass().getClassLoader(),
                bEmployee.getClass().getInterfaces(),
                new SecondInvocationHandler(bEmployee));
    }



Above we have two methods that returns proxy objects , for creating proxy object We are calling Proxy's static method newProxyInstance(), that takes as arguments , classloader of real object,interfaces and invocationhandler.We pass the real object into the constructor of InvocationHandler. 
We will create a Class to create employee database,that we will use in sample program.


package proxypattern;


import java.util.\*;


public class EmployeeDB {
HashMap < String, Employee >theEmployeeDB = new HashMap< String, Employee>();
    public EmployeeDB() {
    }
    public void addEmployee(Employee aEmployee){
        theEmployeeDB.put(aEmployee.getName(), aEmployee);
    }
public Employee getEmployee(String aName){
    return theEmployeeDB.get(aName);
}
}


Now we will put everything togather and will test the whole concept we tried to learn.


TestProxyPattern.java


package proxypattern;
import java.lang.reflect.\*;
public class TestProxyPattern {
EmployeeDB gDB = new EmployeeDB();
    /\*\* Creates a new instance of TestProxyPattern \*/
    public TestProxyPattern() {
        Employee aEmp = new EmployeeImpl();
        aEmp.setName("SunA");
        aEmp.setGrade(1);
        Employee bEmp = new EmployeeImpl();
        bEmp.setName("SunB");
        bEmp.setGrade(2);
        gDB.addEmployee(aEmp);
        gDB.addEmployee(bEmp);
       
    }


    /\*\*
     \* @param args the command line arguments
     \*/
    public static void main(String[] args) {
        TestProxyPattern theProxyPattern = new TestProxyPattern ();
        theProxyPattern.runExample();
    }
    public void runExample(){
        Employee aFirstEmp = gDB.getEmployee("SunA");
        Employee aFirstEmpProxy = getFirstProxy(aFirstEmp);
        aFirstEmpProxy.setName("SunAChanged");
        System.out.println("NEW NAME of SunA is ::"+aFirstEmp.getName());
        try{
            aFirstEmpProxy.setGrade(10);
        }catch(Exception theEx){
            System.out.println(aFirstEmp.getName()+", You can't set your grade yourself," +
                    "Your grade is still::"+aFirstEmp.getGrade());
        }
       Employee aSecondEmp = gDB.getEmployee("SunB");
       Employee aSecondEmpProxy = getSecondProxy(aFirstEmp);
       aSecondEmpProxy.setGrade(5);
       System.out.println(aFirstEmp.getName()+", Your grade is changed by :"
               +aSecondEmp.getName()+". Your grade is now :"+aFirstEmp.getGrade());
       try{
           aSecondEmpProxy.setName("SunA_changed_by_SunB");
       } catch(Exception theEx){
           System.out.println("No one can change anyone name So "
                   +"First employee name is still :"+aFirstEmp.getName());
       }
    }
    Employee getFirstProxy(Employee aEmployee){
        return (Employee)Proxy.newProxyInstance(
                aEmployee.getClass().getClassLoader(),
                aEmployee.getClass().getInterfaces(),
                new FirstInvocationHandler(aEmployee));
    }
    Employee getSecondProxy(Employee bEmployee) {
        return (Employee)Proxy.newProxyInstance(
                bEmployee.getClass().getClassLoader(),
                bEmployee.getClass().getInterfaces(),
                new SecondInvocationHandler(bEmployee));
    }


}


If we run the code we see following output :


NEW NAME of SunA is ::SunAChanged
SunAChanged, You can't set your grade yourself,Your grade is still::1
SunAChanged, Your grade is changed by :SunB. Your grade is now :5
No one can change anyone name So First employee name is still :SunAChanged

Monday Jun 11, 2007

openInstaller : Dynamic calculation of default values

OpenInstaller have  many great features,one of them is ,deducing the default values during runtime.

Sometimes we need to calculate the default value of configuration property at runtime for configuration.There are two ways to define dynamic default values in openInstaller:


1.Define substitution expression as an <if:eval> element
2.Define arbitrary substitution logic as an <if:eval-engine> element

Substitution expression:

If a particular property has an <if:eval> expression, this expression is evaluated and the resulting value substituted as the property's default value (just as though the document author had hard-coded the default value in the <value> element).  An <if:eval> property can contain one of three different supported types of substitution values.

The three types are:

1.Simple Substitution
2.Target Substitution
3.Component Substitution


Simple Substitution:

Syntax    

    :[varname]

Example

    <value if:eval=":[username]">root</value>

During runtime the value in the if:eval property will be resolved against a known set of parameters defined by a default set of parameters supplied by the install author in the ui.prefs file.

If the Substitution Engine is not able to resolve the variable name against the default supplied values then it will fall back to default value provided.
 
- Component Substitution:

Syntax   

    :[component:varname]

Example

    <value if:eval=":[component:SomeComponent.group.username]">root</value>

During runtime the value in the if:eval property will be resolved against the known components and their associated groups/values.  The name is treated as fully-qualified, where the first part of the “.”-separated name represents a component name, then the intermediate parts of the name represent a hierarchy of group names, and the final part of the name represents the parameter name of the parameter whose value should be substituted here.

If the Substitution Engine is not able to resolve the value then it will fall back to default value provided.

- Target Substitution:

Syntax

    :[target:varname]
    :[target(host-redirect):varname]

Examples

<value if:eval=":[target:sys.ipAddress]">127.0.0.1</value>
<value if:eval=":[target(purplehaze.sfbay):sys.ipAddress]">10.4.116.100</value>

In the first example will substitute the value of the IP Address of the localhost whereas the second example will substitute the value of the IP Address of purplehaze.sfbay.

OpenInstaller defines a certain set of attributes associated with a host (target). References to a value associated to a particular host can be made with this style of syntax.

When the (host-redirect) syntax is used, the value returned will be the value of the attributed associated with the specified hostname (or IP address) defined by the (host-redirect). If the value cannot be looked up relative to that host, then the default value is used instead (along with a warning in the engine log).

When the (host-redirect) is not used, the value is assumed to be the local host where the code is executing.

There are 8 predefined variable for target substitution.

1.sys.hostName        Host name of host
2.sys.ipAddress        IP Address of host
3.sys.homeDir        Home Directory of current user\*
4.sys.tmpDir        Temporary directory used by the running VM\*
5.sys.osVersion        Release version of OS (e.g. `uname -r` output on Solaris)\*
6.sys.OSArch        OS Architecture (e.g. `uname -p` output).\*
7.sys.userName        Current user's login account name \*
8.sys.userDir        The current directory from which the engine was invoked \*

These values are only available for the local host. Using with a (host-redirect) has no effect.

Substitution Engine:

Instead of defining a substitution expression, an install author may want to execute arbitrary code ( a substitution engine) to compute the default value.  For example, if the default value changes based on environment (e.g. If a port number is in use, the default port number should be decremented before being shown to the user).

For this purpose, instead of (or in addition to, see below) defining an <if:eval> element, an <if:eval-engine> element can also be defined. 

Example:

    <value if:eval-engine="com.sun.ph.Substitution">default value</value>

In the above example, the specified class is loaded using the engine's classpath (which includes dynamic plugins.  The engine is expected to implement the following interface:

public interface com.sun.install.provider.conf.oor.dynamic.EvalEngine {
  /\*\*
   \* This method should be used to resolve and return the correct value for substitution.
   \* The two arguments to the method, aEvalvalue and aDefaultValue can be used as per
   \* the need. Never return a null string instead return an empty string since the
   \* return value will may be displayed using UI.
   \*
   \*@param aEvalValue        The resolved 'eval' tag value.
   \*@param aDefaultValue    The default value of the value tag.
   \*@return                The resolved value which shouldn't be null.
   \*@throws EnhancedException If an unexpected error occurs
   \*/
  public String resolve(String aEvalValue, String aDefaultValue) throws Enhanced
Exception;
}

Notice that the first argument to the resolve method is the result of evaluating any <if:eval> element, if specified.  This gives a parameter three potential ways to specify a default value:  a hard-coded default, a resolved substitution variable, or the return value of an arbitrary piece of executed code.

Other Substitutions:

In addition to configuration schema definitions, other areas of this project will recognize and evaluate substitution expressions:

Properties files – Any property file supplied by the install author or end user is scanned for potential :[] substitution tokens.  Any expressions found are substituted with the resulting values as computed by the above descriptions.  If no value can be computed, a warning is issued and an empty value is used.

XML Resource files – Any XML file loaded by the engine is scanned for potential :[] substitution tokens. As above, any expressions found are substituted with the resulting values as computed by the above descriptions.  If no value can be computed, a warning is issued and an empty value is used.

User input – Any user input (e.g. In a GUI entry screen, or through an answer file) is scanned for potential :[] substitution tokens.  As above, any expressions found are substituted with the resulting values as computed by the above descriptions.  If no value can be computed, a warning is issued and an empty value is used.

 Want to know more about the openInstaller , visit http://openinstaller.org/ .

Sunday Jun 03, 2007

openInstaller Configuration capabilities


Middleware configuration has been mostly ad-hoc, relying on product installers to be coded with precise, but non-extensible, knowledge of the structure and expectations of configuration requirements.  Configuration data is not exposed outside of the integrated installers in a consistent way, requiring that any applications that wish to provide configuration management capabilities to do so without the help of the work done by the integration effort.  In addition, the incremental cost of adding new components to an already-integrated stack is very high since the already-integrated configuration support is highly coupled and dependent on precise orchestration of the logic for configuring the bundled components.

Through the formalization of the configurator interface, the installer will be only one of many management applications that can drive the configuration mechanism. This effectively separates the development of installers, consoles, remote  monitoring and control mechanisms from that of managed software.  This should improve the ease (in terms of development effort, communication, release engineering and documentation) with which the installer (and other management applications) integrate with the managed software.

So What install developer has to do for configuration!!!Couple of XML file creation,Thats it. Basically installer calls the product configurators through init-config interface, init-config interface can be implemented in user's preferred language.

XML File,open office registry format, contains the configuration attributes to configure the component.Following is the sample XML file that contains the configuration attribute.

<oor:component-schema oor:version="1.1" oor:name="ProductA"
 xsi:schemaLocation="http://openoffice.org/2001/registry"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:oor="http://openoffice.org/2001/registry"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:if="http://openinstaller.org/config/V1"
 xml:lang='en-US'>
 <component>
     <group oor:name="Administration">
        <prop oor:name="A_ADMIN_USER" oor:type="xs:string">
           <value>admin</value>
           <info>
             <desc xml:lang="en-US">Administrator Name</desc>
           </info>
        </prop>
        <prop oor:name="A_ADMIN_PASSWORD" oor:transient="true" oor:type="xs:string">
           <value>admin123</value>
           <info>
             <desc xml:lang="en-US">Administrator Password</desc>
           </info>
        </prop>
        </group>
 </component>
</oor:component-schema>

The component-schema element contains the name of the component and the package belongs to. The name is used for a number of other purposes and is referred to later on (e.g. When other components' parameters refer to this component and its parameters, the reference must use this name). The package name is unused at this time but remains for compatibility with APOC UI Format. The component-schema element contains exactly one component element, which has no attributes.  Within the component element,that contains one or more groups.

Every group element has a name associated with it, which is used to name the group and is used later to reference a parameter within this group.  Every group can have one or more property elements.

Property elements have a name, type, transient, and nillable attribute.  The name of the property is used to refer to this property.The type is the type of property, used for validation of potential values (e.g. An integer must be an integer, etc). A nillable value can take on the empty value (e.g. “” for a string), and is used for passwords that initially have no default value.  Any parameter which is non-nillable (nillable=false) must have a valid, non-nil default value.  The transient attribute, when set to true, means that the variable must not be stored on non-volatile storage (also used for passwords). The Info element within the group element contains human-readable (and internationalized) text describing the element which can be used to show on a user interface.

Property elements also have zero or more Constraint elements associated with them. Constraints restrict the values that can be assigned to the parameter.  For example:

<constraints>
  <minLength oor:value=”9”/>
</constraints>

Says that the any value must be 9 characters or greater before it will successfully be assigned to this parameter.  There are a number of other basic constraints available (see the appendix and schema for the possible values). The Value element contains the default value for this parameter. It should be domain- and machine-independent.  In other words, the default value should be reasonable under any and all circumstances.  This is the value used when no other value is given.  For example, in many cases, a default value of “127.0.0.1” is used for parameters that represent the IP address of a service endpoint:

<component>
     <group oor:name="Service Endpoints">
        <prop oor:name="HTTP-Service-IP" oor:type="oor:ip">
           <value>127.0.0.1</value>
        </prop>
     </group>
</component>

Sometimes it is impossible (or not practical or desirable)  to define a single default value, but rather the default value should be computed at runtime,In my next blog I will be talking about the openInstaller's capability of dynamically deducing the default values.

Where to place the component's configurator !!!!

1. openInstaller will, by default, look for product configurators ("init-config") in the ${INSTALL_HOME}/${COMPONENT-ID}/bin directory.  This is an attempt to track the still-evolving multi-install fileystem layout.

2. In addition, it is now possible to override this default location for one or more configurators.To override the location in which openInstaller looks, you can use the Init-Config-Locations engine option.  e.g.
-p Init-Config-Locations=ProdA:/usr/share/lib/iProdA/install

This tells the openInstaller engine that the configurator for the "ProdA" product is in the /usr/share/lib/iProdA/install directory.  Within that directory, openInstaller will first look for "init-config" (assumed to be an executable file),then "init-config.vbs" (visual basic), finally "init-config.bat" (Windows Batch).  You can also specify a direct path to a regular file, which openInstaller interprets as a complete path to the executable.

In general, you can override the defaults for more than one product:

-p Init-Config-Locations=ProdA:/foo,appsvr:/bar/init-config.exe,/baz

This says that the ProdA configurator is in /foo, and that the appsvr configurator is /bar/init-config.exe, and that for all other products, look in /baz.

If a default value (e.g. one with out a "product:" prefix) is left off, then the old default applies ($INSTALL_HOME/<comp>/bin)

In addition, standard openInstaller substitution syntax applies. For example, to specify a location relative to $INSTALL_HOME,one can say:
-p Init-Config-Locations= ProdA::[component:InstallHome:directory:INSTALL_HOME]/relative/path/to/config.sh

Notice the double ":" - the first part is "ProdA:" (the prefix telling openInstaller which product), and the second part is ":[subst]" where subst is the standard openInstaller substitution syntax.  This can be used to form very dynamic paths when referencing a number of dynamic variables (port numbers, install directories for other components, IP addresses, etc).
openInstaller configuration framework has the capability to cature the error ,if any, occurs during configuration,and pass back to openInstaller,So the openInstaller can display the proper error message.

There are lot more things about the openInstaller configuration, I will be talking in my next blog.

You can visit to http://openinstaller.org/ to know more about openInstaller. 

Monday Apr 16, 2007

My First Blog

This is my first blog and of course this is my first blog for openinstaller too. OpenInstaller!!!!! yep , one more contribution to open source ,innovation in installer area by SUN Microsystems.OpenInstaller provides lot of flexibility to end users and developers. I will be coming with more details in my next blog.
About

sandeeps

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today