Assign String-Data to a URL-Object - java

Is it possible to assign string-data to a java.net.URL?
I'm using an API who's method only accept an URL-Parameter. But i already have the content.
String content = "some text data";
URL url = createURLWithContent(content);
MyApi.handleContent( url );
the createURLWithContent()-Method should create URL-object that containing the data from content, so when URL.getContent() is called, the String (or a Stream containing the String) is returned.
I think I've seen something like this years ago.

Write the content to a file then provide a file: URL, e.g.
public static URL createURLWithContent(String content) throws IOException {
Path tempFile = Files.createTempFile("UrlContent", null);
tempFile.toFile().deleteOnExit();
Files.writeString(tempFile, content);
return tempFile.toUri().toURL();
}
This will return a URL like this:
file:/C:/path/to/temp/UrlContent5767435257817348076.tmp
If your program is long-running, you should handle the deletion of the temporary file yourself, after the API call, rather than rely on deleteOnExit().
If you don't want the content on disk, you could alternatively implement your own in-memory URLStreamHandler, and specify it when creating the URL using the URL(String protocol, String host, int port, String file, URLStreamHandler handler) constructor. This is a lot more involved and beyond the scope of this answer.

Related

parse outlook emails using outlook-message-parser library

I am trying to load emails from INBOX from remote mailbox and parse them to extract attachments and converted body in HTML format.
I use the below code snippet to parse using outlook message parser jar
ResultSuccess insertMessage(Message currentMsg) {
final OutlookMessageParser msgp = new OutlookMessageParser();
final OutlookMessage msg = parseMsg(currentMsg.getInputStream());
}
and the currentMsg is of Type javax.mail.Message
Code snippet of getting emails from server is as follows
Properties props = new Properties();
Message currentMessage;
Session session = Session.getInstance(props, null);
session.setDebug(debug);
store = session.getStore(PROTOCOL);
store.connect(host, username, password);
Message message[] = inboxfolder.getMessages();
Message copyMessage[] = new Message[1];
int n = message.length;
for (int j = 0; j < n; j++) {
currentMessage = message[j];
ResultSuccess result = insertMessage(currentMessage);
Exception details are as follows
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
org.apache.poi.poifs.filesystem.NotOLE2FileException: Invalid header signature; read 0x615F3430305F2D2D, expected 0xE11AB1A1E011CFD0 - Your file appears not to be a valid OLE2 document
at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:151)
at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:117)
at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:285)
at org.simplejavamail.outlookmessageparser.OutlookMessageParser.parseMsg(OutlookMessageParser.java:133)
at com.email.Email_Parse.loadMessages(Email_Parse.java:38)
at com.email.Email_Parse.getMessages(Email_Parse.java:116)
at com.email.Email_Parse.main(Email_Parse.java:26)
However the issue doesn't occur when I try to load emails from local disk and parse them.
Any idea on how to resolve the issue?
I suppose you're using outlook-message-parser to parse the emails stored on disk.
Messages retrieved from the mail server are not in the Outlook file format (even if the remote server is an Microsoft Exchange server or Microsoft's Outlook email service) so outlook-message-parser won't be able to parse them.
You should use the JavaMail Api to retrieve the body of the message and its attachments.
This page has a description (with a few examples) of the steps needed to read a message with attachments. Here is an excerpt :
Q: How do I read a message with an attachment and save the
attachment?
A: As described above, a message with an attachment is
represented in MIME as a multipart message. In the simple case, the
results of the Message object's getContent method will be a
MimeMultipart object. The first body part of the multipart object wil
be the main text of the message. The other body parts will be
attachments. The msgshow.java demo program shows how to traverse all
the multipart objects in a message and extract the data of each of the
body parts. The getDisposition method will give you a hint as to
whether the body part should be displayed inline or should be
considered an attachment (but note that not all mailers provide this
information). So to save the contents of a body part in a file, use
the saveFile method of MimeBodyPart.
To save the data in a body part into a file (for example), use the
getInputStream method to access the attachment content and copy the
data to a FileOutputStream. Note that when copying the data you can
not use the available method to determine how much data is in the
attachment. Instead, you must read the data until EOF. The saveFile
method of MimeBodyPart will do this for you. However, you should not
use the results of the getFileName method directly to name the file to
be saved; doing so could cause you to overwrite files unintentionally,
including system files.
Note that there are also more complicated cases to be handled as well.
For example, some mailers send the main body as both plain text and
html. This will typically appear as a multipart/alternative content
(and a MimeMultipart object) in place of a simple text body part.
Also, messages that are digitally signed or encrypted are even more
complex. Handling all these cases can be challenging. Please refer to
the various MIME specifications and other resources listed on our main
page.
Emails are not always in html, sometimes they are just plain text. Most of the time they are "multipart". For example, an email can have an html part that will be displayed by email clients that support html (gmail, thunderbird ...) and another plain text part that can be used by other email clients that can't display html (think text-based email clients).
So before dumping the content of an email you have to check its content type (or if it has multiple part, check the content type of the parts).
For the html parts, dumping the content verbatim can give you the desired result depending on how images are referenced.
If an image is referenced using an http URL (like <img src="https://example.com/a.png"/>) no further work is necessary to display the result in a browser.
If an image is referenced using a Content-Id URL (like <img src="cid:image002.gif#01D44EB0.904DB790"/>) then you have to do extra work to be able to display the result correctly in a browser.
You have to look for the correct image in the email parts and decide how to include it in the final result.
For example, save it to disk and replace the reference in the html with its path on the disk so that <img src="cid:image002.gif#01D44EB0.904DB790"/> becomes something like this <img src="/path/to/saved/images/imagexyz.png"/>
Or convert it to base64 format and replace the reference in the html with a data URI so that <img src="cid:image002.gif#01D44EB0.904DB790"/> becomes something like this <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="/>.
I don't know if there is a java library that can do this automatically.
The JavaMail api website provides samples that you can read to learn how to use it. You can check msgshow.java from the samples to see how you can use the api to retrieve the content of a message.
Here is a simple example program that downloads the last message from a gmail inbox to a local directory (it may have bugs. don't forget to put your own account and password and replace "/tmp/messages" with a valid directory on your computer).
import javax.mail.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Properties;
public class MessageDownloader {
private File destDir;
public MessageDownloader(File destDir){
this.destDir = destDir;
}
public void download(Part message, String basename) throws MessagingException, IOException {
System.out.println("Type : " + message.getContentType());
if(message.isMimeType("text/plain")) {
downloadTextPart((String) message.getContent(), basename + ".txt");
}else if(message.isMimeType("text/html")) {
downloadTextPart((String) message.getContent(), basename + ".html");
}else if(message.isMimeType("image/*") || Part.ATTACHMENT.equalsIgnoreCase(message.getDisposition())){
downloadDataPart(message, basename);
}else if(message.isMimeType("multipart/*")){
downloadMultiPart((Multipart) message.getContent(), basename);
}else{
System.out.println("Unrecognized type");
}
}
private void downloadDataPart(Part dataPart, String basename) throws IOException, MessagingException {
File dataFile = new File(destDir, basename + "_" + dataPart.getFileName());
Files.copy(dataPart.getInputStream(), dataFile.toPath());
}
private void downloadTextPart(String textContent, String filename) throws MessagingException, IOException{
File textFile = new File(destDir, filename);
Files.writeString(textFile.toPath(), textContent);
}
private void downloadMultiPart(Multipart multiPartMessage, String basename) throws MessagingException, IOException {
for(int partIdx = 0; partIdx < multiPartMessage.getCount(); partIdx++){
BodyPart part = multiPartMessage.getBodyPart(partIdx);
download(part, String.format("%s_%d_", basename, partIdx));
}
}
public static void main(String[] args) throws MessagingException, IOException {
Store store = getStore();
Folder folder = store.getFolder("Inbox");
folder.open(Folder.READ_ONLY);
MessageDownloader msgDownloader = new MessageDownloader(new File("/tmp/messages"));
Message lastMessage = folder.getMessage(folder.getMessageCount()-1);
msgDownloader.download(lastMessage, "last_message");
folder.close();
store.close();
}
private static Store getStore() throws MessagingException {
Properties props = new Properties();
props.setProperty("mail.smtp.ssl.enable", "true");
Session session = Session.getInstance(props, null);
Store store = session.getStore("imaps");
store.connect("imap.gmail.com", "account#gmail.com","password");
return store;
}
}

Transferring and saving MultipartFile instance

I have the following method, with the simple aim to store the contents of a given MultipartFile instance under a specified directory:
private void saveOnDisk(final String clientProductId, final MultipartFile image, final String parentDirectoryPath, final String fileSeparator) throws IOException
{
final File imageFile = new File(parentDirectoryPath + fileSeparator + clientProductId + image.getOriginalFilename());
image.transferTo(imageFile);
OutputStream out = new FileOutputStream(imageFile);
out. //... ? How do we proceed? OutputStream::write() requires a byte array or int as parameter
}
For what it might be worth, the MultipartFile instance is going to contain an image file which I receive on a REST API I'm building.
I've checked some SO posts such as this and this but this problem is not quite touched: I'm effectively looking to create an entirely new image file and store it on a specified location on disk: the method write() of OutputStream, given that it requires byte[] or int params, doesn't seem to be fitting my use case. Any ideas?

uploading file using Restassured

I would like to upload a file using Java and the RestAssured library. Does anyone know how i can use this library to upload a file to a field?
When using Postman, i just make the call to the endpoint and add in the Body section key=upload and value has a "Choose files" button.
How can i upload a file to a field using Restassured? I already have methods that make the body of the request and set all parameters for it, like here:
public CustomizationSetClientField(String clientId, String fieldSetName, String version, String fieldName, String name, String type, String value, String language, String role){
this.body.put("name", name);
this.body.put("type", type);
this.body.put("value", value);
this.url = Config.getByName("customization_url");
this.pathTemplate = Config.getByName("customization_set_client_field");
this.path = Utils.createPath(pathTemplate, clientId, fieldSetName, version, fieldName);
this.role = role;
}
Now this is for setting fields, but i have no idea how to use Restassured with uploads, can you please show me how?
You're probably looking for multipart file uploads. For example:
given().
multiPart("file", new File("/path/to/file")).
when().
post("/upload");
To upload a file using REST API it require 'Content-Type' as 'multipart/form-data'.
Now you need to understand with the developer that are they allowing to directly passing the file to API or need to convert the file content to Byte Array.
If require to convert into byte then you can use the below code
Map<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "multipart/form-data");
byte[] fileContent = FileUtils.readFileToByteArray(new File(filePath));
RestAssured.given().headers(headers).body(fileContent ).post(url);
else you can try directly with the code shared by Johan in another comment.

Issues writing file metadata with Java nio

I'm looking to add a custom metadata tag to any type of file using functionality from java.nio.file.Files. I have been able to read metadata correctly, but am having issues whenever I try to set metadata.
I've tried to set a custom metadata element with a plain string using Files.setAttribute with the following
Path photo = Paths.get("C:\\Users\\some\\picture\\path\\2634.jpeg");
try{
BasicFileAttributes attrs = Files.readAttributes(photo, BasicFileAttributes.class);
Files.setAttribute(photo, "user:tags", "test");
String attribute = Files.getAttribute(photo, "user:tags").toString();
System.out.println(attribute);
}
catch (IOException ioex){
ioex.printStackTrace();
}
but end up with the following error :
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.nio.ByteBuffer
if I try to cast that string to a ByteBuffer like so
Path photo = Paths.get("C:\\Users\\some\\picture\\path\\2634.jpeg");
try{
BasicFileAttributes attrs = Files.readAttributes(photo, BasicFileAttributes.class);
Files.setAttribute(photo, "user:tags", ByteBuffer.wrap(("test").getBytes("UTF-8")));
String attribute = Files.getAttribute(photo, "user:tags").toString();
System.out.println(attribute);
}
catch (IOException ioex){
ioex.printStackTrace();
}
instead of outputting the text 'test', it outputs the strange character string '[B#14e3f41'
What is the proper way to convert a String to a bytebuffer and have it be convertable back into a string, and is there a more customizable way to modify metadata on a File using java?
User defined attributes, that is any attribute defined by UserDefinedFileAttributeView (provided that your FileSystem supports them!), are readable/writable from Java as byte arrays; if a given attribute contains text content, it is then process dependent what the encoding will be for the string in question.
Now, you are using the .{get,set}Attribute() methods, which means that you have two options to write user attributes:
either using a ByteBuffer like you did; or
using a plain byte array.
What you will read out of it however is a byte array, always.
From the javadoc link above (emphasis mine):
Where dynamic access to file attributes is required, the getAttribute method may be used to read the attribute value. The attribute value is returned as a byte array (byte[]). The setAttribute method may be used to write the value of a user-defined attribute from a buffer (as if by invoking the write method), or byte array (byte[]).
So, in your case:
in order to write the attribute, obtain a byte array with the requested encoding from your string:
final Charset utf8 = StandardCharsets.UTF_8;
final String myAttrValue = "Mémé dans les orties";
final byte[] userAttributeValue = myAttrValue.getBytes(utf8);
Files.setAttribute(photo, "user:tags", userAttributeValue);
in order to read the attribute, you'll need to cast the result of .getAttribute() to a byte array, and then obtain a string out of it, again using the correct encoding:
final Charset utf8 = StandardCharsets.UTF_8;
final byte[] userAttributeValue
= (byte[]) Files.readAttribute(photo, "user:tags");
final String myAttrValue = new String(userAttributeValue, utf8);
A peek into the other solution, just in case...
As already mentioned, what you want to deal with is a UserDefinedFileAttributeView. The Files class allows you to obtain any FileAttributeView implementation using this method:
final UserDefinedFileAttributeView view
= Files.getFileAttributeView(photo, UserDefinedFileAttributeView.class);
Now, once you have this view at your disposal, you may read from, or write to, it.
For instance, here is how you would read your particular attribute; note that here we only use the attribute name, since the view (with name "user") is already there:
final Charset utf8 = StandardCharsets.UTF_8;
final int attrSize = view.size("tags");
final ByteBuffer buf = ByteBuffer.allocate(attrSize);
view.read("tags", buf);
return new String(buf.array(), utf8);
In order to write, you'll need to wrap the byte array into a ByteBuffer:
final Charset utf8 = StandardCharsets.UTF_8;
final int array = tagValue.getBytes(utf8);
final ByteBuffer buf = ByteBuffer.wrap(array);
view.write("tags", buf);
Like I said, it gives you more control, but is more involved.
Final note: as the name pretty much dictates, user defined attributes are user defined; a given attribute for this view may, or may not, exist. It is your responsibility to correctly handle errors if an attribute does not exist etc; the JDK offers no such thing as NoSuchAttributeException for this kind of scenario.

Read PDVInputStream dicomObject information on onCStoreRQ association request

I am trying to read (and then store to 3rd party local db) certain DICOM object tags "during" an incoming association request.
For accepting association requests and storing locally my dicom files i have used a modified version of dcmrcv() tool. More specifically i have overriden onCStoreRQ method like:
#Override
protected void onCStoreRQ(Association association, int pcid, DicomObject dcmReqObj,
PDVInputStream dataStream, String transferSyntaxUID,
DicomObject dcmRspObj)
throws DicomServiceException, IOException {
final String classUID = dcmReqObj.getString(Tag.AffectedSOPClassUID);
final String instanceUID = dcmReqObj.getString(Tag.AffectedSOPInstanceUID);
config = new GlobalConfig();
final File associationDir = config.getAssocDirFile();
final String prefixedFileName = instanceUID;
final String dicomFileBaseName = prefixedFileName + DICOM_FILE_EXTENSION;
File dicomFile = new File(associationDir, dicomFileBaseName);
assert !dicomFile.exists();
final BasicDicomObject fileMetaDcmObj = new BasicDicomObject();
fileMetaDcmObj.initFileMetaInformation(classUID, instanceUID, transferSyntaxUID);
final DicomOutputStream outStream = new DicomOutputStream(new BufferedOutputStream(new FileOutputStream(dicomFile), 600000));
//i would like somewhere here to extract some TAGS from incoming dicom object. By trying to do it using dataStream my dicom files
//are getting corrupted!
//System.out.println("StudyInstanceUID: " + dataStream.readDataset().getString(Tag.StudyInstanceUID));
try {
outStream.writeFileMetaInformation(fileMetaDcmObj);
dataStream.copyTo(outStream);
} finally {
outStream.close();
}
dicomFile.renameTo(new File(associationDir, dicomFileBaseName));
System.out.println("DICOM file name: " + dicomFile.getName());
}
#Override
public void associationAccepted(final AssociationAcceptEvent associationAcceptEvent) {
....
#Override
public void associationClosed(final AssociationCloseEvent associationCloseEvent) {
...
}
I would like somewhere between this code to intercept a method wich will read dataStream and will parse specific tags and store to a local database.
However wherever i try to put a piece of code that tries to manipulate (just read for start) dataStream then my dicom files get corrupted!
PDVInputStream is implementing java.io.InputStream ....
Even if i try to just put a:
System.out.println("StudyInstanceUID: " + dataStream.readDataset().getString(Tag.StudyInstanceUID));
before copying datastream to outStream ... then my dicom files are getting corrupted (1KB of size) ...
How am i supposed to use datastream in a CStoreRQ association request to extract some information?
I hope my question is clear ...
The PDVInputStream is probably a PDUDecoder class. You'll have to reset the position when using the input stream multiple times.
Maybe a better solution would be to store the DICOM object in memory and use that for both purposes. Something akin to:
DicomObject dcmobj = dataStream.readDataset();
String whatYouWant = dcmobj.get( Tag.whatever );
dcmobj.initFileMetaInformation( transferSyntaxUID );
outStream.writeDicomFile( dcmobj );

Categories