Find files in inner zipfile Commons VFS - java

Is it possible to use the FileObject::findFiles method or similar to search in ZIP files which are stored in a folder? Or do I have to open the zipfiles by myself?
FileObject root = vfs.resolveFile(file:///home/me/test/vfsdir);
// shows everything except the content of the zip
FileObject[] allFiles = root.findFiles(Selectors.SELECT_ALL);
// should contain only the three xmls
FileObject[] xmlFiles = root.findFiles(xmlSelector);
VFS Directory-Tree
/ (root)
/folderwithzips
/folderwithzips/myzip.zip (Zipfile not a folder)
/folderwithzips/myzip.zip/myfile.xml
/folderwithzips/myzip.zip/myfile2.xml
/folderwithzips/other.zip
/folderwithzips/other.zip/another.xml

Sadly it's not possible to search through the content of zips in a VFS as if they were folders.
So I have to load every zip manually and execute my selector on the content.
This small method does the trick for me.
public static void main(String[] vargs) throws FileSystemException {
FileSystemManager manager = VFS.getManager();
FileObject root = manager.resolveFile("/home/me/test/vfsdir");
List<FileObject> files = findFiles(root, new XMLSelector());
files.stream().forEach(System.out::println);
}
public static List<FileObject> findFiles(FileObject root,FileSelector fileSelector) throws FileSystemException {
List<FileObject> filesInDir = Arrays.asList(root.findFiles(fileSelector));
FileObject[] zipFiles = root.findFiles(new ZipSelector());
FileSystemManager manager = VFS.getManager();
List<FileObject> filesInZips = new ArrayList<>();
for (FileObject zip: zipFiles){
FileObject zipRoot = manager.createFileSystem(zip);
Stream.of(zipRoot.findFiles(fileSelector)).forEach(filesInZips::add);
}
return Stream.concat(filesInDir.stream(),filesInZips.stream()).collect(Collectors.toList());
}

Related

How to load folder using classpath in java [duplicate]

I have the following directory layout:
src
main
java
resources
sql (scripts for database)
spring (configuration)
webapp
Within a ServletContextListener class, I want to access the files under the SQL directory and list them. Basically my problem is with the path, because I know that listing files under a directory in a nutshell is:
File folder = new File(path);
File[] listOfFiles = folder.listFiles();
Maybe I could use the ServletContextEvent Object to try and build a path to resources/sql
public void contextInitialized(ServletContextEvent event) {
event.getServletContext(); //(getRealPath etc.)
}
Does something exist to set that path in a relative, non-hardcoded way?
Something like new File("classpath:sql") (preferably spring if possible) or what should I do with the servletContext to point at resources/sql?
I'm assuming the contents of src/main/resources/ is copied to WEB-INF/classes/ inside your .war at build time. If that is the case you can just do (substituting real values for the classname and the path being loaded).
URL sqlScriptUrl = MyServletContextListener.class
.getClassLoader().getResource("sql/script.sql");
Finally, this is what I did:
private File getFileFromURL() {
URL url = this.getClass().getClassLoader().getResource("/sql");
File file = null;
try {
file = new File(url.toURI());
} catch (URISyntaxException e) {
file = new File(url.getPath());
} finally {
return file;
}
}
...
File folder = getFileFromURL();
File[] listOfFiles = folder.listFiles();
import org.springframework.core.io.ClassPathResource;
...
File folder = new ClassPathResource("sql").getFile();
File[] listOfFiles = folder.listFiles();
It is worth noting that this will limit your deployment options, ClassPathResource.getFile() only works if the container has exploded (unzipped) your war file.
Just use com.google.common.io.Resources class. Example:
URL url = Resources.getResource("file name")
After that you have methods like: .getContent(), .getFile(), .getPath() etc

How to add files inside temporary directory in JUnit

I found two ways to create temporary directories in JUnit.
Way 1:
#Rule
public TemporaryFolder tempDirectory = new TemporaryFolder();
#Test
public void testTempDirectory() throws Exception {
tempDirectory.newFile("test.txt");
tempDirectory.newFolder("myDirectory");
// how do I add files to myDirectory?
}
Way 2:
#Test
public void testTempDirectory() throws Exception {
File myFile = File.createTempFile("abc", "txt");
File myDirectory = Files.createTempDir();
// how do I add files to myDirectory?
}
As the comment above mentions, I have a requirement where I want to add some temporary files in these temporary directories. Run my test against this structure and finally delete everything on exit.
How do I do that?
You can do it the same way you do it for real folders.
#Rule
public TemporaryFolder rootFolder = new TemporaryFolder();
#Test
public void shouldCreateChildFile() throws Exception {
File myFolder = rootFolder.newFolder("my-folder");
File myFile = new File(myFolder, "my-file.txt");
}
Using new File(subFolderOfTemporaryFolder, "fileName") did not work for me. Calling subFolder.list() returned an empty array. This is how I made it work:
#Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
#Test
public void createFileInSubFolderOfTemporaryFolder() throws IOException {
String subFolderName = "subFolder";
File subFolder = temporaryFolder.newFolder(subFolderName);
temporaryFolder.newFile(subFolderName + File.separator + "fileName1");
String[] actual = subFolder.list();
assertFalse(actual.length == 0);
}
Using TemporaryFolder creates a directory with a common root. Once you have created a folder, you can then create a file by specifying the directory structure and the final filename as the name.
#Rule
public TemporaryFolder rootFolder = new TemporaryFolder();
#Test
public void shouldCreateChildFile() throws Exception {
File myFolder = rootFolder.newFolder("my-folder");
File myFileInMyFolder = rootFolder.newFile("/my-folder/my-file.txt");
}
You can create child directories in the same way.
There two ways to delete temp directory or temp file.Fist,delete the dirctory or file manually use file.delete() method,Second,delete the temp directory or file when program exis user file.deleteOnExist().
You can try this,I print the path to console,you can to check realy delte or not,I test on windows7 system.
File myDirectory = Files.createTempDir();
File tmpFile = new File(myDirectory.getAbsolutePath() + File.separator + "test.txt");
FileUtils.writeStringToFile(tmpFile, "HelloWorld", "UTF-8");
System.out.println(myDirectory.getAbsolutePath());
// clean
tmpFile.delete();
myDirectory.deleteOnExit();

How to get resources directory path programmatically

I have the following directory layout:
src
main
java
resources
sql (scripts for database)
spring (configuration)
webapp
Within a ServletContextListener class, I want to access the files under the SQL directory and list them. Basically my problem is with the path, because I know that listing files under a directory in a nutshell is:
File folder = new File(path);
File[] listOfFiles = folder.listFiles();
Maybe I could use the ServletContextEvent Object to try and build a path to resources/sql
public void contextInitialized(ServletContextEvent event) {
event.getServletContext(); //(getRealPath etc.)
}
Does something exist to set that path in a relative, non-hardcoded way?
Something like new File("classpath:sql") (preferably spring if possible) or what should I do with the servletContext to point at resources/sql?
I'm assuming the contents of src/main/resources/ is copied to WEB-INF/classes/ inside your .war at build time. If that is the case you can just do (substituting real values for the classname and the path being loaded).
URL sqlScriptUrl = MyServletContextListener.class
.getClassLoader().getResource("sql/script.sql");
Finally, this is what I did:
private File getFileFromURL() {
URL url = this.getClass().getClassLoader().getResource("/sql");
File file = null;
try {
file = new File(url.toURI());
} catch (URISyntaxException e) {
file = new File(url.getPath());
} finally {
return file;
}
}
...
File folder = getFileFromURL();
File[] listOfFiles = folder.listFiles();
import org.springframework.core.io.ClassPathResource;
...
File folder = new ClassPathResource("sql").getFile();
File[] listOfFiles = folder.listFiles();
It is worth noting that this will limit your deployment options, ClassPathResource.getFile() only works if the container has exploded (unzipped) your war file.
Just use com.google.common.io.Resources class. Example:
URL url = Resources.getResource("file name")
After that you have methods like: .getContent(), .getFile(), .getPath() etc

Read a file residing inside a jar being called from another jar file

I have two jar files (Lets say jar1 and jar2). There is one xml file inside a jar2. I want to read the xml file. i used
public void readXmlFile(){
InputStream resourceAsStream = MainFile.class.getResourceAsStream("/test.xml");
}
But now i am calling this function frm a class in jar1 using
File file = new File(jar2);
URL url = file.toURL();
URL[] urls = new URL[] { url };
ClassLoader cl = new URLClassLoader(urls);
Class<?> compositeClass = cl.loadClass(XmlFileReader);
Method declaredMethod = compositeClass.getDeclaredMethod("readXmlFile");
Object newInstance = compositeClass.newInstance();
declaredMethod.invoke(newInstance);
Now I am getting FileNotFoundException as the xml file is being searched in jar1 and not in jar2, I do not know why is this happening. Can anyone help me?
Th Only solution i found is to set a System property using System.setProperty(key, value) in my jar1 as the path of the folder containing my both the jars. Then i read the system property back in my jar2 and then modified my readXml method like this
public void readXmlFile(){
JarFile jarFile = new JarFile(pathToJar2);
JarEntry entry = jarFile.getJarEntry("/test.xml");
InputStream inputStream = jarFile.getInputStream(entry);}

Uploading files to a webserver java FileUpload

I'm using apache's FileUpload in order to upload some files to my webserver. Problem is I don't want to upload them to a specific location on the machine i.e : c:\tmp, but rather to a relative path such as /ProjectName/tmp/
Here's my code:
private static final long serialVersionUID = 1L;
private String TMP_DIR_PATH = "c:\\tmp";
private File tmpDir;
private static final String DESTINATION_DIR_PATH ="/files";
private File destinationDir;
public void init(ServletConfig config) throws ServletException {
super.init(config);
tmpDir = new File(TMP_DIR_PATH);
if(!tmpDir.isDirectory()) {
throw new ServletException(TMP_DIR_PATH + " is not a directory");
}
String realPath = getServletContext().getRealPath(DESTINATION_DIR_PATH);
destinationDir = new File(realPath);
if(!destinationDir.isDirectory()) {
throw new ServletException(DESTINATION_DIR_PATH+" is not a directory");
}
}
I want to change TMP_DIR_PATH so it's relative to my project, help would be appreciated!
If your actual concern is the hardcoding of the c:\\tmp part which makes the code unportable, then consider using File#createTempFile() instead. This will create the file in the platform default temp location as specified by the java.io.tmpdir system property.
File file = File.createTempFile("upload", ".tmp");
OutputStream output = new FileOutputStream(file);
// ...
If you want the temp directory to be relative to your project you'll have to use getRealPath and then make sure you create the directory if it doesn't already exist.
You can also use File dir = (File) getServletContext().getAttribute("javax.servlet.context.tempdir"); to fetch an app-specific temp directory provided by the container.

Categories

Resources