I am having xsd schema..How can I generate the xml by using this schema programmatically in java..? and it should be dynamic ,means I can give any schema.
Is there any library available to do same.?
I have alrady seen the other post also,but unfortunately it did not suit me.. please give tour ideas....???
I am not finding any approach to do same.
XPath is not a tool for generating XML. I'm afraid you're trying to accomplish your goal with the wrong tools. So, I think the answer to your question is: you can't.
Take a look at this link :
JAVA: Build XML document using XPath expressions
And go through this link under the XPath heading :
http://www.vogella.de/articles/JavaXML/article.html
I think this should help you out...:)
The following code performs validation as per your need,
and also tells you the line number where the error occurred during parsing
You will need following jars to run this code
Only code change needed is at validateSchema() method where request response args need to be replaced with a string representation of your xml and String representation of your XSD.
resolver.jar, xml-apis.jar, serializer.jar, xercesImpl.jar
import org.apache.xerces.parsers.SAXParser;
import org.apache.xerces.xni.Augmentations;
import org.apache.xerces.xni.NamespaceContext;
import org.apache.xerces.xni.XMLLocator;
import org.apache.xerces.xni.XNIException;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Performs validation on XML based on the XSD. Overrides the
* {#link SAXParser}.
*
*
*/
public class ValidateSchema extends SAXParser {
/**
* Container for current line and coloum number being parsed in the XML.
*/
private XMLLocator locator;
/**
* Default public constructor.
*/
public ValidateSchema() {
super();
}
/**
* Used for obtaining the {#link XMLLocator} locator object.
*/
#Override
public void startDocument(
XMLLocator locator, String encoding, NamespaceContext namespaceContext, Augmentations augs)
throws XNIException {
this.locator = locator;
super.startDocument(locator, encoding, namespaceContext, augs);
}
/**
* Validates the XML against the provided XSD.
*
* #param req HttpServletRequest object.
* #param resp HttpServletResponse object.
* #throws IOException
*/
public void validateSchema(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
String content = req.getParameter("data");
String selectbox = req.getParameter("selectbox");
content = content.trim();
// Convert the XML string to byte stream.
InputStream is = new ByteArrayInputStream(content.getBytes());
try {
this.setFeature(Constants.VALIDATION_PROP, true);
this.setFeature(Constants.SCHEMA_PROP, true);
this.setFeature(Constants.DYNAMIC_PROP, true);
this.setFeature(Constants.SCHEMA_CHECKING_PROP, true);
if("1".equalsIgnoreCase(selectbox)) {
this.setProperty(Constants.SCHEMA_LOC,"oem.xsd" );
} else if("2".equalsIgnoreCase(selectbox)) {
this.setProperty(Constants.SCHEMA_LOC,"carrier.xsd" );
}
Validator handler = new Validator();
this.setErrorHandler(handler);
InputSource isp = new InputSource();
isp.setByteStream(is);
isp.setEncoding("UTF-8");
this.parse(isp);
if (handler.validationError == true) {
StringBuffer errorMessage = new StringBuffer(512);
errorMessage
.append("<div style='background: #ffebe6;border: 0px solid #ffe0d7;color:#c10000;height:60px;padding: 5px;'>")
.append(Constants.INVALID_XML_DOCUMENT)
.append(" LineNo: ")
.append(handler.saxParseException.getLineNumber())
.append(" ColumnNo: ")
.append(handler.saxParseException.getColumnNumber())
.append("<br/>")
.append(handler.validationError)
.append(handler.saxParseException.getMessage())
.append("</div>");
System.out.println( errorMessage );
} else {
StringBuffer validMsg = new StringBuffer(512);
validMsg.append("<div style='background: #ebeff9;border: 0px solid #6b90da;height:60px;padding: 5px;'>")
.append(Constants.VALID_XML_DOCUMENT).append("</div>");
System.out.println( validMsg );
}
} catch (SAXException e) {
StringBuffer errorMessage = new StringBuffer(512);
errorMessage
.append("<div style='background: #ffebe6;border: 0px solid #ffe0d7;color:#c10000;height:60px;padding: 5px;'>")
.append(Constants.INVALID_XML_DOCUMENT)
.append(" LineNo: ")
.append(this.locator.getLineNumber())
.append(" ColumnNo: ")
.append(this.locator.getColumnNumber())
.append(" <br/>")
.append(e.getMessage())
.append("</div>");
System.out.println( errorMessage );
} catch (Exception e) {
StringBuffer errorMessage = new StringBuffer(512);
errorMessage
.append("<div style='background: #ffebe6;border: 1px solid #ffe0d7;color:#c10000;height:60px;padding: 5px;'>")
.append(Constants.INVALID_XML_DOCUMENT)
.append(" <br/>")
.append(e.getMessage())
.append("</div>");
System.out.println( errorMessage );
}
}
/**
* Writes back the response to client.
*
* #param msg Response message.
* #param resp HttpServletResponse object.
* #throws IOException
*/
private void responseWrite(
String msg, HttpServletResponse resp) throws IOException {
resp.setContentType("text/html");
resp.getWriter().write(msg);
}
/**
* Custom handler for Errors while parsing documents.
*/
private class Validator extends DefaultHandler {
public boolean validationError = false;
public SAXParseException saxParseException = null;
/**
* #throws SAXException
*/
#Override
public void error(SAXParseException exception) throws SAXException {
validationError = true;
saxParseException = exception;
}
/**
* #throws SAXException
*/
#Override
public void fatalError(SAXParseException exception) throws SAXException {
validationError = true;
saxParseException = exception;
}
/**
* #throws SAXException
*/
#Override
public void warning(SAXParseException exception) throws SAXException {
}
}
}
Constants.Java contains the validation properties that you need to specify
public final class Constants {
public static final String VALIDATION_PROP = "http://xml.org/sax/features/validation";
public static final String SCHEMA_PROP = "http://apache.org/xml/features/validation/schema";
public static final String DYNAMIC_PROP = "http://apache.org/xml/features/validation/dynamic";
public static final String SCHEMA_CHECKING_PROP =
"http://apache.org/xml/features/validation/schema-full-checking";
public static final String SCHEMA_LOC =
"http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation";
public static final String VALID_XML_DOCUMENT = "The above XML is valid.";
public static final String INVALID_XML_DOCUMENT = "The Document has error at:";
}
Related
Hello and thank you for reading this question:
I will explain the use case first and the approach I have tried:
I have an ArrayList which holds Courses'data and it is being created in the FrontServlet and it is being stored in the session.
I would like to convert the ArrayList to XML to show it as HTML transforming it with XSL.
Mi doubt is: how could we convert an ArrayList to XML?
I have studied how to annotate classes to transform them: https://www.mkyong.com/java/jaxb-hello-world-example/
I have used an static XML to convert it and show it: Java: Implementing Transform View pattern, to convert XML to HTML with an XSL file
I have read a good post about extending ArrayList<> to be able to transform it: Why my ArrayList is not marshalled with JAXB?
I first tried with:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* #author YonePC
*/
#XmlRootElement
public class Curso {
#XmlElement
public void setTitulo(String titulo) {
this.titulo = titulo;
}
#XmlElement
public void setAutor(String autor) {
this.autor = autor;
}
#XmlElement
public void setAsignatura(String asignatura) {
this.asignatura = asignatura;
}
#XmlElement
public void setDuracion(String duracion) {
this.duracion = duracion;
}
#XmlElement
public void setVideo(String video) {
this.video = video;
}
String titulo, autor, asignatura, duracion, video;
public Curso(String titulo, String autor, String asignatura, String duracion, String video) {
this.titulo = titulo;
this.autor = autor;
this.asignatura = asignatura;
this.duracion = duracion;
this.video = video;
}
public String getTitulo() {
return titulo;
}
public String getAutor() {
return autor;
}
public String getAsignatura() {
return asignatura;
}
public String getDuracion() {
return duracion;
}
public String getVideo() {
return video;
}
}
But I do not need the Curso class itself, I need to convert the ArrayList which stores them.
In addition, I currently stores the courses being created in the session. How could we get the session's info in a servlet? I mean, we can access them from the servlet where it has being currently created, and from JSP pages, but how do we do access into servlets?
I ask the previous question because in all the examples I found about converting Java to XML, they showed new instances and not how to convert previous stored ones.
The code I have tried:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package frontController;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.Curso;
/**
*
* #author YonePC
*/
#WebServlet(name = "CourseInfoCommand", urlPatterns = {"/CourseInfoCommand"})
public class CourseInfoCommand extends FrontCommand {
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code>
* methods.
*
* #param request servlet request
* #param response servlet response
* #throws ServletException if a servlet-specific error occurs
* #throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/**
* Handles the HTTP <code>GET</code> method.
*
* #param request servlet request
* #param response servlet response
* #throws ServletException if a servlet-specific error occurs
* #throws IOException if an I/O error occurs
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP <code>POST</code> method.
*
* #param request servlet request
* #param response servlet response
* #throws ServletException if a servlet-specific error occurs
* #throws IOException if an I/O error occurs
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
*
* #return a String containing servlet description
*/
public String getServletInfo() {
return "Short description";
}// </editor-fold>
#Override
public void process(HttpServletRequest request) {
try {
File file = new File("C:\\Users\\YonePC\\Videos\\ASAPLICACIONCURSOSPRACTICA1\\src\\java\\frontController\\Cursos.xml");
ArrayList courses = (ArrayList) session.getAttribute("cursos");
JAXBContext jaxbContext = JAXBContext.newInstance(ArrayListCourses.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.marshal(courses, file);
TransformerFactory factory = TransformerFactory.newInstance();
StreamSource xsl = new StreamSource(new File(""));
Transformer newTransformer = factory.newTransformer(xsl);
StreamSource xml = new StreamSource(new File(""));
PrintWriter writer = response.getWriter();
Result result = new StreamResult(writer);
newTransformer.transform(xml, result);
writer.println(writer.toString());
forward("/CourseInfo.jsp");
} catch (ServletException ex) {
Logger.getLogger(CourseInfoCommand.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(CourseInfoCommand.class.getName()).log(Level.SEVERE, null, ex);
} catch (TransformerConfigurationException ex) {
Logger.getLogger(CourseInfoCommand.class.getName()).log(Level.SEVERE, null, ex);
} catch (TransformerException ex) {
Logger.getLogger(CourseInfoCommand.class.getName()).log(Level.SEVERE, null, ex);
} catch (JAXBException ex) {
Logger.getLogger(CourseInfoCommand.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Thank you for your help.
You can use xstream to transform the object to xml.
Maven dependency:
<dependency>
<groupId>xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.2.2</version>
</dependency>
XMLTransformer:
public class XMLTransformer {
private XStream xstream = null;
private XMLTransformer() {
xstream = new XStream();
}
public static XMLTransformer getInstance() {
return new XMLTransformer();
}
public String toXMLString(Object object) {
return xstream.toXML(object);
}
public Object toObject(String xml) {
return (Object) xstream.fromXML(xml);
}
}
Main class
public class Main {
public static void main(String[] args) {
XMLTransformer transformer=XMLTransformer.getInstance();
Employee e1=new Employee("gati","id");
Employee e2=new Employee("gati","id");
Employee e3=new Employee("gati","id");
List<Employee> employeeList =new ArrayList<>();
employeeList.add(e1);
employeeList.add(e2);
employeeList.add(e3);
String str=transformer.toXMLString(employeeList);
System.out.println(str);
}
}
public class Employee {
private String name;
private String email;
public Employee(String name, String email) {
this.name = name;
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
I am triggering a spring batch job from my web application. CSV file to be processed will be requested by user. I am using FlatFileItemReader as reader. My job configuration for reader is as below
#Bean
#Scope("job")
public CustomFlatFileItemReader<ProducerMessage> csvReader(#Value("#{jobParameters[fileName]}") String fileName, #Value("#{jobParameters[s3SourceFolderPrefix]}") String s3SourceFolderPrefix, #Value("#{jobParameters[timeStamp]}") long timeStamp, ConfigurationService mongoConfigurationService) {
CustomFlatFileItemReader faltFileReader = new CustomFlatFileItemReader();
DefaultLineMapper<ProducerMessage> lineMapper = new DefaultLineMapper<ProducerMessage>();
lineMapper.setLineTokenizer(new DelimitedLineTokenizer());
CSVFieldMapper csvFieldMapper = new CSVFieldMapper(fileName, s3SourceFolderPrefix, timeStamp, mongoConfigurationService);
lineMapper.setFieldSetMapper(csvFieldMapper);
faltFileReader.setLineMapper(lineMapper);
faltFileReader.setResource(new FileSystemResource(fileName));
return faltFileReader;
}
I am using resource as FileSystemResource does this load the whole file in memory ?
When the CSV file is of big size ( more than 1 Gb ) step execution goes to an never ending loop. I could see the job in repository as STARTED status.
Please help.
My step configuration is :
#Bean(name = "csvFileStep")
public Step csvFileStep(StepBuilderFactory stepBuilderFactory,
ItemReader csvReader, ItemWriter writer,
#Value("${reader.chunkSize}")
int chunkSize) {
LOGGER.info("Step configuration loaded with chunk size {}", chunkSize);
return stepBuilderFactory.get("step1")
.chunk(chunkSize).reader(csvReader)
.faultTolerant()
.skip(CSVFieldMappingException.class)
//Setting the skip limit to maxValue of Int so as to skip as many mapping exceptions.
.skipLimit(Int.MaxValue())
.writer(writer)
.build();
}
My writer class :
package com.fastretailing.catalogPlatformSCMProducer.producerjob.writer.rds;
import com.fastretailing.catalogPlatformSCMProducer.model.Configuration;
import com.fastretailing.catalogPlatformSCMProducer.model.NotificationBean;
import com.fastretailing.catalogPlatformSCMProducer.model.ProducerMessage;
import com.fastretailing.catalogPlatformSCMProducer.notification.JobStatus;
import com.fastretailing.catalogPlatformSCMProducer.util.ProducerUtil;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.item.support.AbstractItemStreamItemWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* Producer Job writer for writing directly to RDS.
*/
public class RdsWriter extends AbstractItemStreamItemWriter<ProducerMessage> {
#Autowired
#Qualifier("rdsJdbcTemplate")
JdbcTemplate rdsJdbcTemplate;
#Autowired
Configuration configuration;
private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
#Override
public void write(List<? extends ProducerMessage> list) throws Exception {
for(ProducerMessage message : list){
handleRecord(message);
}
}
#Transactional
public void handleRecord(ProducerMessage message) {
try {
String pkCheckQuery = ProducerUtil.generatePrimaryKeyCheckQuery(message);
Long returnValue = null;
try {
returnValue = rdsJdbcTemplate.queryForObject(pkCheckQuery, Long.class);
} catch (EmptyResultDataAccessException e) {
LOGGER.debug("Primary key not exists in RDS table. This will insert new row");
}
if(null == returnValue || returnValue < message.getTimeStamp()){
String query = ProducerUtil.getRdsWriteQuery(message);
LOGGER.debug("Executing Query {}", query);
rdsJdbcTemplate.update(query);
JobStatus.addRowsWritten(1);
}else{
JobStatus.addRowsSkippedWriting(1);
LOGGER.debug("Skipped row due to timestamp check failure for feedName {}", message.getFeedConfigName());
}
} catch (Exception e) {
JobStatus.changeStatus(ProducerUtil.SNS_NOTIFICATION_EVENT_IN_COMPLETE);
JobStatus.addRowsSkippedWriting(1);
JobStatus.addExceptionInLogWriter(ExceptionUtils.getStackTrace(e));
LOGGER.error("Exception while writing records to RDS table. These records will be skipped from writing.", e);
}
}
}
My custom reader : ( This is same as FlatFileItemReader apart from custom exception catching in doRead method)
/*
* Copyright 2006-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fastretailing.catalogPlatformSCMProducer.producerjob.reader;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.Charset;
import com.fastretailing.catalogPlatformSCMProducer.exception.CSVFieldMappingException;
import com.fastretailing.catalogPlatformSCMProducer.notification.JobStatus;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ReaderNotOpenException;
import org.springframework.batch.item.file.*;
import org.springframework.batch.item.file.separator.RecordSeparatorPolicy;
import org.springframework.batch.item.file.separator.SimpleRecordSeparatorPolicy;
import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* Reusing Spring's FlatFileItemReader from https://github.com/spring-projects/spring-batch/blob/master/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemReader.java
*to change exception handling policy in case of mapping exceptions.
*
*/
public class CustomFlatFileItemReader<T> extends AbstractItemCountingItemStreamItemReader<T> implements
ResourceAwareItemReaderItemStream<T>, InitializingBean {
private static final Log logger = LogFactory.getLog(CustomFlatFileItemReader.class);
// default encoding for input files
public static final String DEFAULT_CHARSET = Charset.defaultCharset().name();
private RecordSeparatorPolicy recordSeparatorPolicy = new SimpleRecordSeparatorPolicy();
private Resource resource;
private BufferedReader reader;
private int lineCount = 0;
private String[] comments = new String[] { "#" };
private boolean noInput = false;
private String encoding = DEFAULT_CHARSET;
private LineMapper<T> lineMapper;
private int linesToSkip = 0;
private LineCallbackHandler skippedLinesCallback;
private boolean strict = true;
private BufferedReaderFactory bufferedReaderFactory = new DefaultBufferedReaderFactory();
public CustomFlatFileItemReader() {
setName(ClassUtils.getShortName(CustomFlatFileItemReader.class));
}
/**
* In strict mode the reader will throw an exception on
* {#link #open(org.springframework.batch.item.ExecutionContext)} if the input resource does not exist.
* #param strict <code>true</code> by default
*/
public void setStrict(boolean strict) {
this.strict = strict;
}
/**
* #param skippedLinesCallback will be called for each one of the initial skipped lines before any items are read.
*/
public void setSkippedLinesCallback(LineCallbackHandler skippedLinesCallback) {
this.skippedLinesCallback = skippedLinesCallback;
}
/**
* Public setter for the number of lines to skip at the start of a file. Can be used if the file contains a header
* without useful (column name) information, and without a comment delimiter at the beginning of the lines.
*
* #param linesToSkip the number of lines to skip
*/
public void setLinesToSkip(int linesToSkip) {
this.linesToSkip = linesToSkip;
}
/**
* Setter for line mapper. This property is required to be set.
* #param lineMapper maps line to item
*/
public void setLineMapper(LineMapper<T> lineMapper) {
this.lineMapper = lineMapper;
}
/**
* Setter for the encoding for this input source. Default value is {#link #DEFAULT_CHARSET}.
*
* #param encoding a properties object which possibly contains the encoding for this input file;
*/
public void setEncoding(String encoding) {
this.encoding = encoding;
}
/**
* Factory for the {#link BufferedReader} that will be used to extract lines from the file. The default is fine for
* plain text files, but this is a useful strategy for binary files where the standard BufferedReaader from java.io
* is limiting.
*
* #param bufferedReaderFactory the bufferedReaderFactory to set
*/
public void setBufferedReaderFactory(BufferedReaderFactory bufferedReaderFactory) {
this.bufferedReaderFactory = bufferedReaderFactory;
}
/**
* Setter for comment prefixes. Can be used to ignore header lines as well by using e.g. the first couple of column
* names as a prefix.
*
* #param comments an array of comment line prefixes.
*/
public void setComments(String[] comments) {
this.comments = new String[comments.length];
System.arraycopy(comments, 0, this.comments, 0, comments.length);
}
/**
* Public setter for the input resource.
*/
#Override
public void setResource(Resource resource) {
this.resource = resource;
}
/**
* Public setter for the recordSeparatorPolicy. Used to determine where the line endings are and do things like
* continue over a line ending if inside a quoted string.
*
* #param recordSeparatorPolicy the recordSeparatorPolicy to set
*/
public void setRecordSeparatorPolicy(RecordSeparatorPolicy recordSeparatorPolicy) {
this.recordSeparatorPolicy = recordSeparatorPolicy;
}
/**
* #return string corresponding to logical record according to
* {#link #setRecordSeparatorPolicy(RecordSeparatorPolicy)} (might span multiple lines in file).
*/
#Override
protected T doRead() throws Exception {
if (noInput) {
return null;
}
String line = readLine();
if (line == null) {
return null;
}
else {
try {
return lineMapper.mapLine(line, lineCount);
}catch (CSVFieldMappingException e){
String message = "Parsing error at line: " + lineCount + " in resource=["
+ resource.getDescription() + "], input=[" + line + "]";
logger.error(message,e);
Exception customException = new CSVFieldMappingException(message, e);
JobStatus.addExceptionInLogWriter(ExceptionUtils.getStackTrace(customException));
throw customException;
}
catch (Exception ex) {
Exception exNew = new FlatFileParseException("Parsing error at line: " + lineCount + " in resource=["
+ resource.getDescription() + "], input=[" + line + "]", ex, line, lineCount);
JobStatus.addExceptionInLogWriter(ExceptionUtils.getStackTrace(exNew));
throw exNew;
}
}
}
/**
* #return next line (skip comments).getCurrentResource
*/
private String readLine() {
if (reader == null) {
throw new ReaderNotOpenException("Reader must be open before it can be read.");
}
String line = null;
try {
line = this.reader.readLine();
if (line == null) {
return null;
}
lineCount++;
while (isComment(line)) {
line = reader.readLine();
if (line == null) {
return null;
}
lineCount++;
}
line = applyRecordSeparatorPolicy(line);
}
catch (IOException e) {
// Prevent IOException from recurring indefinitely
// if client keeps catching and re-calling
noInput = true;
throw new NonTransientFlatFileException("Unable to read from resource: [" + resource + "]", e, line,
lineCount);
}
return line;
}
private boolean isComment(String line) {
for (String prefix : comments) {
if (line.startsWith(prefix)) {
return true;
}
}
return false;
}
#Override
protected void doClose() throws Exception {
lineCount = 0;
if (reader != null) {
reader.close();
}
}
#Override
protected void doOpen() throws Exception {
Assert.notNull(resource, "Input resource must be set");
Assert.notNull(recordSeparatorPolicy, "RecordSeparatorPolicy must be set");
noInput = true;
if (!resource.exists()) {
if (strict) {
throw new IllegalStateException("Input resource must exist (reader is in 'strict' mode): " + resource);
}
logger.warn("Input resource does not exist " + resource.getDescription());
return;
}
if (!resource.isReadable()) {
if (strict) {
throw new IllegalStateException("Input resource must be readable (reader is in 'strict' mode): "
+ resource);
}
logger.warn("Input resource is not readable " + resource.getDescription());
return;
}
reader = bufferedReaderFactory.create(resource, encoding);
for (int i = 0; i < linesToSkip; i++) {
String line = readLine();
if (skippedLinesCallback != null) {
skippedLinesCallback.handleLine(line);
}
}
noInput = false;
}
#Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(lineMapper, "LineMapper is required");
}
#Override
protected void jumpToItem(int itemIndex) throws Exception {
for (int i = 0; i < itemIndex; i++) {
readLine();
}
}
private String applyRecordSeparatorPolicy(String line) throws IOException {
String record = line;
while (line != null && !recordSeparatorPolicy.isEndOfRecord(record)) {
line = this.reader.readLine();
if (line == null) {
if (StringUtils.hasText(record)) {
// A record was partially complete since it hasn't ended but
// the line is null
throw new FlatFileParseException("Unexpected end of file before record complete", record, lineCount);
}
else {
// Record has no text but it might still be post processed
// to something (skipping preProcess since that was already
// done)
break;
}
}
else {
lineCount++;
}
record = recordSeparatorPolicy.preProcess(record) + line;
}
return recordSeparatorPolicy.postProcess(record);
}
}
I am configuring the jdbcTemplate like this in my jobConfiguration class.
#Primary
#Bean(name = "mysqlDs")
#ConfigurationProperties(prefix = "datasource.sql.jobMetaDataDb")
public DataSource sqlDataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "mysql")
#Autowired
public JdbcTemplate slaveJdbcTemplate(#Qualifier("mysqlDs") DataSource mysqlDs) {
return new JdbcTemplate(mysqlDs);
}
#Bean(name = "rdsDataSource")
#ConfigurationProperties(prefix = "datasource.sql.rdsWriterDb")
public DataSource rdsDataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "rdsJdbcTemplate")
#Autowired
public JdbcTemplate rdsJdbcTemplate(#Qualifier("rdsDataSource") DataSource rdsDataSource) {
return new JdbcTemplate(rdsDataSource);
}
So my Problem is that I have to create a Singleton pattern counter for numeric name giving. For example "1", "2", "3" etc. The idea is that every time i start the application and the Server(tomcat), it gets the last number and when I upload another image it should continue from there. Lets say the last one was "43", so the the next time I start the application it should know it and put "44" for the next image upload.
I'm not that good in Java so please give me some patience :)
This is my FileUploadServlet. It handles the request from the fileUploadForm.jsp by taking the file from the submit.
package upload;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import utils.FormatChecker;
import utils.UnzipFile;
//Servlet for handling the Upload request from the Index.jsp
#MultipartConfig
public class FileUploadServlet extends HttpServlet {
// Instace of the FileUpload object
private FileUploader uploader = new FileUploader();
// Instance of the FormatChecker object
private FormatChecker checker = new FormatChecker();
// Instance of the UnzipFile object
private UnzipFile unzip = new UnzipFile();
private static final long serialVersionUID = 1L;
private static final String SAVE_FOLDER = "C:\\Users\\cuche\\Desktop\\tomcat\\apache-tomcat-7.0.47\\webapps\\files";
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.sendRedirect("error.jsp");
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String contentType;
boolean isFormatValid;
Part filePart = request.getPart("file");
contentType = filePart.getContentType();
ServletContext context = getServletContext();
String appPath = context.getRealPath("/");
String fileNameOld = getFileName(filePart);
String fileNameNew = appPath + fileNameOld;
isFormatValid = checker.check(contentType);
pleas ignore the part with the FileUnziper
if (isFormatValid == true) {
if (contentType == ("application/x-zip-compressed")) {
unzip.FileUnziper(fileNameNew, SAVE_FOLDER);
} else {
//gets the content and saves in form of a stream
InputStream fileContent = filePart.getInputStream();
//using the uploadImage method of uploader class
uploader.uploadImage(fileNameNew, fileContent);
}
try {
response.sendRedirect("result.jsp");
} catch (IOException ex) {
response.getWriter().append(ex.getLocalizedMessage());
}
} else {
response.getWriter().append("Format is wrong");
}
}
// method for removing header for proper file upload
private String getFileName(Part part) {
for (String cd : part.getHeader("content-disposition").split(";")) {
if (cd.trim().startsWith("filename")) {
String filename = cd.substring(cd.indexOf('=') + 1).trim()
.replace("\"", "");
return filename.substring(filename.lastIndexOf('/') + 1)
.substring(filename.lastIndexOf('\\') + 1); // MSIE fix.
}
}
return null;
}
}
This is my FileUploader class
package upload;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* #author Iwan Cuche
* #date:
*/
public class FileUploader {
/**
* This method reads a File
*
* #param fileName
* #param stream
*/
public void uploadImage(String fileName, InputStream stream)
throws IOException {
try {
File file = new File(fileName);
OutputStream os = new FileOutputStream(file);
int data;
while ((data = stream.read()) != -1) {
os.write(data);
}
os.flush();
os.close();
System.out.println("Uploaded file successfully saved in "
+ file.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
throw e;
}
}
}
This is my Singleton class
package utils;
public class ServerCounter {
private static ServerCounter INSTANCE = new ServerCounter();
private ServerCounter() {};
public static ServerCounter getInstance() {
return INSTANCE;
}
}
I hope someone can help me because I'm not sure how to go at it.
In ServerCounter, add
private final AtomicLong counter = new AtomicLong();
public String nextval() { return String.valueOf(counter.incrementAndGet()); }
Each time you call INSTANCE.nextval() you'll get a fresh numeric string.
Clearly, each time you restart your application, the counter will restart.
ok, first you have to persist your counter if you want to get it after tomcat shutdown. we need listener for tomcat:
package utils;
public class ContextListener implements ServletContextListener{
void contextInitialized(ServletContextEvent sce){ // we could call loadFromFile here as well
}
//will be executed at tomcat shutdown
void contextDestroyed(ServletContextEvent sce){
ServerCounter .getInstance().writeToFile();
}
}
now the singleton(like in Marko's answer:)):
package utils;
public class ServerCounter {
private static ServerCounter INSTANCE = new ServerCounter();
private final AtomicLong counter;
private ServerCounter() {
//load value from file, do you need help by it?
long value = this.loadCounterFromFile();
counter = new AtomicLong(value);
};
private long loadCounterFromFile(){
BufferedReader br = null;
try {
//no problem if there is no file, we will return 0 in this case
br = new BufferedReader(new FileReader("C:\\Test\\counter.txt"));
String line = br.readLine();
if(line != null && line.length() > 0)
return Long.parseLong(line);
return 0;
//catch all exceptionse, because we could get NumberFormatException or FileNotFound from parseLong
} catch (Exception e) {
return 0;
} finally {
try {
if (br != null)br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
public static ServerCounter getInstance() {
return INSTANCE;
}
public String nextval() { return String.valueOf(counter.incrementAndGet()); }
//will be executed by listener
public void writeToFile(){
//write the counter to file
writeToFile(counter.get());
}
private void writeToFile(long value){
try{
//you need folder c:\Test, file will be created automatically if there is no file, it will override the old file
BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\Test\\counter.txt"));
//need "" to create String
bw.write("" + value);
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
now you can use ServerCounter.getInstance.nextval() to increment the counter and get the value
last thing is, you need to put the listener to your webApplication:
<web-app>
...
<listener>
<listener-class>utils.ContextListener </listener-class>
</listener>
</web-app>
EDIT: ServerCounter was implementing ServletContextListener by mistake
EDIT2: added read/write file
I'm trying to use mime4j to parse emails, all is working fine, however I'm not able to get the file name of the attachment. Unfortunately the BodyDescriptor doesn't include this information in the content disposition, or content type fields.
I have read that the MaximalBodyDescriptor will include the filename, however I don't know how to tell the parser to return a MaximalBodyDescriptor object.
My handler is implementing the ContentHandler interface. I can't see an alternate interface which would work.
Any advice appreciated.
Here is a helper class that we use successfully to parse e-mails with their attachments.
In this approach attach.getFileName() has the filename.
package com.bitplan.smartCRM;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import org.apache.commons.io.IOUtils;
import org.apache.james.mime4j.MimeException;
import org.apache.james.mime4j.dom.Body;
import org.apache.james.mime4j.dom.Entity;
import org.apache.james.mime4j.dom.Message;
import org.apache.james.mime4j.dom.MessageBuilder;
import org.apache.james.mime4j.dom.MessageServiceFactory;
import org.apache.james.mime4j.dom.Multipart;
import org.apache.james.mime4j.dom.SingleBody;
import org.apache.james.mime4j.dom.TextBody;
import org.apache.james.mime4j.dom.address.MailboxList;
import org.apache.james.mime4j.message.MessageImpl;
import org.apache.james.mime4j.stream.Field;
import com.bitplan.restinterface.Configuration;
/**
* EMail Helper class
*
* #author wf
* #author Denis Lunev <den#mozgoweb.com>
* #see http
* ://www.mozgoweb.com/posts/how-to-parse-mime-message-using-mime4j-library
* /
*/
public class EMailHelper implements ClipboardOwner {
public static boolean debug = true;
public static Logger LOGGER = Logger
.getLogger("com.bitplan.common.EMailHelper");
private StringBuffer txtBody;
private StringBuffer htmlBody;
private ArrayList<Entity> attachments;
/**
* get a String from an input Stream
*
* #param inputStream
* #return
* #throws IOException
*/
public String fromInputStream(InputStream inputStream) throws IOException {
String result = IOUtils.toString(inputStream);
// System.out.println(result);
return result;
}
/**
* get the full Mail from a message
*
* #param message
* #return
* #throws MessagingException
* #throws IOException
*/
public String fullMail(javax.mail.Message message) throws MessagingException,
IOException {
StringBuffer sBuf = new StringBuffer();
#SuppressWarnings("unchecked")
Enumeration<javax.mail.Header> headers = message.getAllHeaders();
while (headers.hasMoreElements()) {
javax.mail.Header header = headers.nextElement();
sBuf.append(header.getName() + ": " + header.getValue() + "\n");
}
sBuf.append(fromInputStream(message.getInputStream()));
return sBuf.toString();
}
/**
* Authentication
*/
public static class Authentication {
enum AuthenticationType {
pop3, smtp
};
String host;
String user;
String password;
AuthenticationType authenticationType;
Transport mTransport;
/**
* create an Authentication from the configuration
*
* #param configuration
* #param pAuthType
*/
public Authentication(Configuration configuration,
AuthenticationType pAuthType) {
authenticationType = pAuthType;
String prefix = pAuthType.name() + ".";
// use prefix e.g. pop3.host / smtp.host
host = (String) configuration.toMap().get(prefix + "host");
user = (String) configuration.toMap().get(prefix + "user");
password = (String) configuration.toMap().get(prefix + "password");
}
/**
* authenticate for sending / receiving e-mail
*
* #throws MessagingException
*/
public Transport authenticate() throws MessagingException {
Properties lProps = new Properties();
Session session = Session.getDefaultInstance(lProps);
switch (authenticationType) {
case pop3:
Store store = session.getStore("pop3");
store.connect(host, user, password);
store.close();
return null;
case smtp:
// http://javamail.kenai.com/nonav/javadocs/com/sun/mail/smtp/package-summary.html
mTransport = session.getTransport("smtp");
mTransport.connect(host, user, password);
return mTransport;
}
return null;
}
}
/**
* send the given e-mail
*
* #param email
* #throws MessagingException
*/
public void send(EMail email, Configuration configuration)
throws MessagingException {
Authentication lAuth = new Authentication(configuration,
Authentication.AuthenticationType.pop3);
Properties lProps = System.getProperties();
lProps.put("mail.smtp.host", lAuth.host);
// WF 2004-09-18: make sure full qualified domain name is used for localhost
// the default InetAddress.getLocalHost().getHostName() might not work ...
// lProps.put("mail.smtp.localhost",java.net.InetAddress.getLocalHost().getCanonicalHostName());
Session lSession = Session.getInstance(lProps);
MimeMessage lMsg = new MimeMessage(lSession);
lMsg.setFrom(new InternetAddress(email.getFromAdr()));
lMsg.setRecipients(javax.mail.Message.RecipientType.TO,
InternetAddress.parse(email.getToAdr()));
if (email.getCC() != null)
lMsg.setRecipients(javax.mail.Message.RecipientType.CC,
InternetAddress.parse(email.getCC()));
/*
* if (bcc()!=null) lMsg.setRecipients(Message.RecipientType.BCC,
* InternetAddress.parse(bcc())); lMsg.setHeader("X-Mailer", "JavaMail");
* lMsg.setSentDate(new Date()); lMsg.setSubject(subject());
* lMsg.setText(content()); lMsg.saveChanges(); Transport
* lTransport=lAuth.authenticate(); if (lTransport!=null)
* lTransport.sendMessage(lMsg,lMsg.getAllRecipients()); } else {
* Transport.send(lMsg); }
*/
}
/**
* retrieve pop3 mail from the given host
*
* #param pop3host
* #param user
* #param password
* #throws Exception
*/
public List<EMail> retrievePop3Mail(EMailManager eMailmanager,
Configuration configuration) throws Exception {
List<EMail> result = new ArrayList<EMail>();
Properties lProps = new Properties();
Session session = Session.getDefaultInstance(lProps);
Store store = session.getStore("pop3");
File attachmentDirectory = (File) configuration.toMap().get(
"attachmentDirectory");
// get a pop3 authentication
Authentication auth = new Authentication(configuration,
Authentication.AuthenticationType.pop3);
store.connect(auth.host, auth.user, auth.password);
Folder remoteInbox = store.getFolder("INBOX");
remoteInbox.open(Folder.READ_WRITE);
javax.mail.Message message[] = remoteInbox.getMessages();
if (message.length > 0) {
// get all messages
LOGGER.log(Level.INFO, "Getting " + message.length
+ " messages from POP3 Server '" + store.getURLName() + "'");
for (int i = 0; i < message.length; i++) {
if (!message[i].isSet(Flags.Flag.DELETED)) {
EMail email = eMailmanager.create();
String mailInput = this.fullMail(message[i]);
// System.out.print(mailInput);
ByteArrayInputStream mailStream = new ByteArrayInputStream(
mailInput.getBytes());
this.parseMessage(email, mailStream, attachmentDirectory);
result.add(email);
message[i].setFlag(Flags.Flag.DELETED, true);
}
} // for
} // if
remoteInbox.close(true);
store.close();
return result;
}
/**
* parse the Message into the given EMail
*
* #param email
* #param fileName
* #param attachmentDirectory
*
* #throws Exception
*/
public void parseMessage(EMail email, String fileName,
String attachmentDirectory) throws Exception {
parseMessage(email, new File(fileName), new File(attachmentDirectory));
}
/**
* strip the brackets
*
* #param addressList
* #return
*/
public String stripBrackets(MailboxList addressList) {
String result = null;
if (addressList != null) {
result = addressList.toString();
if (result.startsWith("[") && result.endsWith("]")) {
result = result.substring(1, result.length() - 1);
}
}
return result;
}
/**
* parse the Message from the given file into the given e-mail using the given
* attachmentDirectory
*
* #param email
* #param file
* #param attachmentDirectory
* #throws Exception
*/
public void parseMessage(EMail email, File file, File attachmentDirectory)
throws Exception {
if (!file.canRead() || (!file.isFile()))
throw new IllegalArgumentException(file.getCanonicalPath()
+ " is not a readable file");
// Get stream from file
FileInputStream fis = new FileInputStream(file);
parseMessage(email, fis, attachmentDirectory);
}
/**
* parse the Message from the given file into the given e-mail using the given
* attachmentDirectory
*
* #param email
* #param emailInputStream
* #param attachmentDirectory
* #throws Exception
*/
public void parseMessage(EMail email, InputStream eMailInputStream,
File attachmentDirectory) throws Exception {
Message mimeMsg = null;
if (!attachmentDirectory.isDirectory())
throw new IllegalArgumentException(attachmentDirectory.getCanonicalPath()
+ " is not a directory");
txtBody = new StringBuffer();
htmlBody = new StringBuffer();
attachments = new ArrayList<Entity>();
Exception ex = null;
try {
// Create message with stream from file
// If you want to parse String, you can use:
// Message mimeMsg = new Message(new
// ByteArrayInputStream(mimeSource.getBytes()));
MessageServiceFactory factory = MessageServiceFactory.newInstance();
MessageBuilder msgBuilder = factory.newMessageBuilder();
try {
mimeMsg = msgBuilder.parseMessage(eMailInputStream);
} catch (Throwable th) {
LOGGER.log(Level.SEVERE,th.getClass().getName());
LOGGER.log(Level.SEVERE,th.getMessage());
}
if (mimeMsg == null) {
LOGGER.log(Level.SEVERE, "could not read mime msg:\n",
this.fromInputStream(eMailInputStream));
return;
}
// Get some standard headers
if (mimeMsg.getTo() != null)
email.setToAdr(stripBrackets(mimeMsg.getTo().flatten()));
email.setFromAdr(stripBrackets(mimeMsg.getFrom()));
email.setSubject(mimeMsg.getSubject());
email.setSendDate(mimeMsg.getDate());
email.setEMailId(mimeMsg.getMessageId());
LOGGER.log(Level.INFO, "To: " + email.getToAdr());
LOGGER.log(Level.INFO, "From: " + email.getFromAdr());
LOGGER.log(Level.INFO, "Subject: " + mimeMsg.getSubject());
// Get custom header by name
Field priorityFld = mimeMsg.getHeader().getField("X-Priority");
// If header doesn't found it returns null
if (priorityFld != null) {
// Print header value
LOGGER.log(Level.FINEST, "Priority: " + priorityFld.getBody());
}
// If message contains many parts - parse all parts
if (mimeMsg.isMultipart()) {
Multipart multipart = (Multipart) mimeMsg.getBody();
parseBodyParts(multipart);
// fix mime4j 0.7.2 behaviour to have no separate text/plain part
if (txtBody.length() == 0) {
txtBody.append(multipart.getPreamble());
}
} else {
// If it's single part message, just get text body
String text = getTxtPart(mimeMsg);
txtBody.append(text);
}
email.setContent(txtBody.toString());
// Print text and HTML bodies
if (debug) {
LOGGER.log(Level.FINEST, "Text body: " + txtBody.toString());
LOGGER.log(Level.FINEST, "Html body: " + htmlBody.toString());
}
// loop over attachments
for (Entity attach : attachments) {
writeAttachment(attach, attachmentDirectory);
}
} catch (Exception cex) {
ex = cex;
} finally {
if (eMailInputStream != null) {
try {
eMailInputStream.close();
} catch (IOException ioex2) {
ioex2.printStackTrace();
}
}
}
if (ex != null) {
throw ex;
}
}
/**
* write the given Attachment
*
* #param attach
* #param attachmentDirectory
* #throws IOException
*/
public void writeAttachment(Entity attach, File attachmentDirectory)
throws IOException {
String attName = attach.getFilename();
// Create file with specified name
if (attName == null) {
LOGGER.log(Level.WARNING, "attachment has no file name using 'attachment"
+ attach.hashCode() + "' instead");
attName = "attachment" + attach.hashCode();
}
FileOutputStream fos = new FileOutputStream(new File(attachmentDirectory,
attName));
try {
writeBody(fos, attach.getBody());
} finally {
fos.close();
}
}
/**
* write the given body to the given fileoutput stream
*
* #param fos
* #param body
* #throws IOException
*/
public void writeBody(FileOutputStream fos, Body body) throws IOException {
if (body instanceof SingleBody) {
((SingleBody) body).writeTo(fos);
} else if (body instanceof MessageImpl) {
writeBody(fos, ((MessageImpl) body).getBody());
} else {
LOGGER.log(Level.WARNING, "can't handle body of type "
+ body.getClass().getSimpleName());
}
}
/**
* This method classifies bodyPart as text, html or attached file
*
* #param multipart
* #throws IOException
*/
private void parseBodyParts(Multipart multipart) throws IOException {
// loop over the parts
for (Entity part : multipart.getBodyParts()) {
String mimeType = part.getMimeType();
if (mimeType.equals("text/plain")) {
String txt = getTxtPart(part);
txtBody.append(txt);
} else if (mimeType.equals("text/html")) {
String html = getTxtPart(part);
htmlBody.append(html);
} else if (part.getDispositionType() != null
&& !part.getDispositionType().equals("")) {
// If DispositionType is null or empty, it means that it's multipart,
// not attached file
attachments.add(part);
}
// If current part contains other, parse it again by recursion
if (part.isMultipart()) {
parseBodyParts((Multipart) part.getBody());
}
}
}
/**
*
* #param part
* #return
* #throws IOException
*/
private String getTxtPart(Entity part) throws IOException {
// Get content from body
TextBody tb = (TextBody) part.getBody();
return this.fromInputStream(tb.getInputStream());
}
/**
* Place a String on the clipboard, and make this class the owner of the
* Clipboard's contents.
*
* #param aString
*/
public void setClipboardContents(String aString) {
StringSelection stringSelection = new StringSelection(aString);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(stringSelection, this);
}
/**
* get text from the clipboard
*
* #return
* #throws Exception
*/
public String getClipboardText() throws Exception {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
String text = (String) clipboard.getData(DataFlavor.stringFlavor);
return text;
}
/**
* get Mail from clipboard
*
* #param email
* #param attachmentDirectory
* #return
* #throws Exception
*/
public boolean getMailFromClipboard(EMail email, File attachmentDirectory)
throws Exception {
String mailText = getClipboardText();
if (mailText == null)
return false;
this.parseMessage(email,
new ByteArrayInputStream(mailText.getBytes("UTF-8")),
attachmentDirectory);
return true;
}
/*
* (non-Javadoc)
*
* #see
* java.awt.datatransfer.ClipboardOwner#lostOwnership(java.awt.datatransfer
* .Clipboard, java.awt.datatransfer.Transferable)
*/
#Override
public void lostOwnership(Clipboard clipboard, Transferable contents) {
}
}
I recommand you to use Token streams.
It is quite straight forward with it.
You can locate attachment by using headers of your multipart section :
Content-Disposition:attachment; filename="toto.txt"
You must be carefull when parsing a header with it ... It can be mail headers or multipart section header....
I have a JSP file, there backend helper class to it. From the back end helper I need to send PDF file to the JSP as an attachment. How can I achieve that?
I would suggest you to use Apache Commons File Upload component. That's probably the best way rather than reinventing the wheel. ;)
Since you haven't told us if you're using any MVC framework or just plain Servlet, I'll go for the basics.
If you want to upload a file, Apache Commons File Upload is the best library that will translate your multipart/form-data encoded HttpServletRequest message and provide you with files uploaded (in InputStream format, mostly preferred).
It's up to you, the developer, to write the data back to a persistent storage of your choice.
The reverse, it's to take the file, get the appropriate MIME-Type, Content-Length (file size), and file data (InputStream, if possible) and render it back to the HttpServletResponse).
This code (fully functional and written by me) does put the file as attachment/inline.
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
/**
* #author Buhake Sindi (The Elite Gentleman)
* #since 01 September 2011
*/
public class FileServletRenderer implements ServletRenderer {
private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB
private static final String OCTECT_STREAM_MIME_TYPE = "application/octect-stream";
private String contentType = OCTECT_STREAM_MIME_TYPE;
private long contentLength;
private String contentDisposition = "inline";
private String fileName;
private InputStream inputStream;
/**
* #return the contentType
*/
public String getContentType() {
return contentType;
}
/**
* #param contentType
* the contentType to set
*/
public void setContentType(String contentType) {
this.contentType = contentType;
}
/**
* #return the contentLength
*/
public long getContentLength() {
return contentLength;
}
/**
* #param contentLength
* the contentLength to set
*/
public void setContentLength(long contentLength) {
this.contentLength = contentLength;
}
/**
* #return the contentDisposition
*/
public String getContentDisposition() {
return contentDisposition;
}
/**
* #param contentDisposition
* the contentDisposition to set
*/
public void setContentDisposition(String contentDisposition) {
this.contentDisposition = contentDisposition;
}
/**
* #return the fileName
*/
public String getFileName() {
return fileName;
}
/**
* #param fileName
* the fileName to set
*/
public void setFileName(String fileName) {
this.fileName = fileName;
}
/**
* #return the inputStream
*/
public InputStream getInputStream() {
return inputStream;
}
/**
* #param inputStream
* the inputStream to set
*/
public void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
public void setFile(File file) throws IOException {
if (file == null) {
throw new IOException("file is null.");
}
setInputStream(new BufferedInputStream(new FileInputStream(file)));
setContentLength(file.length());
}
/*
* (non-Javadoc)
*
* #see org.bfs.bayweb.util.renderer.ServletViewRenderer#render(javax.servlet.
* ServletRequest, javax.servlet.ServletResponse)
*/
public void render(ServletRequest request, ServletResponse response) throws IOException {
// TODO Auto-generated method stub
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
try {
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int inputStreamLength = 0;
int length = 0;
if (contentType == null) {
contentType = request.getServletContext().getMimeType(getFileName());
}
//We couldn't determine Content-Type
if (contentType == null) {
contentType = OCTECT_STREAM_MIME_TYPE;
}
while ((length = getInputStream().read(buffer)) > 0) {
inputStreamLength += length;
bos.write(buffer, 0, length);
}
if (inputStreamLength != getContentLength()) {
setContentLength(inputStreamLength);
}
if (response instanceof HttpServletResponse) {
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.reset();
httpResponse.setHeader("Content-Type", getContentType());
httpResponse.setHeader("Content-Length", String.valueOf(getContentLength()));
httpResponse.setHeader("Content-Disposition", "\"" + getContentDisposition() + "\""
+ ((getFileName() != null && !getFileName().isEmpty()) ? "; filename=\"" + getFileName() + "\"" : ""));
httpResponse.setHeader("Content-Type", getContentType());
}
// finally
bos.flush();
// clear
} finally {
// TODO Auto-generated catch block
close(bos);
close(getInputStream());
}
}
private void close(Closeable resource) throws IOException {
if (resource != null) {
resource.close();
}
}
}
The most important method is render(HttpServletRequest, HttpServletResponse).