Summary
In this document I show a Java application, used in the Cyberspace demo, that wraps a Jini
service and service UI.

In the Cyberspace demo, I launched each Jini service and service UI in its own JVM.
The Java application that I ran to start the JVM for a Jini service and service UI
was named ObjectLauncher. ObjectLauncher was fired up
by CyberspaceConsole.
Here's the code for ObjectLauncher:

/*
* This source code (.java) file is Copyright (C) 2000 Artima Software, Inc. All rights reserved.
* This file accompanies the Jini Place Service Draft Specification, written by Bill
* Venners and published on the World Wide Web at:
*
* http://www.artima.com/jini/cyberspace/DraftSpec.html,
*
* This source file may not be copied, modified, or redistributed EXCEPT as allowed
* by the following statements: From August 11, 2000 through December 31, 2000, you may
* copy and/or modify these files to test and experiment with the Place API,
* described in the Jini Place Service Draft Specification. Any bug fixes must be given
* back to Artima Software, Inc. You may not redistribute this file or any binary (such
* as .class) files generated from this file. You may not distribute modified versions
* this files or any binary (such as .class) files generated from modified versions of
* this file. You may not remove this copyright notice. You may not use this file in
* printed media without the express permission of Bill Venners. And if that weren't
* enough, you must destroy all copies of this file, and any binary (such as
* .class) files generated from this file, by December 31, 2000.
*
* ARTIMA SOFTWARE, INC. MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THIS SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
* BILL VENNERS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY A LICENSEE AS A RESULT
* OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*/
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
import java.rmi.MarshalledObject;
import java.rmi.RMISecurityManager;
import net.jini.core.lookup.ServiceItem;
import net.jini.lookup.entry.UIDescriptor;
import net.jini.core.entry.Entry;
import net.jini.lookup.ui.MainUI;
import net.jini.lookup.ui.attribute.UIFactoryTypes;
import net.jini.lookup.ui.factory.JFrameFactory;
import net.jini.lookup.ui.factory.FrameFactory;
import java.util.Iterator;
import javax.swing.JFrame;
import java.awt.Frame;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
// Launch a Jini service, either from a URL passed as a command line
// argument, or from a serialized marshalled service item read in
// from the standard input.
public class ObjectLauncher {
public static void main(String[] args) {
// If no command line argument, assume a serialized marshalled
// Jini service item is being fed to the standard input.
boolean fromURL = true;
if (args.length == 0) {
fromURL = false;
}
try {
System.setSecurityManager(new RMISecurityManager());
// Will read the serialized marshalled service item from InputStream "is".
// If grabbing via a URL, get the stream from a URL object. Else
// just assume its coming in at the standard input.
InputStream is = System.in;
if (fromURL) {
URL url = new URL(args[0]);
System.out.println(
"Launching object from URL: " + url.toString());
URLConnection conn = url.openConnection();
is = url.openStream();
// Get info about the resource
String type = conn.getContentType();
if ((!type.equals("application/x-serviceui")) && (!type.equals("application/jini"))) {
System.out.println("Wrong MIME type. Not a Jini service item: " + type);
return;
}
}
else {
System.out.println(
"Launching object passed by browser.");
}
try {
ObjectInputStream ois =
new ObjectInputStream(
new BufferedInputStream(is)
);
// Should be a serialized MarshalledObject
MarshalledObject mo = null;
try {
mo = (MarshalledObject) ois.readObject();
}
catch (ClassNotFoundException cnfe) {
System.out.println("Unable to deserialize the marshalled object.");
cnfe.printStackTrace(System.out);
return;
}
// Unmarshalling should yield a Jini ServiceItem
ServiceItem serviceItem;
try {
serviceItem = (ServiceItem) mo.get();
}
catch (ClassNotFoundException cnfe) {
System.out.println("Unable to unmarshal the service item.");
cnfe.printStackTrace(System.out);
return;
}
int attrCount = serviceItem.attributeSets.length;
Entry[] attr = serviceItem.attributeSets;
// Now search for an appropriate service UI from among
// UIDescriptor's in the ServiceItem
UIDescriptor selectedDescriptor = null;
outer: for (int i = 0; i < attrCount; ++i) {
if (attr[i] instanceof UIDescriptor) {
UIDescriptor desc = (UIDescriptor) attr[i];
if (desc.attributes == null) {
continue;
}
// Looking for a Main UI
if (!desc.role.equals(MainUI.ROLE)) {
continue;
}
// Iterate through the attributes, looking for
// a JFrame or Frame.
Iterator it = desc.attributes.iterator();
while (it.hasNext()) {
Object uiAttr = it.next();
if (uiAttr instanceof UIFactoryTypes) {
UIFactoryTypes factoryTypes = (UIFactoryTypes) uiAttr;
boolean found = false;
found = factoryTypes.isAssignableTo(JFrameFactory.class);
if (!found) {
found = factoryTypes.isAssignableTo(FrameFactory.class);
}
if (found) {
// Should also look through required packages here, but
// ignoring that for the demo
selectedDescriptor = desc;
break outer;
}
}
}
}
}
if (selectedDescriptor == null) {
System.out.println("Found no appropriate UI.");
System.exit(0);
}
// Get the UI Factory for the chosen UI
Object uiFactory = null;
try {
uiFactory = selectedDescriptor.getUIFactory(serviceItem.service.getClass().getClassLoader());
}
catch (ClassNotFoundException cnfe) {
System.out.println("Class not found. Couldn't unmarshal the UI factory.");
cnfe.printStackTrace(System.out);
return;
}
if (uiFactory instanceof JFrameFactory) {
JFrameFactory swingJFrameFactory = (JFrameFactory) uiFactory;
JFrame jf = swingJFrameFactory.getJFrame(serviceItem);
// Add a WindowListener so that the process exits nicely
jf.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
// This one gets called after the user Selects some operating
// system thing that requests the window to be closed.
System.exit(0);
}
public void windowClosed(WindowEvent e) {
// This one gets called after dispose() is called, such
// as when the user selects Exit.
System.exit(0);
}
}
);
jf.setLocation(100, 100);
jf.pack();
// If this is a place service, set the size to a nice size for the demo, because
// pack makes all links line up on one long horizontal line, which is 110 pixels
// tall. The only other JFrame is the calculator, which comes out (331, 258)
// This is obviously a hard coded demo thing.
Dimension dim = jf.getSize();
if (dim.height < 150 && dim.width > 360) {
jf.setSize(360, 270);
}
jf.setVisible(true);
}
else {
FrameFactory awtFrameFactory = (FrameFactory) uiFactory;
Frame frame = awtFrameFactory.getFrame(serviceItem);
// Add a WindowListener so that the process exits nicely
frame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
// This one gets called after the user Selects some operating
// system thing that requests the window to be closed.
System.exit(0);
}
public void windowClosed(WindowEvent e) {
// This one gets called after dispose() is called, such
// as when the user selects Exit.
System.exit(0);
}
}
);
frame.setLocation(100, 100);
// This is colorschemer, so just set it to an appropriate size (for a nice looking demo)
// Yet another hard coded demo thing.
frame.setSize(468, 350);
frame.setVisible(true);
}
}
finally {
is.close();
}
}
catch (MalformedURLException e) {
System.out.println(e.toString());
e.printStackTrace(System.out);
}
catch (IOException e) {
System.out.println(e.toString());
e.printStackTrace(System.out);
}
}
}

Discussion Forum

To discuss the ideas presented in this article please post to the cyberspace@jini.org mailing
list, or visit: