Sun Java System Portal Server 7.1 Developer's Guide

Chapter 7 Extending the Base Providers

This chapter includes instructions for creating a custom provider by:

Examples are provided for developing a sample HelloWorldProvider that will display a message (“Hello World”). This is to illustrate the fundamentals of how the Provider interface works first, followed by examples of how ProviderAdapter and ProfileProviderAdapter classes make the implementation easier. Use the instructions (provided with the sample HelloWorldProvider) for developing your custom provider by extending any one of these APIs.

Implementing the Provider Interface

The Provider interface defines the interface for implementing the provider component of a channel. If you want to directly implement the Provider interface, code should be written to implement all of the methods in this interface. You will not have access to the ProviderContext and the properties in the display profile cannot be accessed. If you are implementing this interface, it’s up to the provider implementation to get the properties.

For more information on this interface, see the Javadocs at http://hostname.port/portal/javadocs.

ProcedureTo create a custom provider by implementing the Provider interface

This section provides the instructions for creating a custom provider by implementing the Provider interface. The process described here includes creating a sample HelloWorldProvider that prints “Hello World!” on the provider’s channel.

  1. Create a new Java class which implements the Provider interface.

    For the sample HelloWorldProvider, create the class file as shown below.

    HelloWorldProviderP.java File


    package custom;
    
    import java.net.URL;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.sun.portal.providers.Provider;
    import com.sun.portal.providers.ProviderException;
    import com.sun.portal.providers.UnknownEditTypeException;
    
    public class HelloWorldProviderP implements Provider {
        public void init(
            String name, HttpServletRequest req
        ) throws ProviderException { }
    
        public StringBuffer getContent(
            HttpServletRequest request, HttpServletResponse response
            ) throws ProviderException {
            return new StringBuffer("Hello World!");
        }
    
        public java.lang.StringBuffer getContent(java.util.Map m)
    		throws ProviderException {
            return new StringBuffer("Hello, world!");
        }
    
        public StringBuffer getEdit(HttpServletRequest request, HttpServletResponse
    		response) throws ProviderException {
            // Get the edit page and return it is as a StringBuffer.
            return null;
        }
    
        public java.lang.StringBuffer getEdit(java.util.Map m) throws 
    		ProviderException {
            return null;
        }
    
        public int getEditType() throws UnknownEditTypeException {
            return 0;
        }
    
        public URL processEdit(HttpServletRequest request, 
    		HttpServletResponse response) throws ProviderException {
            return null;
        }
    
        public java.net.URL processEdit(java.util.Map m) throws ProviderException {
            return null;
        }
    
        public boolean isEditable() throws ProviderException {
            return false;
        }
    
        public boolean isPresentable() {
            return true;
        }
    
        public boolean isPresentable(HttpServletRequest req) {
            return true;
        }
    
        public java.lang.String getTitle() throws ProviderException {
            return "HelloWorld Channel";
        }
    
        public java.lang.String getName() {
            return "HelloWorld!";
        }
    
        public java.lang.String getDescription() throws ProviderException {
            return "This is a sample HelloWorld channel";
        }
    
        public java.net.URL getHelp(javax.servlet.http.HttpServletRequest req)
    		throws ProviderException {
            return null;
        }
    
        public long getRefreshTime() throws ProviderException {
            return 0;
        }
    
        public int getWidth() throws ProviderException {
            return 0;
        }
    }
  2. Compile the class and put it in the user defined class directory.

    The default directory for the class file is PortalServer-DataDir/portals/portal-ID/desktop/classes. To compile the HelloWorldProviderP.java file, type:


    javac -d PortalServer-DataDir/portals/portal-ID/desktop/classes -classpath PortalServer-base
    /sdk/desktop/desktopsdk.jar:AccessManager-base
    /lib/servlet.jar HelloWorldProviderP.java
  3. Define the new provider and channel definition in a temporary XML file.

    The sample HelloWorldProvider provider and channel definitions are in the HelloProviderP.xml and HelloChannelP.xml files.

    HelloProviderP.xml File


    <?xml version="1.0" encoding="utf-8" standalone="no"?>
    <!DOCTYPE DisplayProfile SYSTEM "jar://resources/psdp.dtd">
    
    <Provider name="HelloWorldProviderP" class="custom.HelloWorldProviderP">
    	<Properties>
    		<String name="title" value="Hello World Channel"/>
    		<String name="description">This is a test of the hello world provider</String>
    		<String name="width" value="thin"/>
    	</Properties>
    </Provider>

    HelloChannelP.xml File


    <?xml version="1.0" encoding="utf-8" standalone="no"?>
    <!DOCTYPE DisplayProfile SYSTEM "jar://resources/psdp.dtd">
    
    <Channel name="HelloWorldP" provider="HelloWorldProviderP">
    	<Properties>
    		<String name="message" value="Hello World Test!!! - non-localized "/>
    		<Locale language="en" country="US">
    		<String name="message" value="Hello World - 
    			I am speaking English in the United States!!!"/>
    		</Locale>
    	</Properties>
    </Channel>
  4. Upload the provider and channel XML fragments using the psadmin add-display-profile command.

    For the sample HelloWorldProvider, upload the HelloProviderP.xml and HelloChannelP.xml XML fragments using the psadmin add-display-profile command. See the Sun Java System Portal Server 7.1 Command Line Reference for more information on psadmin add-display-profile command.

  5. Specify the URL in your browser to access the channel.


    http://hostname:port/portal/dt?provider=HelloWorldP

