Does anyone see an obvious problem with this applet. I’ve added this applet to the mail template for some users and it’s inconsistently causing their Notes client to hang when a) closing Notes or b) closing their mailbox. It seems to stuck in a thread when the applet is being destroyed. Any guesses?..
/*
-
MailGaugeApplet.java
-
Created on July 25, 2005, 3:23 PM
-
This applet is used in a customized version of the Notes mail template to
-
display an indicator of spaced used for the users mailbox. This resides within
-
the users database for use within the Notes client. This applet was originally designed
-
in the “Dynamic mail file size & quota indicator applet” article by Dhana Sekar.
-
(http://searchdomino.techtarget.com/tip/1,289483,sid4_gci844663,00.html)
*/
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import lotus.domino.*;
import java.text.DateFormat;
import java.util.Date;
/**
-
@author szcklv
*/
public class MailGaugeApplet extends AppletBase implements Runnable {
private Session session=null;
private DbDirectory dbDir=null;
private Database mailDb=null;
private NotesAppletContext ap=null;
private double quota=0.0,prevQuota=0.0;
private double fileSize=0.0,prevFileSize=0.0;
private volatile Thread listener=null;
private volatile boolean keepRunning = false;
private boolean debug = true;
private Thread compact=null;
private int usedVal=0;
private Font font;
private int width = 120;
private int height = 30;
private int offsetwidth = 5;
private int offsetheight = 5;
private int statusCaution = 70;
private int statusAlert = 85;
private int refreshInterval = 60000;
private int percentUsed = 75;
private String allowCompact = "yes";
private String allowRefresh = "yes";
private Button compactButton;
private Color headerBg = new Color(176,200,224);
private Color headerFg = Color.black;
private Color appletBg = new Color(217,217,217);
private Color appletShadow = new Color(92,92,92);
private Color colStatusAlert = new Color(255,0,0);
private Color colStatusCaution = new Color(255,255,0);
private Color colStatusNominal = new Color(51,255,0);
public void notesAppletInit() {
try {
if (isNotesLocal()) {
NotesThread.sinitThread();
}
//Get parameters if passed
getUsageParameters();
if (debug) System.out.println("MailGaugeApplet:notesAppletInit()");
this.setLayout(null);
//Find users session and db in this context
session = this.getSession();
dbDir = session.getDbDirectory(null);
ap = this.getContext(session);
mailDb = ap.getDatabase();
setBackground(Color.white);
font = new Font("Arial",Font.PLAIN,9);
if(mailDb!=null)
{
//Get the quota value to determine if we should create a thread to refresh
quota = mailDb.getSizeQuota();
quota = quota/1024;
if(quota<=0) {
repaint();
}
else {
if (allowRefresh.equals("yes")) {
listener = new Thread(this);
listener.start();
keepRunning = true;
}
}
}
}
catch(NotesException e) {
System.out.println("Notes Applet Start Exception " + e.getMessage());
System.out.println("Session=" + session.toString());
e.printStackTrace();
}
catch(Exception e) {
System.out.println("Notes Applet Start Exception " + e.getMessage());
e.printStackTrace();
}
finally
{
if (isNotesLocal()) {
NotesThread.stermThread();
}
}
}
public void notesAppletStart() {
if (debug) System.out.println("MailGaugeApplet:notesAppletStart()");
keepRunning = true;
}
public void notesAppletStop() {
if (debug) System.out.println("MailGaugeApplet:notesAppletStop()");
keepRunning = false;
}
public void run()
{
try
{
if (isNotesLocal()) {
NotesThread.sinitThread();
}
Thread thisThread = Thread.currentThread();
//Continue to run this method until the thread has been disposed.
if (debug) System.out.println("MailGaugeApplet:run()");
//while(listener == thisThread) {
while(keepRunning) {
if (debug) System.out.println("MailGaugeApplet:Last Updated " + DateFormat.getDateTimeInstance(DateFormat.SHORT,DateFormat.LONG).format(new java.util.Date()));
if(mailDb!=null) {
quota = mailDb.getSizeQuota();
fileSize = mailDb.getSize();
}
double percentUsed = mailDb.getPercentUsed();
//Is quota or size valid
if(quota!=0.0 && fileSize!=0.0) {
quota = quota/1024;
fileSize = fileSize/(1024*1024);
usedVal = (int) Math.floor((fileSize/quota)*100);
//If size has exceeded quota then set used value to 100%
if(usedVal > 100) {
usedVal = 100;
}
//Check if quota or size has changed, if so then repaint
if(quota!=prevQuota || fileSize!=prevFileSize) {
prevQuota = quota;
prevFileSize = fileSize;
repaint();
}
//Pause thread until specified interval
listener.sleep(this.refreshInterval);
}
}
}
catch(Exception e) {
System.out.println("Run Exception " + e.getMessage());
e.printStackTrace();
}
finally {
if (isNotesLocal()) {
NotesThread.stermThread();
}
}
}
public void paint(Graphics g)
{
try
{
if (isNotesLocal()) {
NotesThread.sinitThread();
}
FontMetrics fm = getFontMetrics(font);
int textWidth;
int textHeight = fm.getHeight();
//g.setColor(new Color(81,114,143));
//g.draw3DRect(0, 0, width, height, true);
g.setColor(appletShadow);
g.fillRect(offsetwidth, offsetheight, width, height);
g.setColor(appletBg);
g.fillRect(0, 0, width-offsetwidth, height-offsetheight);
//If no quota is defined then indicate with message
if(quota<=0) {
g.setFont(font);
g.setColor(Color.black);
textWidth = fm.stringWidth("Mail quota is not set");
g.drawString("Mail quota is not set",
(int)((width-offsetwidth)*.5)-(int)(textWidth*.5),
(int)((height-offsetheight)*.5)+(int)(textHeight*.5));
}
else {
//Set color of indicator based on relative size.
if (usedVal >= this.statusAlert) {
g.setColor(colStatusAlert);
}
else if (usedVal >= this.statusCaution & usedVal < this.statusAlert) {
g.setColor(colStatusCaution);
}
else {
g.setColor(colStatusNominal);
}
//Draw the indicator
g.fill3DRect(0,(int)((height-offsetheight)*.5),
(int)((usedVal*.01)*(width-offsetwidth)),(int)(((height-offsetheight)*.5)),true);
//Create the header bar
g.setColor(headerBg);
g.fill3DRect(0,0,width-offsetwidth,(int)((height-offsetheight)*.5),true);
g.setColor(headerFg);
g.setFont(font);
//Write the header text centered based on size of applet.
textWidth = fm.stringWidth("Size: " + (int)fileSize + ", Quota: " + (int)quota);
g.drawString("Size:" + (int)fileSize + ", Quota:" + (int)quota,
(int)((width-offsetwidth)*.5)-(int)(textWidth*.5),
(int)((height-offsetheight)*.25)+(int)(textHeight*.5));
//Write the percentage used inside the indicator bar
g.setColor(headerFg);
textWidth = fm.stringWidth(usedVal +" %");
g.drawString(usedVal +" %",
(int)((width-offsetwidth)*.5)-(int)(textWidth*.5),
(int)((height-offsetheight)*.5) + (int)((height-offsetheight)*.25) + (int)(textHeight*.5));
}
}
catch(Exception e) {
System.out.println("Paint Exception " + e.getMessage());
e.printStackTrace();
}
finally {
if (isNotesLocal()) {
NotesThread.stermThread();
}
}
}
public void notesAppletDestroy()
{
try {
//dispose of objects when the applet is closed.
if (debug) System.out.println("MailGaugeApplet:notesAppletDestroy()");
keepRunning = false;
listener = null;
session = null;
dbDir = null;
mailDb = null;
}
catch(Exception e) {
System.out.println("Destroy Exception " + e.getMessage());
e.printStackTrace();
}
}
private void getUsageParameters() {
int width;
int height;
int statusCaution;
int statusAlert;
int refreshInterval;
int percentUsed;
boolean debug;
String allowCompact;
String allowRefresh;
try {
//Any parameters that are passed in will override default values.
if (getParameter("Width") != null && getParameter("Width") != "") {
width = Integer.parseInt(getParameter("Width"));
this.width = width;
}
if (getParameter("Height") != null && getParameter("Height") != "") {
height = Integer.parseInt(getParameter("Height"));
this.height = height;
}
if (getParameter("StatusCaution") != null && getParameter("StatusCaution") != "") {
statusCaution = Integer.parseInt(getParameter("StatusCaution"));
this.statusCaution = statusCaution;
}
if (getParameter("StatusAlert") != null && getParameter("StatusAlert") != "") {
statusAlert = Integer.parseInt(getParameter("StatusAlert"));
this.statusAlert = statusAlert;
}
if (getParameter("RefreshInterval") != null && getParameter("RefreshInterval") != "") {
refreshInterval = Integer.parseInt(getParameter("RefreshInterval"));
this.refreshInterval = refreshInterval;
}
if (getParameter("Debug") != null && getParameter("Debug") != "") {
debug = (new Boolean(getParameter("Debug"))).booleanValue();
this.debug = debug;
}
if (getParameter("AllowRefresh") != null && getParameter("AllowRefresh") != "") {
allowRefresh = getParameter("AllowRefresh");
this.allowRefresh = allowRefresh;
}
}
catch(Exception e) {
System.out.println("Error retrieving parameters " + e.getMessage());
e.printStackTrace();
}
}
}