Previous     Contents     Index     Next     
iPlanet Portal Server Reference Guide



Appendix B       Putting Code Together


This Appendix describes the development process for a sample iPlanet Portal Server desktop provider application that touches on the public APIs available for integrating an application with the iPlanet Portal Server desktop.



Building an iPlanet Portal Server Provider



Start by taking the HelloWorldProvider.java and reducing it to the bare minimum. For example, change the class name to QuotationProvider and leave the shell of the essential routines:


Table B-1 Minimal Routines for a Provider

Routine

Purpose

QuotationProvider()  

The constructor  

getHTMLContent()  

Used to display the provider's HTML on the desktop  

getHTMLEditForm()  

Used to display an HTML form where the user can set preferences.  

processEditForm()  

Used to process the submitted form created in getHTMLEditForm above.  


Define Specific Requirements and Functionality

For this example, the application should handle Quotation display, as described in the following section:

Depending on a user-specific configuration parameter either:

  • One quote of each user-specified category will be displayed

  • Only one quote from all of the user-specified categories will be displayed

Depending on a user-specific configuration parameter, one of the following will be displayed:

  • The category of, and the quote

  • Only the quote itself

For the "Edit" part of the provider, where the user can edit configuration parameters, the following will displayed:

  • A multiple-choice selection of the types of quotes to be displayed

  • A checkbox to choose whether categories get displayed as well or not

In addition to the user-selectable configuration parameters, only an administrator should be able to change the location of the quotations file (via the Administration Console).


Identify non-iPlanet Portal Server Functionality

In this example, all of the quotations are in a file of the following format:

quote-type|quotation-text

For example:

Computers|blah blah blah - Scott McNealy

Politics|blah blah blah - Genghis kahn

where the category of the quotation is separated from the quotation itself by a vertical bar '|'. For the sake of this example, the file must be located in /var/tmp/quotations. This can be overridden by an iPlanet Portal Server administrator but not by the individual user.


Define Application Attributes/Privileges

For an example, adopt a naming scheme that parallels the default providers that come with iPlanet Portal Server, and name the provider iwtQuotationProvider. The attributes will be called:


Table B-2 Sample Provider Attributes

Attribute

Description

iwtQuotationProvider-possibleCategories  

A multi valued set of strings representing the possible categories of quotes a specific user would be interested in. In the following example, the quotation categories will be limited to "Computers", "Science", and "Freedom".  

iwtQuotationProvider-selectedCategories  

A multi valued set of strings representing the categories of quotes a specific user would be interested in, such as "Computers", "Science", and "Freedom".  

iwtQuotationProvider-displayCategories  

A boolean value indicating whether categories should be displayed with the quotations or not.  

iwtQuotationProvider-fileLocation  

A single string value indicating where the list of quotations is to be found.  


Define the Provider to iPlanet Portal Server

The provider must be registered with the iPlanet Portal Server before the Session, Profile, or Logging APIs may be used. To do this, write (or adapt) an XML file to describe the attributes and privileges, then copy the XML file to /etc/opt/SUNWips/xml, and use ipsadmin to import the XML file into the Profile server. See Chapter 3, "Profile and Policy API" for more details of this function.

The easiest way to begin is to adapt the example helloWorld3 provider's XML file. Take it and modify the names of the component and attributes to be iwtQuotationProvider. The only attributes/privileges in the XML file at this point are the "common" attributes which any provider must have.

Next, add in the attributes specific to this application:

Code Example B-1 XML Defining Attributes and Privileges 

<!--
Attributes, specific
-->

<iwt:Att name="iwtQuotationProvider-possibleCategories"
desc="Possible Quotation Categories"
type="stringlist"
idx="possible_quotation_categories"
userConfigurable="TRUE">
<Val>Computers</Val>
<Val>Freedom</Val>
<Val>Science</Val>
<Val>Work</Val>
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm>
</iwt:Att>