Extending the ProviderAdapter Class

As the ProviderAdapter class has implemented many of the methods of the Provider interface, the custom provider can extend ProviderAdapter and can override some of the methods or define any new methods. The advantage of extending this class versus implementing the Provider interface directly is that you will maintain forward compatibility as additions are made to the PAPI. Existing code will by default call the methods in this class. Also, the ProviderAdapter contains default implementations of methods in the Provider interface that you can use.

ProcedureTo create a custom provider by extending the ProviderAdapter class

This section provides the instructions for creating a custom provider by extending the ProviderAdapter class. The process described here includes creating a sample HelloWorldProvider that prints “Hello World!” on the provider’s channel.

  1. Create a new java class which extends the ProviderAdapter class.

    For the sample HelloWorldProvider, create the class file as shown here.

    HelloWorldProviderPA.java File


    package custom;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import com.sun.portal.providers.ProviderAdapter;
    import com.sun.portal.providers.ProviderException;
    
    public class HelloWorldProviderPA extends ProviderAdapter {
        public java.lang.StringBuffer getContent (HttpServletRequest request,
    		HttpServletResponse response) throws ProviderException  {
            return new StringBuffer("Hello, world!");
        }
    }
  2. Compile the class and put it in the user defined class directory.

    The default directory for the class file is PortalServer-DataDir/portals/portal-ID/desktop/classes. To compile the HelloWorldProviderPA.java file, type:


    javac -d PortalServer-DataDir/portals/portal-ID/desktop/classes -classpath PortalServer-base
    /sdk/desktop/desktopsdk.jar:AccessManager-base/lib/servlet.jar HelloWorldProviderPA.java
  3. Define the new provider and provider’s channel definition in a temporary XML file.

    The sample HelloWorldProvider XML fragment for the provider is in the HelloProviderPA.xml file.

    HelloProviderPA.xml File


    <?xml version="1.0" encoding="utf-8" standalone="no"?>
    <!DOCTYPE DisplayProfile SYSTEM "jar://resources/psdp.dtd">
    
    <Provider name="HelloWorldProviderPA" class="custom.HelloWorldProviderPA">
        <Properties>
            <String name="title" value="*** TITLE ***"/>
            <String name="description" value="*** DESCRIPTION ***"/>
            <String name="refreshTime" value="0"/>
            <Boolean name="isEditable" value="true"/>
            <String name="editType" value="edit_subset"/>
            <String name="width" value="thin" advanced="true"/>
            <ConditionalProperties condition="locale" value="en">
                <String name="helpURL" value="desktop/HelloWorld.htm" advanced="true"/>
            </ConditionalProperties>
            <String name="helpURL" value="desktop/HelloWorld.htm" advanced="true"/>
            <String name="fontFace1" value="Sans-serif"/>
            <String name="productName" value="Sun Java System Portal Server"/>
            <Collection name="aList">
                <String value="i’m aList"/>
            </Collection>
            <String name="message" value="Sample Hello World Provider"/>
        </Properties>
    </Provider>
  4. Upload the provider and channel XML fragments using the psadmin add-display-profile command.

    For the sample HelloWorldProvider, upload the HelloProviderPA.xml XML fragments using the psadmin add-display-profile command. See the Sun Java System Portal Server 7.1 Command Line Reference for more information on psadmin add-display-profile command.

  5. Include the new channel in one of the existing containers.

    The sample HelloWorldProvider will be displayed only in a Table Desktop layout. To add the channel in the JSPTableContainer from the administration console, follow instructions in the Portal Server administation console online help. To add the channel in the JSPTableContainer manually:

    1. Add the HelloWorldProvider channel XML fragment (in the HelloChannelPA.xml file) for the JSPTableContainer.

      HelloChannelPA.xml File


      <?xml version="1.0" encoding="utf-8" standalone="no"?>
      <!DOCTYPE DisplayProfile SYSTEM "jar://resources/psdp.dtd"> 
      <Container name="JSPTableContainer" provider="JSPTableContainerProvider">
      <Properties> 
      	<Collection name="Personal Channels">
      		<String value="HelloWorldPA"/>
      	</Collection>
      	<Collection name="channelsRow">
      		<String name="HelloWorldPA" value="3"/>
      	</Collection>
      	<Collection name="channelsColumn">
      		<String name="HelloWorldPA" value="3"/>
      	</Collection>
      </Properties>
      <Available>
      	<Reference value="HelloWorldPA"/>
      </Available>
      <Selected>
      	<Reference value="HelloWorldPA"/>
      </Selected>
      <Channels>
      	<Channel name="HelloWorldPA" provider="HelloWorldProviderPA">
      		<Properties>
      			<String name="message" value="Hello World Test!!! - non-localized "/>
      		</Properties>
      	</Channel>
      </Channels>
      </Container>
    2. Use the psadmin modify-display-profile sub command to add the changes to the container.

      If you do not specify a parent object with the -p option, the channel is added at the root level.

  6. Specify the URL in your browser to access the HelloWorld channel inside the JSPTableContainer.


    http://hostname:port/portal/dt?provider=JSPTableContainer/HelloWorldPA

Extending the ProfileProviderAdapter Class

