Cannot run public class in one .java from another - java

I have created a basic program that takes whatever is input into two textfields and exports them to a file. I would now like to encrypt that file, and alredy have the encryptor. The problem is that I cannot call it. Here is my code for the encryptor:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.*;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.SecretKeySpec;
public class FileEncryptor {
private String algo;
private File file;
public FileEncryptor(String algo,String path) {
this.algo=algo; //setting algo
this.file=new File(path); //settong file
}
public void encrypt() throws Exception{
//opening streams
FileInputStream fis =new FileInputStream(file);
file=new File(file.getAbsolutePath());
FileOutputStream fos =new FileOutputStream(file);
//generating key
byte k[] = "HignDlPs".getBytes();
SecretKeySpec key = new SecretKeySpec(k,algo.split("/")[0]);
//creating and initialising cipher and cipher streams
Cipher encrypt = Cipher.getInstance(algo);
encrypt.init(Cipher.ENCRYPT_MODE, key);
CipherOutputStream cout=new CipherOutputStream(fos, encrypt);
byte[] buf = new byte[1024];
int read;
while((read=fis.read(buf))!=-1) //reading data
cout.write(buf,0,read); //writing encrypted data
//closing streams
fis.close();
cout.flush();
cout.close();
}
public static void main (String[] args)throws Exception {
new FileEncryptor("DES/ECB/PKCS5Padding","C:\\Users\\*******\\Desktop\\newtext").encrypt();//encrypts the current file.
}
}
Here is the section of my file creator that is failing to call this:
FileWriter fWriter = null;
BufferedWriter writer = null;
try{
fWriter = new FileWriter("C:\\Users\\*******\\Desktop\\newtext");
writer = new BufferedWriter(fWriter);
writer.write(Data);
writer.close();
f.dispose();
FileEncryptor encr = new FileEncryptor(); //problem lies here.
encr.encrypt //public void that does the encryption.
new complete(); //different .java that is working fine.
Ok, I think I have it sussed. Thank you to all those who contributed.

You didn't pass anything into your constructor when using the new operator in your file creator:
FileEncryptor encr = new FileEncryptor(); //problem lies here.
However, you did when testing it in main in FileEncryptor:
new FileEncryptor("DES/ECB/PKCS5Padding","C:\\Users\\*******\\Desktop\\newtext").encrypt();//encrypts the current file.
Pass appropriate parameters.

When you try to create your new FileEncryptor object, you have to use one of the constructors you implemented in the FileEncryptor.java file. Like this:
String anAlgo = "something";
String aPath = "something"'
FileEncryptor encr = new FileEncryptor(anAlgo, aPath);
Hope this helps.

There is only one constructor in this class which takes 2 arguments. This means that the object creation mechanism requires 2 arguments. If you need to create an object without these arguments, you can also provide a no argument constructor in addition to the 2 argument constructor like public FileEncryptor(){//Default Constructor} but then it would not make any sense since algo and path are required to perform encryption

Your public FileEncryptor(String algo,String path) have constructor with two parameter. The compiler automatically provides a no-argument, default constructor for any class which doesn't have constructors. But as soon as you declare one, you won't be able call the empty constructor using new FileEncryptor(); unless you specify it in the class context:
public class FileEncryptor {
private String algo;
private File file;
public FileEncryptor(String algo,String path) {
this.algo=algo; //setting algo
this.file=new File(path); //settong file
}
public FileEncryptor()
{
// your code here
}

You are missing the arguments for the Constructor of your FileEncryptor class.
This is your Constructor.
public FileEncryptor(String algo,String path) {
this.algo=algo; //setting algo
this.file=new File(path); //settong file
}
But you are creating an object like this.
FileEncryptor encr = new FileEncryptor(); //problem lies here.
You need to pass it the encryption algorithm name which you want to use and the path for the file which you want to encrypt.
The Cipher class gets an instance of the algorithm which you want to use for encryption.
Cipher encrypt = Cipher.getInstance(algo);
Go through the documentation of Cipher class to see what types are supported. Here is the link.
http://docs.oracle.com/javase/7/docs/api/javax/crypto/Cipher.html#getInstance%28java.lang.String%29

Related

OutputStream class is used for writing into files. How is it possible?

The below code is quoted from : http://examples.javacodegeeks.com/core-java/io/fileoutputstream/java-io-fileoutputstream-example/
Although the OutputStream is an abstract method, at the below code, OutputStream object is used for writing into the file.
Files.newOutputStream(filepath)) returns OutputStream. Then, the type of out is OutputStream, and out references OutputStream.
How can this be possible while OutputStream is an abstract class?
package com.javacodegeeks.core.io.outputstream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class FileOutputStreamExample {
private static final String OUTPUT_FILE = "C:\\Users\\nikos\\Desktop\\TestFiles\\testFile.txt";
public static void main(String[] args) {
String content = "Hello Java Code Geeks";
byte[] bytes = content.getBytes();
Path filepath = Paths.get(OUTPUT_FILE);
try ( OutputStream out = Files.newOutputStream(filepath)) {
out.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Just because the declared type is OutputStream, that doesn't mean the implementation doesn't create an instance of a concrete subclass of OutputStream. You see this all the time with interfaces. For example:
public List<String> getList() {
return new ArrayList<String>();
}
Basically you need to distinguish between the API exposed (which uses the abstract class) and the implementation (which can choose to use any subclass it wants).
So Files.newOutputStream could be implemented as:
public static OutputStream newOutputStream(Path path)
throws IOException {
return new FileOutputStream(path.toFile());
}

Referencing Files(Java) in an updater

I am writing an updater. I have this code:
package main;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.regex.Pattern;
import java.lang.*;
import static java.lang.System.out;
public class UpdaterCore
{
public static void main(String args[]) throws IOException
{
java.io.BufferedInputStream inv = new java.io.BufferedInputStream(new
java.net.URL("http://unicombox.tk/update/nv").openStream());
java.io.FileOutputStream fosv = new java.io.FileOutputStream("nv");
java.io.BufferedOutputStream boutv = new BufferedOutputStream(fosv,1024);
byte data[] = new byte[1024];
while(inv.read(data,0,1024)>=0)
{
boutv.write(data);
}
boutv.close();
inv.close();
//end version download
Scanner VersionReader= new Scanner(new File ("v")).useDelimiter(",");
int currentVersion= VersionReader.nextInt();
VersionReader.close();
Scanner NewVersionReader= new Scanner(new File ("nv")).useDelimiter(",");
int newVersion= NewVersionReader.nextInt();
NewVersionReader.close();
if (newVersion>currentVersion){
java.io.BufferedInputStream in = new java.io.BufferedInputStream(new
java.net.URL("http://unicombox.tk/update/update.zip").openStream());
java.io.FileOutputStream fos = new java.io.FileOutputStream("update.zip");
java.io.BufferedOutputStream bout = new BufferedOutputStream(fos,1024);
byte data1[] = new byte[1024];
while(in.read(data1,0,1024)>=0)
{
bout.write(data1);
}
bout.close();
in.close();
out.println("Update successfully downloaded!");
}
else{
out.println("You have the latest version!");
}
}
}
It gets the new version from a server, and then compares it to its current version. If the new version is greater than the current version, it downloads the update.
I am having one big problem. My program can never find the files "v" and "nv"!
"v" and "nv" are in the same folder as the compiled jar, yet I get a FileNotFound.
What am I doing wrong?
Get path to current directory (directory where the .jar file is placed) like this:
// import java.io.*;
// import java.net.URLDecoder;
// throws java.io.UnsupportedEncodingException
String path = UpdaterCore.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String decodedPath = URLDecoder.decode(path, "UTF-8");
System.out.println(decodedPath);
and then create File instance like this
new File (decodedPath + File.separatorChar + "v")
You are probably running the program from a different directory, one level up?
You can use getAbsolutePath() on those java.io.File-s to find out what file path are you really trying to read from.
Or just use Marek Sebera's solution, it is fine.

How to convert InputStream to virtual File

I have a method which expects the one of the input variable to be of java.io.File type but what I get is only InputStream. Also, I cannot change the signature of the method.
How can I convert the InputStream into File type with out actually writing the file on to the filesystem?
Something like this should work. Note that for simplicity, I've used a Java 7 feature (try block with closeable resource), and IOUtils from Apache commons-io. If you can't use those it'll be a little longer, but the same idea.
import org.apache.commons.io.IOUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class StreamUtil {
public static final String PREFIX = "stream2file";
public static final String SUFFIX = ".tmp";
public static File stream2file (InputStream in) throws IOException {
final File tempFile = File.createTempFile(PREFIX, SUFFIX);
tempFile.deleteOnExit();
try (FileOutputStream out = new FileOutputStream(tempFile)) {
IOUtils.copy(in, out);
}
return tempFile;
}
}
You can't. The input stream is just a generic stream of data and there is no guarantee that it actually originates from a File. If someone created an InputStream from reading a web service or just converted a String into an InputStream, there would be no way to link this to a file. So the only thing you can do is actually write data from the stream to a temporary file (e.g. using the File.createTempFile method) and feed this file into your method.
If you want to use the MultiPartFile in testing like getting a document from the resource folder -- you can use this.
import org.springframework.mock.web.MockMultipartFile;
ClassLoader classLoader = SomeClass.class.getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream(BASE_DIR + fileName);
MockMultipartFile("file", "NameOfTheFile", "multipart/form-data", inputStream);

Is there an easier way to sign an XML document in Java?

I'm trying to digitally sign an XML document using Java. I've got an implementation working with some references I've found that use various implementations in the javax.xml.crypto.dsig package.
However, my current implementation is like many of the examples I've looked at - it's rather verbose and involves using no less than 23 different API classes from the java.xml.crypto.dsig, javax.xml.transform, and java.security packages, among others. It feels like I've entered factory factory factory land, and it took me several hours just to figure out what was going on.
My question is, is there an easier way to do this? If I've got public/private key files and I want to add a <Signature/> to an XML document, is there a library out there that just lets me call something like:
OutputStream signFile(InputStream xmlFile, File privateKey)
...without all of the XMLSignatureFactory/CanonicalizationMethod/DOMSignContext craziness?
I'm not very well-versed in cryptography, and the Java-provided API seems rather daunting for developers like myself trying to become familiar with digital signing. If all of this is necessary or there's currently no friendlier API out there, that's fine and I'm willing to accept that as an answer. I'd just like to know if I'm unnecessarily taking the hard road here.
Have look at Apache XML Security. To use the package to generate and verify a signature, checkout the samples in src_samples/org/apache/xml/security/samples/signature/.
Building from the Apache Santuario CreateSignature example, the shortest thing I could come up with is this. Without the main() and its accompanying output(), it's 20 lines
import java.io.*;
import java.security.Key;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.commons.io.IOUtils;
import org.apache.xml.security.Init;
import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.transforms.Transforms;
import org.apache.xml.security.utils.Constants;
import org.apache.xml.security.utils.ElementProxy;
import org.w3c.dom.Document;
public class CreateSignature {
private static final String PRIVATE_KEY_ALIAS = "test-alias";
private static final String PRIVATE_KEY_PASS = "test";
private static final String KEY_STORE_PASS = "test";
private static final String KEY_STORE_TYPE = "JKS";
public static void main(String... unused) throws Exception {
final InputStream fileInputStream = new FileInputStream("test.xml");
try {
output(signFile(fileInputStream, new File("keystore.jks")), "signed-test.xml");
}
finally {
IOUtils.closeQuietly(fileInputStream);
}
}
public static ByteArrayOutputStream signFile(InputStream xmlFile, File privateKeyFile) throws Exception {
final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlFile);
Init.init();
ElementProxy.setDefaultPrefix(Constants.SignatureSpecNS, "");
final KeyStore keyStore = loadKeyStore(privateKeyFile);
final XMLSignature sig = new XMLSignature(doc, null, XMLSignature.ALGO_ID_SIGNATURE_RSA);
final Transforms transforms = new Transforms(doc);
transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
sig.addDocument("", transforms, Constants.ALGO_ID_DIGEST_SHA1);
final Key privateKey = keyStore.getKey(PRIVATE_KEY_ALIAS, PRIVATE_KEY_PASS.toCharArray());
final X509Certificate cert = (X509Certificate)keyStore.getCertificate(PRIVATE_KEY_ALIAS);
sig.addKeyInfo(cert);
sig.addKeyInfo(cert.getPublicKey());
sig.sign(privateKey);
doc.getDocumentElement().appendChild(sig.getElement());
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
outputStream.write(Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS).canonicalizeSubtree(doc));
return outputStream;
}
private static KeyStore loadKeyStore(File privateKeyFile) throws Exception {
final InputStream fileInputStream = new FileInputStream(privateKeyFile);
try {
final KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE);
keyStore.load(fileInputStream, KEY_STORE_PASS.toCharArray());
return keyStore;
}
finally {
IOUtils.closeQuietly(fileInputStream);
}
}
private static void output(ByteArrayOutputStream signedOutputStream, String fileName) throws IOException {
final OutputStream fileOutputStream = new FileOutputStream(fileName);
try {
fileOutputStream.write(signedOutputStream.toByteArray());
fileOutputStream.flush();
}
finally {
IOUtils.closeQuietly(fileOutputStream);
}
}
}
I looked at all of the options for signing XML files and decided to go with a non-standard approach. The standards were all way too verbose. Also, I didn't need compatibility with the standards---I just needed signatures on a block of XML.
Probably the easiest way to "sign" a block of XML is to use GPG with a detached signature.

Why am I getting a NullPointerException when trying to read a file?

I use this test to convert txt to pdf :
package convert.pdf;
//getResourceAsStream(String name) : Returns an input stream for reading the specified resource.
//toByteArray : Get the contents of an InputStream as a byte[].
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
import convert.pdf.txt.TextConversion;
public class TestConversion {
private static byte[] readFilesInBytes(String file) throws IOException {
return IOUtils.toByteArray(TestConversion.class.getResourceAsStream(file));
}
private static void writeFilesInBytes(byte[] file, String name) throws IOException {
IOUtils.write(file, new FileOutputStream(name));
}
//just change the extensions and test conversions
public static void main(String args[]) throws IOException {
ConversionToPDF algorithm = new TextConversion();
byte[] file = readFilesInBytes("/convert/pdf/text.txt");
byte[] pdf = algorithm.convertDocument(file);
writeFilesInBytes(pdf, "text.pdf");
}
}
Problem:
Exception in thread "main" java.lang.NullPointerException
at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1025)
at org.apache.commons.io.IOUtils.copy(IOUtils.java:999)
at org.apache.commons.io.IOUtils.toByteArray(IOUtils.java:218)
at convert.pdf.TestConversion.readFilesInBytes(TestConversion.java:17)
at convert.pdf.TestConversion.main(TestConversion.java:28)
I use the debugger, and the problem seems to be located here :
private static byte[] readFilesInBytes(String file) throws IOException {
return IOUtils.toByteArray(TestConversion.class.getResourceAsStream(file));
}
What is my problem?
Sounds like the resource probably doesn't exist with that name.
Are you aware that Class.getResourceAsStream() finds a resource relative to that class's package, whereas ClassLoader.getResourceAsStream() doesn't? You can use a leading forward slash in Class.getResourceAsStream() to mimic this, so
Foo.class.getResourceAsStream("/bar.png")
is roughly equivalent to
Foo.class.getClassLoader().getResourceAsStream("bar.png")
Is this actually a file (i.e. a specific file on the normal file system) that you're trying to load? If so, using FileInputStream would be a better bet. Use Class.getResourceAsStream() if it's a resource bundled in a jar file or in the classpath in some other way; use FileInputStream if it's an arbitrary file which could be anywhere in the file system.
EDIT: Another thing to be careful of, which has caused me problems before now - if this has worked on your dev box which happens to be Windows, and is now failing on a production server which happens to be Unix, check the case of the filename. The fact that different file systems handle case-sensitivity differently can be a pain...
Are you checking to see if the file exists before you pass it to readFilesInBytes()? Note that Class.getResourceAsStream() returns null if the file cannot be found. You probably want to do:
private static byte[] readFilesInBytes(String file) throws IOException {
File testFile = new File(file);
if (!testFile.exists()) {
throw new FileNotFoundException("File " + file + " does not exist");
}
return IOUtils.toByteArray(TestConversion.class.getResourceAsStream(file));
}
or better yet:
private static byte[] readFilesInBytes(String file) throws IOException {
InputStream stream = TestConversion.class.getResourceAsStream(file);
if (stream == null) {
throw new FileNotFoundException("readFilesInBytes: File " + file
+ " does not exist");
}
return IOUtils.toByteArray(stream);
}
This class reads a TXT file in the classpath and uses TextConversion to convert to PDF, then save the pdf in the file system.
Here TextConversion code :
package convert.pdf.txt;
//Conversion to PDF from text using iText.
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import convert.pdf.ConversionToPDF;
import convert.pdf.ConvertDocumentException;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;
public class TextConversion implements ConversionToPDF {
public byte[] convertDocument(byte[] documents) throws ConvertDocumentException {
try {
return this.convertInternal(documents);
} catch (DocumentException e) {
throw new ConvertDocumentException(e);
} catch (IOException e) {
throw new ConvertDocumentException(e);
}
}
private byte[] convertInternal(byte[] documents) throws DocumentException, IOException {
Document document = new Document();
ByteArrayOutputStream pdfResultBytes = new ByteArrayOutputStream();
PdfWriter.getInstance(document, pdfResultBytes);
document.open();
BufferedReader reader = new BufferedReader( new InputStreamReader( new ByteArrayInputStream(documents) ) );
String line = "";
while ((line = reader.readLine()) != null) {
if ("".equals(line.trim())) {
line = "\n"; //white line
}
Font fonteDefault = new Font(Font.COURIER, 10);
Paragraph paragraph = new Paragraph(line, fonteDefault);
document.add(paragraph);
}
reader.close();
document.close();
return pdfResultBytes.toByteArray();
}
}
And here the code to ConversionToPDF :
package convert.pdf;
// Interface implemented by the conversion algorithms.
public interface ConversionToPDF {
public byte[] convertDocument(byte[] documentToConvert) throws ConvertDocumentException;
}
I think the problem come from my file system (devbox on windows and server is Unix).
I will try to modify my classpath.
This problem may be caused by calling methods on test.txt, which can be a folder shortcut. In other words, you're calling a method on a file that doesn't exist, resulting in a NullPointerException.

Categories

Resources