<iwt:Att name="iwtQuotationProvider-selectedCategories"
desc="Selected Quotation Categories"
type="stringlist"
idx="selected_categories"
userConfigurable="TRUE">
<Val>Computers</Val>
<Val>Freedom</Val>
<Val>Science</Val>
<Val>Work</Val>
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm><Wperm>OWNER</Wperm>
</iwt:Att>

<iwt:Att name="iwtQuotationProvider-displayCategories"
desc="Display category along with quotation?"
type="boolean"
idx="display_categories"
userConfigurable="TRUE">
<Val>true</Val>
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm><Wperm>OWNER</Wperm>
</iwt:Att>

<iwt:Att name="iwtQuotationProvider-fileLocation"
desc="Location of the quotations file"
type="string"
idx="file_location"
userConfigurable="TRUE">
<Val>/var/tmp/quotations</Val>
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm>
</iwt:Att>

Attribute by attribute, Table B-3 describes what the XML in the code example means:


Table B-3 Sample Attributes and Privileges

Attribute

Description

iwtQuotationProvider-possibleCategories  

This is a stringlist attribute that the ADMIN and OWNER can read, but only the ADMIN can write. It is preset to use the 3 quotation categories mentioned above, in this example.  

iwtQuotationProvider-selectedCategories  

This is a stringlist attribute that the ADMIN and OWNER can read and write. It is preset to the same categories as the previous attribute.  

iwtQuotationProvider-displayCategories  

This is a boolean attribute that the ADMIN and OWNER can read and write. It is preset to "true" indicating that category names will be displayed with the quotes.  

iwtQuotationProvider-fileLocation  

This is a a single string attribute that the ADMIN and OWNER can read, but only the ADMIN can write. It is preset to /var/tmp/quotations.  



Sample Code



The following code shows how the entire application came together.

Code Example B-2 Sample Desktop Provider File 

// This is a sample desktop provider application used to display
// famous/humorous quotations on the desktop.
//
// It shows how to use the ProfileProviderAdapter API to:
// - display HTML content on the desktop
// - allow the user to edit attributes
//
// It also invokes the Session, Profile and Logging APIs in order to:
// - get/set user-level attributes regarding quotation preferences
// - provide logging

// Where the QuotationProvider.class file can be found.
package com.iplanet.portalserver.providers.quotations;

// Use some basic Java classes
import java.lang.*;
import java.io.*;
import java.util.*;

// Use some basic Java Servlet classes
import javax.servlet.*;
import javax.servlet.http.*;

// Use some iPS classes
import com.iplanet.portalserver.desktop.util.*;
import com.iplanet.portalserver.providers.Provider;
import com.iplanet.portalserver.providers.ProfileProviderAdapter;
import com.iplanet.portalserver.session.Session;
import com.iplanet.portalserver.profile.*;

