I have a function where I am trying to load a file to a URL object, because the example project said so.
public class SecureFTP {
public static void main(String[] args) throws IOException , ClassNotFoundException, SQLException , JSchException, SftpException{
File file = new File("/home/xxxxx/.ssh/authorized_keys");
URL keyFileURL = this.getClass().getClassLoader().getResource(file);
I tried using SecureFTP.class.getResource, but it still could not compile it.
I am fairly new to Java, so I know I am doing something wrong.
The main method is a static method, so trying to access this (= the current Object) will not work.
You can replace that line by
URL keyFileURL = SecureFTP.class.getClassLoader().getResource("/home/xxxxx/.ssh/authorized_keys");
From: How to call getClass() from a static method in Java?
Just use TheClassName.class instead of getClass().
Old question but this hasn't been said yet. You can do this from a static context:
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
classLoader.getResource("filename");
It can't compile because getResource takes a resource name (a String, and not a File) as parameter, in order to load a resource using the class loading mechanism (from the classpath). Using it with a File makes no sense. If you want to open a file, just use a FileInputStream or a FileReader.
See http://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html#getResource%28java.lang.String%29, and include the compiler error message next time you have such a question.
SecureFTP.class.getClassLoader().getResource(<<your resource name>>);
Should do the trick!
Do it this way so that it works EITHER from a static method or an instance method:
public static String loadTestFile(String fileName) {
File file = FileUtils.getFile("src", "test", "resources", fileName);
try {
return FileUtils.readFileToString(file, StandardCharsets.UTF_8);
} catch (IOException e) {
log.error("Error loading test file: " + fileName, e);
return StringUtils.EMPTY;
}
}
Related
I have a simple java program to test Try with resource in java , I am getting the File Not Found error, The Program and file are in the same package, Can somebody tell me what directory does File with resource start to search with
public class LoadConfigFile {
public static String getProperty(String propertyName) {
String propertyValue = null;
try (InputStream in = new FileInputStream("Properties.properties")) {
Properties prop = new Properties();
prop.load(in);
propertyValue = prop.getProperty(propertyName);
} catch (IOException e) {
System.out.println("Error Reading Property File" + e.getMessage().toString());
}
return propertyValue;
}
}
Properties.properties
properties.one=1
properties.two=2
properties.three=3
properties.four=4
properties.five=5
Main.java
public class Main {
public static void main(String[] args) {
String s = LoadConfigFile.getProperty("property.one");
System.out.println(s);
}
}
Working directory for process, to get that in Java you can use
System.out.println(System.getProperty("user.dir"));
If you have file within a Java package you should not access it as file but as resource:
InputStream in = this.getClass().getResourceAsStream("Properties.properties");
If you look at the source code for the FileInputStream constructor, you'll see that it, in turn, invokes File's constructor.
And if you have a look at the documentation for File, you will find a good explanation of how the path string is interpreted.
In particular, notice the following snippet:
A pathname, whether abstract or in string form, may be either absolute
or relative. An absolute pathname is complete in that no other
information is required in order to locate the file that it denotes. A
relative pathname, in contrast, must be interpreted in terms of
information taken from some other pathname. By default the classes in
the java.io package always resolve relative pathnames against the
current user directory. This directory is named by the system property
user.dir, and is typically the directory in which the Java virtual
machine was invoked.
I am currently working on a method that will create files and directories. Bellow is the use case & problem explained.
1) When a user specifies a path e.g "/parent/sub folder/file.txt", the system should be able to create the directory along with the file.txt. (This one works)
2) When a user specifies a path e.g "/parent/sub-folder/" or "/parent/sub-folder", the system should be able to create all directories. (Does not work), Instead of it creating the "/sub-folder/" or /sub-folder" as a folder, it will create a file named "sub-folder".
Here is the code I have
Path path = Paths.get(rootDir+"test/hello/");
try {
Files.createDirectories(path.getParent());
if (!Files.isDirectory(path)) {
Files.createFile(path);
} else {
Files.createDirectory(path);
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
You need to use createDirectories(Path) instead of createDirectory(path). As explained in the tutorial:
To create a directory several levels deep when one or more of the
parent directories might not yet exist, you can use the convenience
method, createDirectories(Path, FileAttribute). As with the
createDirectory(Path, FileAttribute) method, you can specify an
optional set of initial file attributes. The following code snippet
uses default attributes:
Files.createDirectories(Paths.get("foo/bar/test"));
The directories
are created, as needed, from the top down. In the foo/bar/test
example, if the foo directory does not exist, it is created. Next, the
bar directory is created, if needed, and, finally, the test directory
is created.
It is possible for this method to fail after creating some, but not
all, of the parent directories.
Not sure of which File API you are using. But find below the simplest code to create file along with folders using java.io package.
import java.io.File;
import java.io.IOException;
public class FileTest {
public static void main(String[] args) {
FileTest fileTest = new FileTest();
fileTest.createFile("C:"+File.separator+"folder"+File.separator+"file.txt");
}
public void createFile(String rootDir) {
String filePath = rootDir;
try {
if(rootDir.contains(File.separator)){
filePath = rootDir.substring(0, rootDir.lastIndexOf(File.separator));
}
File file = new File(filePath);
if(!file.exists()) {
System.out.println(file.mkdirs());
file = new File(rootDir);
System.out.println(file.createNewFile());
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
In the unit tests as a side effect I am creating screenshots for various parts of the GUI.
I want to use these screenshots when compiling the documentation.
Therefore I want to save them to a directory within the source tree.
Is there any reliable way to get the source directory root when running a junit test?
If not, how can I make sure that unit tests run with cwd=project root when using eclipse, and when using maven?
wether you execute tests on eclipse or using maven, if you don't specify a path when you create the file it's automatically created at project root directory.
so if you specify a relative folder your files will go there :
public class TestFileCreation {
#Test
public void testFileCreation() throws IOException {
File f = new File("src/main/resources/hello.txt");
OutputStream ostream = new FileOutputStream(f);
String data = "Hello there !";
ostream.write(data.getBytes());
ostream.close();
}
}
will create a file inside the $PROJECT/src/main/resources.
Hope my answer helps
You can base on your classes location. Proposed solution here is to use class that will surely be in classpath. Then you can use class.getResource(""). Example
public class ResouceRoot {
public static String get() {
String s = ResouceRoot.class.getResource("").toString();
if (s.startsWith("jar:")) {
s = s.replace("jar:", "").replaceAll("!.*", "");
} else {
s = s.replaceAll("classes.*", "classes");
}
File f = new File(s.replace("file:", ""));
return f.getParentFile().getParentFile().getAbsolutePath();
}
public static void main(String[] args) throws IOException {
System.out.println(get());
}
}
(this code will give base dir for netbeans projects if they are launched from netbeans or by java -jar ... )
I'm currently developing a web site using servlets & spring framework. As usual it contains lots of files (jsp, js, css, images, various resources etc).
I'm trying to avoid writing any hardcoded path, or domain in any file ...
For example as you may know when a request is handled you 'forward' it to a jsp page (it's path probably will be hardcoded). Other examples are imports images/css/js etc in jsp files ...
Is there any general way (or tools) to avoid hardcoded paths/urls so any refactorings won't cause troubles?
EDIT
I use netbeans 7.1.2 ... Unfortunately netbeans only helps with pure java code. When working with jsp files things are limited, and if you add custom tag files and Jsp 2.0 EL is like programming in console mode :p
In the JSP files themselves, you can avoid nearly all hardcoded domain / urls by using JSTL
For example, when creating a link to another page, you would do it like this:
Refer an Entrepreneur!
This means that, regardless of where your webapp is, the link will always have the right url. For example, in my development box this link would be:
http://localhost:8080/accounts/referrals/send.html
But on my production server, it resolves correctly to:
http://wwww.mydomain.com/referrals/send.html
You can see that in my dev server, the webapp context is under /accounts, but on the production machine, it's just under / as the webapp is under the root context.
You can read a small tutorial here
Properties file is always a good option so that you have to make changes if any only at one point.
If you are referencing any static contents (js, images, css, etc), you don't have to hardcode the entire file path. Instead, you can do this:-
<img src="${pageContext.request.contextPath}/resources/images/test.jpg"/>
The rest of the file paths (Hibernate domain mappings, forwarded page in Spring controller, etc) should be relative to your project structure, and most IDEs are smart enough to refactor them without problem... or at least in my case, IntelliJ seems to handle of all that for me.
At some point of time, you need to ask yourself, how much of hardcoding is acceptable vs not acceptable? Further, I wouldn't try to stray too far away from the Spring/Hibernate recommended solutions. If you make everything too abstract, you have a different set of problem to deal with and it becomes counterproductive to other peers that may be inheriting your project in the future.
Actually I just came up with an idea. Since netbeans does analysis and shows dependencies on java code, maybe it's better to handle all paths & domains as java variables.
I've created a package on my project named FileResolver and inside I have one class for each file type on my project (eg one class for Jsp files, one for Css files etc). Inside those files I'll record & hardcode all paths of all files in public static final String variables. Sample:
public class Jsps {
public class layouts{
public static final String main = "layouts/main.jsp";
}
public class pages{
public static final String error = "pages/error.jsp";
public static final String login = "pages/login.jsp";
public static final String register = "pages/register.jsp";
}
...
}
All over my project I should use the variables instead of paths. Then anytime I refactor a file, I'll have only one file to change is the mapping value in those variables ...
And if somethime I need to change the variable, netbeans will refactor all of them in the project at once ...
I think this will work just fine since I keep my project clean from file paths and the only thing I have to worry about is the mapping in that file of the variables to appropriate file paths.
EDIT
I'll write a simple parser to create those java files instead of writting by hand for all files ... I'll update when I finish it
UPDATE
Here is my FileResolverGenerator
public class FileResolverGenerator {
private static final String newFilePath = "C:/Users/Foo/Desktop/Jsps.java";
private static final String scanRootFolder = "C:/Users/Foo/Desktop/myProject/web/WEB-INF/jsp";
private static final String varValueReplaceSource = "C:/Users/Foo/Desktop/myProject/web/WEB-INF/jsp/";
private static final String varValueReplaceTarget = "";
private static final boolean valueAlign = true;
private static final int varNameSpaces = 15;
public static void main(String[] args){
try {
// Create file and a writer
File f = new File(newFilePath);
f.createNewFile();
bw = new BufferedWriter( new FileWriter(f) );
// Execute
filesParser( new File(scanRootFolder) );
// 'Burn' file
bw.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(ResolverGenerator.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ResolverGenerator.class.getName()).log(Level.SEVERE, null, ex);
}
}
// ================================================================================================ //
// ============================================= WORK ============================================= //
// ================================================================================================ //
private static void filesParser(File rootFolder) throws FileNotFoundException, IOException{
folderIn(rootFolder);
// Files first
if(!rootFolder.exists()) throw new FileNotFoundException();
for(File f : rootFolder.listFiles()){
if(f==null){ return; }
if(f.isDirectory()){ continue; }
else if(f.isFile()){ writeFileVariable(f); }
}
// Folders next
for(File f : rootFolder.listFiles()){
if(f==null){ return; }
if(f.isDirectory()){ filesParser(f); }
else if(f.isFile()){ continue; }
}
folderOut(rootFolder);
}
// ================================================================================================ //
// ============================================ PRINTS ============================================ //
// ================================================================================================ //
private static BufferedWriter bw;
private static int tabCount = 0;
private static void folderIn(File f) throws IOException{
bw.append("\n\n");
for(int i=0; i<tabCount; i++)
bw.append("\t");
bw.append("public class "+f.getName()+"{\n");
tabCount++;
}
private static void folderOut(File f) throws IOException{
tabCount--;
for(int i=0; i<tabCount; i++)
bw.append("\t");
bw.append("}\n");
}
private static void writeFileVariable(File f) throws IOException{
String varName = f.getName().split("\\.")[0].replaceAll("-", "");
String varValue = f.getPath().replaceAll("\\\\","/")
.replace(varValueReplaceSource.replaceAll("\\\\","/"),varValueReplaceTarget.replaceAll("\\\\","/"));
for(int i=0; i<tabCount; i++)
bw.append("\t");
bw.append("public static final String "+varName+" = ");
if(valueAlign){
for(int i=0; i<varNameSpaces-varName.length(); i++) bw.append(" ");
bw.append("\t"); }
bw.append("\""+varValue+"\";\n");
}
}
Just to be specific ... This scans all files under "/WEB-INF/jsp/" and creates a java file having all jsp files 'registered' to public static final String variables with each path ... The idea is to use the generated java file as reference for all jsps are in project ... always use these variables instead of hardcoded paths ..
This has nothing to do with the project or any project. It's just a tool which saves you
time, instead of doing this by hand for every file in the project.
I also created another class ResolverConsistencyChecker, which takes all variables and checks if the filepath is correct (file exists) ... since we didn't made any changes to filenames and filepaths all tests are passed.
This method should run when testing project for 'errors'
public class ResolverConsistencyChecker {
private static Class checkClass = Jsps.class;
private static String fullPathPrefix = "C:/Users/Foo/Desktop/myProject/web/WEB-INF/jsp/";
public static void main(String[] args){
try {
filesChecker( checkClass );
System.out.println( "Tests passed. All files locations are valid" );
} catch (FileNotFoundException ex) {
Logger.getLogger(ResolverConsistencyChecker.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ResolverConsistencyChecker.class.getName()).log(Level.SEVERE, null, ex);
}
}
// ================================================================================================ //
// ============================================= WORK ============================================= //
// ================================================================================================ //
private static void filesChecker(Class rootClass) throws FileNotFoundException, IOException{
// Check file paths in current class depth
for(Field f : rootClass.getFields()){
try {
String fullFilePath = fullPathPrefix+f.get(f.getName()).toString();
File file = new File( fullFilePath );
if( !file.exists() )
throw new FileNotFoundException("Variable: '"+f.getName()+"'\nFile "+fullFilePath);
} catch (IllegalArgumentException ex) {
Logger.getLogger(ResolverConsistencyChecker.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(ResolverConsistencyChecker.class.getName()).log(Level.SEVERE, null, ex);
}
}
// Check for embedded classes
for(Class c : rootClass.getClasses()){
filesChecker(c);
}
}
}
This question already has answers here:
How to load JAR files dynamically at Runtime?
(20 answers)
Closed 7 years ago.
Is it possible to add a file (not necessarily a jar file) to java classpath at runtime.
Specifically, the file already is present in the classpath, what I want is whether I can add a modified copy of this file to the classpath.
Thanks,
You can only add folders or jar files to a class loader. So if you have a single class file, you need to put it into the appropriate folder structure first.
Here is a rather ugly hack that adds to the SystemClassLoader at runtime:
import java.io.IOException;
import java.io.File;
import java.net.URLClassLoader;
import java.net.URL;
import java.lang.reflect.Method;
public class ClassPathHacker {
private static final Class[] parameters = new Class[]{URL.class};
public static void addFile(String s) throws IOException {
File f = new File(s);
addFile(f);
}//end method
public static void addFile(File f) throws IOException {
addURL(f.toURL());
}//end method
public static void addURL(URL u) throws IOException {
URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class sysclass = URLClassLoader.class;
try {
Method method = sysclass.getDeclaredMethod("addURL", parameters);
method.setAccessible(true);
method.invoke(sysloader, new Object[]{u});
} catch (Throwable t) {
t.printStackTrace();
throw new IOException("Error, could not add URL to system classloader");
}//end try catch
}//end method
}//end class
The reflection is necessary to access the protected method addURL. This could fail if there is a SecurityManager.
Try this one on for size.
private static void addSoftwareLibrary(File file) throws Exception {
Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
method.setAccessible(true);
method.invoke(ClassLoader.getSystemClassLoader(), new Object[]{file.toURI().toURL()});
}
This edits the system class loader to include the given library jar. It is pretty ugly, but it works.
The way I have done this is by using my own class loader
URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
DynamicURLClassLoader dynalLoader = new DynamicURLClassLoader(urlClassLoader);
And create the following class:
public class DynamicURLClassLoader extends URLClassLoader {
public DynamicURLClassLoader(URLClassLoader classLoader) {
super(classLoader.getURLs());
}
#Override
public void addURL(URL url) {
super.addURL(url);
}
}
Works without any reflection
You coud try java.net.URLClassloader with the url of the folder/jar where your updated class resides and use it instead of the default classloader when creating a new thread.
Yes I believe it's possible but you might have to implement your own classloader. I have never done it but that is the path I would probably look at.
yes, you can. it will need to be in its package structure in a separate directory from the rest of your compiled code if you want to isolate it. you will then just put its base dir in the front of the classpath on the command line.
My solution:
File jarToAdd = new File("/path/to/file");
new URLClassLoader(((URLClassLoader) ClassLoader.getSystemClassLoader()).getURLs()) {
#Override
public void addURL(URL url) {
super.addURL(url);
}
}.addURL(jarToAdd.toURI().toURL());