How to download libraries from JNLP file - java

I'm trying to load a specific JNLP file from a Java program and get its .jar files. I've downloaded the .pack.gz files (because it uses compressing), but now I can't unpack them. I'm trying it by using the class java.util.jar.Pack200.Unpacker, but it throws an Exception with the following information:
SEVERE: null
java.io.IOException: Corrupted pack file: magic/ver = 1F8B0800/0.0 should be CAFED00D/150.7 OR CAFED00D/160.1 OR CAFED00D/170.1 OR CAFED00D/171.0
at com.sun.java.util.jar.pack.NativeUnpack.start(Native Method)
at com.sun.java.util.jar.pack.NativeUnpack.run(NativeUnpack.java:198)
at com.sun.java.util.jar.pack.NativeUnpack.run(NativeUnpack.java:247)
at com.sun.java.util.jar.pack.UnpackerImpl.unpack(UnpackerImpl.java:138)
at com.sun.java.util.jar.pack.UnpackerImpl.unpack(UnpackerImpl.java:174)
at rmiattack.Util.loadJNLP(Util.java:186)
at rmiattack.RmiAttack.debugFunction(RmiAttack.java:50)
at rmiattack.RmiAttack.main(RmiAttack.java:74)
I've looked for that error and then I tried to unpack the file with the command "unpack200" and it works. Then I tried to find the unpack200 sources in the openjdk project, but I didn't found them. So, could anyone tell me where can I find those sources to know how to use the Unpacker class?
I'm attaching the code I'm using:
public static void loadJNLP(String file, String outDir) throws IOException, ParserConfigurationException, SAXException {
byte[] encoded = Files.readAllBytes(Paths.get(file));
Document document = stringToXML(new String(encoded, Charset.defaultCharset()), false);
System.out.println(document.getElementsByTagName("title").item(0));
String baseURL = document.getElementsByTagName("jnlp").item(0).getAttributes().getNamedItem("codebase").getTextContent();
int i;
NodeList nodeList = document.getElementsByTagName("jar");
Unpacker unpacker = Pack200.newUnpacker();
SortedMap<String,String> properties = unpacker.properties();
properties.entrySet().stream().forEach((entry) -> {
System.out.println(entry.getKey() + " - " + entry.getValue());
});
for (i = 0; i < nodeList.getLength(); i++) {
//This can be threaded
NamedNodeMap attributes = nodeList.item(i).getAttributes();
String fileName = attributes.getNamedItem("href").getTextContent().replace(".jar", "") + "__V" + attributes.getNamedItem("version").getTextContent() + ".jar.pack.gz";
File packedJar = new File(outDir + '/' + fileName); //File path to download packed jar
FileUtils.copyURLToFile(new URL(baseURL + '/' + fileName), packedJar); //Download packed jar
FileOutputStream fileOutputStream = new FileOutputStream(outDir+'/'+attributes.getNamedItem("href").getTextContent()); //Save jar without version
try (JarOutputStream jarOutputStream = new JarOutputStream(fileOutputStream)) {
unpacker.unpack(packedJar, jarOutputStream);
} finally {
fileOutputStream.close();
}
packedJar.delete();
}
System.out.println("Save to " + outDir);
}
The output before the exception is this:
[title: null]
com.sun.java.util.jar.pack.class.format.error - pass
com.sun.java.util.jar.pack.default.timezone - false
com.sun.java.util.jar.pack.disable.native - false
com.sun.java.util.jar.pack.verbose - 0
pack.class.attribute.CompilationID - RUH
pack.class.attribute.SourceID - RUH
pack.code.attribute.CharacterRangeTable - NH[PHPOHIIH]
pack.code.attribute.CoverageTable - NH[PHHII]
pack.deflate.hint - keep
pack.effort - 5
pack.keep.file.order - true
pack.modification.time - keep
pack.segment.limit - -1
pack.unknown.attribute - pass
Thanks in advance.
Edit:
Thanks to #Thorbjoern comment I've solved it. I just had to uncompress files and then unpack them. File code looks like this:
public static void loadJNLP(String file, String outDir) throws IOException, ParserConfigurationException, SAXException {
byte[] encoded = Files.readAllBytes(Paths.get(file));
Document document = stringToXML(new String(encoded, Charset.defaultCharset()), false);
System.out.println(document.getElementsByTagName("title").item(0));
String baseURL = document.getElementsByTagName("jnlp").item(0).getAttributes().getNamedItem("codebase").getTextContent();
int i;
int length;
byte[] buffer = new byte[1024];
NodeList nodeList = document.getElementsByTagName("jar");
Unpacker unpacker = Pack200.newUnpacker();
for (i = 0; i < nodeList.getLength(); i++) {
//This can be threaded
NamedNodeMap attributes = nodeList.item(i).getAttributes();
String fileName = attributes.getNamedItem("href").getTextContent().replace(".jar", "") + "__V" + attributes.getNamedItem("version").getTextContent() + ".jar";
File compressedPackedIn = new File(outDir + '/' + fileName + ".pack.gz"); //File path to download compressed packed jar
FileUtils.copyURLToFile(new URL(baseURL + '/' + fileName + ".pack.gz"), compressedPackedIn); //Download packed jar
FileOutputStream uncompressedPackedOut;
try (GZIPInputStream compressed = new GZIPInputStream(new FileInputStream(outDir + '/' + fileName + ".pack.gz"))) {
uncompressedPackedOut = new FileOutputStream(outDir + '/' + fileName + ".pack");
//http://www.mkyong.com/java/how-to-decompress-file-from-gzip-file/
while ((length = compressed.read(buffer))> 0) {
uncompressedPackedOut.write(buffer, 0, length);
}
}
uncompressedPackedOut.close();
File uncompressedPackedIn = new File(outDir + '/' + fileName + ".pack");
FileOutputStream uncompressedUnpacked = new FileOutputStream(outDir + '/' + fileName);
try (JarOutputStream jarOutputStream = new JarOutputStream(uncompressedUnpacked)) {
unpacker.unpack(uncompressedPackedIn, jarOutputStream);
} finally {
uncompressedUnpacked.close();
}
compressedPackedIn.delete();
uncompressedPackedIn.delete();
}
}

Related

Duplicate results in recursion, connected database

I have a database connected that I am retrieving and storing local files and directories in. It works properly except when I run this segment, it will duplicate some of the results and store them. I believe the issue is in the way that I am grabbing them here, but I am not sure how to remedy it.
public static void Recursion(File dir, int dirid) {
for (java.io.File file : dir.listFiles()) {
if (file.isDirectory()) {
saveDir(dir, file);
} else if (file.isFile()) {
if (dirid == 0) {
saveDir(dir, file.getParentFile());
} // Begin Recursion, File
BoFile file1 = new BoFile();
file1.setFileName(file.getName());
file1.setFileType(file.getName().substring(file.getName().lastIndexOf('.') + 1).trim());
file1.setFileSize(new Long(file.length()).doubleValue() / 1024 + "MB");
file1.setFilePath(file.getPath());
file1.setDirNameId(dirid);
FileDAO fileDAO = new FileDAOImpl();
int id = fileDAO.insertFile(file1);
logger.info("New File: " + file.getName() + " ID = " + id);
}
}
}
private static void saveDir(File dir, File file) { // // Begin Recursion, Dir
Dir directory = new Dir();
directory.setDirName(file.getName());
directory.setDirNumberofFiles(dir.listFiles().length);
directory.setDirSize(new Long(dir.length()).doubleValue() / 1024 + "MB");
directory.setDirpath(dir.getPath());
DirDAO dirDAO = new DirDAOImpl();
int id = dirDAO.insertDir(directory);
logger.info("New Directory, " + file.getName() + " ID = " + id);
Recursion(file, id);
}

Warning: You did not close a PDF Document looping when renderImageWithDPI

