Creating a URL object with a relative path - java

I am creating a Swing application with a JEditorPane that should display an HTML file named url1.html stored locally in the page folder in the root folder of the project.
I have instantiated the following String object
final String pagePath = "./page/";
and in order to be displayed by the JEditorPane pane I have created the following URL object:
URL url1 = new URL("file:///"+pagePath+"url1.html");
However when the setPage() method is called with the created URL object as a parameter:
pagePane.setPage(url1);
it throws me a java.io.FileNotFoundException error.
It seems that there is something wrong with the way url1 has been constructed. Anyone knows a solution to this problem?

The solution is to find an absolute path to url1.html make an object of java.io.File on it, and then use toURI().toURL() combination:
URL url1 = (new java.io.File(absolutePathToHTMLFile)).toURI().toURL();
Assuming if the current directory is the root of page, you can pass a relative path to File:
URL url1 = (new java.io.File("page/url1.html")).toURI().toURL();
or
URL url1 = (new java.io.File(new java.io.File("page"), "url1.html")).toURI().toURL();
But this will depend on where you run the application from. I would make it taking the root directory as a command-line argument if it is the only configurable option for the app, or from a configuration file, if it has one.
The another solution is to put the html file as a resource into the jar file of your application.

To load a resource from the classpath (as khachik mentioned) you can do the following:
URL url = getClass().getResource("page/url1.html");
or from a static context:
URL url = Thread.currentThread().getContextClassLoader().getResource("page/url1.html");
So in the case above, using a Maven structure, the HTML page would be at a location such as this:
C:/myProject/src/main/resources/page/url1.html

I would try the following
URL url = new URL("file", "", pagePath+"url1.html");
I believe by concatenating the whole string, you are running into problems. Let me know, if that helped

Related

Java Class Loader not able to read resource

I have a file in structure. projectName/src/config/keyfiles/file and my code is in folder projectName/src/main/java/customProject/package/filename.java
I am trying to read my file with class loader like.
URL url = CommonUtil.class.getClassLoader().getResource(filename);
but every time I am getting url as null. passed filename is ./keyfiles/file.
Please let me know where I am going wrong
To make sure "where you are" in the directory tree, do the following:
URL url = YourMainClass.class.getClassLoader().getResource(".");
System.out.printf("%s\n", url);
Then you will know why you can't get your file

How to Play .wav file when your execute a jar file in java. [duplicate]

In my application I load resources in this manner:
WinProcessor.class.getResource("repository").toString();
and this gives me:
file:/root/app/repository (and I replace "file:" with empty string)
This works fine when I run my application from the IDE, but when I run the jar of my application:
java -jar app.jar
The path becomes:
jar:/root/app.jar!/repository
is there any way to solve this problem?
I'll use the "repository" dir name in order to create this:
ConfigurationContext ctx = (ConfigurationContext) ConfigurationContextFactory.createConfigurationContextFromFileSystem(repositoryString, null);
In the same manner, I'll get one file name (instead of a dir) and I'll use it this way:
System.setProperty("javax.net.ssl.trustStore", fileNameString)
It sounds like you're then trying to load the resource using a FileInputStream or something like that. Don't do that: instead of calling getResource, call getResourceAsStream and read the data from that.
(You could load the resources from the URL instead, but calling getResourceAsStream is a bit more convenient.)
EDIT: Having seen your updated answer, it seems other bits of code rely on the data being in a physical single file in the file system. The answer is therefore not to bundle it in a jar file in the first place. You could check whether it's in a separate file, and if not extract it to a temporary file, but that's pretty hacky IMO.
When running code using java -jar app.jar, java uses ONLY the class path defined in the manifest of the JAR file (i.e. Class-Path attribute). If the class is in app.jar, or the class is in the class path set in the Class-Path attribute of the JAR's manifest, you can load that class using the following code snippet, where the className is the fully-qualified class name.
final String classAsPath = className.replace('.', '/') + ".class";
final InputStream input = ClassLoader.getSystemResourceAsStream( path/to/class );
Now if the class is not part of the JAR, and it isn't in the manifest's Class-Path, then the class loader won't find it. Instead, you can use the URLClassLoader, with some care to deal with differences between windows and Unix/Linux/MacOSX.
// the class to load
final String classAsPath = className.replace('.', '/') + ".class";
// the URL to the `app.jar` file (Windows and Unix/Linux/MacOSX below)
final URL url = new URL( "file", null, "///C:/Users/diffusive/app.jar" );
//final URL url = new URL( "file", null, "/Users/diffusive/app.jar" );
// create the class loader with the JAR file
final URLClassLoader urlClassLoader = new URLClassLoader( new URL[] { url } );
// grab the resource, through, this time from the `URLClassLoader` object
// rather than from the `ClassLoader` class
final InputStream input = urlClassLoader.getResourceAsStream( classAsPath );
In both examples you'll need to deal with the exceptions, and the fact that the input stream is null if the resource can't be found. Also, if you need to get the InputStream into a byte[], you can use Apache's commons IOUtils.toByteArray(...). And, if you then want a Class, you can use the class loader's defineClass(...) method, which accepts the byte[].
You can find this code in a ClassLoaderUtils class in the Diffusive source code, which you can find on SourceForge at github.com/robphilipp/diffusive
And a method to create URL for Windows and Unix/Linux/MacOSX from relative and absolute paths in RestfulDiffuserManagerResource.createJarClassPath(...)
Construct a URL, you can then load a resource (even in a jar file) using the openStream method.

