Problem: Java applet can't load resources located inside its jar when run locally on windows platforms. The same applet can load the resources if it is launched from a web server instead of launched locally or if it's launched locally on a linux system. In all cases the applet is launched using an applet tag.
Steps to reproduce
1) Build applet class code below and create a jar containing the following:
TestApplet.class
iconimg.png
test.html
META-INF folder (standard manifest with one line: "Manifest-Version: 1.0")
Here's a link to the image png file I used:
http://flexibleretirementplanner.com/java/java-test/iconimg.png
The file test.html has one line:
<h1>Text from test.html file</h1>
2) create launch.html in same folder as test.jar as follows:
<html><center><title>Test Applet</title><applet
archive = "test.jar"
code = "TestApplet.class"
name = "Test Applet"
width = "250"
height = "150"
hspace = "0"
vspace = "0"
align = "middle"
mayscript = "true"
></applet></center></html>
3) With test.jar in the same local folder as launch.html, click on launch.html
4) Notice that getResource() calls for imgicon.png and test.html both return null.
5) Upload launch.html and test.jar to a web server and load launch.html and notice that the resources are found.
TestApplet.java
import java.applet.AppletContext;
import java.io.IOException;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JApplet;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class TestApplet extends JApplet {
public TestApplet() {
try {
jbInit();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void init() {
JPanel topPanel = new JPanel();
JLabel iconLabel;
URL url = TestApplet.class.getClassLoader().getResource("iconimg.png");
if (url != null)
iconLabel = new JLabel(new ImageIcon(url));
else
iconLabel = new JLabel("getResource(iconimg.png)==null");
topPanel.add(iconLabel);
URL url2;
url2 = TestApplet.class.getClassLoader().getResource("test.html");
if (url2 == null) {
JLabel errorLabel = new JLabel("getResource(test.html) == null");
topPanel.add(errorLabel);
} else {
try {
JEditorPane htmlPane = new JEditorPane(url2);
topPanel.add(htmlPane);
} catch (IOException ioe) {
System.err.println("Error displaying " + url2);
}
}
getContentPane().add(topPanel);
}
private void jbInit() throws Exception { }
}
Oracle has decided to modify the behavior of getDocumentBase(), getCodeBase() and getResource() because security reasons since 1.7.0_25 on Windows: http://www.duckware.com/tech/java-security-clusterfuck.html
It seems there is a lot of discussion about this change because it breaks some important valid and secure use cases.
After further research and discovering that this is a windows-only problem, I'm calling this one answered.
It's almost certainly a java 1.7.0.25 bug. The applet runs fine from a web server and also runs fine locally on a virtual Ubuntu system (using VirtualBox on windows). Hopefully the bug report i submitted will be helpful to the java folks.
Thanks for the responses. Btw, it was Joop's comment about case sensitivity that spurred me to test a linux system just for kicks. Thanks for that!
Related
I am beginner in java.
I want run native application from applet.
I found Run App In Every Browser
Java Code
import com.ms.security.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.io.* ;
import java.util.*;
import netscape.security.PrivilegeManager;
public class RunApp extends Applet implements ActionListener {
TextArea ta = new TextArea (25, 80);
Button startbutton = new Button("Start Application") ;
private static String execommand = "C:\\windows\\notepad.exe" ;
private String osname;
public void init() {
try {
if (Class.forName("com.ms.security.PolicyEngine") != null) { // required for IE
PolicyEngine.assertPermission(PermissionID.SYSTEM);
}
}
catch (Throwable cnfe) {
}
this.setBackground(Color.white) ;
startbutton.addActionListener(this) ;
add(startbutton) ;
startbutton.setBackground(Color.red) ;
try{
PrivilegeManager.enablePrivilege("UniversalExecAccess") ; // required for NN
}
catch(Exception cnfe) {
System.out.println("netscape.security.PrivilegeManager class not found") ;
}
osname = System.getProperty("os.name"); // if NT, Win2000 or WinXP, adjust path
if(osname.equals("Windows NT") || osname.equals("Windows 2000")|| osname.equals("Windows XP"))
execommand = "C:\\winnt\\notepad.exe" ;
}
public void actionPerformed(ActionEvent e) {
if( (e.getActionCommand()).equals("Start Application")) {
try{
PrivilegeManager.enablePrivilege("UniversalExecAccess") ; // required for NN
}
catch(Exception cnfe) {
System.out.println("netscape.security.PrivilegeManager class not found") ;
}
try {
Process proc = Runtime.getRuntime().exec(execommand) ;
}
catch(IOException ieo) {
System.out.println("Problem starting " + execommand) ;
}
// System.out.println("execommand: " + execommand) ;
}
}
}
But when run it say error:package com.ms.security does not exit!
I does not any folder with ms or security name .
I should create folder with ms and then security in root file or should import library ms.security .
where is com.ms.security or netscape.security.PrivilegeManager?
how can download it?i search for download this package but i does not found anythings
I use eclipse for write code.
This package does not exist any more. The tutorial you point to dates from 2002. You can look at this javaranch post: http://www.coderanch.com/t/375470/java/java/Location-Jar-ms-security, and at the Microsoft documentation (https://msdn.microsoft.com/en-us/library/aa242534(v=vs.60).aspx). So basically your code would have worked 13 years ago, but with Microsoft not supporting their own JVM any more it's obsolete. Sorry!
You need to download that jar having this package ,com.ms.security. And b4 compiling your java class set that jar in your classpath from command prompt.
set classpath=%classpath%;path_of_your_jar;
This package is not existed anymore. Microsoft is not supporting their own JVM anymore. You should try to learn java applet in the new way, such as http://www.tutorialspoint.com/java/java_applet_basics.htm.
The import statement import com.ms.security.*; requires you to have a folder com, with a subfolder ms, with a subfolder security, which contains the needed files.
I think you are missing some files for your application.
I recommend reading this post, for the use of imports: https://stackoverflow.com/a/12620773/3234981
Please check your jar file which contain the respective package are present in the classpath or not. If not, push them to classpath and re-compile the same class on a new command line.
Happy Learning.
I've got an issue with my .jar file. It runs fine in Eclipse but as soon as I export it, it won't open. I've checked the manifest file and it looks like it's okay.
I've tried exporting it as a runnable jar, as well as just using the jar builder. Nothing worked.
I've tried to run it in command prompt and it says it can't access the jar file... I've searched around a while on here and haven't found an answer yet.
I'm not sure what I'm doing wrong. The only thing I can think of is I'm not getting my images correctly.
I'm using .png files for the program's sprites and here's an example of how I get them for my program.
This code begins the building of a level from a .png file.
public class SpawnLevel extends Level{
public SpawnLevel(String path) {
super(path);
}
protected void loadLevel(String path){
try{
System.out.println("classpath is: " + System.getProperty("java.class.path"));
BufferedImage image = ImageIO.read(SpawnLevel.class.getResource(path));
int w = width = image.getWidth();
int h = height= image.getHeight();
tiles = new int[w*h];
image.getRGB(0,0,w,h,tiles,0,w);
}catch(IOException e){
e.printStackTrace();
System.out.println("EXEPTION FOUND!!! Could not load the level file!");
}
}
protected void generateLevel(){
System.out.println("Tiles: " + tiles[0]);
}
}
I've made one other .jar before for another program and didn't have a problem. Any help would be greatly appreciated.
If it helps, I used this code to display the resource folder path information.
System.out.println("classpath is: " + System.getProperty("java.class.path"));
Here's what my current path for my resources folder looks like. Before I export it from eclipse.
classpath is: C:\Users\name\workspace\Rpg_Game\bin;C:\Users\name\workspace\Rpg_Game\res
After I export to .jar
classpath is: 2ndGameTest.jar
If your images are in your resources package in the src The path you should be using for getResource() is something like
class.getResource("/resources/levels/level1.png")
UPDATE with test program
import java.awt.Image;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
public class TestImage {
public static void main(String[] args) throws IOException {
Image image = ImageIO.read(TestImage.class.getResource("/resources/images/image.png"));
ImageIcon icon = new ImageIcon(image);
JLabel label = new JLabel(icon);
JOptionPane.showMessageDialog(null, label);
}
}
I tried this way, but it didnt changed?
ImageIcon icon = new ImageIcon("C:\\Documents and Settings\\Desktop\\favicon(1).ico");
frame.setIconImage(icon.getImage());
Better use a .png file; .ico is Windows specific. And better to not use a file, but a class resource (can be packed in the jar of the application).
URL iconURL = getClass().getResource("/some/package/favicon.png");
// iconURL is null when not found
ImageIcon icon = new ImageIcon(iconURL);
frame.setIconImage(icon.getImage());
Though you might even think of using setIconImages for the icon in several sizes.
Try putting your images in a separate folder outside of your src folder. Then, use ImageIO to load your images. It should look like this:
frame.setIconImage(ImageIO.read(new File("res/icon.png")));
Finally I found the main issue in setting the jframe icon. Here is my code. It is similar to other codes but here are few things to mind the game.
this.setIconImage(new ImageIcon(getClass().getResource("Icon.png")).getImage());
1) Put this code in jframe WindowOpened event
2) Put Image in main folder where all of your form and java files are created e.g.
src\ myproject\ myFrame.form
src\ myproject\ myFrame.java
src\ myproject\ OtherFrame.form
src\ myproject\ OtherFrame.java
src\ myproject\ Icon.png
3) And most important that name of file is case sensitive that is icon.png won't work but Icon.png.
this way your icon will be there even after finally building your project.
This works for me.
frame.setIconImage(Toolkit.getDefaultToolkit().getImage(".\\res\\icon.png"));
For the export jar file, you need to configure the build path to include the res folder and use the following codes.
URL url = Main.class.getResource("/icon.png");
frame.setIconImage(Toolkit.getDefaultToolkit().getImage(url));
Yon can try following way,
myFrame.setIconImage(Toolkit.getDefaultToolkit().getImage("Icon.png"));
Here is the code I use to set the Icon of a JFrame
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
try{
setIconImage(ImageIO.read(new File("res/images/icons/appIcon_Black.png")));
}
catch (IOException e){
e.printStackTrace();
}
Just copy these few lines of code in your code and replace "imgURL" with Image(you want to set as jframe icon) location.
JFrame.setDefaultLookAndFeelDecorated(true);
//Create the frame.
JFrame frame = new JFrame("A window");
//Set the frame icon to an image loaded from a file.
frame.setIconImage(new ImageIcon(imgURL).getImage());
I'm using the following utility class to set the icon for JFrame and JDialog instances:
import java.awt.*;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.Scanner;
public class WindowUtilities
{
public static void setIconImage(Window window)
{
window.setIconImage(Toolkit.getDefaultToolkit().getImage(WindowUtilities.class.getResource("/Icon.jpg")));
}
public static String resourceToString(String filePath) throws IOException, URISyntaxException
{
InputStream inputStream = WindowUtilities.class.getClassLoader().getResourceAsStream(filePath);
return toString(inputStream);
}
// http://stackoverflow.com/a/5445161/3764804
private static String toString(InputStream inputStream)
{
try (Scanner scanner = new Scanner(inputStream, "UTF-8").useDelimiter("\\A"))
{
return scanner.hasNext() ? scanner.next() : "";
}
}
}
So using this becomes as simple as calling
WindowUtilities.setIconImage(this);
somewhere inside your class extending a JFrame.
The Icon.jpg has to be located in myproject\src\main\resources when using Maven for instance.
I use Maven and have the structure of the project, which was created by entering the command:
mvn archetype:generate
The required file icon.png must be put in the src/main/resources folder of your maven project.
Then you can use the next lines inside your project:
ImageIcon img = new ImageIcon(getClass().getClassLoader().getResource("./icon.png"));
setIconImage(img.getImage());
My project code is as below:
private void setIcon() {
setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/slip/images/cage_settings.png")));
}
frame.setIconImage(new ImageIcon(URL).getImage());
/*
frame is JFrame
setIcon method, set a new icon at your frame
new ImageIcon make a new instance of class (so you can get a new icon from the url that you give)
at last getImage returns the icon you need
it is a "fast" way to make an icon, for me it is helpful because it is one line of code
*/
public FaceDetection() {
initComponents();
//Adding Frame Icon
try {
this.setIconImage(ImageIO.read(new File("WASP.png")));
} catch (IOException ex) {
Logger.getLogger(FaceDetection.class.getName()).log(Level.SEVERE, null, ex);
}
}'
this works for me.
I'm fairly new to programming and I just wrote an applet program that is supposed to list the files in a directory. The applet works well in eclipse, yet the issue is when I attempt to run the applet in a browser the GUI loads, yet the applet will not respond as it does in eclipse. Any help would be greatly appreciated. :)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.swing.JApplet;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class DirReader extends JApplet{
private JTextArea outputWindow;
private JTextField dirPath;
private String path;
private Font font;
private File folder;
private File[] listOfFiles;
public void init(){
font = new Font("Times New Roman", Font.PLAIN, 16);
dirPath = new JTextField("Enter Directory Path");
dirPath.setFont(font);
outputWindow = new JTextArea();
outputWindow.setEditable(false);
outputWindow.setFont(font);
outputWindow.setBackground(Color.DARK_GRAY);
outputWindow.setForeground(Color.ORANGE);
add(dirPath, BorderLayout.NORTH);
add(outputWindow, BorderLayout.CENTER);
setSize(400,750);
dirPath.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent event) {
path = dirPath.getText();
folder = new File(path);
listOfFiles = folder.listFiles();
System.out.println("Directory path set");
ListOfFiles();
}
}
);
System.out.println("Progam Intilized:");
}
public void ListOfFiles(){
outputWindow.setText(null);
try{
for(int counter = 0 ; counter < listOfFiles.length ; counter++ ){
if(listOfFiles[counter].isFile()){
outputWindow.append("[FILE] " + listOfFiles[counter].getName()+ "\n");
System.out.println("[FILE] " + listOfFiles[counter].getName());
}
else if(listOfFiles[counter].isDirectory()){
outputWindow.append("[DIR] " + listOfFiles[counter].getName() + "\n");
System.out.println("[DIR] " + listOfFiles[counter].getName());
}
}
}catch(Exception e){
System.out.println("Error: Directory could not be found.");
outputWindow.setText("Error: Could not find directory.");
}
}
}
Of course it does NOT work in browser
Because
when applet run in a browser as a security precaution there is no access to read files on the local file system.
Solution
Make your program as a Desktop application run in desktop NOT Applet run in browser
An untrusted applet cannot get a directory listing
A trusted applet cannot get a directory listing on the server (only the client).
For an applet to gain a file listing on the server, it will need to be explicitly told what the files are. Two common ways are:
Add the file list as parameters for the applet.
Have the applet access server side functionality to get a file listing.
BTW:
}catch(Exception e){
Should become..
}catch(Exception e){
e.printStackTrace(); //...
Be sure to figure out how to access the Java Console to see the output. Debugging applets without that information is like trying to debug wearing a blind-fold.
I want to write a Java program to delete ~12 directories or files which are under my home directory. I am able to do this by using
Process proc = Runtime.getRuntime().exec("rm -rf *path*")
But I have to run this command 12 times or I can keep it in loop. What I really want is to have a file in my home directory that contains the names of all the directories and files to delete in it. My Java program should go to the home directory, read the file, and delete all the specified files.
I am stuck at the very first step – I am not able to cd to the home directory. Please let me know how can I achieve this.
Thanks for all of your replies.
But, here I don't really want to use the Java util classes rather I want to learn a way using which I can run Linux commands in my Java class. Being a deployment Intern, I have to reset the environment every time before deploying a new environment for the customer. For this, I repeatedly use some basic Linux commands. I can write a shell script to do this but for this time, I want to write a Java class in which I can put all these Linux commands and run from one class.
The commands which I use are:
kill all java processes which are started by the admin ONLY – for this I need to use multiple Linux commands with “pipe”
Remove all 12-directories/files from home directory
stop some services (like siebel, etc.) – for this I need to go under the particular directories and run ./shutdown.sh or ./stop_ns, etc.
run some database scripts – to reset the database schemas
again start the services – same as step 2 except this time I need to run ./start_ns, etc.
I really appreciate if you can let me know
a. How can I navigate into a directory using Java code
b. How can I run multiple Linux commands using pipe using Java code
Why do you need to "go" to the home directory? Just read the file wherever you are:
String homeDirectory = System.getProperty("user.home");
File file = new File(homeDirectory, "filenames.txt"); // Or whatever
// Now load the file using "file" in the constructor call to FileInputStream etc
It's very rarely a good idea to require that a process changes working directory just to do the right thing.
You dont need to change directory. You can just read file using absolute path using FileReader(String fileName).
For deleting entire directories, try Apache Commons IO's class FileUtils:
FileUtils.deleteDirectory(new File(System.getProperty("user.home")));
Or use cleanDirectory to delete everything in home but not home itself:
FileUtils.cleanDirectory(new File(System.getProperty("user.home")));
If you want to delete specific files only (e.g. those matching a name pattern), list the files first, then delete them:
File startDir = new File(System.getProperty("user.home"));
//this should return the leaf files first, then the inner nodes of the directory tree
Collection<File> files = FileUtils.listFiles(startDir , someFileFiler, someDirFilter);
for(File f : files) {
f.delete();
}
"cd" is a shell internal command, not a executable program.
Even you can change dir in java program by whatever means like JNA, when it exit, the current dir in shell is not changed, because the java program runs in another process than the shell.
But we still can do something about it.
eg. I want to make a new shell command called xcd, it popup a GUI shows a list let you select directories existed in bash history, and change current dir to it for you.
in ~/.bashrc add a line:
xcd(){
XCDRES=`xcd.sh`
if [ "$XCDRES" ]; then
cd "$XCDRES"
fi
}
2.xcd.sh is
#!/bin/bash
java -cp $PATH1/xcd.jar neoe.xcd.Main
and add xcd.sh to PATH
the java program is
package neoe.xcd;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
public class Main {
public static String getUserHomeDir() {
return System.getProperty("user.home");
}
public static void main(String[] args) throws Exception {
new Main().run();
}
public static String readString(InputStream ins, String enc) throws IOException {
if (enc == null)
enc = "UTF-8";
BufferedReader in = new BufferedReader(new InputStreamReader(ins, enc));
char[] buf = new char[1000];
int len;
StringBuffer sb = new StringBuffer();
while ((len = in.read(buf)) > 0) {
sb.append(buf, 0, len);
}
in.close();
return sb.toString();
}
private String[] selection = new String[1];
private void run() throws Exception {
File hisfile = new File(getUserHomeDir(), ".bash_history");
if (!hisfile.exists()) {
System.err.println(".bash_history not exists, quit");
return;
}
String[] ss = readString(new FileInputStream(hisfile), null).split("\n");
List<String> res = new ArrayList<String>();
Set uniq = new HashSet();
for (String s : ss) {
s = s.trim();
if (!s.startsWith("cd /")) {
continue;
}
s = s.substring(3);
File f = new File(s);
if (f.isDirectory()) {
s = f.getAbsolutePath();
if (uniq.contains(s)) {
continue;
}
uniq.add(s);
res.add(s);
}
}
if (res.isEmpty()) {
System.err.println("no cd entry, quit");
return;
}
Collections.sort(res);
String cd1 = selectFromList(res);
if (cd1 == null) {
System.err.println("not selected, quit");
return;
}
doCd(cd1);
}
private void doCd(String cd1) throws Exception {
System.out.println(cd1);
}
private String selectFromList(List<String> res) {
final JList list = new JList(res.toArray());
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
final JDialog frame = wrapFrame(new JScrollPane(list), "select dir to cd");
list.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() > 1) {
String s = (String) list.getSelectedValue();
selection[0] = s;
frame.dispose();
}
}
});
list.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
int kc = e.getKeyCode();
if (kc == KeyEvent.VK_ESCAPE) {
frame.dispose();
} else if (kc == KeyEvent.VK_ENTER) {
String s = (String) list.getSelectedValue();
selection[0] = s;
frame.dispose();
}
}
});
frame.setVisible(true);
frame.requestFocus();
return selection[0];
}
private JDialog wrapFrame(JComponent comp, String title) {
JDialog frame = new JDialog();
frame.setTitle("select dir to cd");
frame.setModal(true);
frame.add(comp);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(400, 600);
frame.setLocationRelativeTo(null);
return frame;
}
}
use xcd in shell.
You can't really do that. Java programs don't really allow you to change the "current working directory" as most people understand it (not without using native code, anyway). The normal Java approach is to open a File instance on the directory you want to manipulate, and then use operations on that instance to manipulate the files/directories in question.
For details on how to delete directories programatically in Java, see: Delete directories recursively in Java