i want to split pdf to image file by page, but i got Warning: You did not close a PDF Document looping when renderImageWithDPI
Still have warning
UPDATE CODE :
public void splitImage(PDDocument document, File checkFile, File theDirSplit, String fileExtension, File theDir, File watermarkDirectory, int numberOfPages)
throws InvalidPasswordException, IOException {
String fileName = checkFile.getName().replace(".pdf", "");
int dpi = 300;
if (theDirSplit.list().length < numberOfPages)
{
for (int i = 0; i < numberOfPages; ++i)
{
if (i == numberOfPages)
break;
if (theDirSplit.list().length != numberOfPages)
{
File outPutFile = new File(theDirSplit + Constan.simbol + fileName + "_" + (i + 1) + "." + fileExtension);
document = PDDocument.load(checkFile);
PDFRenderer pdfRenderer = new PDFRenderer(document);
BufferedImage bImage = pdfRenderer.renderImageWithDPI(i, dpi, ImageType.RGB);
ImageIO.write(bImage, fileExtension, outPutFile);
}
// splitService.watermark(outPutFile, (i + 1), watermarkDirectory, "pdf");
}
document.close();
//System.out.println("Converted Images are saved at -> " + theDirSplit.getAbsolutePath());
}
System.out.println("Done Partial SPlit");
/*
* int i = 1; while (iterator.hasNext()) { PDDocument pd = iterator.next();
* pd.save(theDirSplit + Constan.simbol + i++ + ".pdf"); }
* System.out.println("Multiple PDF’s created");
*/
}
error looping
total warning same with number of pages...
i already try to close but not work, this process make my server java.lang.OutOfMemoryError: Java heap space
update :
else if ("pdf".equalsIgnoreCase(typeFile)) {
System.out.println(
"target file " + downloadPath + R_OBJECT_ID + Constan.simbol + R_OBJECT_ID + "." + typeFile);
//get jumlah halaman
try(PDDocument document = PDDocument.load(checkFile)){
File theDirSplit = new File(theDir.getAbsolutePath() + Constan.simbol + "splitImage");
createFolder(theDirSplit);
String fileExtension = "jpeg";
File watermarkDirectory = new File(theDir.getAbsolutePath() + Constan.simbol + "watermarkImage");
createFolder(watermarkDirectory);
// split 2 page image
if (theDirSplit.list().length <= document.getNumberOfPages()) {
try {
splitImage(document,checkFile, theDirSplit, fileExtension, theDir, watermarkDirectory, document.getNumberOfPages()/2);
} catch (IOException e) {
System.out.println("ERROR SPLIT PDF " + e.getMessage());
e.printStackTrace();
}
}
res.setTotalPages(document.getNumberOfPages());
document.close();
return new ResponseEntity<>(res, HttpStatus.OK);
}
} else {
res.setTotalPages(1);
return new ResponseEntity<>(res, HttpStatus.OK);
}
this is code to call split method....
This is somewhat lost from the question, but the cause was failing to close the documents generated by splitter.split().

How to increment the filename number if the file exists