"Access Denied" when trying to access file in web app

I have an xslt file stored in the folder Project/tools. (I'm using Netbeans IDE.)
I try to access this file in my code, but at run time, I get an AccessControlException: access denied.
The code is:
java.net.URI xsltURI = new java.net.URI(myUtil.getUri("xsltFile.xslt"));
Transformer transformer = factory.newTransformer(new StreamSource(new File(xsltURI)));
The myUtil instance must be used to access the URI for reasons not important here. I printed its output, and it correctly gives the relative path of the file.
I have tried to prefix the relative path with file:/// and file:///[fulldomain], but in each of these cases, it actually tries to access a hard drive on the server, even though I did not give a drive name anywhere. (!) It tries to access C:[relative-path], which isn't even where the file is anyway.
If I omit file:/// then I get that the URI is not absolute, and if I just give the full web address of the file I get a NullPointerException.
Any help at all would be greatly appreciated.
UPDATE: Following my comment below, my code resembles
java.net.URI xsltURI = new java.net.URI("https://host" + myB2U.getUri("xsltFile.xslt"));
java.net.URL xsltURL = xsltURI.toURL();
java.net.URLConnection myConnection = xsltURL.openConnection();
myConnection.connect(); //AccessControlException: access denied ("java.net.SocketPermission"...
java.io.InputStream xsltStream = myConnection.getInputStream();
Transformer transformer = factory.newTransformer(new StreamSource(xsltStream));
Is there something obvious that is wrong?
The file:// protocol tells Java to use file access to open the stream. If you don't want file access you should use a different protocol such as http://.
If you're using a relative path the URI should look something like file://./My/Relative/Path. The 3rd slash means that it is relative to the root.
From what I've gathered, I'm supposed to instantiate a URL object with the path of the file. From there, I'm supposed to be able to initialize a URLConnection from the URL. After I call the URL's connect() method, I'm supposed to be able to obtain an InputStream by calling the getInputStream() method.

ClassNotFound With URLClassLoader

I currently have the following directory tree structure:
CLASSES
-> ClassOne
->package
-> my
->App.class
I would like to load the App.class from my local drive. I looked around, particularly stackoverflow, and most seem to suggest that I should use the URLClassLoader.
In order to do this, I used this following code:
However, I get a ClassNotFoundError. Can anybody help me please.
String url = "file://" + classOneFolder.getAbsolutePath(); //Where classesFolder is a File representing the ClassOne directory
URL[] urls = {new URL(url)};
urlClassLoader = URLClassLoader.newInstance(urls);
//class loader needs the fully classified class name. Therefore:
Class appClass = urlClassLoader.loadClass("package.my.App");
I would suggest you use classOneFolder.toURI().toURL() instead of building the URL yourself as a String and then recreate a URL from it. On some systems (like Windows) you need to add another slash in front on the absolute filename for a valid URL. Using File.toURI().toURL() should always build a correct URL.

How can I get a URL from relative path under a jar?

What I have done so far is :
/** Default location of help files folder */
private static final String DEFAULT_PATH = "../../../../resources/files/help/";
/** A 404 error file */
private static final String ERROR_404 = "../../../../resources/files/help/404.html";
/**
* #param fileName
* #return The URL of file, if found at default location, otherwise a 404 error page URL.
*/
public static URL getURL(String fileName) throws MalformedURLException{
URL url = (new File(ERROR_404)).toURI().toURL();
System.out.println(url);
url = (new File(DEFAULT_PATH + fileName)).toURI().toURL();
System.out.println(url);
return url;
}
Output:
file:/H:/My%20Project/Project%20Name%20Module/../../../../resources/files/help/404.html
file:/H:/My%20Project/Project%20Name%20Module/../../../../resources/files/help/plazaCode.html
Folder Hierarchy in the JAR created through NetBeans:
I am on Windows 7, JDK 7.
UPDATE:
Actually I want this URL for a JTextPane to show a HTML page by method:
textPane.setPage(URL url);
Can I have any better solution than this? and with the same Folder Heirarchy.. ?
404.html since this is an application resource, it will probably end up embedded in a Jar.
Resources in archives cannot be accessed using a File object.
URL getURL(String fileName) To help avoid confusion, change that to URL getURL(String resourceName).
Use Class.getResource(String) much as discussed on your previous questions.
'Relative' URLs become dangerous by that stage, since they depend on the package of the class that calls them, I generally make them 'absolute' by prefixing the entire path with a single / which effectively means 'look for this resource, from the root of the run-time class-path'.
So that String might read (adjusting the rest of the code as already advised):
private static final String ERROR_404 = "/resources/files/help/404.html";
You can use URL url = getClass().getResource("..."). Probably "/files/help/404.html".
When you create a File in this way you will get a relative file (and therefore a relative URL). To get a absolute URL from that path you need to get an absolute File first.
Try this:
new File(ERROR_404).getCanonicalFile().toURI().toURL()
(EDIT: After you JTextPane information above)
I haven't ever tried this, so I have no clue on why that's not working. But its a different question, you should ask a new Question.

Categories