Link to home
Start Free TrialLog in
Avatar of numberkruncher
numberkruncherFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Copy and Paste in Applet

I am trying to create a simple text editor in Java for my website. When attempt to paste content from the clipboard (using the source shown below) I am getting the following exception:

java.security.AccessControlException: access denied
(java.awt.AWTPermission accessClipboard)

From a Google search I have been led to believe that it is possible to sign the applet so that it gains the required permission. Or perhaps there is another way I can do this?

If it's of any difference, I use JCreator for creating Java applets.
Clipboard clipboard = getToolkit().getSystemClipboard();
Transferable clipboardContent = clipboard.getContents(this);
if (clipboardContent != null && clipboardContent.isDataFlavorSupported (DataFlavor.stringFlavor))
{
	try
	{
		result = (String)clipboardContent.getTransferData(DataFlavor.stringFlavor);
	}
	catch(Exception e)
	{
	}
}

Open in new window

Avatar of n_sachin1
n_sachin1
Flag of India image

The java applets run in a sandbox provided by the jre and cannot by default access any properties from the client system. The clipboard is also a client system resource and you would need to sign the applet to access it.
Signing your applet would be the only clean solution. You sure can do a self-signing.

The only other way I can think of is via javascript-Applet communication. Have the text area as a html input (instead of a java control). On ctrl+v, trigger a call to your applet. This would however be pretty workaroundish.
Avatar of numberkruncher

ASKER

Could you please explain how I go about signing the applet?

When I build the applet in JCreator it gives me a selection of class files. The class file is then associated with the HTML page. What is the difference between a JAR and a class file? Is a JAR just an archive of class files?
yes. A jar is just a archive of class files with a few specific additions. It contains a META-INF folder with a manifest.mf file (contains information about the jar and special clauses like a main class, classpaths etc. - not specifically relevant for your applet).

When you are using a jar, In the html applet tag, you would need to specify an 'archive' attribute that will be the location of the jar file and you can get rid of codebase (that you might be specifying to show the base location of your class).

I'd suggest you read this:
http://java.sun.com/docs/books/tutorial/deployment/jar/signing.html
The link will give you a general overview of jars, and a brief on signing.

A signed applet basically means - packaging the class files in a jar and then, signing the jar with your key/digital certificate, so that when users of your applet download it, they know that its from you, and they can trust it.

Read the first post at this link about the entire signing process in brief:
http://forums.sun.com/thread.jspa?threadID=174214
Thanks for the links!

I've read through and tried to follow the instructions to generate and sign a jar. It says that the certificate should be valid for 6 months. In web browsers the following causes a "htmlEditor.class" not found error, but within JCreator it appears to open the .jar file with the same HTML (#1).

I also tried using the HtmlConverter utility, but still no luck.

I have also tried using (#2), but this also causes the clipboard security exception.
#1:
 
<applet
	 id		= "myApplet"
	 archive	= "htmlEditor.jar"
	 width	= "500"
	 height	= "300"
	 code	= "htmlEditor"
	>
</applet>
 
 
#2:
	public String doSomething() {
		String result = "";
			
	    result = (String)java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() {
			public Object run() {
				String result = "";
				
				Clipboard clipboard = getToolkit().getSystemClipboard();
				Transferable clipboardContent = clipboard.getContents(this);
				if (clipboardContent != null && clipboardContent.isDataFlavorSupported(DataFlavor.stringFlavor))
				{
					try
					{
						result = (String)clipboardContent.getTransferData(DataFlavor.stringFlavor);
					}
					catch(Exception e)
					{
					}
				}
				return result;
			}
	    });
		
		return result;
	}

Open in new window

Try this on your html applet tag:
<applet
       name            = "myApplet"
       archive      = "htmlEditor.jar"
       width      = "500"
       height      = "300"
       code      = "<fully qualified class name like com.test.htmlEditor.class if thats the name>"
      >
</applet>