How can I increment the filename if the file already exists?
Here's the code that I am using -
int num = 0;
String save = at.getText().toString() + ".jpg";
File file = new File(myDir, save);
if (file.exists()) {
save = at.getText().toString() + num + ".jpg";
file = new File(myDir, save);
num++;
}
This code works, but only two files are saved, like file.jpg and file2.jpg.
This problem is to always initialize num = 0, so if file exists, it saves file0.jpg and does not check whether file0.jpg exists.
So, to code work. You should check until it is available:
int num = 0;
String save = at.getText().toString() + ".jpg";
File file = new File(myDir, save);
while(file.exists()) {
save = at.getText().toString() + (num++) + ".jpg";
file = new File(myDir, save);
}
Try this:
File file = new File(myDir, at.getText().toString() + ".jpg");
for (int num = 0; file.exists(); num++) {
file = new File(myDir, at.getText().toString() + num + ".jpg");
}
// Now save/use your file here
In addition to the first answer, I made some more changes:
private File getUniqueFileName(String folderName, String searchedFilename) {
int num = 1;
String extension = getExtension(searchedFilename);
String filename = searchedFilename.substring(0, searchedFilename.lastIndexOf("."));
File file = new File(folderName, searchedFilename);
while (file.exists()) {
searchedFilename = filename + "(" + (num++) + ")" + extension;
file = new File(folderName, searchedFilename);
}
return file;
}
int i = 0;
String save = at.getText().toString();
String filename = save +".jpg";
File f = new File(filename);
while (f.exists()) {
i++;
filename =save+ Integer.toString(i)+".jpg";
f = new File(filename);
}
f.createNewFile();
You can avoid the code repetition of some of the answers here by using a do while loop
Here's an example using the newer NIO Path API introduced in Java 7
Path candidate = null;
int counter = 0;
do {
candidate = Paths.get(String.format("%s-%d",
path.toString(), ++counter));
} while (Files.exists(candidate));
Files.createFile(candidate);
Kotlin version:
private fun checkAndRenameIfExists(name: String): File {
var filename = name
val extension = "pdf"
val root = Environment.getExternalStorageDirectory().absolutePath
var file = File(root, "$filename.$extension")
var n = 0
while (file.exists()) {
n += 1
filename = "$name($n)"
file = File(root, appDirectoryName + File.separator + "$filename.$extension")
}
return file
}
Another simple logic solution to get the unique file name under a directory using Apache Commons IO using WildcardFileFilter to match the file name and get the number of exists with the given name and increment the counter.
public static String getUniqueFileName(String directory, String fileName) {
String fName = fileName.substring(0, fileName.lastIndexOf("."));
Collection<File> listFiles = FileUtils.listFiles(new File(directory), new WildcardFileFilter(fName + "*", IOCase.INSENSITIVE), DirectoryFileFilter.DIRECTORY);
if(listFiles.isEmpty()) {
return fName;
}
return fName.concat(" (" + listFiles.size() + ")");
}
This is the solution I use to handle this case. It works for folders as well as for files.
var destination = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "MyFolder")
if (!destination.exists()) {
destination.mkdirs()
} else {
val numberOfFileAlreadyExist =
destination.listFiles().filter { it.name.startsWith("MyFolder") }.size
destination = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
"MyFolder(${numberOfFileAlreadyExist + 1})"
)
destination.mkdirs()
}
Having needed to solve this problem in my own code, I took Tejas Trivedi's answer, made it work like Windows when you happen to download the same file several times.
// This function will iteratively to find a unique file name to use when given a file: example (###).txt
// More or less how Windows will save a new file when one already exists: 'example.txt' becomes 'example (1).txt'.
// if example.txt already exists
private File getUniqueFileName(File file) {
File originalFile = file;
try {
while (file.exists()) {
String newFileName = file.getName();
String baseName = newFileName.substring(0, newFileName.lastIndexOf("."));
String extension = getExtension(newFileName);
Pattern pattern = Pattern.compile("( \\(\\d+\\))\\."); // Find ' (###).' in the file name, if it exists
Matcher matcher = pattern.matcher(newFileName);
String strDigits = "";
if (matcher.find()) {
baseName = baseName.substring(0, matcher.start(0)); // Remove the (###)
strDigits = matcher.group(0); // Grab the ### we'll want to increment
strDigits = strDigits.substring(strDigits.indexOf("(") + 1, strDigits.lastIndexOf(")")); // Strip off the ' (' and ').' from the match
// Increment the found digit and convert it back to a string
int count = Integer.parseInt(strDigits);
strDigits = Integer.toString(count + 1);
} else {
strDigits = "1"; // If there is no (###) match then start with 1
}
file = new File(file.getParent() + "/" + baseName + " (" + strDigits + ")" + extension); // Put the pieces back together
}
return file;
} catch (Error e) {
return originalFile; // Just overwrite the original file at this point...
}
}
private String getExtension(String name) {
return name.substring(name.lastIndexOf("."));
}
Calling getUniqueFileName(new File('/dir/example.txt') when 'example.txt' already exists while generate a new File targeting '/dir/example (1).txt' if that too exists it'll just keep incrementing number between the parentheses until a unique file is found, if an error happens, it'll just give the original file name.
I hope this helps some one needing to generate a unique file in Java on Android or another platform.
This function returns the exact new file with an increment number for all kind of extensions.
private File getFileName(File file) {
if (file.exists()) {
String newFileName = file.getName();
String simpleName = file.getName().substring(0, newFileName.indexOf("."));
String strDigit = "";
try {
simpleName = (Integer.parseInt(simpleName) + 1 + "");
File newFile = new File(file.getParent() + "/" + simpleName + getExtension(file.getName()));
return getFileName(newFile);
}
catch (Exception e){
}
for (int i=simpleName.length()-1; i>=0; i--) {
if (!Character.isDigit(simpleName.charAt(i))) {
strDigit = simpleName.substring(i + 1);
simpleName = simpleName.substring(0, i+1);
break;
}
}
if (strDigit.length() > 0) {
simpleName = simpleName + (Integer.parseInt(strDigit) + 1);
}
else {
simpleName += "1";
}
File newFile = new File(file.getParent() + "/" + simpleName + getExtension(file.getName()));
return getFileName(newFile);
}
return file;
}
private String getExtension(String name) {
return name.substring(name.lastIndexOf("."));
}

How to rename file java ?

I'm trying to rename files in a folder. But instead all of them get deleted
File thisFolder = new File("C:\\ . . . ");
File [] filesArray = thisFolder.listFiles();
int filesArrayLength = filesArray.length;
if (filesArray != null) {
for (int i = 0; i < filesArrayLength; i++) {
filesArray[i].renameTo(new File("test" + i + ".pdf"));
}
}
What am i doing wrong ? Why do all of the files get deleted instead of renamed
As #Pshemo pointed out you might be moving the file to the current directory. Try doing this instead. This will tell it to create the file under the given parent directory:
filesArray[i].renameTo(new File(thisFolder, "test" + i + ".pdf"));//thisFolder is your parent directory
String strFilePath= "C:/Users/";
public void renameFile(String strOldFileName, String strNewFileName) {
File oldName = new File(strFilePath + "/" + strOldFileName);
File newName = new File(strFilePath + "/" + strNewFileName);
if (oldName.renameTo(newName)) {
System.out.println("renamed");
} else {
System.out.println("Error");
}
}
Code example for you to rename the List of files in a given directory as below,
Suppose C:\Test\FileToRename isthe folder, the files which are listed under that has been renamed to test1.pdf,test2.pdf... etc..
File folder = new File("\\Test\\FileToRename");
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
File f = new File("c:\\Test\\FileToRename\\"+listOfFiles[i].getName());
f.renameTo(new File("c:\\Test\\FileToRename\\"+"test"+i+".pdf"));
}
}

