Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1509
  • Last Modified:

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

0
numberkruncher
Asked:
numberkruncher
  • 6
  • 5
1 Solution
 
n_sachin1Commented:
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.
0
 
numberkruncherAuthor Commented:
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?
0
 
n_sachin1Commented:
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
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
numberkruncherAuthor Commented:
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

0
 
n_sachin1Commented:
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.

0
 
numberkruncherAuthor Commented:
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

0
 
n_sachin1Commented:
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() ),
0
 
n_sachin1Commented:
Ok, I have corrected a few things:
1. Your applet needs to reside in a package.
2. Please see my previous comment about accessing applet methods from javascript and its security implications.
//The applet changes for signing to work.
package numberkruncher;
....
public class htmlEditor extends JApplet {
.....
}
 
//The html file
<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"
				code	= "numberkruncher.htmlEditor.class"
				width	= "500"
				height	= "300"
				archive	= "numberkruncher.jar"
				>
			</applet>
		</center>
		<br />
		<input type="button" value="Do Something!" onclick="test()" />
	</body>
</html>
 
//The ant script that does the jar and signs the applet
//You need to follow the following folder structure or adapt the script
//<root>--src (source files and html)
//      --bin (compiled classes will go here)    
//      --dist (will contain the signed jar and the html)  
//      --KeyStore (will contain your Key Store)
<?xml version="1.0" encoding="UTF-8"?>
 
<project basedir="." default="all" name="numberkruncher">
	
	<property file="${basedir}/build.properties"/>
	<property name="bin" value="${basedir}/bin" />
	<property name="src" value="${basedir}/src" />
	<property name="dist" value="${basedir}/dist" />
	<property name="app.jar" value="numberkruncher.jar" />
	
	<path id="project.class.path">
		<pathelement location="${bin}" />
	</path>
	
	<target name="clean">
		<delete file="${dist}/${app.jar}" />
		<delete failonerror="false" includeemptydirs="true">
			<fileset dir="${bin}" />
		</delete>
	</target>
	
	<target name="init">
		<mkdir dir="${bin}" />
		<mkdir dir="${dist}" />
	</target>
 
	<target  name="compile" depends="init">
		<javac classpathref="project.class.path" destdir="${bin}">
			<src path="${src}" />
		</javac>
	</target>
	
	<target name="dist"  depends=" compile">
		<jar compress="true" destfile="${dist}/${app.jar}">
			<fileset dir="${bin}">
				<include name="**/*.class" />
			</fileset>
			<manifest>
				<attribute name="Main-Class" value="htmlEditor" />
			</manifest>
		</jar>
		<copy todir="${dist}">
			<fileset dir="${src}">
				<include name="**/*.html" />
			</fileset>
		</copy>
	</target>
	
	<target name="keytoolexec" unless="keystore.exists">
		<mkdir dir="${basedir}/Keystore"/>
		<exec dir="${basedir}" executable="keytool" failonerror="true">
			<arg value="-genkey "/>
			<arg value="-alias" />
			<arg value="numberkruncher"/>
			<arg value="-keystore" />
			<arg value="${basedir}/Keystore/Kruncher.jks"/>	
			<arg value="-keypass" />
			<arg value="n_sachin1"/>
			<arg value="-dname" />
			<arg value="CN=Test CA, OU=NK, O=NK, L=Bangalore, S=KA, C=IN"/>	
			<arg value="-storepass" />
			<arg value="n_sachin1"/>
			<arg value="-validity" />
			<arg value="365"/>
			
		</exec> 
	</target>
	
	<target name="testKeyStore">
		<available property="keystore.exists" file="${basedir}/Keystore/Kruncher.jks" />
	</target>
 
	  <target name="signjar" depends="dist, testKeyStore, keytoolexec">
	  	
	    <echo message="------ Signing JAR files"/>
	     <signjar jar="${dist}/${app.jar}" storepass="n_sachin1" alias="numberkruncher"
	           keystore="${basedir}/Keystore/Kruncher.jks" keypass="n_sachin1" />
	  </target>
 
	
	<target name="all" depends="clean, dist, signjar"/>
</project>

Open in new window

0
 
n_sachin1Commented:
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

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

Featured Post

New feature and membership benefit!

New feature! Upgrade and increase expert visibility of your issues with Priority Questions.

  • 6
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now