UIDescriptor.getUIFactory
method.
Removed the sentence, "Because setting
and getting the context class loader is a privileged operation, the getUIFactory()
method wraps those operations in AccessController.doPrivileged()
calls," from the
description of getUIFactory
in section 2 of this specification.
UIDescriptor
,
Locales
, UIFactoryTypes
, and RequiredPackages
. These
constructors are now required to copy the contents of the passed Set
or
Map
to an unmodifiable version that has a consistent serialized form
across all VMs.
AccessibleUI.hashcode
so that it returns the hashcode of its fully qualified String
name, rather than
the hashcode of its Class
instance.
UIDescriptorBean
to net.jini.lookup.entry
, as suggested
by the Jini Lookup Attributes Schema specification.
MainUI
, AdminUI
,
and AboutUI
to match the semantics given in the
specification. Originally (prior to the 1.0 release), these role
interfaces defined their role object to be exactly the service item.
Ken Arnold requested we say that the service item must be accepted
as the role object, which yields more flexibility. Although a
service item is required to always work when passed as the role
object to factory methods for main, admin, and about UIs, other
objects may also work. I made this change back then to the
specification, but forgot to change the Javadoc comments. The
specification and the Javadoc comments are now in sync.
JDialogFactory
that were both incorrectly
named getDialog()
in ServiceUI 1.0. The methods are now correctly named getJDialog()
.
Added serialVersionID
s
to all classes in the API in order to accelerate deserialization. Improved
javadoc comments: added missing serial, author, param, throws, and return
tags, as well as added clarifying javadoc text where it seemed helpful.
Added flat javadoc documentation to the end of Service UI API Specification
to make sure the API's semantics are specified in detail in the
specification itself.
Administratable
to Administrable
.
Fixed grammar: In last paragraph of section 3.1, changed "had"
to "had had."
MainUI
,
AdminUI
,
and AboutUI
,
changed constant role
to ROLE
.
In all factories, changed toolkit
to TOOLKIT
and typeName
to TYPE_NAME
.
Flavor
and FlavorSelectorUI
.
splitwebpage
net.jini.lookup.ui.MainUI
Role
net.jini.lookup.ui.AdminUI
Role
net.jini.lookup.ui.AboutUI
Role
AccessibleUI
Attribute
Locales
Attribute
RequiredPackages
Attribute
UIFactoryTypes
Attribute
net.jini.lookup.entry
net.jini.lookup.entry.UIDescriptor
net.jini.lookup.entry.UIDescriptorBean
net.jini.lookup.ui
net.jini.lookup.ui
net.jini.lookup.ui
Exception
s In Package net.jini.lookup.ui
Error
s In Package net.jini.lookup.ui
net.jini.lookup.ui.AboutUI
net.jini.lookup.ui.AdminUI
net.jini.lookup.ui.MainUI
net.jini.lookup.ui.factory
net.jini.lookup.ui.factory
net.jini.lookup.ui.factory
Exception
s In Package net.jini.lookup.ui.factory
Error
s In Package net.jini.lookup.ui.factory
net.jini.lookup.ui.factory.DialogFactory
net.jini.lookup.ui.factory.FrameFactory
net.jini.lookup.ui.factory.JComponentFactory
net.jini.lookup.ui.factory.JDialogFactory
net.jini.lookup.ui.factory.JFrameFactory
net.jini.lookup.ui.factory.JWindowFactory
net.jini.lookup.ui.factory.PanelFactory
net.jini.lookup.ui.factory.WindowFactory
net.jini.lookup.ui.attribute
net.jini.lookup.ui.attribute
net.jini.lookup.ui.attribute
Exception
s In Package net.jini.lookup.ui.attribute
Error
s In Package net.jini.lookup.ui.attribute
net.jini.lookup.ui.attribute.AccessibleUI
net.jini.lookup.ui.attribute.Locales
net.jini.lookup.ui.attribute.RequiredPackages
net.jini.lookup.ui.attribute.UIFactoryTypes
splitwebpage
Traditionally, desktop applications are designed with a built-in user interface (UI). The code for the application's UI is often highly coupled to the code that implements the application's functionality. Over time, tentacles of UI code may burrow deep into functionality code, and tentacles of functionality code may burrow back into UI code. In the traditional desktop application, therefore, the UI code and functionality code are usually inseparable, married for all eternity.
Jini's service proxy architecture encourages you to think differently about UI and functionality:
A Jini service proxy should represent the service's pure functionality, expressed via the methods of its object interface. For example, the service proxy interface for a toaster service should express or model the conceptual toaster service's functionality -- the interface should say "what it means to be a toaster." The service proxy should not supply human access to the toaster service; a separate UI object should provide such access.
One reason for excluding the UI from the service proxy is to enable client programs (clients) to access the service without human intervention or supervision. Clients written by programmers who knew about a particular service proxy's (potentially well-known or standard) interface can interact with a service directly. As Figure 1 shows, client code can interact directly with a service by invoking the methods in the service proxy interface. Such a client is called a direct-use client, because its programmers, based on their knowledge of the service proxy interface, can write code that uses the service directly via that interface.
Direct-use clients need not be completely devoid of a user. For example, a user could operate a device that acts as a direct-use client in certain cases. If the user requested that the device save some data in a file, the device could acquire a storage service proxy and directly invoke methods on that object to save data in a file, without further user intervention. In this case, the user-operated device acts as a direct-use client of storage services, because the device's programmers had prior knowledge of the storage service proxy interface and used that knowledge to program the device to use those services directly.
On the other hand, direct-use clients can also function independently of human supervision or intervention. Such clients act as autonomous agents, which decide for themselves when to enlist a service's help. When an autonomous agent uses a service, it invokes the methods offered by the service proxy interface directly. Thus, an autonomous agent's programmers must have prior knowledge of the service proxy interfaces their agent uses. (Although the human programmer actually has the prior knowledge when he or she writes the client code, in this document the code itself will often be said to have prior knowledge.)
When you design a Jini service, you should attempt to capture the service's entire functionality in the service proxy interface. To access any aspect of your service, a direct-use client should only need a reference to the service proxy. The service proxy should not include any code that defines a user interface to the service, just code that provides the service functionality at the method invocation level.
To provide a user interface for the service, you should encapsulate the user interface code in a separate UI object. As Figure 2 shows, a UI object grants a user access to some aspect of a Jini service. Think of a service UI object as a user adapter -- an object that adapts a service proxy interface that a human user cannot interact with directly into one a human user can interact with directly. Sitting between the service proxy interface and a human user, a UI object can grant the user access to a service.
A UI object can represent a graphical UI component, such as an AWT Frame
or Swing
JPanel
,
but doesn't necessarily need to be graphical. A UI object could also represent
a speech interface, a text interface, a speech and graphic combination, or a
3D-immersive world. (The UI object is called UI object, rather than GUI
object or view object, because the object represents UI components
in general, not just graphical UI components.) Any kind of Jini Service UI,
including a 3D-immersible world with speech and virtual text display, should be
represented by a UI object, which is distinct from the service proxy.
One advantage of this architecture, in which UI and functionality are separated, is that you can associate multiple UIs with the same service. Associating multiple UIs with one service lets you tailor different UIs for clients that have particular UI capabilities, such as Swing or speech. Clients can then choose the UI that best fits their user interface capabilities. In addition, you may want to associate different UIs that serve different purposes, such as a main UI or an administration UI, with a service. Often, you may need to associate multiple UIs with one Jini service, where each UI has a particular purpose and targets a particular set of client capabilities.
This specification standardizes how UI providers associate a UI (user adapter) object with a Jini service, and shows how client programs can find the best-fit UI among multiple UIs associated with the same service. To associate a UI with a Jini service, UI providers (primarily service providers, but also possibly third parties) must supply three items:
A UI factory is an object that has one or more
factory methods that produce and return a UI object. A UI descriptor, an
instance of net.jini.lookup.entry.UIDescriptor
(UIDescriptor
),
serves as a container for the UI factory and other objects that describe the UI produced by the factory.
Because UIDescriptor
implements net.jini.core.entry.Entry
(Entry
),
you can include a UIDescriptor
in a Jini service item's attribute sets array, thereby associating the UI with
the service. A UI descriptor contains four public fields:
factory
: A reference to a java.rmi.MarshalledObject
that contains the UI factory object in marshalled form
attributes
: A java.util.Set
of attribute objects that describe the factory-produced UI
toolkit
: A String
that names the main package of the UI toolkit the UI requires
role
: A String
that gives the fully qualified name of a Java interface type that
represents the UI's role
The attributes
,
toolkit
,
and role
fields' purpose is to describe the UI produced by the marshalled UI factory.
Using these fields, clients can choose from multiple UIs associated with a
service. Once they select a UI object, clients can use the other field, factory
, to
create the object.
To associate a UI with a Jini service, the UI provider must first fill a UI
descriptor with a role String
,
a toolkit String
,
an attribute set, and a marshalled UI factory. The UI provider must then place
the UI descriptor in the attribute sets of the Jini service's service item.
A UI's role indicates both its purpose and its role-related semantics. Each
UI role is defined as a Java interface type, which UI objects playing that role
implement. The role
field references a String
whose value is the role interface type's fully qualified name. For example, a net.jini.lookup.ui.MainUI
role UI provides general access to a service. A net.jini.lookup.ui.AdminUI
role
UI enables a user to administer a service. Although most UI object semantics of
interest to the client program are defined by the UI factory's return type,
some semantics may be tied to the role. For example, for a role that represents
a user dialog, the role interface might include methods that let the client
determine the dialog's result.
The UI descriptor's attributes
field holds a reference to a java.util.Set
of serializable objects that contain
information about the UI the descriptor represents. These objects can be of any
class, so long as they are serializable. Clients can search through the
attributes set for attribute types about which they have prior knowledge. The
objects can then help the client decide whether or not to use the
descriptor-represented UI. Several attribute classes, defined in the net.jini.lookup.ui.attribute
package, are described later in this document.
The toolkit
field facilitates matching when querying the Jini lookup service. For example,
if a client seeks all services that have main UIs working with the Swing
toolkit, it could form a net.jini.core.lookup.ServiceItem
(ServiceItem
)
whose attributeSetTemplates
array includes a UI descriptor template. If the UI descriptor template's factory
and attributes
fields are set to null
,
the role
field is set to net.jini.lookup.ui.MainUI
,
and toolkit
field is set to javax.swing
,
the lookup would only return services that have at least one main UI for Swing.
The factory
field contains the UI factory object inside a MarshalledObject
so that you
can place the class files for the factory and the UI it produces in a different
codebase than the service item containing the UI descriptor. By placing the
class files for UI factories and UI objects in separate codebases than that of
the service item, clients can download a service item without downloading all
the JAR files containing those class files, most or all of which the client may
never use. Only if the client attempts to use a UI will it need to unmarshal
the UI factory; this would trigger the downloading of the JAR file containing
the factory class files, and possibly the class files for the factory-generated
UI.
To use a UI, a client program must have prior knowledge of both the UI factory type (including, of course, the UI object type returned by its factory methods) and the UI role type. These types define the UI object semantics, which client programmers must understand before they can write code to interact properly with the UI. A client doesn't need prior knowledge of all the attributes types that appear in the attributes set. To the extent the client has prior knowledge of the attribute types, it can use that knowledge to select an appropriate UI from multiple UIs associated with a service.
splitwebpage
A net.jini.lookup.entry.UIDescriptor
(UIDescriptor
)
is a net.jini.core.lookup.Entry
(Entry
)
that enables a UI to be associated with a service in the service item's
attribute sets. A UIDescriptor
holds a marshalled UI factory object in the factory
field, a role type name in the
role
field, a toolkit package name in the toolkit
field, and an attribute set
that describes the factory-generated UI in the attributes
field.
The UIDescriptor
not only houses a marshalled UI factory that produces a UI, but also describes
the produced UI to help clients decide whether or not to unmarshal the UI
factory. The UI is described in the role
, toolkit
, and attributes
fields.
Class UIDescriptor
's
public interface looks like this:
package net.jini.lookup.entry; import java.util.Set; import java.rmi.MarshalledObject; import java.io.IOException; public class UIDescriptor extends net.jini.entry.AbstractEntry { public String role; public String toolkit; public Set attributes; public MarshalledObject factory; public UIDescriptor() {...} public UIDescriptor(String role, String toolkit, Set attributes, MarshalledObject factory) {...} public final Object getUIFactory(ClassLoader parentLoader) throws IOException, ClassNotFoundException {...} }
Because the marshalled UI factory is referenced from a public field, programs
can simply invoke get()
directly on the marshalled object to unmarshal the factory client. Clients must
ensure, however, that the class loader that loads the class files for the UI
can also (likely via a parent class loader) load the class files of the service
proxy with which the UI will interact. The UIDescriptor
includes a convenience
method named getUIFactory()
to help clients unmarshal the UI factory with the proper class loader context.
The getUIFactory()
method saves a reference
to the current context class loader, sets the context class loader
to the class loader passed as parentLoader
, invokes
get()
on the marshalled object, then resets the
context class loader to the saved reference before returning
the object that get()
produces.
The class loader passed to the getUIFactory()
method in the parentLoader
parameter should be able to load types (classes and interfaces) needed when the
UI interacts with the role object, which is passed as the first
parameter to any factory method. A UI role's semantic description indicates,
among other things, what object should be passed to the factory as the role
object. For the net.jini.lookup.ui.MainUI
role, for example, the role object is the service item. Thus, to unmarshal a UI
factory for a main UI, the class loader passed to getUIFactory()
should be able
to load types needed when the UI interacts with the service proxy contained in
the service item. For example,
the client could pass to getUIFactory()
the class loader the client previously used to load the service proxy.
The String
referenced from the toolkit
field (which names the main package of the primary UI toolkit) is determined by
the UI factory type. Each UI factory type's semantics should include a toolkit
string, so UI providers will know what string to put in the toolkit
field
for their selected UI factory type. Two toolkit strings currently defined are java.awt
, for
graphical UIs that depend on AWT but not Swing, and javax.swing
,
for graphical UIs that depend on Swing (and AWT, since Swing is built on top
AWT).
splitwebpage
The UIDescriptor's
role
field gives the fully qualified name of the interface that
represents the role of the UI the marshalled UI factory generates. If the
client program unmarshals the UI factory and invokes a factory method, the UI
the factory method returns must implement the role interface that role
specifies.
For a client program to use a UI, the client must have prior knowledge of
the UI semantics, a portion of which the UI's role type defines. Thus, for a
client to use a UI, the client must understand the semantics of the type whose
fully qualified name appears in the role
field of that UI's UIDescriptor
.
For example, three role types defined in the net.jini.lookup.ui
package by
the Jini Service UI Specification are MainUI
, for a main UI to a Jini
service; AdminUI
,
for an administration UI; and AboutUI
for an about UI. Future incarnations of
the Jini Service UI Specification, individual Jini service API specifications,
or any other party may define other role types. The UI role types' fully
qualified names should, as with any other type, follow the recommended naming
convention for unique packages outlined in the Java Language Specification:
You form a unique package name by first having (or belonging to an organization that has) an Internet domain name, such as sun.com. You then reverse this name, component by component, to obtain, in this example, com.sun, and use this as a prefix for your package names, using a convention developed within your organization to further administer package names.
For example, printers in general don't have a main UI, but they may have a
UI for printer setup, a UI for print job setup, and a UI for administering the
printer. The Printer working group, therefore, could define two role types as
part of its Printer API definition, one for printer setup and one for print job
setup. (The printer's administration UI could likely use the existing net.jini.lookup.ui.AdminUI
role.) The Printer working group would start its role type names with a package
prefix it has either received or obtained control over. For example, if the
Jini Community grants the Printer working group the right to place its APIs in
the net.jini.print
package, the group could name its role
types: net.jini.print.ui.PrinterSetup
and net.jini.print.ui.PrintJobSetup
.
Each working group or other entity that defines Jini Service APIs can include,
as part of its specification, any new UI role types useful in the context of
its service.
As the strings referenced from the role
field are Java type names, they
should only be manipulated by client programs. Users should not view them. A
client may, nevertheless, display localized strings representing roles about
which the client has prior knowledge.
For example, imagine a Jini browser client shows a service list using icons
and names provided by net.jini.lookup.entry.ServiceType
(ServiceType
)
entries. Such a Jini browser could, when the user double-clicks on a service
icon or name, attempt to display a MainUI
for the service. In addition,
such a Jini browser could, when the user right-clicks on a service icon or
name, pop up a list of verb strings, one for each UI role the service offers in
a form the client believes it can use. For example, imagine that the user
right-clicked, among the UIs offered by the service, three java.swing.JFrame
(JFrame
)
UIs (produced by net.jini.lookup.ui.factory.JFrameFactory
s);
one for each of net.jini.lookup.ui
package's three defined roles: MainUI
, AdminUI
, and AboutUI
. If
the client can use JFrame
s,
the client could display three verbs on the pop-up list when the user
right-clicks. In the US-English locale, the verb strings could be: "Open..."
,
"Administer..."
,
and "About..."
.
If the user selects About...
,
the client could display the AboutUI
JFrame
.
Note that the service did not provide the strings shown to the user -- "Open..."
,
"Administer..."
,
and "About..."
.
The developers of the Jini browser client decided upon these strings. Given
that these developers had prior knowledge of the MainUI
role, they were able to
decide that, in their client, "Open"
would be a sensible verb string
for MainUI
s
in the US-English locale. Of course, those developers may have selected other
verb strings for other locales. German users of the same browser, for example,
could potentially encounter the verb string "Jetzt Geht's Los..."
for MainUI
s, "Was Ist Das
Ding..."
for AboutUI
s, and "Spielen Sie Mit Die Viele Kleine Nummern..."
for AdminUI
s.
Because the client program, not the Jini service, provides the verb strings,
the client will be unable to show a verb in its list for any role about which
it did not have prior knowledge. Thus, if the user right-clicks a service that
also offers a JFrame
UI with the role net.jini.blender.ui.FrappeUI
,
the client will be able to display a localized string for that UI in its verb
list only if the client's developers had had prior knowledge of that role. If
the client's programmers did not endow the program with prior knowledge of FrappeUI
s, the
client will not be able to list a verb for that UI in its pop-up, and therefore
the user will not be able to select it. This prior-knowledge requirement is
intentional, because as mentioned previously, the role defines a portion of the
UI's semantics. Before the client program can properly use a UI, it must have
prior knowledge of the role interface. If a client doesn't know how to use a
UI, then letting the user select that UI makes no sense.
net.jini.lookup.ui.MainUI
Rolenet.jini.lookup.ui.MainUI
(MainUI
)
is a UI role interface implemented by main UIs, which enable client programs to
grant users general access to a service. If a UI descriptor's UI factory
produces a UI that implements this interface (i.e., produces a main UI), the UI
descriptor's role
field must reference a String
with the value net.jini.lookup.ui.MainUI
.
The first parameter of any factory method declared in a UI factory type is a
role object. Any factory method that produces a main UI must accept as the role
object the service item (the net.jini.core.lookup.ServiceItem
) of the service
associated with the main UI.
Main UIs should let clients configure them before they begin. For example,
main UIs produced by FrameFactory
,
JFrameFactory
,
WindowFactory
and JWindowFactory
(all members of the net.jini.lookup.ui.factory
package) should not be visible when they return from the factory method. This
allows clients to set the UI's position and size, for example, before making
the UI visible by invoking setVisible(true)
on the UI.
A client should be able to invoke a main UI factory method multiple times sequentially. In other words, if a user uses a service via a main UI, then exits, and then double-clicks once again on the service icon, the client can simply invoke a UI factory method again, and acquire another main UI for the same service. Therefore, you should write main UIs so that they work regardless of the service proxy's state when the main UI is created.
It is recommended that clients use multiple main UIs for the same service only sequentially, and avoid creating for the same service proxy multiple main UIs that operate concurrently with one another. But because some clients may create and use multiple main UIs simultaneously for the same service proxy, service and main UI providers should program defensively to ensure that multiple main UIs for the same service proxy will all work together concurrently.
Here's the net.jini.lookup.ui.MainUI
tag interface:
package net.jini.lookup.ui; public interface MainUI { String ROLE = "net.jini.lookup.ui.MainUI"; }
net.jini.lookup.ui.AdminUI
Rolenet.jini.lookup.ui.AdminUI
(AdminUI
)
is a UI role interface implemented by admin UIs, which enable users to
administer a service. If a UI descriptor's UI factory produces a UI that implements
this interface (i.e., produces an admin UI), the UI descriptor's role
field must reference a String
with the value "net.jini.lookup.ui.AdminUI"
.
The first parameter of any factory method declared in a UI factory type is a
role object. Any factory method that produces an admin UI must accept as the
role object the service item (the net.jini.core.lookup.ServiceItem
) of
the service associated with the main UI.
Admin UIs have precisely the same semantics as main UIs. The only difference
is their purpose. Here's the net.jini.lookup.ui.AdminUI
interface:
package net.jini.lookup.ui; public interface AdminUI { String ROLE = "net.jini.lookup.ui.AdminUI"; }
net.jini.lookup.ui.AboutUI
Rolenet.jini.lookup.ui.AboutUI
(AboutUI
)
is a UI role interface implemented by about UIs, which enable users to view (or
in some way experience) information about a service. If a UI descriptor's UI
factory produces a UI that implements this interface (i.e., produces an about
UI), the UI descriptor's role
field must reference a String
with the value "net.jini.lookup.ui.AboutUI"
.
The first parameter of any factory method declared in a UI factory type is a
role object. Any factory method that produces an about UI must accept as the
role object the service item (the net.jini.core.lookup.ServiceItem
) of
the service associated with the main UI.
About UIs have precisely the same semantics as main UIs. The only difference
is their purpose. Here's the net.jini.lookup.ui.AboutUI
interface:
package net.jini.lookup.ui; public interface AboutUI { String ROLE = "net.jini.lookup.ui.AboutUI"; }
As mentioned previously, any party may define new role interfaces. New UI
role interfaces will likely be defined in conjunction with new Jini Service API
definitions, and many of those roles will likely represent service-specific
dialogs with users. As used here, a dialog is a short conversation with
the user, usually to obtain some information from the user. Although for
graphical toolkits, a dialog is often implemented with a dialog box, such as
AWT's Dialog
or Swing's JDialog
,
the term dialog is used here in the generic sense, not strictly in the
graphical sense. Service-specific dialog UIs will enable clients to enlist a
user's help at various points throughout an otherwise direct use of a service.
As an example, consider a user asking a word processor that has prior
knowledge of a well-known Jini Printer API to print a document. (Note that the
types appearing in this example were invented for illustration purposes. At the
time of this writing, the Jini Printer Service API had not been finalized.) To
print via the Jini Print Service API, the word processor first obtains a net.jini.print.service.PrintService
(PrintService
)
object and invokes createPrintJob()
on that object to obtain a net.jini.print.job.PrintJob
(PrintJob
)
object. A purely direct-use client must do two things with the PrintJob
object -- configure the print job and supply the print data -- before invoking close()
on the
print job, thereby queuing the printing job. Although the word processor could
potentially do both jobs directly, it may not have prior knowledge of the portion of the PrintJob
object's interface that lets the client configure the print job, and besides,
users are accustomed to configuring print jobs. Given an available user, the
word processor would likely want to provide a dialog UI that lets the user
configure the print job. Once the user completes his or her configuration and
dismisses the dialog UI (with "OK," not "Cancel"), the word
processor could supply the print data and invoke close()
on the PrintJob
.
Given that Jini Print Service API clients would prefer a dialog UI that
allows for user configuration, the Printer working group could define a new UI
role type for that purpose. The Printer working group would likely place the
role interface in some subpackage of its API's main package. For example, it
could define an interface named: net.jini.print.ui.PrintJobSetup
(PrintJobSetup
).
A PrintJobSetup
UI would represent a dialog that enables user configuration of a print job,
such as page orientation, and so on. Once the user selects configuration
parameters, he or she dismisses the dialog UI, which in some way communicates
back to the client those parameters (likely by invoking methods on the PrintJob
object itself, which is likely the role object for the PrintJobSetup
role) and indicates to the client that the dialog is finished. The PrintJobSetup
interface's semantics would define how the client interacts with the UI, such
as how the client knows the UI has been dismissed, and whether or not the user
dismissed the UI with "OK" or "Cancel." If the client
receives "OK," the client could then write print data to the PrintJob
object and invoke close()
on the PrintJob
,
thereby sending it to the printer.
The semantics of the PrintJobSetup
role interface defines the way in which the PrintJobSetup
UI interacts with the
client (i.e., communicates the configuration data and indicates the dialog's
dismissal). As the dialog may require sophisticated UI and client interaction,
the role interface may be more than just a tag interface; it may include
methods that define how the UI and client interact. The word processor client
would know how to display this PrintJobSetup
dialog because the PrintJobSetup
role interface, and its semantics, would be defined in the Jini Print Service
API, of which that client has prior knowledge.
Besides creating new role types for service-specific dialogs, a working
group for a Jini service API or a provider of a Jini service API implementation
could also provide multiple incarnations of an already-defined role. For
example, what if the manufacturer of a combined printer/scanner/faxer/copier
product (a "four-in-one box") wanted to deliver four AdminUI
s, each
dedicated to administering one of four product functions? Such a manufacture
could take several approaches.
First, assuming the Jini Community has adopted a standard API for each
product function (i.e., a Jini Print Service API, a Jini Scanner Service API, a
Jini Faxer Service API, and a Jini Copier Service API), the four-in-one-box
manufacturer could, rather than registering one Jini service whose service
proxy implements four interfaces (such as Printer
, Scanner
, Faxer
, and Copier
),
simply offer four separate Jini services, each of which implements only one
interface. In this approach, each service could offer an AdminUI
dedicated to that one function.
Alternatively (or in addition), the manufacturer could register one Jini
service whose service proxy implements all four interfaces. The AdminUI
for
that service could present a user interface device (such as a tabbed pane for a
graphical UI) that lets users select between the four main functions. In this
way, one AdminUI
exists, which grants users access to the four conceptual administration UIs.
Lastly, the manufacturer could propose to the Jini Community a Jini
Four-in-One Service API that includes four new role types, each dedicated to
administering a product subset. The Four-in-One working group, which defines
the Jini Four-in-One Service API, could control a package that holds the role
types, PrinterAdminUI
,
ScannerAdminUI
,
FaxerAdminUI
,
and CopierAdminUI
.
Clients with prior knowledge of the Jini Four-in-One Service API would also
have prior knowledge of the four role types, and therefore could offer verb
strings for them. Four-in-One service providers could offer those four admin UI
types, but should also offer a basic net.jini.lookup.ui.AdminUI
, which as
described previously, grants a user access to all four admin UIs. Including an AdminUI
lets
clients that don't have prior knowledge of the Four-in-One service to offer a
UI that will let users administer that service.
In general, role interfaces should not extend other role interfaces, because
only one role interface is described in the UI descriptor's role
field.
For example, the FaxerAdminUI
from the previous section appears to be able to extend AdminUI
,
because you could consider a FaxerAdminUI
to be an AdminUI
type.
However, only one role interface can appear in the UI descriptor's role
field. If
a UI is both a FaxerAdminUI
and an AdminUI
,
then which role goes into the role
field? If the same UI registers twice, once
with AdminUI
and once with FaxerAdminUI
,
then what is the point of FaxerAdminUI
?
In other words, if a FaxerAdminUI
is the default admin UI of the four, then the Four-in-One working group wouldn't
need to define a FaxerAdminUI
in the first place. They would only need to mention that an AdminUI
should
behave as an admin UI for the fax machine.
Role interfaces can extend other interfaces; in general, they simply shouldn't extend other role interfaces. If a dialog UI role's semantics are already defined in an interface, then the role interface could extend that interface and thereby inherit those methods and semantics.
Nevertheless, if a party decides to create a role interface that extends
another role interface, any factory method that generates the subinterface UI
role type must accept the same role object categories accepted by factory
methods that generate the superinterface UI role type. For example, if FaxerAdminUI
were declared as an AdminUI
subinterface, any factory method that produces a FaxerAdminUI
would have to accept
as the role object the FaxerAdminUI
-associated
service item, because factory methods that produce AdminUI
s
accept that role object category.
It is recommended that all role interfaces include a compile time String
constant named ROLE
,
which gives the UI role interface's fully qualified string type name, as it
should appear in UI descriptor's role
fields. Such convenience
constants not only help reduce typing and increase code readability, they also
leverage compile-time type checking to help minimize the chance of
typographical errors in role
strings.
splitwebpage
The UI descriptor's attributes
field references a java.util.Set
of objects that describe the UI generated by the marshalled UI factory. Any
object can appear in this set, so long as it is serializable. (Note that if any
object in this set is not serializable, the entire set will not appear at the
client side -- the UI descriptor's attributes
field will be null
.)
If a UI provider wishes to register a UI descriptor that has no attributes,
it may register the UI descriptor with either a reference to an empty java.util.Set
or null
in the UI descriptor's attributes
field. Nevertheless, because clients would know little about the UI represented
by that UI descriptor, many clients would likely ignore the descriptor
entirely.
Although all attributes are optional, this specification recommends that all
UI descriptors include at least the attributes (all of which are members of the
net.jini.lookup.ui.attribute
package) described in this list:
AccessibleUI
attribute
Locales
attribute: Lists the locales the UI supports
RequiredPackages
attribute: Lists packages the UI requires to be installed at the client
UIFactoryTypes
attribute: Lists Java types of which the marshalled UI factory is an
instance
The remainder of this section describes these four attribute classes in detail.
AccessibleUI
AttributeAccessibleUI
indicates that a generated UI implements the javax.accessibility.Accessible
interface and that the UI's designer made sure the UI would work well with Java
Accessibility API-aware assistive technologies.
The attribute should appear in a UIDescriptor
's attributes set only if
the marshalled UI factory produces an Accessibility API-supported UI. This
attribute's presence in an attributes set means the produced UI will work well
with Java Accessibility API-aware assistive technologies.
The AccessibleUI
attribute looks like this:
package net.jini.lookup.ui.attribute; public class AccessibleUI implements java.io.Serializable { }
Locales
Attribute
The Locales
attribute lists locales supported by a generated UI.
Zero to many Locales
instances may appear in a UI descriptor's attributes set. UI providers are encouraged to
provide in any UI descriptor's attributes set one Locales
object that contains the
complete set of locales supported by the UI. Given that UI providers are not required
to give complete or even accurate information about locales, clients should
program defensively and consider the supported locales a strong hint that
locales are supported by the UI, but not necessarily 100 percent complete or accurate.
The public interface of Locales
looks like this:
package net.jini.lookup.ui.attribute; import java.util.Locale; import java.util.Iterator; import java.util.Set; import java.util.List; public class Locales implements java.io.Serializable { public Locales(Set locales) {...} public boolean isLocaleSupported(Locale locale) {...} public Locale getFirstSupportedLocale(Locale[] locales) {...} public Locale getFirstSupportedLocale(List locales) {...} public Iterator iterator() {...} public Set getLocales() {...} }
RequiredPackages
AttributeRequiredPackages
lets clients obtain a list of fully qualified names and version numbers of
packages a UI requires.
Zero to many RequiredPackages
attributes may appear in a UIDescriptor
's
attributes
set. Client programs interested in a UI may wish to verify that they have all
required packages mentioned in the RequiredPackages
attributes (if any)
before they attempt to create the UI. If the client lacks any required packages
(either because the package is absent or because the package is incompatible),
the client will not be able to use the UI.
This attribute intends to provide a quick way for a client program to determine that a client cannot use a UI, not to guarantee that a client can definitely use a UI. If a client is missing a required package, or has an incompatible version, the client cannot use the UI. But if the client has compatible versions of all required packages, the client may or may not be able to use the UI.
UI providers should attempt to list in a RequiredPackages
attribute all
packages that must be installed at the client for the UI to work. In this case,
if the client has compatible versions of all listed packages and attempts to
generate the UI via the factory method, the client will likely succeed. (Note
that packages used by the UI that could potentially be installed at the client,
but are also available at the UI's or service's codebase, should not be listed
in a RequiredPackages
attribute. The client does not actually require such packages, because if the
client doesn't have them, it can download the packages.)
Client programmers should bear in mind that a RequiredPackages
attribute
doesn't necessarily list all required packages. As a result,
satisfying all required packages doesn't guarantee the UI will work on the
client. Client programs should therefore program defensively. (For example,
clients should probably catch LinkageError
in appropriate places when dealing
with UIs, even if they have compatible versions of all required packages.)
The version numbers listed in RequiredPackages
attributes must take
the form of specification version numbers, as used by the java.lang.Package
class:
Specification version numbers use a "Dewey Decimal" syntax that consists of positive decimal integers separated by periods ".", for example, "2.0" or "1.2.3.4.5.6.7". This allows an extensible number to be used to represent major, minor, micro, etc versions. The version number must begin with a number.
Here's what the RequiredPackages
's
public interface looks like:
package net.jini.lookup.ui.attribute; import java.util.Map; import java.util.Set; import java.util.Collection; import java.util.Iterator; public class RequiredPackages implements java.io.Serializable { public RequiredPackages(Map packages) {...} public Iterator iterator() {...} public String getVersion(String packageName) {...} public Map getRequiredPackages() {...} }
UIFactoryTypes
AttributeUIFactoryTypes
allows client programs to determine Java types of which a UI factory (marshalled
in the same UIDescriptor
)
is an instance.
Zero to many UIFactoryTypes
may appear in the UI descriptor's attributes set. The marshalled UI factory in
a UI descriptor's factory
field should be an instance of
each type that appears in any UIFactoryTypes
attribute in that UI descriptor's attributes
set.
Of all attributes that could appear in the attributes set, UIFactoryTypes
is perhaps the most important. If a UI descriptor's attributes set includes no UIFactoryTypes
attribute, then the only way for clients to know what kind of factory a UI
descriptor represents is to unmarshal it. But unmarshalling a UI factory will
likely involve downloading code, which a client wants to avoid unless it is
fairly certain it can use the UI. As a result, UI providers are strongly
encouraged to include in every UI descriptor a UIFactoryTypes
attribute that
includes those Java types (of which the UI factory is an instance) that clients
would likely be searching for. In general, clients will be looking for
well-known factory interface types, such as those appearing in the net.jini.lookup.ui.factory
package.
The public interface of UIFactoryTypes
looks like this:
package net.jini.lookup.ui.attribute; import java.util.Set; import java.util.Iterator; public class UIFactoryTypes implements java.io.Serializable { public Types(Set typeNames) {...} public boolean isAssignableTo(Class classObj) {...} public Iterator iterator() {...} public Set getTypeNames() {...} }
splitwebpage
The UI factory object should implement one or more UI factory interfaces appropriate to the type of UI generated (the factory method's return value) and the options clients have at creation time (the parameters the client can and must pass to the factory method). Factory interfaces can be implemented in many ways, but in general, factory objects should use lazy instantiation of the UI object. For example, rather than instantiating a UI object when the factory instantiates, and returning that already-instantiated UI when a factory method is invoked, a factory object should wait until a factory method is actually invoked before instantiating the UI object. Lazy instantiation lets you marshal the factory object without requiring the UI object's image to be included in the UI factory's marshalled image.
UI factories define methods that indicate by their return type the generated
UI's Java type and indicate by their parameters the objects and primitive
values that the client can and must supply to the factory. The first parameter
to any UI factory method is a role object. The UI's role determines this
object's category (but not the type). As used here, category means how
the client program obtains the role object. For example, a role might specify
that its role object is the service item, the service proxy, or an object
obtained by invoking a method on the service proxy. The UI role describes how
the client acquires the object that must be passed as the first parameter to
the factory method. For example, the MainUI
role's semantics indicate that
the role object is the service item.
You should write UI factories such that their factory methods can be invoked multiple times. A client may wish to show a user the same UI several times, and therefore may invoke a factory method on the same factory object multiple times. Each time the factory method is invoked, it should produce and return a new UI object copy.
The Jini Service UI API's first version defines eight factory interfaces:
DialogFactory
: Returns an
instance of class java.awt.Dialog
,
or one of its subclasses, that depends on the AWT, not the Swing,
libraries
FrameFactory
: Returns an
instance of class java.awt.Frame
,
or one of its subclasses, that depends on the AWT, not the Swing,
libraries
JComponentFactory
: Returns
an instance of class javax.swing.JComponent
,
or one of its subclasses, that depends on both the AWT and Swing libraries
JDialogFactory
: Returns an
instance of class javax.swing.JDialog
,
or one of its subclasses, that depends on both the AWT and Swing libraries
JFrameFactory
: Returns an
instance of class javax.swing.JFrame
,
or one of its subclasses, that depends on both the AWT and Swing libraries
JWindowFactory
: Returns an
instance of class javax.swing.JWindow
,
or one of its subclasses, that depends on both the AWT and Swing libraries
PanelFactory
: Returns an
instance of class java.awt.Panel
,
or one of its subclasses, that depends on the AWT, but not the Swing,
libraries
WindowFactory
: Returns an
instance of class java.awt.Window
,
or one of its subclasses other than Frame
or Dialog
,
that depends on the AWT, not the Swing, libraries
Future incarnations of the Jini Service UI Specification or any other party may define additional UI factory interface types. The fully qualified names of UI factory interface types should, as with any other type, follow the recommended naming convention for unique packages outlined in the Java Language Specification:
You form a unique package name by first having (or belonging to an organization that has) an Internet domain name, such as sun.com. You then reverse this name, component by component, to obtain, in this example, com.sun, and use this as a prefix for your package names, using a convention developed within your organization to further administer package names.
Here's an example UI factory interface:
package net.jini.lookup.ui.factory; import javax.swing.JFrame; public interface JFrameFactory extends java.io.Serializable { String TOOLKIT = "javax.swing"; String TYPE_NAME = "net.jini.lookup.ui.factory.JFrameFactory"; JFrame getJFrame(Object roleObject); }
Given that only one toolkit field exists, all UIFactory
interfaces implemented
by a UI factory class must have the same toolkit.
Although anyone can define new factory types, to prevent a chaotic explosion
of factory types, you should define new factory types with the utmost care. In
general, new factory types will be justified only when new UI toolkits appear
on the scene. If possible, new factory types should be agreed upon by the Jini
Community and placed into the net.jini.lookup.ui.factory
package so they are easy
to find. For example, if a toolkit is defined for speech-only UIs, a set of
factory methods for speech-only UIs could be added to those already in net.jini.lookup.ui.factory
.
If a graphical toolkit is defined for extremely small screens, a set of factory
methods for small-screen UIs could be added to those already in net.jini.lookup.ui.factory
.
A UI factory must be an interface, and each method in the interface must
take an Object
called the roleObject
as its first parameter. Other than the role object, nothing should be passed to
a factory method except information or context required by the toolkit.
It is recommended that all UI factory interfaces include two compile time String
constants:
TOOLKIT
: Gives the package
name of the produced UI's toolkit, which should appear in the UI descriptor's
toolkit
field
TYPE_NAME
: Gives the fully
qualified string type name of the UI factory, as it should appear in UIFactoryTypes
attributes
Such convenience constants not only help reduce typing and increase code
readability, they also leverage compile-time type checking to help minimize the
chance of typographical errors in toolkit
strings and type names added
to UIFactoryTypes
attributes.
splitwebpage
UI objects should be user adapters, as shown in Figure 2. Two temptations that service and UI providers may have are:
Both temptations should be avoided. The Jini service proxy should contain the service functionality, the whole service functionality, and nothing but the service functionality. No user-interface code should appear in the service proxy, and no service functionality should appear in the UI object unless it also appears in the service proxy. In short, Jini Service UIs should merely offer users all or part of the functionality available to direct-use clients via the Jini service proxy's methods.
Note that even though the service item may be passed as the role object for
some roles -- as it is to factories that produce MainUI
s, AdminUI
s, and AboutUI
s --
the full service functionality should nevertheless be available
exclusively through the service proxy. The service item may be passed as the
role object to UI factories because extra information (but not extra
functionality) could exist elsewhere in the service item, in the service ID
or attribute sets, and the UI may wish to display that extra information to
the user.
It is strongly encouraged that service and UI providers decouple the class files required by a particular service item from the class files required by any UIs associated with that service via UI descriptors in the service item. If the class files for the service item and those of all service-associated UIs via UI descriptors are placed into the same JAR file, then a client must download all class files for all UIs just to download the service item, even if the client never uses a single UI.
This specification does not mandate any UI types to be associated with services. Service providers are free to provide any types of UI, or no UIs, with their services. Nevertheless, some discussion of client expectations may help service providers decide what UI types to supply.
First, if a service provider only supplies one UI, it should likely be an
embeddable component, such as an AWT Panel
or Swing JComponent
.
Although Swing UIs can be more attractive than AWT UIs, an AWT Panel
may
allow the greatest reach with one UI type.
A Panel
allows clients to show a UI without another pop-up window, whether they support
AWT or Swing. If a client wants to pop up a UI, it can embed a Panel
UI in a
new Frame
and pop that up. If a client wants to display a Panel
title and icon, it can use the
localized name and icon provided by a ServiceType
.
A Panel
doesn't usually provide an exit for the client, and a menu bar at the top of a Panel
is uncommon.
So as a UI provider, you may also want to provide either a Frame
or a Window
in
which Panel
is placed
and add other UI elements, such as menu bar, status bar, and title. If you take
this approach, one factory object could implement both the PanelFactory
and the FrameFactory
interfaces, because their toolkit is the same. This might make sense if the Panel
is used
in the Frame
,
and the Frame
doesn't require many classes not already used by the panel. Alternatively, you could produce the Panel
and Frame
by two
different UI factories sitting in two different UI descriptors.
You may also wish to support Swing in addition to, or instead of,
AWT. If so, at a minimum a Swing JComponent
UI, or a JComponent
with either a JFrame
or a JWindow,
may
be more suitable. If you take the second approach, one factory object could
implement both the JComponentFactory
and the JFrameFactory
interfaces, because their toolkit is the same. Alternatively, two different UI
factories sitting in two different UI descriptors could produce the JComponent
and
JFrame
.
On the other hand, for those UI roles that represent user dialogs, an AWT Dialog
or
Swing JDialog
may be more appropriate.
Currently no direct support exists in the Jini Service UI API for
speech-only interfaces, but an AWT or Swing UI could be enhanced with speech
capabilities, produced by an appropriate AWT or Swing UI factory type, and
identified as speech-enabled with the appropriate required package names (such
as javax.speech
)
in the RequiredPackages
attribute. If a speech-enhanced GUI is provided, a GUI-only version should also
be provided, as many clients won't have speech capabilities.
Service-level data and client-context data are two data types you may be tempted to pass to UI objects, either directly or via factory methods (which may then tempt you to define new factories). It is strongly recommended that you avoid both temptations.
For example, imagine a service provider requires a user name and password for its service. The service provider wants clients to be able to save a user's name and password locally and enter them automatically the next time the user uses the service. If no user name and password were previously saved, the service UI would prompt the user to type them into a logon dialog box. But if the user name and password were saved, the user would never see the logon dialog box. Rather, the client program would log on automatically with the saved user name and password, and display to the user only the service UI that appears after a successful logon.
To implement this functionality, a service provider might be tempted to define interfaces that allow the client to pass a saved user name and password to the UI. Alternatively, a service provider might be tempted to define new factory methods that enable clients to pass a user name and password to the factory, which could then send them to the UI.
The trouble with either of these approaches is that functionality is being put into the UI that isn't in the service. As mentioned previously, a Jini service's functionality should be modeled in the service proxy, so direct-use client code can just use the service directly. If a service requires a user name and password, the service proxy's interface should allow the client to provide the user name and password. Thus, a client with a user could give the user name and password to the service proxy first, then create the UI. The UI could ask the service proxy if it has a user name and password yet. If not, the UI would show the logon dialog box prompting for the user name and password. Otherwise, the UI wouldn't show the logon dialog box.
The recommended way to design a Jini service and its UIs is to make sure the full functionality is available via the service proxy interface, and keep the UIs focused on being user adapters -- adapting some or all functionality available via the service proxy interface, but offering no more functionality available via the service proxy interface.
Service providers are not the only Jini Community members who will face UI-related temptations in the years ahead; client providers may also be tempted to pass client context data to UI objects.
For example, a client provider wishing to differentiate his or her product from the competition might add a toolbar and status bar to the client program. The client provider might be tempted to define interfaces that allow the client to pass references to the toolbar and status bar to the UI. Alternatively, the client might be tempted to define new factory interfaces whose factory methods include parameters that allow the client to pass references to the toolbar and status bar to the factory, which could then pass it along to the UI. UIs that obtain references to the toolbar and status bar in either of these two ways could then put buttons on the toolbar and write messages to the status bar.
The trouble lurking behind this seemingly innocuous value-add is that the toolbar and status bar references represent client context data, which complicates the UI providers' jobs. If other clients devise their own toolbar and status bar interfaces, and perhaps even up the ante by also defining other client context innovations, UI providers will have to worry about which kinds of client context to support. To the extent a UI provider supports various kinds of client context, that UI provider's test matrix will expand. To the extent that client context becomes complicated, such as the invention of a general compound document model for Jini Service UIs, everyone's job, and the user's experience, become more complicated.
Client providers, therefore, should avoid the temptation to invent client
context for Jini Service UIs. The only context data that should be passed to UI
factory methods is context a UI toolkit requires, such as the Frame
or Window
reference required by an AWT Dialog
. Similarly, the only context in which Jini
Service UIs should be embedded is context the toolkit provides. For example, a
client could embed a Jini Service UI JComponent
in a JFrame
, and
then pop up the JFrame
.
The JComponent
's ability to embed
is provided by its toolkit, Swing.
UI providers can do their part by ensuring that their UIs don't depend on any context other than that provided by the UI toolkit. Jini Service UIs should be self-contained and care only about the context of their toolkit. If a UI provider wants its UI to write messages to a status bar, the UI should not look for a status bar provided by the client, the UI should itself include a status bar.
splitwebpage
To add a third-party UI to an existing service's attribute sets, you must have the service's cooperation. The service can veto your request at any of several points in the process. The steps are:
net.jini.admin.Administrable
(Administrable
).
If the service proxy does not implement Administrable
,
the service provider has already thwarted your wishes. You won't be able to add
a third-party UI directly to the service item's attribute sets.
Administrable
and invoke getAdmin()
.
getAdmin()
implements the net.jini.admin.JoinAdmin
(JoinAdmin
).
If the admin object does not implement JoinAdmin
, the
service provider has thwarted your wishes. You won't be able to add a
third-party UI directly to the service item's attribute sets.
JoinAdmin
,
and invoke appropriate methods to add or modify one or more UIDescriptor
s.
You add or modify UIDescriptor
s in the same manner as
you would add or modify any kind of Entry
in the service's attribute sets.
The JoinAdmin
's
addLookupAttribute()
method lets you add new UIDescriptor
s.
Its modifyLookupAttribute()
method lets you modify existing UIDescriptor
s. Once again, the service provider
can veto your request, even at this step, by throwing an exception from these
methods.
Once a new UIDescriptor
for a third-party UI is successfully added via the process described
previously, the third party won't need to add it again. From that point
forward, whenever a service registers itself with a lookup service, its service
item will include the third-party UIDescriptor
. It will also reregister
itself with any lookup services with which it is currently registered, so that
the new UIDescriptor
will appear there as well. Even if the service provider crashes and restarts,
it should remember the new UIDescriptor
and include it in its registrations
after the crash and restart.
On the other hand, the UI, UI factory, and possibly the attributes require
class files to be available in some codebase. Although the third party never
needs to worry about the UIDescriptor
being included in future service registrations, the third party must make sure
the class files are forever available at some codebase.
One potential problem with adding a third-party UI is that in a strict client-side security policy, downloaded code will by default only have permission to connect back to the host from which the code was downloaded. In that case, if the third-party UI's codebase is on a different host than the service proxy's codebase, the service proxy won't be allowed to talk back to its host at the behest of the UI. Therefore, for a third-party UI to work in practice, either the third-party UI's codebase must be on the same host that serves the service's codebase, or the client must specifically relax its security policy in order to use the third-party UI.
splitwebpage
In the future, the Service UI API can evolve in several different ways. Any party can define new role types and their meanings, new attribute classes, and new factory types. Any party can identify new toolkit types. For clients to be able to use these new types, the new types will need to be publicized. Before a client will be able to use a role, factory, or attribute type, that client's programmers must have had prior knowledge of the type.
Other than service-specific UI roles created under Jini Service APIs, new roles should come from the Service UI project at the Jini Community. Service providers should resist temptation to define new role types, as that complicates clients' jobs. Clients should be able to program to the interface (particular Jini Service APIs about which they have prior knowledge), rather than be forced to program to one or more implementations of that interface. Whether role types are being defined for particular Jini Service APIs, or globally for the Jini Service UI API, the preferred way to define the role interfaces is via the Jini Community Process.
As mentioned previously, new UI factory interface types should be defined with great care. The main justification for a new set of UI factory types is when new UI toolkits appear on the scene. The preferred way to define these interfaces is via the Jini Community Process. Similarly, although anyone can define new attribute types, the preferred way to define these types is through the Jini Community Process.
The Jini Community is the preferred process to define new role, factory, and attribute types because it is the best way to avoid a explosion of types. For example, if a certain attribute type is needed, and twenty different parties define basically the same attribute, but with twenty slightly different names and behaviors, and in twenty different packages, then clients wanting to use that kind of attribute would need to support all twenty variations. It would be far better if those twenty parties agreed on one attribute class. Enabling such collaborations is the Jini Community's main purpose. If twenty parties can agree upon one attribute class, then clients need to be aware of less information (one attribute class versus twenty), and the resulting client programs would likely work more reliably.
splitwebpage
Because the Jini lookup service uses exact matching of the serialized forms of entry fields, it is critical that fields that will be used in template lookups have serialized forms that are consistent across all virtual machines. However, there is no guarantee that implementations of the Set
interface, the declared type of the attributes
field of UIDescriptor
, have consistent serialized forms across all virtual machines. For example, java.util.HashSet
, perhaps the most commonly used implementation of Set
, does not guarantee a consistent serialized form. As a result, if a UIDescriptor
that contains a HashSet
in its attributes
field is retrieved from a Jini lookup service, the serialized a form of the attributes
field could be different if the UIDescriptor
is reserialized as part of a template. This means that a UIDescriptor
, when retrieved from a Jini lookup service and used immediately in a lookup template, may not match itself.
The Service UI API was defined under the assumption that
UIDescriptor
s in
Jini lookup templates might contain non-null
role
and toolkit
fields, but
would always contain null
in their
attributes
and factory
fields.
It was expected that attributes could be inspected on the client side to
select between multiple matches of a Jini lookup. Once a
UIDescriptor
was selected, it was expected that clients would use
the factory
field to produce the selected UI. Because of
these assumptions, the UIDescriptor
class was not designed to
ensure a template in which all four fields were non-null
would work. In other words, the designers were aware that the
attributes
field could not be used in lookup templates,
but did not imagine that anyone would ever need to do that.
When used in templates intended for basic lookup of Jini services,
UIDescriptor
s will likely never have non-null
attributes
fields. Nevertheless, UIDescriptor
s
used in templates intended to modify the attribute sets of
already-registered Jini services could very likely contain
non-null
attributes
fields. For example,
to add an object to the attributes set of a
UIDescriptor
already registered as part
particular Jini service item, you must pass a template UIDescriptor
that exactly matches the registered UIDescriptor
in
the attrSetTemplates
parameter of either:
modifyAttributes
method of net.jini.core.lookup.ServiceRegistration
modifyLookupAttributes
method of net.jini.admin.ServiceRegistration
Unfortunately, the use case of modifying a UIDescriptor
in
an already-registered Jini service item was never considered during the initial
design discussions leading to 1.0 release of the Service UI API. To
address this need, the 1.1 version of this specification narrows slightly
the contracts of these methods and constructors:
UIDescriptor(java.lang.String role,
java.lang.String toolkit, java.util.Set attributes,
java.rmi.MarshalledObject factory)
constructor of
net.jini.lookup.entry.UIDescriptor
Locales(java.util.Set locales)
constructor of
net.jini.lookup.ui.attribute.Locales
RequiredPackages(java.util.Map packages)
constructor of
net.jini.lookup.ui.attribute.RequiredPackages
UIFactoryTypes(java.util.Set typeNames)
constructor of
net.jini.lookup.ui.attribute.UIFactoryTypes
The 1.1 specification adds to the contracts of each of these constructors
a requirement that they copy the contents of the passed Set
or Map
into a serializable read-only version that has a consistent serialized
form across all VMs. This new requirement yields the desired behavior when
attempting to modify UIDescriptor
s already part of service items registered in lookup
services.
splitwebpage
net.jini.lookup.entry
The Service UI API defines two classes, UIDescriptor
and UIDescriptorBean
,
that were placed in a pre-existing package,
net.jini.lookup.entry
.
This specification does not provide a complete specification of
the net.jini.lookup.entry
package. It does, however,
provide a complete specification of classes
net.jini.lookup.entry.UIDescriptor
and
net.jini.lookup.entry.UIDescriptorBean
.
net.jini.lookup.entry.UIDescriptor
public class UIDescriptor
extends net.jini.entry.AbstractEntry
Entry
that enables a UI for a service to be associated
with the service in the attribute sets of the service item.
UIDescriptor
holds a marshalled UI factory object, as
well as a role string, a sub-role string, and set of attributes that describe the
UI generated by the factory.
UIDescriptor()
public UIDescriptor()
Constructs a UIDescriptor
with all fields set to null
.
UIDescriptor(java.lang.String, java.lang.String, java.util.Set, java.rmi.MarshalledObject)
public UIDescriptor(java.lang.String role, java.lang.String toolkit, java.util.Set attributes, java.rmi.MarshalledObject factory)
Constructs a UIDescriptor
with the fields set to passed values.
This constructor copies the contents of the passed attributes Set
into a
serializable read-only Set
that has a
consistent serialized form across all VMs, and initializes the attributes
field with the consistent Set
.
role
- the roletoolkit
- the toolkitattributes
- the attributesfactory
- the factoryrole
public role
Gives the fully qualified name of the interface that represents
the role of the UI generated by the marshalled UI factory.
If the client program unmarshals the UI factory and invokes a factory method, the
UI returned by the factory method must implement the role the interface specified by
role
.
For a client program to be able to use a UI, the client has to have prior knowledge
of the UI semantics, which is defined by the UI's role type. Thus, for a client
to be able to use a UI, the client must understand the semantics
of the type whose fully qualified name is given in the String
referenced from the role
field of that UI's UIDescriptor
.
For example, two role types that are defined in the net.jini.lookup.ui
package by the Jini Service UI Specification are MainUI
, for a main UI
to a Jini service, and AdminUI
, for an administration UI. Other role types
may be defined by the Jini Service UI Specification and by individual Jini service API
specifications.
As the strings referenced from the role
field are Java type names, they
are intended to be manipulated by client programs only. They should not be shown to a user.
toolkit
public toolkit
A String
to facilitate searching whose value represents the main UI toolkit (for example
Swing or AWT) which the produced UI makes use of. The value to which this field should
be set is defined by the semantics of the factory type. (This field is intended
to facilitate searches. For example, a client can search for all blender services that have Swing
MainUI's.)
attributes
public attributes
A set of objects that describe the UI generated by the marshalled UI factory.
factory
public factory
The get()
method of this MarshalledObject
must return an object that implements one or more UI factory interfaces. The actual
UI factory type or types implemented by the returned object
must be described by a UIFactoryTypes
attribute placed in
the attributes set of this UIDescriptor
.
getUIFactory(java.lang.ClassLoader)
public final java.lang.Object getUIFactory(java.lang.ClassLoader parentLoader)
throws java.io.IOException, java.lang.ClassNotFoundException
A convenience method for unmarshalling the UI factory stored
in the MarshalledObject
referenced from the
factory
field. This method saves a reference
to the current context class loader, sets the context class loader
to the class loader passed as parentLoader
, invokes
get()
on the marshalled object, then resets the
context class loader to the saved reference before returning
the object produced by get()
.
The class loader
passed in parentLoader
should be able to load classes
needed when the UI interacts with the roleObject
passed as the first
parameter to the factory method. For example, if the roleObject
is
the service item (as it is for the MainUI
and AdminUI
roles), the class loader passed in parentLoader
could be
the class loader with which the service proxy object referenced
from the service item's service
field was loaded.
For example:
Object uiFactory = uiDescriptor.getUIFactory( serviceItem.service.getClass().getClassLoader());
NullPointerException
- if parentLoader
is null.net.jini.lookup.entry.UIDescriptor
role
java.lang.String role
Gives the fully qualified name of the interface that represents
the role of the UI generated by the marshalled UI factory.
If the client program unmarshals the UI factory and invokes a factory method, the
UI returned by the factory method must implement the role the interface specified by
role
.
For a client program to be able to use a UI, the client has to have prior knowledge
of the UI semantics, which is defined by the UI's role type. Thus, for a client
to be able to use a UI, the client must understand the semantics
of the type whose fully qualified name is given in the String
referenced from the role
field of that UI's UIDescriptor
.
For example, two role types that are defined in the net.jini.lookup.ui
package by the Jini Service UI Specification are MainUI
, for a main UI
to a Jini service, and AdminUI
, for an administration UI. Other role types
may be defined by the Jini Service UI Specification and by individual Jini service API
specifications.
As the strings referenced from the role
field are Java type names, they
are intended to be manipulated by client programs only. They should not be shown to a user.
toolkit
java.lang.String toolkit
A String
to facilitate searching whose value represents the main UI toolkit (for example
Swing or AWT) which the produced UI makes use of. The value to which this field should
be set is defined by the semantics of the factory type. (This field is intended
to facilitate searches. For example, a client can search for all blender services that have Swing
MainUI's.)
attributes
java.util.Set attributes
A set of objects that describe the UI generated by the marshalled UI factory.
factory
java.rmi.MarshalledObject factory
The get()
method of this MarshalledObject
must return an object that implements one or more UI factory interfaces. The actual
UI factory type or types implemented by the returned object
must be described by a UIFactoryTypes
attribute placed in
the attributes set of this UIDescriptor
.
net.jini.lookup.entry.UIDescriptorBean
public class UIDescriptorBean
extends java.lang.Object
implements net.jini.lookup.entry.EntryBean, java.io.Serializable
A JavaBeans(TM) component that encapsulates a UIDescriptor
object.
UIDescriptorBean()
public UIDescriptorBean()
Construct a new JavaBeans component, linked to a new empty UIDescriptor
object.
assoc
protected assoc
The UIDescriptor
object associated with this JavaBeans component.
makeLink(net.jini.core.entry.Entry)
public void makeLink(net.jini.core.entry.Entry e)
Make a link to a UIDescriptor
object.
e
- the Entry
object, which must be a UIDescriptor
, to which to linkjava.lang.ClassCastException
- the Entry
is not
a UIDescriptor
, the correct type for this JavaBeans componentfollowLink()
public net.jini.core.entry.Entry followLink()
Return the UIDescriptor
linked to by this JavaBeans component.
getRole()
public java.lang.String getRole()
Return the value of the role
field in the object linked to by
this JavaBeans component.
setRole(java.lang.String)
public void setRole(java.lang.String role)
Set the value of the role
field in the object linked to by this
JavaBeans component.
role
- a String
specifying the role valuegetToolkit()
public java.lang.String getToolkit()
Return the value of the toolkit
field in the object linked to by
this JavaBeans component.
setToolkit(java.lang.String)
public void setToolkit(java.lang.String toolkit)
Set the value of the toolkit
field in the object linked to by this
JavaBeans component.
toolkit
- a String
specifying the toolkit valuegetAttributes()
public java.util.Set getAttributes()
Return the value of the attributes
field in the object linked to by
this JavaBeans component.
setAttributes(java.util.Set)
public void setAttributes(java.util.Set attributes)
Set the value of the attributes
field in the object linked to by this
JavaBeans component.
attributes
- a Set
specifying the attributes valuegetFactory()
public java.rmi.MarshalledObject getFactory()
Return the value of the factory
field in the object linked to by
this JavaBeans component.
setFactory(java.rmi.MarshalledObject)
public void setFactory(java.rmi.MarshalledObject factory)
Set the value of the factory
field in the object linked to by this
JavaBeans component.
factory
- a MarshalledObject
specifying the factory valuenet.jini.lookup.entry.UIDescriptorBean
assoc
net.jini.lookup.entry.UIDescriptor assoc
The UIDescriptor
object associated with this JavaBeans component.
net.jini.lookup.ui
net.jini.lookup.ui
AboutUI
- UI role interface implemented by About UIs, which enable users to
view (or in some way experience) information about a service.
AdminUI
- UI role interface implemented by Admin UIs,
which enable users to administer a service.
MainUI
- UI role interface implemented by Main UIs,
which enable client programs to grant users general access to a service.
net.jini.lookup.ui
No classes are declared in package net.jini.lookup.ui
.
Exception
s In Package net.jini.lookup.ui
No Exception
s are declared in package net.jini.lookup.ui
.
Error
s In Package net.jini.lookup.ui
No Error
s are declared in package net.jini.lookup.ui
.
net.jini.lookup.ui.AboutUI
public interface AboutUI
UI role interface implemented by About UIs, which enable users to
view (or in some way experience) information about a service.
If a UI descriptor's UI factory produces a UI that implements
this interface (i.e., produces a About UI), the UI descriptor's
role
field must reference a String
with the value
"net.jini.lookup.ui.AboutUI"
.
The first parameter of any factory method declared in a UI factory type is an
object called the "role object."
Any factory method that produces an About UI must accept as the role object the
service item (the net.jini.core.lookup.ServiceItem
) of the service
with which the About UI is associated.
About UIs should allow clients to configure them before they
begin. For example, About UIs produced by FrameFactory
,
JFrameFactory
, WindowFactory
and JWindowFactory
(all members of the net.jini.lookup.ui.factory
package)
should not be visible when they are returned from the factory method. This allows clients to set
the UI's position and size, for example, before making the UI
visible by invoking setVisible(true)
on the UI.
A client should be able to invoke a About UI factory method multiple times sequentially. In other words, if a user uses a service via a About UI, then says exit, then double clicks once again on the service icon, the client can just simply invoke a UI factory method again, and get another About UI for the same service. About UIs, therefore, should be written so that they work no matter what state the service object happens to be in when the About UI is created.
It is recommended that clients use multiple About UIs for the same service only sequentially, and avoid creating multiple About UIs for the same service that operate concurrently with one another. But because some clients may create and use multiple About UIs at the same time for the same service, providers of services and About UIs should program defensively, to ensure that multiple About UIs for the same service at the same time will all work together concurrently.
ROLE
public static final ROLE
Convenience constant to use in the role
field of UIDescriptor
s for AboutUI role UIs.
The value of this constant is "net.jini.lookup.ui.AboutUI"
.
net.jini.lookup.ui.AdminUI
public interface AdminUI
UI role interface implemented by Admin UIs,
which enable users to administer a service.
If a UI descriptor's UI factory produces a UI that implements
this interface (i.e., produces a Admin UI), the UI descriptor's
role
field must reference a String
with the value
"net.jini.lookup.ui.AdminUI"
.
The first parameter of any factory method declared in a UI factory type is an
object called the "role object."
Any factory method that produces an Admin UI must accept as the role object the
service item (the net.jini.core.lookup.ServiceItem
) of the service
with which the Admin UI is associated.
Admin UIs should allow clients to configure them before they
begin. For example, Admin UIs produced by FrameFactory
,
JFrameFactory
, WindowFactory
and JWindowFactory
(all members of the net.jini.lookup.ui.factory
package)
should not be visible when they are returned from the factory method. This allows clients to set
the UI's position and size, for example, before making the UI
visible by invoking setVisible(true)
on the UI.
A client should be able to invoke a Admin UI factory method multiple times sequentially. In other words, if a user uses a service via a Admin UI, then says exit, then double clicks once again on the service icon, the client can just simply invoke a UI factory method again, and get another Admin UI for the same service. Admin UIs, therefore, should be written so that they work no matter what state the service object happens to be in when the Admin UI is created.
It is recommended that clients use multiple Admin UIs for the same service only sequentially, and avoid creating multiple Admin UIs for the same service that operate concurrently with one another. But because some clients may create and use multiple Admin UIs at the same time for the same service, providers of services and Admin UIs should program defensively, to ensure that multiple Admin UIs for the same service at the same time will all work together concurrently.
ROLE
public static final ROLE
Convenience constant to use in the role
field of UIDescriptor
s for AdminUI role UIs.
The value of this constant is "net.jini.lookup.ui.AdminUI"
.
net.jini.lookup.ui.MainUI
public interface MainUI
UI role interface implemented by Main UIs,
which enable client programs to grant users general access to a service.
If a UI descriptor's UI factory produces a UI that implements
this interface (i.e., produces a Main UI), the UI descriptor's
role
field must reference a String
with the value
"net.jini.lookup.ui.MainUI"
.
The first parameter of any factory method declared in a UI factory type is an
object called the "role object."
Any factory method that produces an Main UI must accept as the role object the
service item (the net.jini.core.lookup.ServiceItem
) of the service
with which the Main UI is associated.
Main UIs should allow clients to configure them before they
begin. For example, Main UIs produced by FrameFactory
,
JFrameFactory
, WindowFactory
and JWindowFactory
(all members of the net.jini.lookup.ui.factory
package)
should not be visible when they are returned from the factory method. This allows clients to set
the UI's position and size, for example, before making the UI
visible by invoking setVisible(true)
on the UI.
A client should be able to invoke a Main UI factory method multiple times sequentially. In other words, if a user uses a service via a Main UI, then says exit, then double clicks once again on the service icon, the client can just simply invoke a UI factory method again, and get another Main UI for the same service. Main UIs, therefore, should be written so that they work no matter what state the service object happens to be in when the Main UI is created.
It is recommended that clients use multiple Main UIs for the same service only sequentially, and avoid creating multiple Main UIs for the same service that operate concurrently with one another. But because some clients may create and use multiple Main UIs at the same time for the same service, providers of services and main UIs should program defensively, to ensure that multiple Main UIs for the same service at the same time will all work together concurrently.
ROLE
public static final ROLE
Convenience constant to use in the role
field of UIDescriptor
s for MainUI role UIs.
The value of this constant is "net.jini.lookup.ui.MainUI"
.
net.jini.lookup.ui.factory
net.jini.lookup.ui.factory
DialogFactory
- UI factory for a modal or non-modal AWT Dialog
with a
predetermined title.
FrameFactory
- UI factory for an AWT Frame
with a predetermined
title.
JComponentFactory
- UI factory for a Swing JComponent
.
JDialogFactory
- UI factory for a modal or non-modal Swing JDialog
with a predetermined title.
JFrameFactory
- UI factory for a Swing JFrame
with a predetermined
title.
JWindowFactory
- UI factory for a Swing JWindow
.
PanelFactory
- UI factory for an AWT Panel
.
WindowFactory
- UI factory for an AWT Window
that isn't a Frame
or a Dialog
.
net.jini.lookup.ui.factory
No classes are declared in package net.jini.lookup.ui.factory
.
Exception
s In Package net.jini.lookup.ui.factory
No Exception
s are declared in package net.jini.lookup.ui.factory
.
Error
s In Package net.jini.lookup.ui.factory
No Error
s are declared in package net.jini.lookup.ui.factory
.
net.jini.lookup.ui.factory.DialogFactory
public interface DialogFactory
extends java.io.Serializable
UI factory for a modal or non-modal AWT Dialog
with a
predetermined title.
If the UI generated by the method declared in this interface implements
javax.accessibility.Accessible
and supports the Java Accessibility
API, an AccessibleUI
attribute
should be placed in the UIDescriptor
's attributes
set.
TOOLKIT
public static final TOOLKIT
Convenience constant to use in the toolkit
field of UIDescriptor
s that contain a
DialogFactory
.
The value of this constant is "java.awt"
.
TYPE_NAME
public static final TYPE_NAME
Convenience constant to use in the UIFactoryTypes
set in the attributes
set of UIDescriptor
s
that contain a DialogFactory
.
The value of this constant is "net.jini.lookup.ui.factory.DialogFactory"
.
getDialog(java.lang.Object, java.awt.Dialog)
public java.awt.Dialog getDialog(java.lang.Object roleObject, java.awt.Dialog owner)
Returns a non-modal Dialog
with predetermined title
and the specified owner Dialog
.
roleObject
- an object defined by the semantics of the UI role interface
implemented by the returned UI object. (UI role is indicated in the
role
field of UIDescriptor
s.)owner
- the Dialog
to act as owner of the returned
Dialog
getDialog(java.lang.Object, java.awt.Frame)
public java.awt.Dialog getDialog(java.lang.Object roleObject, java.awt.Frame owner)
Returns a non-modal Dialog
with predetermined title and the
specified owner Frame
.
roleObject
- an object defined by the semantics of the UI role interface
implemented by the returned UI object. (UI role is indicated in the
role
field of UIDescriptor
s.)owner
- the Frame
to act as owner of the returned
Dialog
getDialog(java.lang.Object, java.awt.Dialog, boolean)
public java.awt.Dialog getDialog(java.lang.Object roleObject, java.awt.Dialog owner, boolean modal)
Returns a Dialog
with predetermined title and the
specified modality and owner Dialog
.
roleObject
- an object defined by the semantics of the UI role interface
implemented by the returned UI object. (UI role is indicated in the
role
field of UIDescriptor
s.)owner
- the Dialog
to act as owner of the returned
Dialog
modal
- if true
, the returned Dialog
will block
input to other windows when showngetDialog(java.lang.Object, java.awt.Frame, boolean)
public java.awt.Dialog getDialog(java.lang.Object roleObject, java.awt.Frame owner, boolean modal)
Returns a Dialog
with predetermined title and the
specified modality and owner Frame
.
roleObject
- an object defined by the semantics of the UI role interface
implemented by the returned UI object. (UI role is indicated in the
role
field of UIDescriptor
s.)owner
- the Frame
to act as owner of the returned
Dialog
modal
- if true
, the returned Dialog
will block
input to other windows when shownnet.jini.lookup.ui.factory.FrameFactory
public interface FrameFactory
extends java.io.Serializable
UI factory for an AWT Frame
with a predetermined
title.
If the UI generated by the method declared in this interface implements
javax.accessibility.Accessible
and supports the Java Accessibility
API, an AccessibleUI
attribute
should be placed in the UIDescriptor
's attributes
set.
TOOLKIT
public static final TOOLKIT
Convenience constant to use in the toolkit
field of UIDescriptor
s that contain a
FrameFactory
.
The value of this constant is "java.awt"
.
TYPE_NAME
public static final TYPE_NAME
Convenience constant to use in the UIFactoryTypes
set in the attributes
set of UIDescriptor
s
that contain a FrameFactory
.
The value of this constant is "net.jini.lookup.ui.factory.FrameFactory"
.
getFrame(java.lang.Object)
public java.awt.Frame getFrame(java.lang.Object roleObject)
Returns a Frame
with predetermined title.
roleObject
- an object defined by the semantics of the UI role interface
implemented by the returned UI object. (UI role is indicated in the
role
field of UIDescriptor
s.)net.jini.lookup.ui.factory.JComponentFactory
public interface JComponentFactory
extends java.io.Serializable
UI factory for a Swing JComponent
.
If the UI generated by the method declared in this interface implements
javax.accessibility.Accessible
and supports the Java Accessibility
API, an AccessibleUI
attribute
should be placed in the UIDescriptor
's attributes
set.
TOOLKIT
public static final TOOLKIT
Convenience constant to use in the toolkit
field of UIDescriptor
s that contain a
JComponentFactory
.
The value of this constant is "javax.swing"
.
TYPE_NAME
public static final TYPE_NAME
Convenience constant to use in the UIFactoryTypes
set in the attributes
set of UIDescriptor
s
that contain a JComponentFactory
.
The value of this constant is "net.jini.lookup.ui.factory.JComponentFactory"
.
getJComponent(java.lang.Object)
public javax.swing.JComponent getJComponent(java.lang.Object roleObject)
Returns a JComponent
.
roleObject
- an object defined by the semantics of the UI role interface
implemented by the returned UI object. (UI role is indicated in the
role
field of UIDescriptor
s.)net.jini.lookup.ui.factory.JDialogFactory
public interface JDialogFactory
extends java.io.Serializable
UI factory for a modal or non-modal Swing JDialog
with a predetermined title.
If the UI generated by the method declared in this interface implements
javax.accessibility.Accessible
and supports the Java Accessibility
API, an AccessibleUI
attribute
should be placed in the UIDescriptor
's attributes
set.
TOOLKIT
public static final TOOLKIT
Convenience constant to use in the toolkit
field of UIDescriptor
s that contain a
JDialogFactory
.
The value of this constant is "javax.swing"
.
TYPE_NAME
public static final TYPE_NAME
Convenience constant to use in the UIFactoryTypes
set in the attributes
set of UIDescriptor
s
that contain a JDialogFactory
.
The value of this constant is "net.jini.lookup.ui.factory.JDialogFactory"
.
getJDialog(java.lang.Object)
public javax.swing.JDialog getJDialog(java.lang.Object roleObject)
Returns a non-modal JDialog
with
predetermined title and no specified owner.
roleObject
- an object defined by the semantics of the UI role interface
implemented by the returned UI object. (UI role is indicated in the
role
field of UIDescriptor
s.)getJDialog(java.lang.Object, java.awt.Dialog)
public javax.swing.JDialog getJDialog(java.lang.Object roleObject, java.awt.Dialog owner)
Returns a non-modal JDialog
with a
predetermined title with the specified owner Dialog
.
roleObject
- an object defined by the semantics of the UI role interface
implemented by the returned UI object. (UI role is indicated in the
role
field of UIDescriptor
s.)owner
- the Dialog
to act as owner of the returned
JDialog
getJDialog(java.lang.Object, java.awt.Frame)
public javax.swing.JDialog getJDialog(java.lang.Object roleObject, java.awt.Frame owner)
Returns a non-modal JDialog
with a
predetermined title with the specified owner Frame.
roleObject
- an object defined by the semantics of the UI role interface
implemented by the returned UI object. (UI role is indicated in the
role
field of UIDescriptor
s.)owner
- the Frame
to act as owner of the returned
JDialog
getJDialog(java.lang.Object, java.awt.Dialog, boolean)
public javax.swing.JDialog getJDialog(java.lang.Object roleObject, java.awt.Dialog owner, boolean modal)
Returns a JDialog
with predetermined title and the
specified modality and owner Dialog
.
roleObject
- an object defined by the semantics of the UI role interface
implemented by the returned UI object. (UI role is indicated in the
role
field of UIDescriptor
s.)owner
- the Dialog
to act as owner of the returned
JDialog
modal
- if true
, the returned JDialog
will block
input to other windows when showngetJDialog(java.lang.Object, java.awt.Frame, boolean)
public javax.swing.JDialog getJDialog(java.lang.Object roleObject, java.awt.Frame owner, boolean modal)
Returns a JDialog
with predetermined title and the
specified modality and owner Frame
.
roleObject
- an object defined by the semantics of the UI role interface
implemented by the returned UI object. (UI role is indicated in the
role
field of UIDescriptor
s.)owner
- the Frame
to act as owner of the returned
JDialog
modal
- if true
, the returned JDialog
will block
input to other windows when shownnet.jini.lookup.ui.factory.JFrameFactory
public interface JFrameFactory
extends java.io.Serializable
UI factory for a Swing JFrame
with a predetermined
title.
If the UI generated by the method declared in this interface implements
javax.accessibility.Accessible
and supports the Java Accessibility
API, an AccessibleUI
attribute
should be placed in the UIDescriptor
's attributes
set.
TOOLKIT
public static final TOOLKIT
Convenience constant to use in the toolkit
field of UIDescriptor
s that contain a
JFrameFactory
.
The value of this constant is "javax.swing"
.
TYPE_NAME
public static final TYPE_NAME
Convenience constant to use in the UIFactoryTypes
set in the attributes
set of UIDescriptor
s
that contain a JFrameFactory
.
The value of this constant is "net.jini.lookup.ui.factory.JFrameFactory"
.
getJFrame(java.lang.Object)
public javax.swing.JFrame getJFrame(java.lang.Object roleObject)
Returns a JFrame
with predetermined title.
roleObject
- an object defined by the semantics of the UI role interface
implemented by the returned UI object. (UI role is indicated in the
role
field of UIDescriptor
s.)net.jini.lookup.ui.factory.JWindowFactory
public interface JWindowFactory
extends java.io.Serializable
UI factory for a Swing JWindow
.
If the UI generated by the method declared in this interface implements
javax.accessibility.Accessible
and supports the Java Accessibility
API, an AccessibleUI
attribute
should be placed in the UIDescriptor
's attributes
set.
TOOLKIT
public static final TOOLKIT
Convenience constant to use in the toolkit
field of UIDescriptor
s that contain a
JWindowFactory
.
The value of this constant is "javax.swing"
.
TYPE_NAME
public static final TYPE_NAME
Convenience constant to use in the UIFactoryTypes
set in the attributes
set of UIDescriptor
s
that contain a JWindowFactory
.
The value of this constant is "net.jini.lookup.ui.factory.JWindowFactory"
.
getJWindow(java.lang.Object)
public javax.swing.JWindow getJWindow(java.lang.Object roleObject)
Returns a JWindow
with no specified
owner.
roleObject
- an object defined by the semantics of the UI role interface
implemented by the returned UI object. (UI role is indicated in the
role
field of UIDescriptor
s.)getJWindow(java.lang.Object, java.awt.Window)
public javax.swing.JWindow getJWindow(java.lang.Object roleObject, java.awt.Window owner)
Returns a JWindow
with specified
owner Window
.
roleObject
- an object defined by the semantics of the UI role interface
implemented by the returned UI object. (UI role is indicated in the
role
field of UIDescriptor
s.)owner
- the Window
to act as owner of the returned
JWindow
getJWindow(java.lang.Object, java.awt.Frame)
public javax.swing.JWindow getJWindow(java.lang.Object roleObject, java.awt.Frame owner)
Returns a JWindow
with specified
owner Frame
.
roleObject
- an object defined by the semantics of the UI role interface
implemented by the returned UI object. (UI role is indicated in the
role
field of UIDescriptor
s.)owner
- the Frame
to act as owner of the returned
JWindow
net.jini.lookup.ui.factory.PanelFactory
public interface PanelFactory
extends java.io.Serializable
UI factory for an AWT Panel
.
If the UI generated by the method declared in this interface implements
javax.accessibility.Accessible
and supports the Java Accessibility
API, an AccessibleUI
attribute
should be placed in the UIDescriptor
's attributes
set.
A PreferredTitle
may be placed in the attributes set to indicate
a preferred title of a pop-up window containing this component.
TOOLKIT
public static final TOOLKIT
Convenience constant to use in the toolkit
field of UIDescriptor
s that contain a
PanelFactory
.
The value of this constant is "java.awt"
.
TYPE_NAME
public static final TYPE_NAME
Convenience constant to use in the UIFactoryTypes
set in the attributes
set of UIDescriptor
s
that contain a JPanelFactory
.
The value of this constant is "net.jini.lookup.ui.factory.PanelFactory"
.
getPanel(java.lang.Object)
public java.awt.Panel getPanel(java.lang.Object roleObject)
Returns a Panel
.
net.jini.lookup.ui.factory.WindowFactory
public interface WindowFactory
extends java.io.Serializable
UI factory for an AWT Window
that isn't a Frame
or a Dialog
.
AWT Frame
s should be produced by a FrameFactory
.
AWT Dialog
s should be produced by a DialogFactory
.)
If the UI generated by the method declared in this interface implements
javax.accessibility.Accessible
and supports the Java Accessibility
API, an AccessibleUI
attribute
should be placed in the UIDescriptor
's attributes
set.
TOOLKIT
public static final TOOLKIT
Convenience constant to use in the toolkit
field of UIDescriptor
s that contain a
WindowFactory
.
The value of this constant is "java.awt"
.
TYPE_NAME
public static final TYPE_NAME
Convenience constant to use in the UIFactoryTypes
set in the attributes
set of UIDescriptor
s
that contain a WindowFactory
.
The value of this constant is "net.jini.lookup.ui.factory.WindowFactory"
.
getWindow(java.lang.Object, java.awt.Window)
public java.awt.Window getWindow(java.lang.Object roleObject, java.awt.Window owner)
Returns a Window
with specified
owner Window
roleObject
- an object defined by the semantics of the UI role interface
implemented by the returned UI object. (UI role is indicated in the
role
field of UIDescriptor
s.)owner
- the Window
to act as owner of the returned
Window
getWindow(java.lang.Object, java.awt.Frame)
public java.awt.Window getWindow(java.lang.Object roleObject, java.awt.Frame owner)
Returns a Window
with specified
owner Frame
owner
- the Frame
to act as owner of the returned
Window
net.jini.lookup.ui.attribute
net.jini.lookup.ui.attribute
No interfaces are declared in package net.jini.lookup.ui.attribute
.
net.jini.lookup.ui.attribute
AccessibleUI
- UI attribute that indicates a generated
UI implements the the javax.accessibility.Accessible
interface
and that the designer of the UI did the necessary work to make sure the UI
would work well with assistive technologies that are aware of the Java Accessibility API.
Locales
- UI attribute that lists the locales supported
by a generated UI.
RequiredPackages
- UI attribute that enables clients to get a list of
the fully qualified names and version numbers of packages
required by a UI.
UIFactoryTypes
- UI attribute that lists UI factory interfaces of which a UI factory
is an instance.
Exception
s In Package net.jini.lookup.ui.attribute
No Exception
s are declared in package net.jini.lookup.ui.attribute
.
Error
s In Package net.jini.lookup.ui.attribute
No Error
s are declared in package net.jini.lookup.ui.attribute
.
net.jini.lookup.ui.attribute.AccessibleUI
public class AccessibleUI
extends java.lang.Object
implements java.io.Serializable
UI attribute that indicates a generated
UI implements the the javax.accessibility.Accessible
interface
and that the designer of the UI did the necessary work to make sure the UI
would work well with assistive technologies that are aware of the Java Accessibility API.
Only UIDescriptor
s whose marshalled UI factory produces
a UI that supports the Accessibility API should include this attribute.
The presence of this attribute in an attribute set means the produced
UI will work well with assistive technologies that are aware of the Java
Accessibility API.
AccessibleUI()
public AccessibleUI()
Constructs a new AccessibleUI
attribute.
equals(java.lang.Object)
public boolean equals(java.lang.Object o)
Compares the specified object (passed in o
) with this
AccessibleUI
object for equality. Returns true
if
o
is non-null
and the fully qualified class name of the specified object (passed
in o
) is the same as the fully qualified class name of this object.
o
- the object to compare againsthashCode()
public int hashCode()
Returns the hash code value for this AccessibleUI
. As
all AccessibleUI
objects are conceptually equivalent, this
method returns the hash code value for this object's fully qualified
class name String
.
net.jini.lookup.ui.attribute.AccessibleUI
Serialized form of class
net.jini.lookup.ui.attribute.AccessibleUI
has no serialized fields.
net.jini.lookup.ui.attribute.Locales
public class Locales
extends java.lang.Object
implements java.io.Serializable
UI attribute that lists the locales supported by a generated UI.
Locales(java.util.Set)
public Locales(java.util.Set locales)
Constructs a Locales
using the
passed Set
. The Set
can
be mutable or immutable, and must contain only
java.util.Locale
objects. Each Locale
must
represent a locale that is supported by the UI generated
by the UI factory stored in marshalled form in the
same UIDescriptor
. This constructor copies
the contents of the passed Set
into a
serializable read-only Set
that has a
consistent serialized form across all VMs.
locales
- A Set
of Locale
objects. Each element must be non-null and an instance
of java.util.Locale
.NullPointerException
- if locales
is null
or any element of locales
set is null
.IllegalArgumentException
- if any non-null element of
locales
set is not an instance of
java.util.Locale
.isLocaleSupported(java.util.Locale)
public boolean isLocaleSupported(java.util.Locale locale)
Indicates whether or not a locale is supported
by the UI generated by the UI factory stored in
the marshalled object of the same UIDescriptor
.
This method returns true
only if the passed
Locale
exactly matches a Locale
supported by the UI, as defined by the equals()
method of class java.util.Locale
. For example, imagine the UI supports the
"en" (General English) locale, but not the "en_US" (US English) locale.
Then, if "en_US" is passed to this method, the method will return
false
.
locale
- the locale to checkNullPointerException
- if locale
is null
.getFirstSupportedLocale(java.util.Locale[])
public java.util.Locale getFirstSupportedLocale(java.util.Locale[] locales)
Looks through the passed array of Locale
s
(in the order they appear in the array)
and returns the first Locale
that is
supported by the UI (as defined by isLocaleSupported()
),
or null
, if none of the Locale
s in
the passed array are supported by the UI.
locales
- an array of locales in order of most desired to
least desiredNullPointerException
- if locales
is null
.getFirstSupportedLocale(java.util.List)
public java.util.Locale getFirstSupportedLocale(java.util.List locales)
Iterates through the passed List
of Locale
s
and returns the first Locale
that is
supported by the UI (as defined by isLocaleSupported()
),
or null
, if none of the Locale
s in
the passed array are supported by the UI.
locales
- a List
of locales in order of most
desired to least desiredNullPointerException
- if locales
is null
.iterator()
public java.util.Iterator iterator()
Returns an iterator over the set of java.util.Locale
objects, one for each locale supported
by the UI generated by the UI factory stored in
the marshalled object of the same UIDescriptor
.
The returned Iterator
does not support
remove()
.
getLocales()
public java.util.Set getLocales()
Returns an unmodifiable java.util.Set
that contains
java.util.Locale
objects, one for each locale supported
by the UI generated by the UI factory stored in
the marshalled object of the same UIDescriptor
.
equals(java.lang.Object)
public boolean equals(java.lang.Object o)
Compares the specified object (the Object
passed
in o
) with this Locales
object for equality. Returns true if the specified object
is not null, if the specified object's class is
Locales
, if the two sets of
supported locales are the same size, and if every locale mentioned in the
specified Locales
object (passed in o
) is also mentioned
in this Locales
object.
o
- the object to compare againsthashCode()
public int hashCode()
Returns the hash code value for this Locales
object.
net.jini.lookup.ui.attribute.Locales
supportedLocales
java.util.Set supportedLocales
A Set
of java.util.Locale
objects,
each of which represents one locale supported by the UI generated
by the UI factory stored in marshalled form in the same
UIDescriptor
.
net.jini.lookup.ui.attribute.RequiredPackages
public class RequiredPackages
extends java.lang.Object
implements java.io.Serializable
UI attribute that enables clients to get a list of the fully qualified names and version numbers of packages required by a UI.
One or more RequiredPackages
attributes may appear
in the attributes of a UIDescriptor
. Client programs
interested in a UI may wish to verify that they have all required
packages mentioned in the RequiredPackages
attributes
(if any) contained in the UI's UIDescriptor
, before
they attempt to create the UI. If the client is lacking any required
packages (either because the entire package is absent or because the
package is present but of an incompatible version), the client will
not be able to use the UI,
The intent of this attribute is to provide a quick way for a client program
to determine that a UI is unusable by a client, not to grant a guarantee that a UI
is definitely usable by the client. If a client is missing a required package,
or has an incompatible version of a required package, the client cannot use the UI.
But if the client has compatible versions of all required packages listed in a
RequiredPackage
attribute, the client may or may not be able to
use the UI.
UI providers should take bold and valiant strides to list in a RequiredPackage
attribute all known packages required of the client, so that if
the client discovers it has compatible versions of all listed packages and
attempts to generate the UI via the factory method, the client will likely
succeed. However, client programmers should bear in mind that a
RequiredPackage
attribute doesn't necessarily list
all required packages. As a result, satisfying all required packages
doesn't absolutely guarantee the UI will work on the client.
As a result, client programs should program defensively.
(For example, clients should probably catch LinkageError
in appropriate places when dealing with UIs, even if they find they have
compatible versions of all required packages listed in RequiredPackage
attributes.)
The version numbers must take the form of "specification version numbers," as used
by the java.lang.Package
class:
Specification version numbers use a "Dewey Decimal" syntax that consists of positive decimal integers separated by periods ".", for example, "2.0" or "1.2.3.4.5.6.7". This allows an extensible number to be used to represent major, minor, micro, etc versions. The version number must begin with a number.
RequiredPackages(java.util.Map)
public RequiredPackages(java.util.Map packages)
Constructs a RequiredPackages
attribute
with the passed Map
. The keys contained
in the passed Map
must be String
s
that represent fully qualified names of required packages.
Each value contained in the passed Map
must
be the oldest version number of the package (defined by the
key) that is compatible with the UI. Version numbers are
String
s in the form of
"specification version numbers," as used
by the java.lang.Package
class. This constructor copies
the contents of the passed Map
into a
serializable unmodifiable Map
that has a
consistent serialized form across all VMs.
packages
- a map of String
fully qualified
names of required packages to String
version
numbersNullPointerException
- if packages
is null
or if any keys or values contained
in packages
are null
.IllegalArgumentException
- if any non-null key or
value contained in packages
set is not an instance of
java.lang.String
.iterator()
public java.util.Iterator iterator()
Returns an iterator over the set of String
fully qualified package names required
by the UI generated by the UI factory stored in
the marshalled object of the same UIDescriptor
.
The returned Iterator
does not support
remove()
.
getVersion(java.lang.String)
public java.lang.String getVersion(java.lang.String packageName)
Returns a version number for the required package
whose fully qualified package name is passed as
the packageName
parameter. If the
passed String
does not represent a
required package listed in this RequiredPackage
attribute, this method returns null
.
The version number returned should be a "specification version number," as used
by the java.lang.Package
class:
Specification version numbers use a "Dewey Decimal" syntax that consists of positive decimal integers separated by periods ".", for example, "2.0" or "1.2.3.4.5.6.7". This allows an extensible number to be used to represent major, minor, micro, etc versions. The version number must begin with a number.
NullPointerException
- if packageName
is null
.getRequiredPackages()
public java.util.Map getRequiredPackages()
Returns a java.util.Map
whose keys
are String
s that represent fully
qualified names of required packages and whose
values are be the oldest version number of the
package (defined by the
key) that is compatible with the UI. Version numbers are
String
s in the form of
"specification version numbers," as used
by the java.lang.Package
class:
The version numbers contained as values in the returned Map
should be a "specification version number," as used
by the java.lang.Package
class:
Specification version numbers use a "Dewey Decimal" syntax that consists of positive decimal integers separated by periods ".", for example, "2.0" or "1.2.3.4.5.6.7". This allows an extensible number to be used to represent major, minor, micro, etc versions. The version number must begin with a number.
equals(java.lang.Object)
public boolean equals(java.lang.Object o)
Compares the specified object (the Object
passed
in o
) with this RequiredPackages
object for equality. Returns true if the specified object
is not null, if the specified object's class is
RequiredPackages
, if the two sets of
package-version pairs are the same size, and if every package-version pair mentioned in the
specified RequiredPackages
object (passed in o
) is also mentioned
in this RequiredPackages
object.
o
- the object to compare againsthashCode()
public int hashCode()
Returns the hash code value for this RequiredPackages
object.
net.jini.lookup.ui.attribute.RequiredPackages
requiredPackages
java.util.Map requiredPackages
A Map
of String
keys to
String
values. The keys contained
in the Map
must be String
s
that represent fully qualified names of required packages.
Each value contained in the Map
must
be the oldest version number of the package (defined by the
key) that is compatible with the UI. Version numbers are
String
s in the form of "specification version
numbers," as used by the java.lang.Package
class.
net.jini.lookup.ui.attribute.UIFactoryTypes
public class UIFactoryTypes
extends java.lang.Object
implements java.io.Serializable
UI attribute that lists UI factory interfaces of which a UI factory is an instance.
UIFactoryTypes(java.util.Set)
public UIFactoryTypes(java.util.Set typeNames)
Constructs a UIFactoryTypes
attribute using the
passed Set
. The Set
can
be mutable or immutable, and must contain only
String
s. Each String
should
represent a fully qualified Java type name of a UI factory
interface. This constructor copies
the contents of the passed Set
into a
serializable read-only Set
that has a
consistent serialized form across all VMs.
The isAssignableTo
method of this class will only
return true
for types whose names are passed
explicitly to this constructor via the typeNames
parameter.
This constructor does not inspect the inheritance hierarchies of the
types whose names are passed via the typeNames
parameter. It is the client's responsibility to include the name of
every UI factory interface of which the relevant UI factory (the UI factory being described
by this class) is an instance.
typeNames
- A Set
of String
objects. Each element must be non-null and an instance
of java.lang.String
.NullPointerException
- if typeNames
is null
or any element of typeNames
set is null
.IllegalArgumentException
- if any non-null element of
typeNames
set is not an instance of
java.lang.String
.isAssignableTo(java.lang.Class)
public boolean isAssignableTo(java.lang.Class classObj)
Returns true
if the UI factory (contained in
marshalled form in the same UIDescriptor
) is
an instance of the UI factory interface
type passed in parameter classObj
.
Else, returns false
.
This method compares the fully qualified name
of the type represented by the passed Class
with
the fully qualified names of UI factory interfaces implemented
by the UI factory's class. If
an exact string match is found, this method returns true
.
If the UI factory is ultimately loaded with a class loader whose
parent-delegation chain doesn't include the class loader
that defined the passed class, a type with the same name
would be loaded into a different namespace of
the virtual machine. If so, the two types would
be considered different by the virtual machine, even though
they shared the same fully qualified name.
classObj
- the type to checkNullPointerException
- if classObj
is null
iterator()
public java.util.Iterator iterator()
Returns an iterator over the set of types of which
a UI factory object is an instance in no particular order.
The returned Iterator
does not support
remove()
.
getTypeNames()
public java.util.Set getTypeNames()
Returns an unmodifiable Set of fully qualified type name
String
s of which
a UI factory is an instance in no particular order.
equals(java.lang.Object)
public boolean equals(java.lang.Object o)
Compares the specified object (the Object
passed
in o
) with this UIFactoryTypes
object for equality. Returns true if the specified object
is not null, if the specified object's class is
UIFactoryTypes
, if the two sets of
factory types are the same size, and if every factory type mentioned in the
specified UIFactoryTypes
object (passed in o
) is also mentioned
in this UIFactoryTypes
object.
o
- the object to compare againsthashCode()
public int hashCode()
Returns the hash code value for this UIFactoryTypes
object.
net.jini.lookup.ui.attribute.UIFactoryTypes
typeNames
java.util.Set typeNames
A Set
of String
s,
each of which represents one fully qualified type name.
Each String
type name should indicate one
UI factory interface implemented by the UI factory contained
in marshalled form in the same UIDescriptor
in
which this UIFactoryTypes
appears.