You need to ensure that the htmlEditor.jar is in the same location (for eg:- for the above archive def, place the jar and the html in the same folder.

Do you use ANT? If yes, attach your html and the applet code and I'll give you a sample ant build script to jar and sign it.

I have not used ANT before, but JCreator does offer the ability to create ANT files, so that would be brilliant. I have added my HTML and Applet code below.

I have simplified the applet to the bare minimum which causes the clipboard security access error.
HTML:
=====
<html>
	<head>
		<title>Test Page</title>
		<script type="text/javascript">
			function test() {
				var myApplet = document.getElementById('myApplet');
				if (myApplet)
					alert(myApplet.doSomething());
				else
					alert('Invalid applet!');	
			}
		</script>
	</head>
	<body>
		<center style="border: solid 1px black">
			<applet
				id		= "myApplet"
				class	= "htmlEditor.class"
				width	= "500"
				height	= "300"
				code	= "htmlEditor"
				>
			</applet>
		</center>
		<br />
		<input type="button" value="Do Something!" onclick="test()" />
	</body>
</html>
 
 
Java Applet:
============
import java.applet.*;
import java.io.*;
import javax.swing.event.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.text.html.*;
import javax.swing.text.*;
import java.net.*;
import java.awt.datatransfer.*;
 
public class htmlEditor extends JApplet {
	public htmlEditor() {
	}
 
	public void init() {
	}
 
	public String doSomething() {
		String result = "";
			
	    result = (String)java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() {
			public Object run() {
				String result = "";
				
				Clipboard clipboard = getToolkit().getSystemClipboard();
				Transferable clipboardContent = clipboard.getContents(this);
				if (clipboardContent != null && clipboardContent.isDataFlavorSupported(DataFlavor.stringFlavor))
				{
					try
					{
						result = (String)clipboardContent.getTransferData(DataFlavor.stringFlavor);
					}
					catch(Exception e)
					{
					}
				}
				return result;
			}
	    });
		
		return result;
	}
}

Open in new window

Now I see your issue, and why the previous comment didn't work for you.
You are trying to invoke an applet method from javascript (more like - 'the workaroundish way' I talked about.
Well, modern jres do not treat java script as a secure app. Thus, if a applet method called by a javascript tries to do privileged operations, it denies it (even if the applet is signed).

You would need to have a Thread that listens for your java script call..and then, delegates the request to another thread (created outside the context of this method called by javascript - may be in init() ),
ASKER CERTIFIED SOLUTION
Avatar of n_sachin1
n_sachin1
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Below is the modified applet code (full).
As you can see, you can simply do a ctrl+v to paste string contents in your text area, or have the 'Do Something' button inside your applet, to eliminate the need for a java script to applet call.

Let me know if it was helpful.
package numberkruncher;
 
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
 
import javax.swing.JApplet;
import javax.swing.JComponent;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
 
public class htmlEditor extends JApplet {
 
	private JTextArea jTxtArea = null;
 
	public htmlEditor() {
	}
 
	public void init() {
		if (jTxtArea == null) {
			jTxtArea = new JTextArea();
 
			KeyStroke paste = KeyStroke.getKeyStroke(KeyEvent.VK_V,
					ActionEvent.CTRL_MASK, false);
			ActionListener al = new ActionListener() {
 
				public void actionPerformed(ActionEvent arg0) {
					jTxtArea.setText(doSomething());
				}
 
			};
 
			jTxtArea.registerKeyboardAction(al, "Paste", paste,
					JComponent.WHEN_FOCUSED);
 
			this.add(jTxtArea);
		}
	}
 
	public String doSomething() {
		String result = "";
 
		result = (String) java.security.AccessController
				.doPrivileged(new java.security.PrivilegedAction() {
					public Object run() {
						String result = "";
 
						Clipboard clipboard = getToolkit().getSystemClipboard();
						Transferable clipboardContent = clipboard
								.getContents(this);
						if (clipboardContent != null
								&& clipboardContent
										.isDataFlavorSupported(DataFlavor.stringFlavor)) {
							try {
								result = (String) clipboardContent
										.getTransferData(DataFlavor.stringFlavor);
							} catch (Exception e) {
								StackTraceElement[] stacks = e.getStackTrace();
								StringBuffer sBuff = new StringBuffer("");
								for (int i = 0; i < stacks.length; i++) {
									sBuff.append(stacks[i].toString()).append(
											"\n");
								}
 
								result = sBuff.toString();
							}
						}
						return result;
					}
				});
 
		return result;
	}
}

Open in new window

That works perfectly!
Thanks again for all of your time and effort, it is much appreciated!