OPEN - issue BATCH-116: Create XML input/output source which will work directly with StAX parser

http://opensource.atlassian.com/projects/spring/browse/BATCH-116

Added additional unit tests.
This commit is contained in:
lucasward
2007-09-25 05:19:48 +00:00
parent de5af44898
commit 8b6dd1e31b
12 changed files with 474 additions and 213 deletions

View File

@@ -8,7 +8,6 @@ import javax.xml.transform.Result;
import org.springframework.batch.io.stax.ObjectToXmlSerializer;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.oxm.Marshaller;
import org.springframework.util.Assert;
import org.springframework.xml.transform.StaxResult;
/**

View File

@@ -7,21 +7,21 @@ import javax.xml.stream.XMLEventReader;
import org.springframework.batch.io.stax.FragmentDeserializer;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.oxm.Unmarshaller;
import org.springframework.oxm.UnmarshallingFailureException;
import org.springframework.oxm.XmlMappingException;
import org.springframework.util.Assert;
import org.springframework.xml.transform.StaxSource;
/**
* Delegates deserializing to Spring-WS {@link Unmarshaller}.
*
* @author Robert Kasanicky
* @authoer Lucas Ward
* @author Lucas Ward
*/
public class UnmarshallingFragmentDeserializer implements FragmentDeserializer {
private Unmarshaller unmarshaller;
public UnmarshallingFragmentDeserializer(Unmarshaller unmarshaller){
Assert.notNull(unmarshaller);
this.unmarshaller = unmarshaller;
}
@@ -30,9 +30,6 @@ public class UnmarshallingFragmentDeserializer implements FragmentDeserializer {
try {
item = unmarshaller.unmarshal(new StaxSource(eventReader));
}
catch (XmlMappingException e) {
throw new UnmarshallingFailureException("Mapping failure during unmarshalling", e);
}
catch (IOException e) {
throw new DataAccessResourceFailureException("IO error during unmarshalling", e);
}

View File

@@ -0,0 +1,58 @@
package org.springframework.batch.io.stax;
import javax.xml.namespace.NamespaceContext;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;
/**
* Delegates all functionality to the wrapped writer allowing
* subclasses to override only the methods they want to change.
*
* @author Robert Kasanicky
*/
abstract class AbstractEventWriterWrapper implements XMLEventWriter {
protected XMLEventWriter wrappedEventWriter;
public AbstractEventWriterWrapper(XMLEventWriter wrappedEventWriter) {
this.wrappedEventWriter = wrappedEventWriter;
}
public void add(XMLEvent event) throws XMLStreamException {
wrappedEventWriter.add(event);
}
public void add(XMLEventReader reader) throws XMLStreamException {
wrappedEventWriter.add(reader);
}
public void close() throws XMLStreamException {
wrappedEventWriter.close();
}
public void flush() throws XMLStreamException {
wrappedEventWriter.flush();
}
public NamespaceContext getNamespaceContext() {
return wrappedEventWriter.getNamespaceContext();
}
public String getPrefix(String uri) throws XMLStreamException {
return wrappedEventWriter.getPrefix(uri);
}
public void setDefaultNamespace(String uri) throws XMLStreamException {
wrappedEventWriter.setDefaultNamespace(uri);
}
public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
wrappedEventWriter.setNamespaceContext(context);
}
public void setPrefix(String prefix, String uri) throws XMLStreamException {
wrappedEventWriter.setPrefix(prefix, uri);
}
}

View File

@@ -1,8 +1,9 @@
package org.springframework.batch.io.stax;
import java.util.NoSuchElementException;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.XMLEvent;
import org.springframework.beans.factory.InitializingBean;
@@ -11,27 +12,26 @@ import org.springframework.util.Assert;
/**
* Class used to wrap XMLEventReader. Events from wrapped reader are stored in
* {@link EventSequence} to support transactions.
*
* @author tomas.slanina
*
* @author Tomas Slanina
* @author Robert Kasanicky
*/
class DefaultTransactionalEventReader implements TransactionalEventReader, InitializingBean {
class DefaultTransactionalEventReader extends AbstractEventReaderWrapper implements TransactionalEventReader, InitializingBean {
private EventSequence recorder = new EventSequence();
private XMLEventReader parent;
/**
* Creates instance of this class and wraps XMLEventReader.
*
*
* @param parent event reader to be wrapped.
*/
public DefaultTransactionalEventReader(XMLEventReader parent) {
setParent(parent);
public DefaultTransactionalEventReader(XMLEventReader wrappedReader) {
super(wrappedReader);
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(parent);
Assert.notNull(wrappedEventReader);
}
/**
@@ -43,178 +43,54 @@ class DefaultTransactionalEventReader implements TransactionalEventReader, Initi
/**
* Callback on transacion commit.
*
*
*/
public void onCommit() {
recorder.clear();
}
/**
* @return the parent
*/
public XMLEventReader getParent() {
return parent;
}
/**
* @param parent the parent to set
*/
public void setParent(XMLEventReader parent) {
this.parent = parent;
}
/**
* @param recorder the recorder to set
*/
public void setRecorder(EventSequence recorder) {
this.recorder = recorder;
}
/**
* Returns the xml event recorder
* @return the xml event recorder
*/
public EventSequence getRecorder() {
return recorder;
}
/**
* Frees any resources associated with this Reader. This method does not
* close the underlying input source.
*
* @throws XMLStreamException if there are errors freeing associated
* resources
*/
public void close() throws XMLStreamException {
parent.close();
}
/**
* Reads the content of a text-only element. Precondition: the current event
* is START_ELEMENT. Postcondition: The current event is the corresponding
* END_ELEMENT.
*
* @throws XMLStreamException if the current event is not a START_ELEMENT or
* if a non text element is encountered
*/
public String getElementText() throws XMLStreamException {
StringBuffer buf = new StringBuffer();
XMLEvent e = nextEvent();
if (!e.isStartElement()) {
throw new XMLStreamException(
"Precondition for readText is nextEvent().getEventType() == START_ELEMENT (got " + e.getEventType()
+ ")");
}
while (hasNext()) {
e = peek();
if (e.isStartElement()) {
throw new XMLStreamException("Unexpected Element start");
}
if (e.isCharacters()) {
buf.append(((Characters) e).getData());
}
if (e.isEndElement()) {
return buf.toString();
}
nextEvent();
}
throw new XMLStreamException("Unexpected end of Document");
}
/**
* Get the value of a feature/property from the underlying implementation
*
* @param name The name of the property
* @return The value of the property
* @throws IllegalArgumentException if the property is not supported
*/
public Object getProperty(String name) throws IllegalArgumentException {
return parent.getProperty(name);
}
/**
* Check if there are more events. Returns true if there are more events and
* false otherwise.
*
*
* @return true if the event reader has more events, false otherwise
*/
public boolean hasNext() {
return recorder.hasNext() || parent.hasNext();
return recorder.hasNext() || wrappedEventReader.hasNext();
}
/**
* Get the next XMLEvent
*
*
* @see XMLEvent
* @throws XMLStreamException if there is an error with the underlying XML.
* @throws NoSuchElementException iteration has no more elements.
*/
public XMLEvent nextEvent() throws XMLStreamException {
if (!recorder.hasNext()) {
recorder.addEvent(parent.nextEvent());
recorder.addEvent(wrappedEventReader.nextEvent());
}
return recorder.nextEvent();
}
/**
* Skips any insignificant space events until a START_ELEMENT or END_ELEMENT
* is reached. If anything other than space characters are encountered, an
* exception is thrown. This method should be used when processing
* element-only content because the parser is not able to recognize
* ignorable whitespace if the DTD is missing or not interpreted.
*
* @throws XMLStreamException if anything other than space characters are
* encountered
*/
public XMLEvent nextTag() throws XMLStreamException {
while (hasNext()) {
XMLEvent e = nextEvent();
if (e.isCharacters() && !((Characters) e).isWhiteSpace()) {
throw new XMLStreamException("Unexpected text");
}
if (e.isStartElement() || e.isEndElement()) {
return e;
}
}
throw new XMLStreamException("Unexpected end of Document");
}
/**
* Check the next XMLEvent without reading it from the stream. Returns null
* if the stream is at EOF or has no more XMLEvents. A call to peek() will
* be equal to the next return of next().
*
*
* @see XMLEvent
* @throws XMLStreamException
*/
public XMLEvent peek() throws XMLStreamException {
return (recorder.hasNext()) ? recorder.peek() : parent.peek();
return (recorder.hasNext()) ? recorder.peek() : wrappedEventReader.peek();
}
/**
* Returns the next element in the iteration. Calling this method repeatedly
* until the {@link #hasNext()} method returns false will return each
* element in the underlying collection exactly once.
*
* @return the next element in the iteration.
* @exception NoSuchElementException iteration has no more elements.
*/
public Object next() {
try {
return nextEvent();
}
catch (XMLStreamException e) {
return null;
}
}
/**
* In this implementation throws UnsupportedOperationException.
*/
public void remove() {
throw new java.lang.UnsupportedOperationException();
throw new UnsupportedOperationException();
}
}

View File

@@ -1,7 +1,5 @@
package org.springframework.batch.io.stax;
import javax.xml.namespace.NamespaceContext;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;
@@ -11,52 +9,17 @@ import javax.xml.stream.events.XMLEvent;
* but passes through everything else.
*
* @author peter.zozom
* @author Robert Kasanicky
*/
class NoStartEndDocumentStreamWriter implements XMLEventWriter {
private XMLEventWriter delegate;
class NoStartEndDocumentStreamWriter extends AbstractEventWriterWrapper {
public NoStartEndDocumentStreamWriter(XMLEventWriter delegate) {
this.delegate = delegate;
public NoStartEndDocumentStreamWriter(XMLEventWriter wrappedEventWriter) {
super(wrappedEventWriter);
}
public void add(XMLEvent event) throws XMLStreamException {
if ((!event.isStartDocument()) && (!event.isEndDocument())) {
delegate.add(event);
wrappedEventWriter.add(event);
}
}
public void add(XMLEventReader reader) throws XMLStreamException {
delegate.add(reader);
}
public void close() throws XMLStreamException {
delegate.close();
}
public void flush() throws XMLStreamException {
delegate.flush();
}
public NamespaceContext getNamespaceContext() {
return delegate.getNamespaceContext();
}
public String getPrefix(String uri) throws XMLStreamException {
return delegate.getPrefix(uri);
}
public void setDefaultNamespace(String uri) throws XMLStreamException {
delegate.setDefaultNamespace(uri);
}
public void setNamespaceContext(NamespaceContext context)
throws XMLStreamException {
delegate.setNamespaceContext(context);
}
public void setPrefix(String prefix, String uri) throws XMLStreamException {
delegate.setPrefix(prefix, uri);
}
}

View File

@@ -8,25 +8,28 @@ import org.springframework.util.Assert;
/**
* Utility methods for files used in batch processing.
*
* @author peter.zozom
*
* @author Peter Zozom
*/
public class FileUtils {
// forbids instantiation
private FileUtils() {}
/**
* Set up output file for batch processing. This method implements common logic for
* Set up output file for batch processing. This method implements common logic for
* handling output files when starting or restarting job/step.
* <p> When starting output file processing, method creates/overwrites new file.
* When restaring output file processing, method checks whether file is writable.
*
* When starting output file processing, method creates/overwrites new file.
* When restarting output file processing, method checks whether file is writable.
*
* @param file file to be set up
* @param restarted TRUE signalizes that we are restarting output file processing
* @param overwriteOutputFile If set to TRUE, output file will be overwritten
* @param overwriteOutputFile If set to TRUE, output file will be overwritten
* (this flag is ignored when processing is restart)
*
*
* @throws IllegalArgumentException when file is NULL
* @throws IllegalStateException when staring output file processing, file exists and
* flag "shouldDeleteExisting" is set to FALSE
* @throws IllegalStateException when staring output file processing, file exists and
* flag "shouldDeleteExisting" is set to FALSE
* @throws DataAccessResourceFailureException when unable to create file or file is not writable
*/
public static void setUpOutputFile(File file, boolean restarted,
@@ -37,8 +40,10 @@ public class FileUtils {
try {
if (!restarted) {
if (file.exists()) {
Assert.state(overwriteOutputFile, "File already exists: ["
+ file.getAbsolutePath() + "]");
if(!overwriteOutputFile){
throw new DataAccessResourceFailureException("File already exists: ["
+ file.getAbsolutePath() + "]");
}
file.delete();
}

View File

@@ -61,6 +61,7 @@ public class MarshallingObjectToXmlSerializerTests extends TestCase {
mockMarshaller.setThrowException(true);
try{
xmlSerializer.serializeObject(new Object());
fail("Exception expected");
}catch(DataAccessResourceFailureException ex){
//expected
}

View File

@@ -0,0 +1,91 @@
package org.springframework.batch.io.oxm;
import java.io.IOException;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessException;
import org.springframework.oxm.Unmarshaller;
/**
* Tests for {@link UnmarshallingFragmentDeserializer}
*
* @author Robert Kasanicky
*/
public class UnmarshallingFragmentDeserializerTests extends TestCase {
// object under test
private UnmarshallingFragmentDeserializer deserializer;
private XMLEventReader eventReader;
private String xml = "<root> </root>";
private Unmarshaller unmarshaller;
private MockControl unmarshallerControl = MockControl.createStrictControl(Unmarshaller.class);
protected void setUp() throws Exception {
Resource input = new ByteArrayResource(xml.getBytes());
eventReader = XMLInputFactory.newInstance().createXMLEventReader(input.getInputStream());
unmarshaller = (Unmarshaller) unmarshallerControl.getMock();
unmarshallerControl.setDefaultMatcher(MockControl.ALWAYS_MATCHER);
deserializer = new UnmarshallingFragmentDeserializer(unmarshaller);
}
/**
* Regular scenario when deserializer returns the object provided by Unmarshaller
*/
public void testSuccessfulDeserialization() throws Exception {
Object expectedResult = new Object();
unmarshaller.unmarshal(null);
unmarshallerControl.setReturnValue(expectedResult);
unmarshallerControl.replay();
Object result = deserializer.deserializeFragment(eventReader);
assertEquals(expectedResult, result);
unmarshallerControl.verify();
}
/**
* Appropriate exception rethrown in case of failure.
*/
public void testFailedDeserialization() throws Exception {
unmarshaller.unmarshal(null);
unmarshallerControl.setThrowable(new IOException());
unmarshallerControl.replay();
try {
deserializer.deserializeFragment(eventReader);
fail("Exception expected");
}
catch (DataAccessException e) {
// expected
}
unmarshallerControl.verify();
}
/**
* It makes no sense to create UnmarshallingFragmentDeserializer with null Unmarshaller,
* therefore it should cause exception.
*/
public void testExceptionOnNullUnmarshaller() {
try {
deserializer = new UnmarshallingFragmentDeserializer(null);
fail("Exception expected");
}
catch (IllegalArgumentException e) {
// expected
}
}
}

View File

@@ -32,6 +32,7 @@ public class DefaultTransactionalEventReaderTests extends TestCase {
* Rollback scenario.
*/
public void testRollback() throws Exception {
assertTrue(reader.hasNext());
reader.nextEvent(); //start document
reader.nextEvent(); //start root element
reader.nextEvent(); //whitespace
@@ -44,8 +45,22 @@ public class DefaultTransactionalEventReaderTests extends TestCase {
assertTrue(EventHelper.endElementName(reader.peek()).equals("misc1"));
reader.onRollback(); // now we should be at the last commit point
assertTrue(reader.hasNext());
assertTrue(EventHelper.startElementName(reader.nextEvent()).equals("fragment"));
reader.nextEvent();
assertTrue(EventHelper.startElementName(reader.nextEvent()).equals("misc1"));
}
/**
* Remove operation is not supported
*/
public void testRemove() {
try {
reader.remove();
fail("UnsupportedOperationException expected on calling remove()");
}
catch (UnsupportedOperationException e) {
// expected
}
}
}

View File

@@ -0,0 +1,50 @@
package org.springframework.batch.io.stax;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.events.XMLEvent;
import junit.framework.TestCase;
import org.easymock.MockControl;
/**
* Tests for {@link NoStartEndDocumentStreamWriter}
*
* @author Robert Kasanicky
*/
public class NoStartEndDocumentWriterTests extends TestCase {
// object under test
private NoStartEndDocumentStreamWriter writer;
private XMLEventWriter wrappedWriter;
private MockControl wrappedWriterControl = MockControl.createStrictControl(XMLEventWriter.class);
private XMLEventFactory eventFactory = XMLEventFactory.newInstance();
protected void setUp() throws Exception {
wrappedWriter = (XMLEventWriter) wrappedWriterControl.getMock();
writer = new NoStartEndDocumentStreamWriter(wrappedWriter);
}
/**
* StartDocument and EndDocument events are not passed to the wrapped writer.
*/
public void testNoStartEnd() throws Exception {
XMLEvent event = eventFactory.createComment("testEvent");
//mock expects only a single event
wrappedWriter.add(event);
wrappedWriterControl.setVoidCallable();
wrappedWriterControl.replay();
writer.add(eventFactory.createStartDocument());
writer.add(event);
writer.add(eventFactory.createEndDocument());
wrappedWriterControl.verify();
}
}

View File

@@ -1,6 +1,9 @@
package org.springframework.batch.io.stax;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
@@ -15,13 +18,15 @@ import javax.xml.stream.events.XMLEvent;
import junit.framework.TestCase;
import org.springframework.batch.restart.RestartData;
import org.springframework.core.io.AbstractResource;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.transaction.support.TransactionSynchronization;
/**
* Tests for {@link StaxEventReaderInputSource}.
*
*
* @author Robert Kasanicky
*/
public class StaxEventReaderInputSourceTests extends TestCase {
@@ -32,7 +37,7 @@ public class StaxEventReaderInputSourceTests extends TestCase {
// test xml input
private String xml = "<root> <fragment> <misc1/> </fragment> <misc2/> <fragment> testString </fragment> </root>";
private FragmentDeserializer deserializer = new FragmentDeserializerMock();
private FragmentDeserializer deserializer = new MockFragmentDeserializer();
private static final String FRAGMENT_ROOT_ELEMENT = "fragment";
@@ -40,15 +45,34 @@ public class StaxEventReaderInputSourceTests extends TestCase {
source = createNewInputSouce();
}
public void testAfterPropertiesSet() throws Exception{
source.afterPropertiesSet();
}
public void testAfterPropertesSetException() throws Exception{
source.setResource(null);
try{
source.afterPropertiesSet();
fail();
}catch(IllegalArgumentException ex){
//expected;
}
}
/**
* Regular usage scenario.
* InputSource should pass XML fragments to deserializer wrapped with
* StartDocument and EndDocument events.
*/
public void testFragmentWrapping() {
public void testFragmentWrapping() throws Exception {
source.afterPropertiesSet();
// see asserts in the mock deserializer
assertNotNull(source.read());
assertNotNull(source.read());
assertNull(source.read()); // there are only two fragments
source.destroy();
}
/**
@@ -95,10 +119,10 @@ public class StaxEventReaderInputSourceTests extends TestCase {
}
/**
* Rollback to last commited record.
* Rollback to last commited record.
*/
public void testRollback() {
//rollback between deserializing records
List first = (List) source.read();
source.getSynchronization().afterCompletion(TransactionSynchronization.STATUS_COMMITTED);
@@ -107,8 +131,8 @@ public class StaxEventReaderInputSourceTests extends TestCase {
source.getSynchronization().afterCompletion(TransactionSynchronization.STATUS_ROLLED_BACK);
assertEquals(second, source.read());
//rollback while deserializing record
source.getSynchronization().afterCompletion(TransactionSynchronization.STATUS_ROLLED_BACK);
source.setFragmentDeserializer(new ExceptionFragmentDeserializer());
@@ -119,7 +143,7 @@ public class StaxEventReaderInputSourceTests extends TestCase {
source.getSynchronization().afterCompletion(TransactionSynchronization.STATUS_ROLLED_BACK);
}
source.setFragmentDeserializer(deserializer);
assertEquals(second, source.read());
}
@@ -141,6 +165,45 @@ public class StaxEventReaderInputSourceTests extends TestCase {
assertEquals(NUMBER_OF_RECORDS, extractRecordCountFrom(source.getStatistics()));
}
public void testClose() throws Exception{
MockStaxEventReaderInputSource newSource = new MockStaxEventReaderInputSource();
Resource resource = new ByteArrayResource(xml.getBytes());
newSource.setResource(resource);
newSource.setFragmentRootElementName(FRAGMENT_ROOT_ELEMENT);
newSource.setFragmentDeserializer(deserializer);
Object item = newSource.read();
assertNotNull(item);
assertTrue(newSource.isOpenCalled());
newSource.destroy();
newSource.setOpenCalled(false);
//calling read again should require re-initialization because of close
item = newSource.read();
assertNotNull(item);
assertTrue(newSource.isOpenCalled());
}
public void testOpenBadIOInput(){
source.setResource(new AbstractResource(){
public String getDescription() { return null; }
public InputStream getInputStream() throws IOException {
throw new IOException();
}
});
try{
source.open();
}catch(DataAccessResourceFailureException ex){
assertTrue(ex.getCause() instanceof IOException);
}
}
private int extractRecordCountFrom(Properties statistics) {
return Integer.valueOf(
source.getStatistics().getProperty(StaxEventReaderInputSource.READ_COUNT_STATISTICS_NAME)).intValue();
@@ -163,7 +226,7 @@ public class StaxEventReaderInputSourceTests extends TestCase {
* document events for the fragment root & end tags + skips the fragment
* contents.
*/
private static class FragmentDeserializerMock implements FragmentDeserializer {
private static class MockFragmentDeserializer implements FragmentDeserializer {
/**
* A simple mapFragment implementation checking the
@@ -225,7 +288,7 @@ public class StaxEventReaderInputSourceTests extends TestCase {
/**
* Moves cursor inside the fragment body and causes rollback.
*/
private class ExceptionFragmentDeserializer implements FragmentDeserializer {
private static class ExceptionFragmentDeserializer implements FragmentDeserializer {
public Object deserializeFragment(XMLEventReader eventReader) {
eventReader.next();
@@ -234,4 +297,21 @@ public class StaxEventReaderInputSourceTests extends TestCase {
}
private class MockStaxEventReaderInputSource extends StaxEventReaderInputSource {
private boolean openCalled = false;
public void open() {
super.open();
openCalled = true;
}
public boolean isOpenCalled() {
return openCalled;
}
public void setOpenCalled(boolean openCalled) {
this.openCalled = openCalled;
}
}
}

View File

@@ -0,0 +1,126 @@
package org.springframework.batch.io.support;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.util.Assert;
import junit.framework.TestCase;
/**
* Tests for {@link FileUtils}
*
* @author Robert Kasanicky
*/
public class FileUtilsTests extends TestCase {
private File file = new File("FileUtilsTests.tmp");
/**
* No restart + file should not be overwritten => file is created if it does
* not exist, exception is thrown if it already exists
*/
public void testNoRestart() throws Exception {
FileUtils.setUpOutputFile(file, false, false);
assertTrue(file.exists());
try {
FileUtils.setUpOutputFile(file, false, false);
fail();
}
catch (Exception e) {
// expected
}
file.delete();
Assert.state(!file.exists());
FileUtils.setUpOutputFile(file, false, true);
assertTrue(file.exists());
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
writer.write("testString");
writer.close();
long size = file.length();
Assert.state(size > 0);
FileUtils.setUpOutputFile(file, false, true);
long newSize = file.length();
assertTrue(size != newSize);
assertEquals(0, newSize);
}
/**
* In case of restart, the file is supposed to exist and exception is thrown
* if it does not.
*/
public void testRestart() throws Exception {
try {
FileUtils.setUpOutputFile(file, true, false);
fail();
}
catch (DataAccessResourceFailureException e) {
// expected
}
try {
FileUtils.setUpOutputFile(file, true, true);
fail();
}
catch (DataAccessResourceFailureException e) {
// expected
}
file.createNewFile();
assertTrue(file.exists());
// with existing file there should be no trouble
FileUtils.setUpOutputFile(file, true, false);
FileUtils.setUpOutputFile(file, true, true);
}
/**
* If the directories on the file path do not exist, they should be created
*/
public void testCreateDirectoryStructure() {
File file = new File("testDirectory/testDirectory2/testFile.tmp");
File dir1 = new File("testDirectory");
File dir2 = new File("testDirectory/testDirectory2");
try {
FileUtils.setUpOutputFile(file, false, false);
assertTrue(file.exists());
assertTrue(dir1.exists());
assertTrue(dir2.exists());
}
finally {
file.delete();
dir2.delete();
dir1.delete();
}
}
public void testBadFile(){
File file = new File("#:/.out");
try{
FileUtils.setUpOutputFile(file, false, false);
fail();
}catch(DataAccessResourceFailureException ex){
assertTrue(ex.getCause() instanceof IOException);
}
}
protected void setUp() throws Exception {
Assert.state(!file.exists());
}
protected void tearDown() throws Exception {
file.delete();
}
}