ProfileProviderAdapter has the default implementation of the Provider interface and extends the ProviderAdapter class. It includes some convenient methods that allow the providers to get the channel data from the ProviderContext object. Developers who wish to create a new provider can take advantage of this, by extending the ProfileProviderAdapter class, and create their customized provider class.

ProcedureTo Create a Provider by Extending the ProfileProviderAdapter Class

This section provides the instructions for creating a custom provider by extending the ProfileProviderAdapter class. The sample HelloWorldProvider reads a string property from the user’s display profile and allows the user to edit the string. This sample also includes an example about using the resource bundle.

  1. Create a new Java class which extends the ProfileProviderAdapter class.

    For the sample HelloWorldProvider, create the class file.


    HelloWorldProviderPPA1.java File
    
    package custom;
    
    import java.net.URL;
    import java.util.Hashtable;
    import java.util.ResourceBundle;
    import javax.servlet.http.HttpServletRequest;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.sun.portal.providers.ProfileProviderAdapter;
    import com.sun.portal.providers.ProviderException;
    
    public class HelloWorldProviderPPA1 extends ProfileProviderAdapter {
        private ResourceBundle bundle = null;
    
        // Implement the getContent method
        public StringBuffer getContent(
            HttpServletRequest req, HttpServletResponse res
        ) throws ProviderException {
            Hashtable<String,Object> tags = new Hashtable<String,Object>();
            if (bundle == null) {
                bundle = getResourceBundle();
            }
            tags.put("welcome", bundle.getString("welcome"));
            tags.put("message", getStringProperty("message", true));
            tags.put("properties", getMapProperty("aMap", true));
            StringBuffer b = getTemplate("content.template", tags);
            return b;
        }
    
        // Implement the getEdit method
        public StringBuffer getEdit(
            HttpServletRequest req, HttpServletResponse res
        ) throws ProviderException {
                Hashtable<String,String> tags = new Hashtable<String,String>();
                tags.put("message", getStringProperty("message"));
                tags.put("properties", "");
                StringBuffer b = getTemplate("edit.template", tags);
                return b;
        }
    
        // Implement the processEdit method
        public URL processEdit (
            HttpServletRequest req, HttpServletResponse res
        ) throws ProviderException {
            String message = req.getParameter("message");
            if(message != null) {
                if (!message.equals(getStringProperty("message"))) {
                    // Set the new message
                    setStringProperty("message",message);
                    return null;
                }
            } else {
                    setStringProperty("message","");
                }
            return null;
        }
    }
  2. Compile the class and put it in the user defined class directory.

    The default directory for the class file is PortalServer-DataDir/portals/portal-ID/desktop/classes. To compile the HelloWorldProviderPPA1.java file, type:


    javac -d PortalServer-DataDir/portals/portal-ID/desktop/classes -classpath PortalServer-base
    /sdk/desktop/desktopsdk.jar:AccessManager-base
    /lib/servlet.jar HelloWorldProviderPPA1.java
  3. Define the new provider and provider’s channel definition in a temporary XML file.

    Following is the sample HelloWorldProvider XML fragment for the provider in the HelloProviderPPA1.xml file.


    <?xml version="1.0" encoding="utf-8" standalone="no"?>
    <!DOCTYPE DisplayProfile SYSTEM "jar://resources/psdp.dtd">
    
    <Provider name="HelloWorldProviderPPA1" class="custom.HelloWorldProviderPPA1">
    	<Properties>
    		<String name="title" value="*** TITLE ***"/>
    		<String name="description" value="*** DESCRIPTION ***"/>
    		<String name="refreshTime" value="0"/>
    		<Boolean name="isEditable" value="true"/>
    		<String name="editType" value="edit_subset"/>
    		<Collection name="aMap">
    			<String name="title" value="Ramag"/>
    			<String name="desc" value="My Map"/>
    			<Boolean name="removable" value="true"/>
    			<Boolean name="renamable" value="true"/>
            </Collection>
            <String name="message" value="Hello World Test Provider"/>
    	</Properties>
    </Provider>

    Following is the sample HelloWorldProvider XML fragment for the channel in the HelloChannelPPA1.xml file.


    <?xml version="1.0" encoding="utf-8" standalone="no"?>
    <!DOCTYPE DisplayProfile SYSTEM "jar://resources/psdp.dtd">
    
    <Channel name="HelloWorldPPA1" provider="HelloWorldProviderPPA1">
    	<Properties>
    		<String name="title" value="Hello World Channel"/>
    		<String name="description">This is a test of the hello 
    		world provider</String>
    		<String name="width" value="thin"/>
    		<String name="message" value="Hello World Test!!! - non-localized "/>
    		<Locale language="en" country="US">
    			<String name="message" value="Hello World - I am speaking 
    			English in the United States!!!"/>
    		</Locale>
    	</Properties>
    </Channel>
  4. Upload the provider and channel XML fragments using the psadmin add-display-profile sub command.

    For the sample HelloWorldProvider, upload the HelloProviderPPA1.xml file and HelloChannelPPA1.xml file XML fragments using the psadmin add-display-profile sub command. See the Sun Java System Portal Server 7.1 Command Line Reference for more information on the psadmin add-display-profile sub command.

  5. Include the provider’s channel in one of the existing containers.

    The sample HelloWorldProvider will be displayed in a Table Desktop layout. To add the channel in the JSPTableContainer from the administration console, follow instructions in the Portal Server administration console online help. To add the channel in the JSPTableContainer manually:

    1. Create the HelloWorldProvider channel XML fragment (in the HelloContainerPPA1.xml file) for the JSPTableContainer as shown in below.


      <?xml version="1.0" encoding="utf-8" standalone="no"?> 
      <!DOCTYPE DisplayProfile SYSTEM "jar://resources/psdp.dtd">
       <Container name="JSPTableContainer" provider="JSPTableContainerProvider">
      		<Properties>
       			<Collection name="Personal Channels">
      				<String value="HelloWorldPPA1"/>
      			</Collection>
      			<Collection name="channelsRow">
      				<String name="HelloWorldPPA1" value="3"/>
      			</Collection>
      		</Properties>
       		<Available>
        		<Reference value="HelloWorldPPA1"/>
       		</Available>
       		<Selected>
       			<Reference value="HelloWorldPPA1"/>
       		</Selected>
       		<Channels>
       		</Channels>
       </Container>
    2. Use the psadmin modify-display-profile sub command to add the channel to a container.

      If you do not specify a parent object with the -p option, the channel is added at the root level.

  6. Create the template files if the new provider requires template files.

    The sample HelloWorldProvider requires content.template and edit.template files.

    1. Create the content.template file for the HelloWorldProvider.

      The contents of content.template file is shown below:.


      <html>
      <head></head>
      <body bgcolor="white">
      [tag:welcome]<br><br>
      [tag:message]<br><br>
      [tag:properties]
      </body>
      </html>
    2. Create the edit.template file for the HelloWorldProvider.

      The contents of edit.template file is shown below:


      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
      <HTML>
      	<HEAD>
      		[tag:noCache]
      		<TITLE>[tag:productName]</TITLE>
      	</HEAD>
      	<BODY BGCOLOR="#FFFFFF">
              <FONT SIZE=+0 FACE="[tag:fontFace1]">
              <LINK REL="stylesheet" TYPE="text/css" HREF="
      			[surl:/desktop/css/style.css]" TITLE="fonts">
              <CENTER>
      
              [tag:bulletColor]
              [tag:banner]
      
              <FORM ACTION="dt" NAME="edit_form" METHOD=POST 
      			ENCTYPE="application/x-www-form-urlencoded">
              <INPUT TYPE=HIDDEN NAME="action" SIZE=-1 VALUE="process">
              <INPUT TYPE=HIDDEN NAME="provider" SIZE=-1 VALUE="[tag:providerName]">
      
              [tag:inlineError]
      
              <TABLE BORDER=0 CELLPADDING=0 CELLSPACING=3 WIDTH="100%">
                 <TR>
                   <TD WIDTH="100%" VALIGN=TOP>
                       <CENTER>
                         <BR>
                         <FONT SIZE="+2" FACE="[tag:fontFace1]">
                         <B>
                         Edit [tag:title]</B></FONT>
                         <BR>
                         [tag:contentOptions]
                       </CENTER>
                   </TD>
                 </TR>
              </TABLE>
      
              <BR>
      
              <FONT SIZE=+0 FACE="[tag:fontFace1]">
              <INPUT TYPE=SUBMIT NAME="Submit" VALUE="Finished" CLASS="button">
              <INPUT TYPE=BUTTON OnClick="location=’[tag:desktop_url]’"
      			VALUE="Cancel" CLASS="button">
              </font>
      
              <br>
      
              <P>
              </FORM>
              <BR>
              [tag:menubar]
              </font>
      	</BODY>
      </HTML>
  7. Create the channel directory under the template root directory.

    By default, the template root directory is PortalServer-DataDir/portals/portal-ID/desktop/desktoptype. For this example, create a HelloWorldPPA1 directory under /var/opt/SUNWportal/portals/portal-ID/desktop/desktoptype directory.

  8. Copy all the template files over to the newly created directory. For example:


    cp content.template PortalServer-DataDir/portals/
    	portal-ID/desktop/desktoptype/HelloWorldPPA1
    cp edit.template /var/opt/SUNWportal/portals/portal-ID
    /desktop/desktoptype/HelloWorldPPA1
  9. Create a resource bundle properties file.

    The sample HelloWorldProvider includes a HelloWorldProviderPPA1.properties file.

    1. Create a HelloWorldProviderPPA1.properties properties file.

    2. Include the following property in the file:

      welcome=Welcome to Hello World!!

    3. Copy the resource bundle to the user defined class directory.

      By default, the class directory to copy the resource bundle into is PortalServer-DataDir/portals/portal-ID/desktop/classes.

  10. Specify the URL in your browser to access the HelloWorld channel inside the JSPTableContainer.


    http://hostname:port/portal-ID/dt?provider=JSPTableContainer

