ControlPoint.subscribe(Service)
StateVariable.setValue()
Interface for different implementations of timers, matches the methods defined for the timer service
/**
* Timer service as per Timer XML description
* This may be subclassed to provide functionality
*/
package service;
import xmltypes.*;
import org.cybergarage.upnp.Service;
public interface Timer {
public void setTime(Time t);
public Time getTime();
public boolean isValidTime();
// Change start
public void setService(Service svc);
// Change end
}
Another implementation that runs a "ticker" in a thread to update the time. This timer is invalid until something else sets its time
/**
* Timer service as per Timer XML description
*
* The timer service has two state vbls, Time and TimeValid.
* Time is continually changing, updated every second. If we kept this
* state in the cybergarage state vbl (which is a string) then every
* second we would be parsing the string into a Time object, incrementing
* it and then turning it back into a string. Kind of wasteful. So it is
* (maybe) better to keep the state in a Time object (in the Ticker) and
* just copy it into the cybergarage state vbl on each change. On the other hand,
* TimeValid changes rarely and isn't checked much, so we can keep it
* in the cybergarage state vbl always
*/
package service;
import xmltypes.*;
import org.cybergarage.upnp.Service;
import org.cybergarage.upnp.StateVariable;
public class TickerTimer implements Timer {
private Ticker ticker;
// Change start
private Service service;
private StateVariable timeVar;
private StateVariable validVar;
// Change end
public TickerTimer() {
}
// Change start
public void setService(Service svc) {
service = svc;
Time time = new Time("12:00:00");
timeVar = svc.getStateVariable("Time");
timeVar.setValue(time.toString());
validVar = svc.getStateVariable("TimeValid");
validVar.setValue("false");
ticker = new Ticker(time, timeVar);
ticker.start();
}
// Change end
public void setTime(Time t) {
if (ticker != null) {
ticker.stopRunning();
}
// Change start
timeVar.setValue(t.toString());
validVar.setValue("true");
// Change end
ticker = new Ticker(t, timeVar);
ticker.start();
}
public Time getTime() {
Time time = new Time(timeVar.getValue());
return time;
}
public boolean isValidTime() {
if (validVar.getValue().equals("true")) {
return true;
} else {
return false;
}
}
}
class Ticker extends Thread {
private Time time;
private boolean keepRunning = true;
// Change start
private StateVariable timeVar;
// Change end
// Change start
public Ticker(Time t, StateVariable tVar) {
time = t;
timeVar = tVar;
}
// Change end
public void run() {
while (keepRunning) {
try {
sleep(1000);
} catch(InterruptedException e) {
}
if (keepRunning) {
time.increment();
// Change start
timeVar.setValue(time.toString());
// Change end
}
}
}
public void stopRunning() {
keepRunning = false;
}
}
/******************************************************************
*
* CyberUPnP for Java
*
* Copyright (C) Satoshi Konno 2002
*
* File : ClockDevice.java
*
******************************************************************/
package device;
import service.*;
import xmltypes.*;
import java.io.*;
import org.cybergarage.upnp.*;
import org.cybergarage.upnp.device.*;
import org.cybergarage.upnp.control.*;
import org.cybergarage.http.*;
import org.cybergarage.upnp.ssdp.*;
public class ClockDevice extends Device implements ActionListener, QueryListener, NotifyListener
{
private final static String DESCRIPTION_FILE_NAME = "description/description.xml";
private final static String PRESENTATION_URI = "clock/presentation";
private ControlPoint ctrlPoint = new ControlPoint();
private Timer timer;
private Service timerService;
private Device lastDeviceSeen;
public ClockDevice() throws InvalidDescriptionException
{
super(new File(DESCRIPTION_FILE_NAME));
UPnP.setEnable(UPnP.USE_ONLY_IPV4_ADDR);
org.cybergarage.util.Debug.on();
ctrlPoint.addNotifyListener(this);
ctrlPoint.start();
Action getTimeAction = getAction("GetTime");
getTimeAction.setActionListener(this);
Action setTimeAction = getAction("SetTime");
setTimeAction.setActionListener(this);
Action timeValidAction = getAction("TimeValid");
timeValidAction.setActionListener(this);
ServiceList serviceList = getServiceList();
// there should only be a timer service
timerService = serviceList.getService(0);
timerService.setQueryListener(this);
setLeaseTime(60);
}
public void setTimer(Timer t) {
timer = t;
System.out.println("Timer " + timer + " service " + timerService);
// *****************************************
// This is the only line that really changed
// *****************************************
// Change start
timer.setService(timerService);
// Change end
System.out.println("Our timer service is " + t);
}
////////////////////////////////////////////////
// ActionListener
////////////////////////////////////////////////
public boolean actionControlReceived(Action action)
{
String actionName = action.getName();
if (actionName.equals("GetTime") == true) {
System.out.println("GetTime action control");
Time now = timer.getTime();
Argument timeArg = action.getArgument("CurrentTime");
timeArg.setValue(now.toString());
return true;
}
if (actionName.equals("SetTime") == true) {
System.out.println("SetTime action control");
Argument timeArg = action.getArgument("NewTime");
String newTime = timeArg.getValue();
timer.setTime(new Time(newTime));
System.out.println("SetTime action to " + newTime);
return true;
}
if (actionName.equals("TimeValid") == true) {
System.out.println("TimeValid action control");
boolean timeValid = timer.isValidTime();
Argument timeArg = action.getArgument("Valid");
timeArg.setValue("" + timeValid);
return true;
}
return false;
}
////////////////////////////////////////////////
// QueryListener
////////////////////////////////////////////////
// Change start
public boolean queryControlReceived(StateVariable stateVar)
{
System.out.println("query control");
if (stateVar.getName().equals("Time")) {
stateVar.setValue(getTime().toString());
return true;
} else if (stateVar.getName().equals("TimeValid")) {
stateVar.setValue("" + isValidTime());
return true;
}
return false;
}
// Change end
////////////////////////////////////////////////
// HttpRequestListner
////////////////////////////////////////////////
public void httpRequestRecieved(HTTPRequest httpReq)
{
System.out.println("HTTP request: " + httpReq);
String uri = httpReq.getURI();
if (uri.startsWith(PRESENTATION_URI) == false) {
super.httpRequestRecieved(httpReq);
return;
}
}
public void setTime(Time time) {
System.out.println("setTime in clock device to " + time);
timer.setTime(time);
}
public Time getTime() {
return timer.getTime();
}
public boolean isValidTime() {
return timer.isValidTime();
}
public void deviceNotifyReceived(SSDPPacket ssdpPacket) {
System.out.println("New SSDPPacket, all " + ssdpPacket);
/* There doesn;t seem to be a simple way of getting the new
* device from the packet, even though CyberLink creates a
* new device from it - and adds it to a list. Looks like we
* have to get the whole list and search through it for the
* device created by this packet :-(
*/
DeviceList devList = ctrlPoint.getDeviceList();
Device dev = null;
System.out.println("Devices: " + devList.size());
for (int n = 0; n < devList.size(); n++) {
if (devList.getDevice(n).getSSDPPacket() == ssdpPacket) {
System.out.println("Found the new device matching SSDP packet");
dev = devList.getDevice(n);
break;
}
}
if (dev == null) {
// couldn't find it? That shouldn't happen...
return;
}
ServiceList timerServices = new ServiceList();
if (dev.getDeviceType().equals("urn:schemas-upnp-org:device:clock:1")) {
ServiceList services = dev.getServiceList();
for (int m = 0; m < services.size(); m++) {
Service svc = services.getService(m);
if (svc.getServiceType().equals("urn:schemas-upnp-org:service:timer:1")) {
timerServices.add(svc);
}
}
}
tryClockValidation(timerServices);
}
private ServiceList getTimerServices() {
ServiceList timerServices = new ServiceList();
DeviceList devList = ctrlPoint.getDeviceList();
System.out.println("Devices: " + devList.size());
for (int n = 0; n < devList.size(); n++) {
Device dev = devList.getDevice(n);
if (dev.getDeviceType().equals("urn:schemas-upnp-org:device:clock:1")) {
ServiceList services = dev.getServiceList();
for (int m = 0; m < services.size(); m++) {
Service svc = services.getService(m);
if (svc.getServiceType().equals("urn:schemas-upnp-org:service:timer:1")) {
timerServices.add(svc);
}
}
}
}
return timerServices;
}
private void tryClockValidation(ServiceList services) {
org.cybergarage.util.Debug.on();
for (int n = 0; n < services.size(); n++) {
Service svc = (Service) services.elementAt(n);
System.out.println("Checking service " + svc);
Action validAction = svc.getAction("TimeValid");
if (validAction.postControlAction()) {
System.out.println("Checking TimeValid succeeded");
Argument arg = validAction.getArgument("Valid");
String value = arg.getValue();
System.out.println("valid time? " + value);
if (isValidTime() && value.equals("false")) {
// other clock needs to be set
Action setTimeAction = svc.getAction("SetTime");
setTimeAction.setArgumentValue("NewTime",
getTime().toString());
setTimeAction.postControlAction();
} else if (! isValidTime() && value.equals("true")) {
Action getTimeAction = svc.getAction("GetTime");
if ( ! getTimeAction.postControlAction()) {
System.out.println("GetTime post action failed");
}
Argument arg2 = getTimeAction.getArgument("CurrentTime");
Object val = arg2.getValue();
System.out.println("Arg type " + val.getClass());
System.out.println("setTime in clock validation to " + arg2.getValue());
setTime(new Time(arg2.getValue()));
}
}
}
}
}
This will listen to events and print them
/**
* Listen for state changes in clocks
*/
package client;
import service.*;
import xmltypes.*;
import java.io.*;
import org.cybergarage.upnp.*;
import org.cybergarage.upnp.device.*;
import org.cybergarage.upnp.control.*;
import org.cybergarage.http.*;
import org.cybergarage.upnp.ssdp.*;
import org.cybergarage.upnp.event.*;
public class ValidityListener implements EventListener, NotifyListener
{
private ControlPoint ctrlPoint = new ControlPoint();
private StateVariable timeVar;
private Device lastDeviceSeen;
public static void main(String[] args) {
ValidityListener client = new ValidityListener();
Object keepAlive = new Object();
synchronized(keepAlive) {
try {
// Wait for a "notify" from another thread
// that will never be sent.
// So we stay alive for ever
keepAlive.wait();
} catch(java.lang.InterruptedException e) {
// do nothing
}
}
}
public ValidityListener()
{
UPnP.setEnable(UPnP.USE_ONLY_IPV4_ADDR);
// org.cybergarage.util.Debug.on();
ctrlPoint.addNotifyListener(this);
// Change start
ctrlPoint.addEventListener(this);
// Change end
ctrlPoint.start();
}
// Change start
public void eventNotifyReceived(String uuid, long seq,
String varName, String value) {
// a new event has arrived
System.out.println("UUID: \"" + uuid + "\"");
System.out.println("Name: \"" + varName + "\"");
System.out.println("Value: \"" + value + "\"");
}
// Change end
public void deviceNotifyReceived(SSDPPacket ssdpPacket) {
DeviceList devList = ctrlPoint.getDeviceList();
Device dev = null;
System.out.println("Devices: " + devList.size());
for (int n = 0; n < devList.size(); n++) {
if (devList.getDevice(n).getSSDPPacket() == ssdpPacket) {
System.out.println("Found the new device matching SSDP packet");
dev = devList.getDevice(n);
break;
}
}
if (dev == null) {
// couldn't find it? That shouldn't happen...
return;
}
if (dev.getDeviceType().equals("urn:schemas-upnp-org:device:clock:1")) {
ServiceList services = dev.getServiceList();
for (int m = 0; m < services.size(); m++) {
Service svc = services.getService(m);
if (svc.getServiceType().equals("urn:schemas-upnp-org:service:timer:1")) {
System.out.println("Subscribing to timer events");
// Change start
// subscribe to events
ctrlPoint.subscribe(svc);
// Change end
}
}
}
}
}
javac
with classpath set to include
src
directory
clink132a.jar
xercesImpl.jar
xml-apis.jar
java
with classpath set to
classes
directory
clink132a.jar
xercesImpl.jar
xml-apis.jar
java clock.TickerClock
java clock.ComputerClock
java client.ValidityListener
Device.httpRequestRecieved()
(note
the spelling mistake)
Device
) can override this
method by looking for HTTP requests relating to UI,and passing all
others to its super-class
JEditorPane
can display HTML pages
loaded through a URL
isEditable()
is set to false
, and then calls a HyperLinkListener
hyperLinkUpdate()
can load or reload a URL,
but the code is a bit messy due to a caching bug in JEditorPane
/******************************************************************
*
* CyberUPnP for Java
*
* Copyright (C) Satoshi Konno 2002
*
* File : ClockDevice.java
*
******************************************************************/
package device;
import service.*;
import xmltypes.*;
import java.io.*;
import org.cybergarage.upnp.*;
import org.cybergarage.upnp.device.*;
import org.cybergarage.upnp.control.*;
import org.cybergarage.http.*;
import org.cybergarage.upnp.ssdp.*;
public class ClockDevice extends Device implements ActionListener, QueryListener, NotifyListener
{
private final static String DESCRIPTION_FILE_NAME = "description/description.xml";
// Change start
private final static String PRESENTATION_URI = "/presentation";
private final static String REFRESH_UI = "/refresh";
// Change end
private ControlPoint ctrlPoint = new ControlPoint();
private Timer timer;
private Service timerService;
private Device lastDeviceSeen;
public ClockDevice() throws InvalidDescriptionException
{
super(new File(DESCRIPTION_FILE_NAME));
UPnP.setEnable(UPnP.USE_ONLY_IPV4_ADDR);
org.cybergarage.util.Debug.on();
ctrlPoint.addNotifyListener(this);
ctrlPoint.start();
Action getTimeAction = getAction("GetTime");
getTimeAction.setActionListener(this);
Action setTimeAction = getAction("SetTime");
setTimeAction.setActionListener(this);
Action timeValidAction = getAction("TimeValid");
timeValidAction.setActionListener(this);
ServiceList serviceList = getServiceList();
// there should only be a timer service
timerService = serviceList.getService(0);
timerService.setQueryListener(this);
setLeaseTime(60);
}
public void setTimer(Timer t) {
timer = t;
System.out.println("Our timer service is " + t);
}
////////////////////////////////////////////////
// ActionListener
////////////////////////////////////////////////
public boolean actionControlReceived(Action action)
{
String actionName = action.getName();
if (actionName.equals("GetTime") == true) {
System.out.println("GetTime action control");
Time now = timer.getTime();
Argument timeArg = action.getArgument("CurrentTime");
timeArg.setValue(now.toString());
return true;
}
if (actionName.equals("SetTime") == true) {
System.out.println("SetTime action control");
Argument timeArg = action.getArgument("NewTime");
String newTime = timeArg.getValue();
timer.setTime(new Time(newTime));
System.out.println("SetTime action to " + newTime);
return true;
}
if (actionName.equals("TimeValid") == true) {
System.out.println("TimeValid action control");
boolean timeValid = timer.isValidTime();
Argument timeArg = action.getArgument("Valid");
timeArg.setValue("" + timeValid);
return true;
}
return false;
}
////////////////////////////////////////////////
// QueryListener
////////////////////////////////////////////////
public boolean queryControlReceived(StateVariable stateVar)
{
System.out.println("query control");
if (stateVar.getName().equals("Time")) {
stateVar.setValue(getTime().toString());
return true;
} else if (stateVar.getName().equals("TimeValid")) {
stateVar.setValue("" + isValidTime());
return true;
}
return false;
}
//
// HttpRequestListner
//
// This is responsible for generating the HTML UI
//
public void httpRequestRecieved(HTTPRequest httpReq)
{
System.out.println("HTTP request: " + httpReq);
String uri = httpReq.getURI();
// Change start
if (uri.startsWith(PRESENTATION_URI)) {
sendPage(httpReq);
} else if (uri.startsWith(REFRESH_UI)) {
sendPage(httpReq);
} else {
super.httpRequestRecieved(httpReq);
return;
}
// Change end
}
// Change start
private void sendPage(HTTPRequest httpReq) {
// deliver an HTML page
String time = getTime().toString();
String refreshUrl = "http://" +
httpReq.getLocalAddress() +
":" +
httpReq.getLocalPort() +
REFRESH_UI;
System.out.println("referesh url " + refreshUrl);
// the page attempts to turn caching off at the client side
// but a bug in JEditorPane ignores the Cache-Control value
String page = "<html>\n" +
"<head>\n" +
"</head>\n" +
"<body>\n" +
"<form method=\"post\" action=\"" +
refreshUrl + "\">\n" +
"New time" +
"<input type=\"text\" name=\"time\">\n" +
"<input type=\"submit\">\n" +
"<p>\n" +
time +
"\n<br>\n" +
"<a href=\"" +
refreshUrl +
"\"> Refresh </a>\n" +
"</p>\n" +
"</body>\n" +
"</html>\n";
System.out.println("Sending page " + page);
HTTPResponse response = new HTTPResponse();
response.setStatusCode(HTTPStatus.OK);
response.setContent(page);
response.setCacheControl(0); // no caching - ignored by JEditorPane
httpReq.post(response);
}
// Change end
public void setTime(Time time) {
System.out.println("setTime in clock device to " + time);
timer.setTime(time);
}
public Time getTime() {
return timer.getTime();
}
public boolean isValidTime() {
return timer.isValidTime();
}
public void deviceNotifyReceived(SSDPPacket ssdpPacket) {
System.out.println("New SSDPPacket, all " + ssdpPacket);
/* There doesn;t seem to be a simple way of getting the new
* device from the packet, even though CyberLink creates a
* new device from it - and adds it to a list. Looks like we
* have to get the whole list and search through it for the
* device created by this packet :-(
*/
DeviceList devList = ctrlPoint.getDeviceList();
Device dev = null;
System.out.println("Devices: " + devList.size());
for (int n = 0; n < devList.size(); n++) {
if (devList.getDevice(n).getSSDPPacket() == ssdpPacket) {
dev = devList.getDevice(n);
break;
}
}
if (dev == null) {
// couldn't find it? That shouldn't happen...
return;
}
/* this doesn't work :-( device changes each time
if (dev == lastDeviceSeen) {
// UPnP sends repeat messages to try to make sure things
// get through. But we don't want to repeat work
System.out.println("Seen this device before");
lastDeviceSeen = dev;
return;
}
*/
ServiceList timerServices = new ServiceList();
if (dev.getDeviceType().equals("urn:schemas-upnp-org:device:clock:1")) {
ServiceList services = dev.getServiceList();
for (int m = 0; m < services.size(); m++) {
Service svc = services.getService(m);
if (svc.getServiceType().equals("urn:schemas-upnp-org:service:timer:1")) {
timerServices.add(svc);
}
}
}
tryClockValidation(timerServices);
}
private ServiceList getTimerServices() {
ServiceList timerServices = new ServiceList();
DeviceList devList = ctrlPoint.getDeviceList();
System.out.println("Devices: " + devList.size());
for (int n = 0; n < devList.size(); n++) {
Device dev = devList.getDevice(n);
if (dev.getDeviceType().equals("urn:schemas-upnp-org:device:clock:1")) {
ServiceList services = dev.getServiceList();
for (int m = 0; m < services.size(); m++) {
Service svc = services.getService(m);
if (svc.getServiceType().equals("urn:schemas-upnp-org:service:timer:1")) {
timerServices.add(svc);
}
}
}
}
return timerServices;
}
private void tryClockValidation(ServiceList services) {
org.cybergarage.util.Debug.on();
for (int n = 0; n < services.size(); n++) {
Service svc = (Service) services.elementAt(n);
System.out.println("Checking service " + svc);
Action validAction = svc.getAction("TimeValid");
if (validAction.postControlAction()) {
System.out.println("Checking TimeValid succeeded");
Argument arg = validAction.getArgument("Valid");
String value = arg.getValue();
System.out.println("valid time? " + value);
if (isValidTime() && value.equals("false")) {
// other clock needs to be set
Action setTimeAction = svc.getAction("SetTime");
setTimeAction.setArgumentValue("NewTime",
getTime().toString());
setTimeAction.postControlAction();
} else if (! isValidTime() && value.equals("true")) {
Action getTimeAction = svc.getAction("GetTime");
if ( ! getTimeAction.postControlAction()) {
System.out.println("GetTime post action failed");
}
Argument arg2 = getTimeAction.getArgument("CurrentTime");
Object val = arg2.getValue();
System.out.println("Arg type " + val.getClass());
System.out.println("setTime in clock validation to " + arg2.getValue());
setTime(new Time(arg2.getValue()));
}
}
}
}
}
/**
* Listen for state changes in clocks
*/
package client;
import service.*;
import xmltypes.*;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.Document;
import java.awt.*;
import org.cybergarage.upnp.*;
import org.cybergarage.upnp.device.*;
import org.cybergarage.upnp.control.*;
import org.cybergarage.http.*;
import org.cybergarage.upnp.ssdp.*;
import org.cybergarage.upnp.event.*;
import java.net.URL;
import java.net.HttpURLConnection;
public class UI extends JFrame implements EventListener, NotifyListener
{
private ControlPoint ctrlPoint = new ControlPoint();
private DeviceList knownDevices = new DeviceList();
private StateVariable timeVar;
private FlowLayout layout = new FlowLayout();
private Container contentPane = getContentPane();
public static void main(String[] args) {
UI client = new UI();
}
public UI()
{
UPnP.setEnable(UPnP.USE_ONLY_IPV4_ADDR);
org.cybergarage.util.Debug.on();
ctrlPoint.addNotifyListener(this);
ctrlPoint.addEventListener(this);
ctrlPoint.start();
contentPane.setLayout(layout);
setSize(200, 200);
setVisible(true);
}
public void eventNotifyReceived(String uuid, long seq,
String varName, String value) {
System.out.println("UUID: \"" + uuid + "\"");
System.out.println("Name: \"" + varName + "\"");
System.out.println("Value: \"" + value + "\"");
}
public void deviceNotifyReceived(SSDPPacket ssdpPacket) {
if ( ! ssdpPacket.getNTS().equals("ssdp:alive")) {
return;
}
/* This code cleaned up to avoid repeating
* service finds, but no changes of relevance
* to UI
*/
/* We can get multiple packets for one device from multiple
* UDP packets sent in case one is lost. Also, we get
* rebroadcasts every few minutes. This is tedious
*/
Device dev = getDeviceFromPacket(ssdpPacket);
if (dev == null) {
// This can happen if the packet describes a service,
// a device, but not a ROOT device
return;
}
// process the packet if it is for a new device
if (isNewDevice(dev)) {
if (dev.getDeviceType().equals("urn:schemas-upnp-org:device:clock:1")) {
// Change start
// The presentation URL is relative e.g. /presentation
String presentationURL = dev.getPresentationURL();
System.out.println("Presentation url is \"" +
presentationURL + "\"");
// the URLBase is the http://hostname
String urlBase = dev.getURLBase();
System.out.println("Adding new device " + dev);
System.out.println("From packet " + ssdpPacket);
addClock(/* urlBase + */ presentationURL);
// Change end
}
} else {
System.out.println("Seen this device before " + dev);
}
}
/* New code, just cleans up old stuff
* No changes for UI
*/
private Device getDeviceFromPacket(SSDPPacket packet) {
DeviceList devList = ctrlPoint.getDeviceList();
for (int n = 0; n < devList.size(); n++) {
Device dev = devList.getDevice(n);
if (dev.getSSDPPacket() == packet) {
return dev;
}
}
// this will happen for services/embedded devices etc
System.out.println("No device found for packet " + packet);
return null;
}
/* New code, just cleans up old stuff
* No changes for UI
*/
private boolean isNewDevice(Device dev) {
System.out.println("UDN " + dev.getUDN());
for (int n = 0; n < knownDevices.size(); n++) {
if (dev.getUDN().equals(knownDevices.getDevice(n).getUDN())) {
return false;
}
}
knownDevices.add(dev);
return true;
}
// Change start has to get UI from device and display it
// Display is done here in a JEditPane
private void addClock(String url) {
// get HTML page from URL, put it in a component and add it to this
System.out.println("URL is " + url);
/* OR: use Runtime.exec() to start IE,Netscape, etc
* and pass it the URL
*/
/* JEditorPane DOES handle forms properly after all!
*/
final JEditorPane pane = new JEditorPane();
try {
pane.setPage(url);
pane.setEditable(false); // or we can't follow hyperlinks
System.out.println("New page contents " + pane.getText());
contentPane.add(pane);
} catch(IOException e) {
e.printStackTrace();
}
// listen for hyperlink events
pane.addHyperlinkListener(new HyperlinkListener() {
// user over/clicking Refresh hyperlink
public void hyperlinkUpdate(HyperlinkEvent e) {
java.net.URL url = e.getURL();
// Turn caching off!
// Due to a bug in JEditorPane, this doesn't work
HttpURLConnection uc = null;
try {
uc = (HttpURLConnection)url.openConnection();
} catch(IOException ioe) {
ioe.printStackTrace();
return;
}
uc.setUseCaches(false);
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
try {
// url was clicked on - we should reload the page
// WORKAROUND for JEditorPane bug always caching
// url even if it's contents have changed, or
// Expires has happened or Cache-Control set to
// "no-cache", etc
// Clear the internal URL object in this control
// TO PREVENT URL CACHING...
Document doc = pane.getDocument();
doc.putProperty(Document.StreamDescriptionProperty,null);
// Sun know of this bug, and just promise to fix the doco :-(
// now reload it
pane.setPage(url);
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
}
}
);
}
// Change end
}
javac
with classpath set to include
src
directory
clink132a.jar
xercesImpl.jar
xml-apis.jar
java
with classpath set to
classes
directory
clink132a.jar
xercesImpl.jar
xml-apis.jar
java clock.TickerClock
java clock.ComputerClock
java client.UI