Data is not in the file created

I have been trying to get data in the file but somehow i am not able to get the data in file, any suggestion is highly appreciated.
File is created as per the requirement, but they are empty.I ahve been trying to fix it by trying various things but it doesnt seem to work.
public class Node {
#SuppressWarnings("unchecked")
public static void main(String[] args) {
// handling the argument and placing it in respective variables for
// further use
int fromNode = 0;
int toNode = 0;
String message = null;
int timeAfter = 0;
// Write a message to the respective node after particular time interval
// to the respective node after
// message example node 2 9 "message" 20 & i.e node x node y the message
// and
for (int i = 0; i < args.length; i++) {
fromNode = Integer.parseInt(args[0]);
toNode = Integer.parseInt(args[1]);
message = args[2];
timeAfter = Integer.parseInt(args[3]);
}
System.out.println("from Node :" + fromNode);
System.out.println("to Node :" + toNode);
System.out.println("message :" + message);
System.out.println("time after which :" + timeAfter);
// ******************************************************************
// opening and closing the file for required appending the content to
// those files
try {
String data = message;
File fileTo = new File(File.separator + "Users"
+ File.separator + "Desktop" + File.separator
+ "Files" + File.separator + "to" + toNode + ".txt");
File fileFrom = new File(File.separator + "Users"
+ File.separator + "Desktop" + File.separator
+ "Files" + File.separator + "from" + fromNode + ".txt");
// if file does not exists, then create it
if (!fileTo.exists()) {
fileTo.createNewFile();
}
if (!fileFrom.exists()) {
fileFrom.createNewFile();
}
// true = append file
FileWriter fileWritter = new FileWriter(fileTo.getName(), true);
BufferedWriter bufferWritter = new BufferedWriter(fileWritter);
bufferWritter.write(data);
bufferWritter.flush();
bufferWritter.close();
FileWriter fileWritterfrom = new FileWriter(fileFrom.getName(),
true);
// System.out.println("------>"+data);
BufferedWriter bufferWritterfrom = new BufferedWriter(
fileWritterfrom);
bufferWritterfrom.write(data);
bufferWritterfrom.flush();
bufferWritterfrom.close();
System.out.println("Files have been created");
} catch (IOException e) {
e.printStackTrace();
}
// ******************************************************************
I guess, the files were written, but not at the place you expected. The call fileTo.getName() just gives you the last component of the path. So you wrote to a file with name to<some number>.txt in the current directory.
Try to use just
FileWriter fileWritter = new FileWriter(fileTo, true);
This should write to the file at the full path.
Btw. it is not necessary to create the files first.

Categories

Resources