ProcedureTo Create a Provider by Extending the ProfileProviderAdapter Class

This section provides the instructions for creating a custom provider by extending the ProfileProviderAdapter. The process includes creating a sample provider that prints “Hello World!” on the provider’s channel. The following sample HelloWorldProvider reads a string property from the user’s display profile and allows the user to edit the string.

The sample HelloWorldProvider described here will also support EDIT_COMPLETE, which means this provider is responsible for generating the complete edit form with header, footer, and handling of the form submit actions. To accomplish this:

  1. Create the Java class, which will generate the content for the channels backed by this provider.

    For the sample HelloWorldProvider, create the class file.


    package custom.helloworld;
    
    import java.util.Hashtable;
    import java.util.ResourceBundle;
    
    import java.net.URL;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.sun.portal.providers.ProfileProviderAdapter;
    import com.sun.portal.providers.ProviderException;
    import com.sun.portal.providers.context.ProviderContext;
    import com.sun.portal.providers.context.
    ProviderContextException;
    import com.sun.portal.providers.context.Theme;
    
    public class HelloWorldProviderPPA2 extends
    ProfileProviderAdapter {
        private ResourceBundle bundle = null;
        private final static String BANNER
    		= "banner";
        private final static String BANNER_TEMPLATE
    	   = "banner.template";
        private final static String BORDER_COLOR
    		= "borderColor";
        private final static String BORDER_WIDTH
    		= "borderWidth";
        private final static String BULLET_COLOR
    		= "bulletColor";
        private final static String BULLET_COLOR_JS
    		= "bulletColor.js";
        private final static String BG_COLOR
    		= "bgColor";
        private final static String CONTENT_LAYOUT
    		= "contentLayout";
        private final static String
    		CONTENT_LAYOUT_TEMPLATE = 
    		"contentLayout.template";
        private final static String DESKTOP_URL
    		= "desktop_url";
        private final static String EDIT_PROVIDER_TEMPLATE =
    		"editTemplate.template";
        private final static String ERR_MESSAGE
    		= "errMessage";
        private final static String FONT_COLOR
     	   = "fontColor";
        private final static String FONT_FACE
    		= "fontFace";
        private final static String FONT_FACE1
    		= "fontFace1";
        private final static String FRONT_CONTAINER_NAME =
    		"frontContainerName";
        private final static String INLINE_ERROR
    		= "inlineError";
        private final static String MENUBAR
    		= "menubar";
        private final static String MENUBAR_TEMPLATE
    		= "menubar.template";
        private final static String MESSAGE
    		= "message";
        private final static String NO_CACHE
    		= "noCache";
        private final static String NO_CACHE_TEMPLATE
    		= "noCache.template";
        private final static String PARENT_CONTAINER_NAME =
    		"parentContainerName";
        private final static String PRODUCT_NAME
    		= "productName";
        private final static String THEME_CHANNEL
    		= "theme_channel";
        private final static String TITLE_BAR_COLOR
    		= "titleBarColor";
        private final static String TOOLBAR_ROLLOVER
    		= "toolbarRollover";
        private final static String TOOLBAR_ROLLOVER_JS = 
    		"toolbarRollovers.js";
    
    /*Implement the getContent method*/
         public StringBuffer getContent(
         HttpServletRequest req, HttpServletResponse res
         ) throws ProviderException {
            Hashtable<String,Object> tags = 
    			getStandardTags(req);
            if (bundle == null) {
                 bundle = getResourceBundle();
            } tags.put("welcome", 
    			bundle.getString("welcome"));
            tags.put("message", 
    			getStringProperty("message"));
            StringBuffer b = getTemplate
    			("content.template", tags);
            return b;
        }
    
    /*Implement the getEdit method*/
        public StringBuffer getEdit(
        HttpServletRequest req, HttpServletResponse res)
        throws ProviderException {
            String containerName = 
    			req.getParameter("containerName");
            String providerName = 
    			req.getParameter("targetprovider");
            String editChannelName = 
    			req.getParameter("provider");
            // Get the standard tags, 
    			which will include the 
    			menubar, footer, etc.
            Hashtable<String,Object> tags = 
    			getStandardTags(req);
            tags.put("help_link", 
    			getHelpLink("editPage",req));
            // Provider specific tags
            tags.put(MESSAGE, getStringProperty(MESSAGE));
            tags.put("title", getTitle());
            tags.put( "providerName", providerName);
            tags.put( "contentOptions", 
    			getTemplate("edit.template",
    			tags).toString());
            if (containerName != null) {
                 tags.put(FRONT_CONTAINER_NAME, containerName);
            }
             StringBuffer b = getTemplate
    			(EDIT_PROVIDER_TEMPLATE, tags);;
             return b;
        }
    
        /* Implement Process Edit Method */
        public URL processEdit(
        HttpServletRequest req, HttpServletResponse res
        ) throws ProviderException {
            String message = req.getParameter(MESSAGE);
            if(message != null) {
                if( !message.equals(getStringProperty(MESSAGE)) ) {
                    setStringProperty(MESSAGE,message);
                    return null;
                }
            } else {
                 setStringProperty(MESSAGE,"");
            }
            return null;
        }
    
    /* HelloWorld Provider supports, 
    		edit_type=edit_complete which means,
    	the provider is responsible for generating
     a complete edit form with header,footer and html 
    buttons. getStandardTags method populates the
    hashtable with all the standard tags */
        protected Hashtable getStandardTags
    		(HttpServletRequest req) throws 
    		ProviderException {
            Hashtable<String,Object> tags = 
    			new Hashtable<String,Object>();
            ProviderContext pc = getProviderContext();
            String property = null;
            property = FONT_FACE1;
            tags.put(FONT_FACE1, getStringProperty(FONT_FACE1));
            property = PRODUCT_NAME;
            tags.put(PRODUCT_NAME, 
    			getStringProperty(PRODUCT_NAME));
            tags.put(PARENT_CONTAINER_NAME, 
    			pc.getDefaultChannelName());
            // templates
            tags.put(MENUBAR, getTemplate(MENUBAR_TEMPLATE));
            tags.put(CONTENT_LAYOUT, 
    			getTemplate(CONTENT_LAYOUT_TEMPLATE));
            tags.put(TOOLBAR_ROLLOVER, 
    			getTemplate(TOOLBAR_ROLLOVER_JS));
            tags.put(NO_CACHE, getTemplate(NO_CACHE_TEMPLATE));
            tags.put(DESKTOP_URL, pc.getDesktopURL(req));
            tags.put(BULLET_COLOR, 
    			getTemplate(BULLET_COLOR_JS));
             tags.put(BANNER, getTemplate(BANNER_TEMPLATE));
            // error tags (if any)
             String err = req.getParameter("error");
             if (err != null) {
                 tags.put(ERR_MESSAGE, err);
                 tags.put("inlineError", 
    				  getTemplate("inlineError.template"));
             } else {
                 // no error, put in dummy 
    					 tags so lookup doesn’t fail
                 tags.put(ERR_MESSAGE, "");
                 tags.put(INLINE_ERROR, "");
            }
            // theme attributes
                try {
                    tags.put( BG_COLOR, Theme.
    						getAttribute( getName(), pc,
    						BG_COLOR ));
                    tags.put( TITLE_BAR_COLOR, 
    						Theme.getAttribute( getName(),
    						pc, TITLE_BAR_COLOR ));
                    tags.put( BORDER_COLOR, 
    						Theme.getAttribute( getName(), pc,
    						BORDER_COLOR ));
                    tags.put( FONT_COLOR, 
    						Theme.getAttribute( getName(), pc,
    						FONT_COLOR ));
                    tags.put( BORDER_WIDTH, 
    						Theme.getAttribute( getName(),
    						pc, BORDER_WIDTH ));
                    tags.put( FONT_FACE, 
    						Theme.getAttribute( getName(),
    						pc, FONT_FACE));
                    if( Theme.getSelectedName(getName(),
    						pc).equals
    						( Theme.CUSTOM_THEME ) ) {
                        tags.put(THEME_CHANNEL, getStringProperty
    							("customThemeChannel"));
                    } else {
                        tags.put(THEME_CHANNEL, getStringProperty
    							("presetThemeChannel"));
                    }
                } catch (ProviderContextException pce) {
                    throw new ProviderException
    							( "TemplateContainerProvider.
    						getStardardTags(): failed to 
    						obtain theme related attribute ", pce );
                }
                 return tags;
            }
    /* GetHelpLink for the Help button in the 
    		banner and footer of the edit page */
            protected String 
    			getHelpLink(String key, HttpServletRequest 
    			req) throws ProviderException{
                try {
                    URL helpLink = getHelp(req, key);
                    if (helpLink != null) {
                        return helpLink.toString();
                    }
                    else {
                        return "";
                }
            }  catch (Throwable t ) {
                throw new ProviderException
    				("HelloWorldProvider.getHelpLink(): 
    					could not get help URL for " + key, t);
            }
        }
    }
  2. Compile the class file.

    To compile the HelloWorldProviderPPA2.java file, type:


    javac -d PortalServer-DataDir/portals/portal-ID/desktop/classes -classpath PortalServer-base
    /sdk/desktop/desktopsdk.jar:AccessManager-base
    /lib/servlet.jar HelloWorldProviderPPA2.java
  3. Create the provider and channel definition for the display profile and load the provider and channel display profile definitions using the psadmin add-display-profile sub command.

    The HelloWorldProvider provider display profile XML fragment (in file HelloProviderPPA2.xml) is shown here:


    <?xml version="1.0" encoding="utf-8" standalone="no"?>
    <!DOCTYPE DisplayProfile SYSTEM "jar://resources/psdp.dtd">
    
    <Provider name="HelloWorldProviderPPA2" class="
    custom.helloworld.HelloWorldProviderPPA2">
    	<Properties>
    		<String name="title" value="*** TITLE ***"/>
    		<String name="presetThemeChannel" value="JSPPresetThemeContainer"
    		advanced="true"/>
    		<String name="customThemeChannel" value="JSPCustomThemeContainer"
    		advanced="true"/>
    		<String name="description" value="*** DESCRIPTION ***"/>
    		<String name="refreshTime" value="0"/>
    		<Boolean name="isEditable" value="true"/>
    		<String name="editType" value="edit_subset"/>
    		<Collection name="aList">
    				<String value="i’m aList"/>
    			</Collection>
    			<Collection name="aMap">
    				<String name="title" value="Ramag"/>
    				<String name="desc" value="My Map"/>
    				<Boolean name="removable" value="true"/>
    				<Boolean name="renamable" value="true"/>
            </Collection>
    		<String name="message" value="Hello World Test Provider"/>
    	</Properties>
    </Provider>

    The HelloWorldProvider channel display profile XML fragment (in file HelloChannelPPA2.xml) is shown here:


    <?xml version="1.0" encoding="utf-8" standalone="no"?>
    <!DOCTYPE DisplayProfile SYSTEM "jar://resources/psdp.dtd">
    
    <Channel name="HelloWorldPPA2" provider="HelloWorldProviderPPA2">
    	<Properties>
    		<String name="title" value="Hello World Channel"/>
    		<String name="fontFace1" value="sans-serif"/>
    		<String name="productName" value="Sun Java System Portal Server"/>
    		<String name="editType" value="edit_complete"/>
    		<String name="description">This is a test of the hello world
    		provider</String>
    		<String name="width" value="thin"/>
    		<String name="message" value="Hello World Test!!! - non-localized "/>
    		<Locale language="en" country="US">
    			<String name="message" value="Hello World - I am speaking
    			English in the United States!!!"/>
    		</Locale>
    	</Properties>
    </Channel>

    Note –

    See the Sun Java System Portal Server 7.1 Command Line Reference for more information on the psadmin sub commands.


  4. Create the resource bundle properties file for the HelloWorldProvider (HelloWorldProviderPPA2.properties) and include the following string:


    welcome=Welcome to Hello World!!
  5. Copy the resource bundle properties file, HelloWorldProviderPPA2.properties, into PortalServer-DataDir/portals/portal-ID/desktop/classes directory.

  6. Develop the template files for the provider.

    The HelloWorldProvider requires the following template files:

    content.template

    <head></head>
    <body bgcolor="white">
    	[tag:welcome]<br><br>
    	[tag:message]<br><br>
    </body>
    </html>
    edit.template

    This file generates the editable fields in the form.


    <p>
    <table border="0" cellpadding="2" cellspacing="0"
    width="100%">
    
    	<tr>
    		<td colspan="3" bgcolor="#333366">
    			<font size=+1 face="[tag:fontFace1]" 
    			color="#FFFFFF"><b>Welcome</b></font>
    		</td>
    	</tr>
    
    	<tr><td><br><br><br></td></tr>
    
    	<tr>
    		<td width="20%" align="RIGHT" NOWRAP>
    			<font face="[tag:fontFace1]" 
    			color="#000000"><label 
    			for="message"><b>Greeting:</b>
    </label></font>
    		</td>
    		<td width="45%">
    			<font face="[tag:fontFace1]"
    			size="+0">
    				<input type="TEXT" name="message"
    				size="50"
    				maxlength="50" value="[tag:message]"
    				id="message">
    			</font>
    		</td>
    	</tr>
    
    	<tr>
    		<td width="20%">&nbsp;</td>
    		<td width="45%">&nbsp;</td>
    	</tr>
    
    </table>
    editTemplate.template

    This file generates a complete form


    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
    <HTML>
    <HEAD>
    	[tag:noCache]
    	<TITLE>[tag:productName]</TITLE>
    </HEAD>
    	<BODY BGCOLOR="#FFFFFF">
    		<FONT SIZE=+0 FACE="[tag:fontFace1]">
    		<LINK REL="stylesheet" TYPE="text/css" HREF="
    		[surl:/desktop/css/style.css]" TITLE="fonts">
    		<CENTER>
    
    		[tag:bulletColor]
    		[tag:banner]
    
    		<FORM ACTION="dt" NAME="edit_form" METHOD=POST 
    		ENCTYPE="application/x-www-form-urlencoded">
    		<INPUT TYPE=HIDDEN NAME="action" SIZE=-1 
    		VALUE="process">
    		<INPUT TYPE=HIDDEN NAME="provider" 
    		SIZE=-1 VALUE="
    		[tag:providerName]">
    
    		[tag:inlineError]
    
    		<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=3
    		WIDTH="100%">
    			<TR>
    				<TD WIDTH="100%" VALIGN=TOP>
    					<CENTER>
    						<BR>
    						<FONT SIZE="+2" 
    						FACE="[tag:fontFace1]">
    						<B>
    						Edit [tag:title]</B></FONT>
    						<BR>
    						[tag:contentOptions]
    					</CENTER>
    				</TD>
    			</TR>
    		</TABLE>
    
    		<BR>
    
    		<FONT SIZE=+0 FACE="[tag:fontFace1]">
    		<INPUT TYPE=SUBMIT NAME="Submit" 
    		VALUE="Finished" 
    		CLASS="button">
    		<INPUT TYPE=BUTTON OnClick="
    		location=’[tag:desktop_url]’
    		"VALUE="Cancel" CLASS="button">
    		</font>
    
    		<br>
    
    		<P>
    		</FORM>
    		<BR>
    		[tag:menubar]
    		</font>
    	</BODY>
    </HTML>
  7. Create the channel directory under the template root directory and copy the templates for the provider into the channel directory under the templates root directory.

    By default, the template root directory is PortalServer-DataDir/portals/portal-ID/desktop/desktoptype. For this example, create a HelloWorldPPA2 directory under PortalServer-DataDir/portals/portal-ID/desktop/desktoptype directory. To copy the templates, for example, type:


    cp content.template PortalServer-DataDir/portals/
    portal-ID/desktop/desktoptype/HelloWorldPPA2
    cp edit.template PortalServer-DataDir/portals/
    portal-ID/desktop/desktoptype/HelloWorldPPA2
    cp editTemplate.template PortalServer-DataDir
    /portals/portal-ID/desktop/desktoptype
    /HelloWorldPPA2
  8. Specify the URL to access the channel from a browser.


    http://hostname:port/portal-ID/dt?provider=HelloWorldPPA2

    To display the provider’s channel as one of the leaf channels for a container, you have to add the channel into the container’s available and selected list. To accomplish this:

  9. Add it to the Available and Selected list for the container.

    For example, to add the HelloWorldProvider to the TemplateTableContainer, use the psadmin modify-display-profile sub command. For more information on the psadmin utility and its sub commands, see the Sun Java System Portal Server 7.1 Command Line Reference.

  10. Login to the Desktop and specify the URL in your browser to access the HelloWorld Channel inside the TemplateTableContainer.


    http://hostname:port/portal-ID/dt?provider=TemplateTableContainer

    Utilize the psadmin utility for transporting channels and providers. Using the psadmin command, the contents of the helloworld.par can be imported to as HelloWorld channel in a different Portal Server software installation. For more information on the psadmin utility and its sub commands, see the Sun Java System Portal Server 7.1 Command Line Reference.

Extending the PropertiesFilter Class

Developers who wish to implement an arbitrary filter to selectively look up properties with certain criteria and/or to store properties that are specific to certain setting can extend the PropertiesFilter class.

ProcedureTo create a custom filter by extending the PropertiesFilter class

  1. Create the Java class, which will implement the filter.

    The class file for the sample DateLaterThanPropertiesFilter is shown here:


    package com.acme.filters;
    
    import java.util.Iterator;
    import java.util.Date;
    import java.text.DateFormat;
    import java.text.ParseException;
    
    import com.sun.portal.providers.context.PropertiesFilter;
    import com.sun.portal.providers.context.PropertiesFilterException;
    import com.sun.portal.providers.context.ProviderContext;
    public class DateLaterThanPropertiesFilter extends PropertiesFilter {
    
        private static final DateFormat dateFormat = 
    		DateFormat.getDateInstance(DateFormat.SHORT);
        private Date date = null;
    
        public DateLaterThanPropertiesFilter() {
            super();
        }
    
        protected void init(String value, boolean required)
    		throws PropertiesFilterException {
            super.init(value, required);
            try {
                date = dateFormat.parse(value);
            } catch (ParseException pe) {
            throw new PropertiesFilterException("DateLaterThanPropertiesFilter:
    			 ", pe);
            }
        }
    
        public String getCondition() {
            return "dateLaterThan";
        }
    
        public boolean match(String condition, String value) throws
    		PropertiesFilterException {
            if (!condition.equals("dateLaterThan")) {
                return false;
            }
            Date cdate = null;
            try {
                cdate = dateFormat.parse(value);
            } catch (ParseException pe) {
                throw new PropertiesFilterException
    				("DateLaterThanPropertiesFilter.match(): ", pe);
            }
            return cdate.after(date);
        }
    }
  2. Compile the class file.

    To compile the DateLaterThanPropertiesFilter.java file, type:


    javac -d /var/opt/SUNWportal/portals/portal-ID
    /desktop/classes -classpath PortalServer-base/sdk/desktop/desktopsdk.jar:
    AccessManager-base/lib/servlet.jar DateLaterThanPropertiesFilter.java
  3. Create the provider display profile XML fragment for the conditional properties.

    The sample display profile XML fragment for the DateLaterThanPropertiesFilter is here:


    <?xml version="1.0" encoding="utf-8" standalone="no"?>
    <!DOCTYPE DisplayProfile SYSTEM "jar://resources/psdp.dtd">
    <Properties>
    	<String name="foo" value="bar">
    	<ConditionalProperties condition="locale" value="en">
    		<String name="foo" value="bar"/>
    		<ConditionalProperties condition="dateLaterThan" value="03/03/2003">
    			<ConditionalProperties condition="client" value="nokia">
    				<String name="foo" value="en 03/03/2003 nokia">
    			</ConditionalProperties>
    		</ConditionalProperties>
    			<ConditionalProperties condition="client" value="nokia">
    				<String name="foo" value="en nokia">
            </ConditionalProperties>
    	</ConditionalProperties>
    </Properties>
  4. Load the display profile using the psadmin modify-display-profile sub command.

    See the Sun Java System Portal Server 7.1 Command Line Reference for more information on this sub command. Alternatively, you can also use the administration console to add and/or modify display profile. See the Portal Server administration console online help for more information.

  5. Implement the code to access the filter in your custom provider class file where you wish to implement this filter.

    For example, in your provider, you can access the sample DateLaterThanPropertiesFilter by doing one of the following:

    • The following Provider implementation for DateLaterThanPropertiesFilter will return “en 03/03/2003 nokia”


      List pflist = new List();
      pflist.add(getProviderContext().getLocalePropertiesFilter( "en", true));
      String filter = "com.acme.filters.DateLaterThanPropertiesFilter" ;
      pflist.add(getProviderContext().getPropertiesFilter( filter, "02/02/2003", true));
      pflist.add(getProviderContext().getClientPropertiesFilter( "nokia", true));
      getStringProperty(getName(), "foo", pflist);
    • The following Provider implementation for DateLaterThanPropertiesFilter will return “en nokia”


      List pflist = new List();
      pflist.add(getProviderContext().getLocalePropertiesFilter( "en", true));
      String filter = "com.acme.filters.DateLaterThanPropertiesFilter" ;
      pflist.add(getProviderContext().getPropertiesFilter
      ( filter, "04/04/2003", false)); // this filter is optional
      pflist.add(getProviderContext().getClientPropertiesFilter( "nokia", true));
      getStringProperty(getName(), "foo", pflist);