// The QuotationProvider Class
public class QuotationProvider extends ProfileProviderAdapter implements Provider {

// The constructor - don't need to do any special initialization
// so just invoke the ProfileProviderAdapter's constructor.
public QuotationProvider() {
super();
}

// Generate the HTML that will be displayed in this content provider's
// area on the desktop
public StringBuffer getHTMLContent() throws Exception {
Profile p = getSession().getUserProfile();
StringBuffer content = new StringBuffer(); // Contains HTML to be displayed.
Hashtable quotesHash = new Hashtable(); // A Hash of quote Vectors, one vector per category.
BufferedReader quotesReader; // Used to read the quotes.
String quote; // A single quotation.
Random randomGenerator = new Random(); // To randomly pick quotes.

// Read in the quotations into a Hashtable of Vectors, each containg
// the quotations of a specific category. If we can't read the
// quotations file it's okay - we just won't display any quotes later.
// The category and quotation are separated by a "|" in the quotations
// file.
try {
String quotationFileName = p.getAttributeString("iwtQuotationProvider-fileLocation");
quotesReader = new BufferedReader(new FileReader(new File(quotationFileName)));
while ((quote = quotesReader.readLine()) != null) {
String type = quote.substring(0,quote.indexOf('|'));
if (!quotesHash.containsKey(type)) {
quotesHash.put(type,new Vector());
}
((Vector)(quotesHash.get(type))).addElement(quote.substring(quot e.indexOf('|')+1));
}
} catch (Exception e) {
}

// Determine if user's preference is to display the category along with a quotation.
boolean displayCategories = true;
if (p.getAttributeString("iwtQuotationProvider-displayCategories"). equals("false")) {
displayCategories = false;
}

// Get the possible quotation categories.
Enumeration e = p.getAttribute("iwtQuotationProvider-selectedCategories");

// Print a quotation for each category selected by the user.
while (e.hasMoreElements()) {
String category = (String)e.nextElement();

// If the user wanted to display the category along with the
// quotation then do so.
if (displayCategories) {
content.append("<BOLD>");
content.append(category);
content.append("</BOLD>");
}

// If there are any quotations for this category, pick a random
// one and display it, otherwise note that we didn't find one.
if (quotesHash.containsKey(category)) {
Vector quoteVector = (Vector)quotesHash.get(category);
int whichQuoteIndex = Math.abs(randomGenerator.nextInt())%(quoteVector).size();
content.append("<UL>");
content.append("<LI>");
content.append((String)(quoteVector.elementAt(whichQuoteIndex))) ;
content.append("</LI>");
content.append("</UL>");
} else {
content.append("<UL>");
content.append("<LI>");
content.append("(no quotes of this type found)");
content.append("</LI>");
content.append("</UL>");
}
}

// Now return the HTML we have constructed.
return content;
}

// Generate the HTML that will be displayed to let the user set his preferences.
public StringBuffer getHTMLEditForm() {
StringBuffer content = new StringBuffer();

try {
Profile p = getSession().getUserProfile();

// Display things in a single column table - so things line up.
content.append("<P><TABLE>");

// Let the user choose which categories he wants.
content.append("<TR>");
content.append("<TD VALIGN='top' HALIGN='left'>");
content.append("Types of Quotes to Display");
content.append("</TD>");

// Get the user's selected categories
Vector selectedCategories = new Vector();
Enumeration e2 = p.getAttribute("iwtQuotationProvider-selectedCategories");
while (e2.hasMoreElements()) {
selectedCategories.addElement((String)e2.nextElement());
}

// List the possible categories, marking those that have already
// been selected by the user.
content.append("<TD VALIGN='top' HALIGN='left'>");
Enumeration e = p.getAttribute("iwtQuotationProvider-possibleCategories");
while (e.hasMoreElements()) {
String category = (String)e.nextElement();
content.append("<INPUT TYPE='checkbox' NAME='category-");
content.append(category);
content.append("' VALUE='");
content.append(category);
content.append("'");
if (selectedCategories.contains(category)) {
content.append(" CHECKED");

content.append(">");
content.append(category);
content.append("<BR>");
}
content.append("</TD>");
content.append("</TR>");

// Let the user decide if he wants to display a category with each quotation.
content.append("<TR>");
content.append("<TD VALIGN='top' HALIGN='left'>");
content.append("<INPUT TYPE='checkbox' NAME='display_categories' VALUE='yes'");
if (p.getAttributeString("iwtQuotationProvider-displayCategories"). equals("true")) {
content.append(" CHECKED");
}
content.append(">Display the Category Along With the Quotation");
content.append("</TD>");
content.append("</TR>");

content.append("</TABLE>");
} catch (Exception e) {
}

return content;
}

// Handle the submittal of the edit form.
public int processEditForm(HttpServletRequest req) throws Exception {
Profile p = getSession().getUserProfile();
Enumeration parameterNames = req.getParameterNames();
Vector categorySelections = new Vector();
boolean displayCategories = false;

// Check all the passed parameters and add the selected categories
// as well as check to see if user opted to display categories.
while (parameterNames.hasMoreElements()) {
String parameter = (String)parameterNames.nextElement();
if (parameter.equals("display_categories")) {
displayCategories = true;
} else if (parameter.startsWith("category-")) {
String category = req.getParameter(parameter);
categorySelections.addElement(category);
}
}

// Set the list of selected categories for later storing in the profile database.
p.setAttribute("iwtQuotationProvider-selectedCategories", categorySelections.elements(), Profile.NEW);

// Set whether the user wants to display categories or not for later
// storing in the profile database.
if (displayCategories) {
p.setAttributeString("iwtQuotationProvider-displayCategories", "true", Profile.NEW);
} else {
p.setAttributeString("iwtQuotationProvider-displayCategories", "false", Profile.NEW);
}

// Done processing the edit form - now store the user's preferences.
p.store(true);

return DtConstants.BUILD_FRONT;
}
}

The sample below is the complete XML file used to register this sample provider with the Profile and Policy Server.

Code Example B-3 Sample XML File 

<!--
Copyright 11/30/99 Sun Microsystems, Inc. All Rights Reserved.
"@(#)iwtQuotationProvider.xml 1.2 99/11/30 Sun Microsystems"
-->

<iwt:Component name="iwtQuotationProvider"
ver="1.0"
desc="Quotation Provider"
resB="iwtQuotationProvider.rb"
idx="iwtQuotationProvider-desc" >

<!--
Attributes, common
-->

<iwt:Att name="iwtQuotationProvider-title"
desc="Title for this provider"
type="string"
idx="title-desc"
userConfigurable="TRUE">
<Val>Quotation Provider</Val>
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm>
</iwt:Att>
<iwt:Att name="iwtQuotationProvider-width"
desc="Width for this provider"
type="singlechoice"
idx="width-desc"
userConfigurable="TRUE">
<Val>thick</Val>
<CVal>thin</CVal><CVal>thick</CVal>
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm>
</iwt:Att>
<iwt:Att name="iwtQuotationProvider-isDetached"
desc="Is this provider detached from the desktop?"
type="boolean"
idx="isDetached-desc"
userConfigurable="TRUE">
<Val>false</Val>
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm><Wperm>OWNER</Wperm>
</iwt:Att>
<iwt:Att name="iwtQuotationProvider-isMinimized"
desc="Is this provider minimized on the desktop?"
type="boolean"
idx="isMinimized-desc"
userConfigurable="TRUE">
<Val>false</Val>
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm><Wperm>OWNER</Wperm>
</iwt:Att>
<iwt:Att name="iwtQuotationProvider-debug"
desc="Is debugging output on for this provider?"
type="boolean"
idx="debug-desc"
userConfigurable="FALSE">
<Val>false</Val>
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm>
</iwt:Att>
<iwt:Att name="iwtQuotationProvider-helpLink"
desc="Help page for this provider"
type="string"
idx="helpLink-desc"
userConfigurable="TRUE">
<Val>user_help/desktop/desktopTOC.html</Val>
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm>
</iwt:Att>
<iwt:Att name="iwtQuotationProvider-templateKeys"
desc="Template keys for this provider"
type="stringlist"
idx="templateKeys-desc"
userConfigurable="TRUE">
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm>
</iwt:Att>
<iwt:Att name="iwtQuotationProvider-templateFiles"
desc="Template files for this provider"
type="stringlist"
idx="templateFiles-desc"
userConfigurable="TRUE">
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm>
</iwt:Att>
<iwt:Att name="iwtQuotationProvider-column"
desc="Column to display this provider in"
type="string"
idx="column-desc"
userConfigurable="TRUE">
<Val>1</Val>
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm><Wperm>OWNER</Wperm>
</iwt:Att>

<!--
Attributes, specific
-->

<iwt:Att name="iwtQuotationProvider-possibleCategories"
desc="Possible Quotation Categories"
type="stringlist"
idx="possible_quotation_categories"
userConfigurable="FALSE">
<Val>Computers</Val>
<Val>Freedom</Val>
<Val>Science</Val>
<Val>Stupid</Val>
<Val>Work</Val>
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm><Wperm>OWNER</Wperm>
</iwt:Att>

<iwt:Att name="iwtQuotationProvider-selectedCategories"
desc="Selected Quotation Categories"
type="stringlist"
idx="selected_categories"
userConfigurable="TRUE">
<Val>Computers</Val>
<Val>Freedom</Val>
<Val>Science</Val>
<Val>Stupid</Val>
<Val>Work</Val>
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm><Wperm>OWNER</Wperm>
</iwt:Att>

<iwt:Att name="iwtQuotationProvider-displayCategories"
desc="Display category along with quotation?"
type="boolean"
idx="display_categories"
userConfigurable="TRUE">
<Val>true</Val>
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm><Wperm>OWNER</Wperm>
</iwt:Att>

<iwt:Att name="iwtQuotationProvider-fileLocation"
desc="Location of the quotations file"
type="string"
idx="file_location"
userConfigurable="FALSE">
<Val>/var/tmp/quotations</Val>
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm>
</iwt:Att>

<!--
Priviliges, common
-->

<iwt:Priv name="iwtQuotationProvider-isMinimizable"
desc="Can this provider be minimized on the desktop?"
type="boolean"
idx="isMinimizable-desc"
userConfigurable="TRUE"
val="true">
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm>
</iwt:Priv>
<iwt:Priv name="iwtQuotationProvider-isDetachable"
desc="Can this provider be detached from the desktop?"
type="boolean"
idx="isDetachable-desc"
userConfigurable="TRUE"
val="true">
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm>
</iwt:Priv>
<iwt:Priv name="iwtQuotationProvider-hasHelp"
desc="Does this provider have a help page?"
type="boolean"
idx="hasHelp-desc"
userConfigurable="TRUE"
val="true">
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm>
</iwt:Priv>
<iwt:Priv name="iwtQuotationProvider-isEditable"
desc="Does this provider have an edit page?"
type="boolean"
idx="isEditable-desc"
userConfigurable="TRUE"
val="true">
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm>
</iwt:Priv>
<iwt:Priv name="iwtQuotationProvider-isRemovable"
desc="Can this provider be removed from the desktop?"
type="boolean"
idx="isRemovable-desc"
userConfigurable="TRUE"
val="true">
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm>
</iwt:Priv>
<iwt:Priv name="iwtQuotationProvider-hasBorder"
desc="Should this provider be drawn with a border around it?"
type="boolean"
idx="hasBorder-desc"
userConfigurable="TRUE"
val="true">
<Rperm>ADMIN</Rperm><Rperm>OWNER</Rperm>
<Wperm>ADMIN</Wperm>
</iwt:Priv>

</iwt:Component>

The following code sample shows the sample quotations file used for this example.

Code Example B-4 Sample Quotation File 

Computers|"If you can't beat your computer at chess, try kickboxing." -Anon.
Computers|"What goes up must come down. Ask any system administrator." -Anon.
Computers|"Perl - The only language that looks the same before and after RSA encryption." -Keith Bostic
Computers|"C makes it easy to shoot yourself in the foot. C++ makes it harder, but when you do, it blows away your whole leg." -Bjarne Stroustrup
Freedom|"Live free or die." -New Hampshire State Motto
Freedom|"Man is free at the moment he wishes to be." -Voltaire
Freedom|"People demand freedom of speech as a compensation for the freedom of thought which they seldom use." -Kierkegaard
Freedom|"The right to be heard does not autmatically include the right to be taken seriously." -Hubert Humphrey
Freedom|"Extremism in the defense of liberty is no vice. And moderation in the pursuit of justice is no virtue." -Barry Goldwater
Freedom|"I disapprove of what you say, but I will defend to the death your right to say it." -Voltaire
Science|"Give me a lever long enough and a fulcrum on which to place it, and I shall move the world." -Archimedes, Pappus of Alexandria
Science|"A scientific truth does not triumph by convincing its opponents and making them see the light, but rather because its opponents eventually die and a new generation grows up that is familiar with it." -Maxwell Planck
Science|"Every great advance in science has issued from a new audacity of imagination." -John Dewey, The Quest for Certainty


Previous     Contents     Index     Next     
Copyright © 2000 Sun Microsystems, Inc. Some preexisting portions Copyright © 2000 Netscape Communications Corp. All rights reserved.

Last Updated May 04, 2000