I've a signed applet (which verifies correctly with jarsigner) that for some reason will not allow copy and paste from the system clipboard into a JTextField despite the documentation telling me that it is supposed to work for signed applets.
Furthermore, I've other applets which are signed with the same keyfile that do let me copy and paste text. I have searched high and low on the internet and can't seem to find any clues. What is making me pull my hair out is that there seems to be no way to debug this (no output in the console - no thrown exceptions).
Does any one have any ideas on how I can debug this to find out why Java doesn't like this particular applet?
Many thanks for any suggestions!
Well, it turns out with the release of the Java Plug-in 1.6.0_24 in February 2011, copy and paste from the system clipboard was deemed a security hole and disabled. You can copy and paste BETWEEN applets. But if you try to use something from your main clipboard, it can't be copied in.
So there are a couple of options for a workaround. You can roll back to an earlier version of the plug-in. That will work, but chances are all future releases will still keep copy and paste disabled, so you'd never be able to upgrade.
The other alternative is to provide a custom java security policy file which enables access to the system clipboard again.
First locate your local Java Security Policy file. The file is named java.policy and should be in the lib\security folder of your Java installation. On Windows 7, it can be found at C:\Program Files (x86)\Java\jre6\lib\security.
Copy this file to your home folder (ex. C:\Users\Kyle).
Rename the file to .java.policy (note the period at the beginning).
Edit the file in a text editor. Locate this line of text:
// "standard" properies that can be read by anyone
Add the following line just below it like so:
// "standard" properies that can be read by anyone
permission java.awt.AWTPermission "accessClipboard";
Save the file.
Close any open browsers and ensure that Java is not running before testing.
source: http://blogs.oracle.com/kyle/entry/copy_and_paste_in_java
Besides Dennis' overview, see Copy in sand-boxed app. in 1.6.0_24+ at the OTN.
While Ctrl-c copy no longer works by default, it is possible to add the functionality back in for any applet run in a 'Next Generation' Java Plug-In. Since Java Web Start existed, JWS provided sand-boxed copy via. the JNLP API's javax.jnlp.ClipboardService, & since Sun 1.6.0_10, & the next gen. plug-in, embedded applets can be deployed using JWS & can access the JNLP API.
See also
http://pscode.org/prop/js.html. Direct link to the test applet used in that thread. It offers copy ability in a sand-boxed applet. If it works on the problem machine (browser, set-up ..whatever) you should be able to rework it to offer (unprompted) paste in a signed applet.
Frame based Demo. of the ClipboardService, with source and build file.
I'm not sure why, but the JTextField object I'm using doesn't seem to be properly connected to the key events (maybe because I added a FocusListener?) - but adding the following code:
searchTextField.addKeyListener(new java.awt.event.KeyListener() {
public void keyPressed(KeyEvent e) {
//System.out.println("KEY:"+e);
if (e.getKeyCode() == 86 && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0)) {
java.awt.datatransfer.Clipboard clipboard = java.awt.Toolkit.getDefaultToolkit().getSystemClipboard();
java.awt.datatransfer.Transferable clipData = clipboard.getContents(clipboard);
String s;
try {
s = (String)(clipData.getTransferData(java.awt.datatransfer.DataFlavor.stringFlavor));
} catch (Exception ex) {
s = ex.toString();
}
searchTextField.setText(s);
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
});
...allows me to paste into the field.
Take a backup of java.policy which is at (Ex: C:\Program Files (x86)\Java\jre7\lib\security)
Look for line in java.policy file
// "standard" properies that can be read by anyone
Then modify java.policy and add as below
// "standard" properies that can be read by anyone
permission java.security.AllPermission;
Related
I have a self signed applet running in the browser, this applet should create a directory on the client machine using this code.
boolean success = (new File("myDir")).mkdirs();
if (!success) {
System.err.println("Directory creation failed");
}
However, when I run it in the browser (under Apache) and after accepting all the security warnings I can't find myDir directory on my machine.
Am I doing something wrong?
I guess you are not looking at the right place...
Given your code snippet, this directory will be created in the current working directory. To be sure where that is on your machine just try to see what the following code gives out :
System.out.println(System.getProperty("user.dir"));
You're not giving it an absolute path so it's creating myDir in the working directory that the browser runs it in, probably a temp dir, or even a "sandbox" area in some browsers.
Because you run applet in sandbox, so You cannot access into user machine resource.
Please see document:
Applet security
I have made a Java webstart application, and created an HTML page with the link to launch it. The problem is, in Google Chrome, there is no option to just 'Open' a file without saving it. I want to make an HTML page that can automatically launch a JNLP file without having to save it. Or rather, without the user having to open their file explorer to launch it) Is this possible?
After getting fed up this problem, I wrote my own work around extension.
It's written under ubuntu, but should be portable (even to win32 with some work/reading).
Single click launches a jnlp file without prompting, or downloading. it just passes the url for the jnlp file to javaws directly. no cluttered Downloads folder, no extra clicks.
It's simple, crude and effective. I filtered the URL so it would only apply to my own internal server so I don't accidentally launch some random jnlp file. Lots more could be done to improve it, I'm sure. Use AS-IS, no warranty, etc, etc.
The files:
/usr/local/bin/jnlp-launcher
#!/usr/bin/env python
import struct
import sys
import threading
import Queue
import json
import os
# On Windows, the default I/O mode is O_TEXT. Set this to O_BINARY
# to avoid unwanted modifications of the input/output streams.
if sys.platform == "win32":
import os, msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
# Helper function that sends a message to the webapp.
def send_message(message):
# Write message size.
sys.stdout.write(struct.pack('I', len(message)))
# Write the message itself.
sys.stdout.write(message)
sys.stdout.flush()
# Thread that reads messages from the webapp.
def read_thread_func(queue):
message_number = 0
while 1:
# Read the message length (first 4 bytes).
text_length_bytes = sys.stdin.read(4)
if len(text_length_bytes) == 0:
if queue:
queue.put(None)
sys.exit(0)
# Unpack message length as 4 byte integer.
text_length = struct.unpack('i', text_length_bytes)[0]
# Read the text (JSON object) of the message.
text = sys.stdin.read(text_length).decode('utf-8')
decoded = json.loads(text);
os.system("javaws " + decoded['url']);
def Main():
read_thread_func(None)
send_message('"complete"')
sys.exit(0)
if __name__ == '__main__':
Main()
The chrome extension is 2 files placed in a local directory:
manifest.json
{
"manifest_version": 2,
"background": {
"persistent": false,
"scripts": [ "bg.js" ]
},
"name": "JNLP Fixer",
"description": "Handle JNLPs",
"version": "1.0",
"permissions": [
"downloads", "nativeMessaging"
]
}
And bg.js (edit as needed for host filters)
chrome.downloads.onCreated.addListener(function(downloadId) {
var expr = /\.jnlp$/;
//this is to limit where we apply the auto-launch.
//for our use, i only wanted it for internal jnlps.
var hostExpr = /(http|https):\/\/internal.company.com\//;
if (hostExpr.test(downloadId.url)) {
if (downloadId.state == "in_progress") {
console.log(downloadId.url);
chrome.downloads.cancel(downloadId.id,function() {
console.log("cancelled");
});
chrome.runtime.sendNativeMessage("com.hcs.jnlplauncher",
{url:downloadId.url},
function(response)
{
console.log(chrome.runtime.lastError);
console.log(response);
}
);
}
}
})
Put manifest.json and bg.js in a folder and load it as an Unpacked extension in chrome in developer mode under chrome://extensions
Get the ID for the extension from the chrome://extensions pages.
Next is the bridge between the extension and the shell script.
File: com.hcs.jnlplauncher.json
{
"name": "com.hcs.jnlplauncher",
"description": "JNLP Launcher",
"path": "/usr/local/bin/jnlp-launcher",
"type": "stdio",
"allowed_origins": [
"chrome-extension://iacomlhfiphkdfjjjmlgckdkhmkhkibe/"
]
}
Place this under "~/.config/google-chrome/NativeMessagingHosts" (for linux). see google for windows locations.
Put your extension ID from the previous step into that file.
Make sure javaws is in the path. (that chrome runs with). link to /usr/bin is easiest way to be sure.
Click on a jnlp file and enjoy!!! No prompt, no ClickToOpen, and no file saved in the Downloads directory.!
If someone would like to bundle this all together into a nice packaged installer and/or chrome extension feel free. Please credit me (Chris Holt -- hobie744#gmail.com) and let me know. At first glance, I couldn't see how to bundle the NativeMessagingHosts piece into the extension. Perhaps it has to be 2 pieces? This is my first adventure in Chrome Extensions and NativeMessaging. Most of the code comes from the API docs and examples, and there are probably a few bugs.
Launch the JNLP using an embedded applet deployed using web start.
Start with a Swing based JApplet that accepts an image path (icon) and a string for the button. Deploy the applet (embedded in the web page, where the link would be) using JWS.
When the user clicks the button, use the BasicService.showDocument(URL) method to launch the JWS (frame based) app. As I note in the demo. of the BasicService..
..In Java 6+, a call to show another web start launch file (e.g. BasiceService.showDocument(another.jnlp)) will be handed directly to JavaWS, with no browser window appearing.
Unfortunately this is a bug(/feature?) in Google Chrome which still exists, however it is partly fixed: you can now automatically open jnlp files, but it they are still saved to the downloads folder
download the jnlp
right click in the download bar and select to always open files of this type
clicking the jnlp now directly launches it
This sample(Embedding JavaFX 2 in Swing) and articles are a great sample and they also work with modern browsers
sample http://www.oracle.com/technetwork/java/javase/overview/javafx-samples-2158687.html
documentation : https://docs.oracle.com/javase/8/docs/technotes/guides/deploy/deployment_toolkit.html#BABIJEHC
For testing or webscraping (when you cannot change or control jnlp handling) I found a workaround via Selenium + Python (but similar thing should be feasible in Java or other language too). In Python I just click programmatically on the notification in Chrome to allow downloading and installation of the jnlp file (with help of win32api and win32con, but similar approach could work also on Linux or Mac, after code rework). You can see details here
I'm trying to set up JRI with Eclipse on a Windows 7 x64 system. I tried it once on my Laptop and it worked. Now on my Desktop it fails although everything of the R, rJava and JRI installation is exactly the same.
I set the JRI and R Paths correctly to:
C:\Program Files\R\R-2.15.1\library\rJava\jri;C:\Program Files\R\R-2.15.1\bin\x64
Also I set R_DOC_DIR etc in Eclipse.
Every time I try to run new Rengine(...); it fails without any error or exception. Debugging revealed an: <terminated, exit value: 10>C:\Program Files\Java\jre6\bin\javaw.exe (01.10.2012 18:00:31)
Is there anything I can try? It really bothers me that it works an my Laptop but not on my Workstation despite the same settings everywhere.
Edit: The code that is used to get the Rengine object.
public static Rengine getRengine(){
if (re == null) createRengine();
return re;
}
public static void createRengine(){
if (re!=null) return;
try{
if (!Rengine.versionCheck()) {
System.err.println("** Version mismatch **");
System.exit(1);
}
String[] arguments = {"--save"};
re=new Rengine(arguments, false, null);
if (!re.waitForR()) {
System.out.println("Cannot load R");
return;
}
}
catch (Exception e){
e.printStackTrace();
}
}
Edit: The last time i tried it i got an errormessage (creating of the REngine worked, this happened never before), R was missing a registryentry. After installing R 2.15.1 again it suddenly worked. Now after a restart it's the same like before. The program crashes at the creation of the REngine.
I was having the exact same problem. It turns out I had unchecked the box that asks to make a registry entry with the R version number. Once I let the installer run with that box checked, it seemed to work.
I would make sure your regedit looks like this:
Next up: getting this working in a portable way...
I am using R 3.2.2 and eclipse Mars on Windows 10 x64.
I faced the described issue today and tried around a bit. Finally, I found the root cause in the build path. Please check whether the following conditions are fulfilled:
1.) The following Java libraries from the JIRI folder on your hard disk shall be included as (user) libraries:
JIRI.jar
REngine.jar
JRIEngine.jar
2.) The native library jiri.dll is located in the subfolder "i386" for x86, whereas for x64 it is available in the subfolder "x64". The relevant one shall be added as separate native library location to the Java Build Path of the eclipse project. Otherwise, the file may not be considered as it is not located in the main JIRI folder.
Best regards
Philipp
Scenario:
I have an applet that must use a .dll.
That .dll MUST live on PATH.
In order to get the .dll on PATH, through the applet, the user running the browser MUST have administrative rights (Usually done as right-click icon Run As Administrator...).
Problem:
I would like to remove the need of having to gain administrative privelages.
The bad idea
I would like to have the applet save the file somewhere inside the users home directory. I would like to add that path to PATH. Appearently, it can be done via:
System.setProperty("java.library.path", <new path>);
try {
// this forces JVM to reload "java.library.path" property
Field fieldSysPath = ClassLoader.class.getDeclaredField( "sys_paths" );
fieldSysPath.setAccessible( true );
fieldSysPath.set( null, null );
} catch (Exception e) {
e.printStackTrace();
init_failure = true;
}
Question
Is it a bad idea to force the JVM to do this? Is this using undocumented methods/is it just plain hacky?
Other bits
Because this is an applet, I can not specify java.library.path via -D option, correct ?
This code is in an intranet. Not intended for the average internet tough guy.
field.setAccessible( true ) is always hacky and undocumented. It changes a private field! Maybe you get lucky and it works for all supported JVM's, and it doesn't change anytime in the future.
I also worry about what would happen if the JVM found and loaded a version of your dll in the previous java.library.path for some reason, before you changed the path. I guess it would keep the loaded version, and not load the new one.
If you work in a controlled environment you might ignore these issues, but I'd encourage you to find another solution. E.g. tell users to remote install the dll with a simple installer.
I tried the code below to run a stand-alone utility app I created from Apple script but, I get a No File or Directory Exists error.
I put identical copies (for testing) in the project, dist, parent directories but, it didn't help.
So, my questions are:
Is my call to run the app bad (perhaps because it's not a Windows exe)?
How to run a mac app from java?
Thanks
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
Runtime r=Runtime.getRuntime();
Process p=null;
String s="MyLineInInput.app";
try {
p = r.exec(s);
} catch (IOException ex) {
Logger.getLogger(AudioSwitcherView.class.getName()).log(Level.SEVERE, null, ex);
}
}
A Mac App Bunde is not an executable file, it's a folder with a special structure. It can be opened using the open command, passing the App Bundle path as an argument: open MyLineInInput.app.
EDIT:
Even better would be using Desktop.getDesktop().open(new File("MyLineInInput.app"));
I used the Runtime.getRuntime().exec() method with the open command mentioned in the selected answer. I didn't use Desktop.getDesktop().open() since it unwantedly opened a terminal in my case and I didn't want to create an extra File object.
Process process = Runtime.getRuntime().exec("open /System/Applications/Books.app");
Reason for adding '/System':
It seems we need to use the /System prefix for System apps. For user-installed apps, that's not required, and it can be like /Applications/Appium.app.
To answer #Pantelis Sopasakis' issue that I also faced initially -
I get the error message: java.lang.IllegalArgumentException: The file: >/Applications/Microsoft Office 2011/Microsoft\ Excel.app doesn't exist.
In this case, it could be simply due to not escaping the space characters in the path.
Environment: JDK 11 Zulu - macOS Monterey 12.2.1 - M1 Silicon