KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > repo > content > RoutingContentServiceTest


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.repo.content;
18
19 import java.io.File JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.io.OutputStream JavaDoc;
22
23 import javax.transaction.RollbackException JavaDoc;
24 import javax.transaction.UserTransaction JavaDoc;
25
26 import org.alfresco.model.ContentModel;
27 import org.alfresco.repo.content.filestore.FileContentWriter;
28 import org.alfresco.repo.policy.JavaBehaviour;
29 import org.alfresco.repo.policy.PolicyComponent;
30 import org.alfresco.repo.security.authentication.AuthenticationComponent;
31 import org.alfresco.service.ServiceRegistry;
32 import org.alfresco.service.cmr.repository.ChildAssociationRef;
33 import org.alfresco.service.cmr.repository.ContentData;
34 import org.alfresco.service.cmr.repository.ContentIOException;
35 import org.alfresco.service.cmr.repository.ContentReader;
36 import org.alfresco.service.cmr.repository.ContentService;
37 import org.alfresco.service.cmr.repository.ContentWriter;
38 import org.alfresco.service.cmr.repository.NoTransformerException;
39 import org.alfresco.service.cmr.repository.NodeRef;
40 import org.alfresco.service.cmr.repository.NodeService;
41 import org.alfresco.service.cmr.repository.StoreRef;
42 import org.alfresco.service.namespace.NamespaceService;
43 import org.alfresco.service.namespace.QName;
44 import org.alfresco.service.transaction.TransactionService;
45 import org.alfresco.util.BaseSpringTest;
46 import org.alfresco.util.GUID;
47 import org.alfresco.util.PropertyMap;
48 import org.alfresco.util.TempFileProvider;
49
50 /**
51  * @see org.alfresco.repo.content.RoutingContentService
52  *
53  * @author Derek Hulley
54  */

55 public class RoutingContentServiceTest extends BaseSpringTest
56 {
57     private static final String JavaDoc SOME_CONTENT = "ABC";
58         
59     private static final String JavaDoc TEST_NAMESPACE = "http://www.alfresco.org/test/RoutingContentServiceTest";
60     
61     private ContentService contentService;
62     private PolicyComponent policyComponent;
63     private NodeService nodeService;
64     private NodeRef rootNodeRef;
65     private NodeRef contentNodeRef;
66     private AuthenticationComponent authenticationComponent;
67     
68     public RoutingContentServiceTest()
69     {
70     }
71     
72     @Override JavaDoc
73     public void onSetUpInTransaction() throws Exception JavaDoc
74     {
75         super.onSetUpInTransaction();
76         nodeService = (NodeService) applicationContext.getBean("dbNodeService");
77         contentService = (ContentService) applicationContext.getBean(ServiceRegistry.CONTENT_SERVICE.getLocalName());
78         this.policyComponent = (PolicyComponent)this.applicationContext.getBean("policyComponent");
79         this.authenticationComponent = (AuthenticationComponent)this.applicationContext.getBean("authenticationComponent");
80         
81         this.authenticationComponent.setSystemUserAsCurrentUser();
82         // create a store and get the root node
83
StoreRef storeRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, getName());
84         if (!nodeService.exists(storeRef))
85         {
86             storeRef = nodeService.createStore(storeRef.getProtocol(), storeRef.getIdentifier());
87         }
88         rootNodeRef = nodeService.getRootNode(storeRef);
89         // create a content node
90
ContentData contentData = new ContentData(null, "text/plain", 0L, "UTF-16");
91         
92         PropertyMap properties = new PropertyMap();
93         properties.put(ContentModel.PROP_CONTENT, contentData);
94         
95         ChildAssociationRef assocRef = nodeService.createNode(
96                 rootNodeRef,
97                 ContentModel.ASSOC_CHILDREN,
98                 QName.createQName(TEST_NAMESPACE, GUID.generate()),
99                 ContentModel.TYPE_CONTENT,
100                 properties);
101         contentNodeRef = assocRef.getChildRef();
102     }
103     
104     @Override JavaDoc
105     protected void onTearDownInTransaction() throws Exception JavaDoc
106     {
107         try
108         {
109             authenticationComponent.clearCurrentSecurityContext();
110         }
111         catch (Throwable JavaDoc e)
112         {
113             // ignore
114
}
115         super.onTearDownInTransaction();
116     }
117     
118     private UserTransaction JavaDoc getUserTransaction()
119     {
120         TransactionService transactionService = (TransactionService)applicationContext.getBean("transactionComponent");
121         return (UserTransaction JavaDoc) transactionService.getUserTransaction();
122     }
123     
124     public void testSetUp() throws Exception JavaDoc
125     {
126         assertNotNull(contentService);
127         assertNotNull(nodeService);
128         assertNotNull(rootNodeRef);
129         assertNotNull(contentNodeRef);
130         assertNotNull(getUserTransaction());
131         assertFalse(getUserTransaction() == getUserTransaction()); // ensure txn instances aren't shared
132
}
133     
134     /**
135      * Checks that the URL, mimetype and encoding are automatically set on the readers
136      * and writers
137      */

138     public void testAutoSettingOfProperties() throws Exception JavaDoc
139     {
140         // get a writer onto the node
141
ContentWriter writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true);
142         assertNotNull("Writer should not be null", writer);
143         assertNotNull("Content URL should not be null", writer.getContentUrl());
144         assertNotNull("Content mimetype should not be null", writer.getMimetype());
145         assertNotNull("Content encoding should not be null", writer.getEncoding());
146         
147         // write some content
148
writer.putContent(SOME_CONTENT);
149         
150         // get the reader
151
ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
152         assertNotNull("Reader should not be null", reader);
153         assertNotNull("Content URL should not be null", reader.getContentUrl());
154         assertNotNull("Content mimetype should not be null", reader.getMimetype());
155         assertNotNull("Content encoding should not be null", reader.getEncoding());
156         
157         // check that the content length is correct
158
// - note encoding is important as we get the byte length
159
long length = SOME_CONTENT.getBytes(reader.getEncoding()).length; // ensures correct decoding
160
long checkLength = reader.getSize();
161         assertEquals("Content length incorrect", length, checkLength);
162
163         // check the content - the encoding will come into effect here
164
String JavaDoc contentCheck = reader.getContentString();
165         assertEquals("Content incorrect", SOME_CONTENT, contentCheck);
166     }
167     
168     public void testWriteToNodeWithoutAnyContentProperties() throws Exception JavaDoc
169     {
170         // previously, the node was populated with the mimetype, etc
171
// check that the write has these
172
ContentWriter writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true);
173         assertNotNull(writer.getMimetype());
174         assertNotNull(writer.getEncoding());
175
176         // now remove the content property from the node
177
nodeService.setProperty(contentNodeRef, ContentModel.PROP_CONTENT, null);
178         
179         writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true);
180         assertNull(writer.getMimetype());
181         assertEquals("UTF-8", writer.getEncoding());
182         
183         // now set it on the writer
184
writer.setMimetype("text/plain");
185         writer.setEncoding("UTF-8");
186         
187         String JavaDoc content = "The quick brown fox ...";
188         writer.putContent(content);
189         
190         // the properties should have found their way onto the node
191
ContentData contentData = (ContentData) nodeService.getProperty(contentNodeRef, ContentModel.PROP_CONTENT);
192         assertEquals("metadata didn't get onto node", writer.getContentData(), contentData);
193         
194         // check that the reader's metadata is set
195
ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
196         assertEquals("Metadata didn't get set on reader", writer.getContentData(), reader.getContentData());
197     }
198     
199     public void testNullReaderForNullUrl() throws Exception JavaDoc
200     {
201         // set the property, but with a null URL
202
ContentData contentData = new ContentData(null, null, 0L, null);
203         nodeService.setProperty(contentNodeRef, ContentModel.PROP_CONTENT, contentData);
204
205         // get the reader
206
ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
207         assertNull("Reader must be null if the content URL is null", reader);
208     }
209     
210     /**
211      * Checks what happens when the physical content disappears
212      */

213     public void testMissingContent() throws Exception JavaDoc
214     {
215         File JavaDoc tempFile = TempFileProvider.createTempFile(getName(), ".txt");
216         
217         ContentWriter writer = new FileContentWriter(tempFile);
218         writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
219         writer.setEncoding("UTF-8");
220         writer.putContent("What about the others? Buckwheats!");
221         // check
222
assertTrue("File does not exist", tempFile.exists());
223         assertTrue("File not written to", tempFile.length() > 0);
224         
225         // update the node with this new info
226
ContentData contentData = writer.getContentData();
227         nodeService.setProperty(contentNodeRef, ContentModel.PROP_CONTENT, contentData);
228         
229         // delete the content
230
tempFile.delete();
231         assertFalse("File not deleted", tempFile.exists());
232         
233         // now attempt to get the reader for the node
234
ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
235         assertFalse("Reader should indicate that content is missing", reader.exists());
236         
237         // check the indexing doesn't spank everthing
238
setComplete();
239         endTransaction();
240     }
241     
242     /**
243      * Tests simple writes that don't automatically update the node content URL
244      */

245     public void testSimpleWrite() throws Exception JavaDoc
246     {
247         // get a writer to an arbitrary node
248
ContentWriter writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, false); // no updating of URL
249
assertNotNull("Writer should not be null", writer);
250         
251         // put some content
252
writer.putContent(SOME_CONTENT);
253         
254         // get the reader for the node
255
ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
256         assertNull("No reader should yet be available for the node", reader);
257     }
258     
259     private boolean policyFired = false;
260     private boolean readPolicyFired = false;
261     private boolean newContent = true;
262     
263     /**
264      * Tests that the content update policy firs correctly
265      */

266     public void testOnContentUpdatePolicy()
267     {
268         // Register interest in the content update event for a versionable node
269
this.policyComponent.bindClassBehaviour(
270                 QName.createQName(NamespaceService.ALFRESCO_URI, "onContentUpdate"),
271                 ContentModel.ASPECT_VERSIONABLE,
272                 new JavaBehaviour(this, "onContentUpdateBehaviourTest"));
273         
274         // First check that the policy is not fired when the versionable aspect is not present
275
ContentWriter contentWriter = this.contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true);
276         contentWriter.putContent("content update one");
277         assertFalse(this.policyFired);
278         
279         this.newContent = false;
280         
281         // Now check that the policy is fired when the versionable aspect is present
282
this.nodeService.addAspect(this.contentNodeRef, ContentModel.ASPECT_VERSIONABLE, null);
283         ContentWriter contentWriter2 = this.contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true);
284         contentWriter2.putContent("content update two");
285         assertTrue(this.policyFired);
286         this.policyFired = false;
287         
288         // Check that the policy is not fired when using a non updating content writer
289
ContentWriter contentWriter3 = this.contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, false);
290         contentWriter3.putContent("content update three");
291         assertFalse(this.policyFired);
292     }
293     
294     public void onContentUpdateBehaviourTest(NodeRef nodeRef, boolean newContent)
295     {
296         assertEquals(this.contentNodeRef, nodeRef);
297         assertEquals(this.newContent, newContent);
298         assertTrue(this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE));
299         this.policyFired = true;
300     }
301     
302     public void testOnContentReadPolicy()
303     {
304         // Register interest in the content read event for a versionable node
305
this.policyComponent.bindClassBehaviour(
306                 QName.createQName(NamespaceService.ALFRESCO_URI, "onContentRead"),
307                 ContentModel.ASPECT_VERSIONABLE,
308                 new JavaBehaviour(this, "onContentReadBehaviourTest"));
309         
310         // First check that the policy is not fired when the versionable aspect is not present
311
this.contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
312         assertFalse(this.readPolicyFired);
313         
314         // Write some content and check that the policy is still not fired
315
ContentWriter contentWriter2 = this.contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true);
316         contentWriter2.putContent("content update two");
317         this.contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
318         assertFalse(this.readPolicyFired);
319         
320         // Now check that the policy is fired when the versionable aspect is present
321
this.nodeService.addAspect(this.contentNodeRef, ContentModel.ASPECT_VERSIONABLE, null);
322         this.contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
323         assertTrue(this.readPolicyFired);
324     }
325     
326     public void onContentReadBehaviourTest(NodeRef nodeRef)
327     {
328         this.readPolicyFired = true;
329     }
330     
331     public void testTempWrite() throws Exception JavaDoc
332     {
333         // get a temporary writer
334
ContentWriter writer1 = contentService.getTempWriter();
335         // and another
336
ContentWriter writer2 = contentService.getTempWriter();
337         
338         // check
339
assertNotSame("Temp URLs must be different",
340                 writer1.getContentUrl(), writer2.getContentUrl());
341     }
342     
343     /**
344      * Tests the automatic updating of nodes' content URLs
345      */

346     public void testUpdatingWrite() throws Exception JavaDoc
347     {
348         // check that the content URL property has not been set
349
ContentData contentData = (ContentData) nodeService.getProperty(
350                 contentNodeRef,
351                 ContentModel.PROP_CONTENT);
352         assertNull("Content URL should be null", contentData.getContentUrl());
353         
354         // before the content is written, there should not be any reader available
355
ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
356         assertNull("No reader should be available for new node", reader);
357         
358         // get the writer
359
ContentWriter writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true);
360         assertNotNull("No writer received", writer);
361         // write some content directly
362
writer.putContent(SOME_CONTENT);
363         
364         // make sure that we can't reuse the writer
365
try
366         {
367             writer.putContent("DEF");
368             fail("Failed to prevent repeated use of the content writer");
369         }
370         catch (ContentIOException e)
371         {
372             // expected
373
}
374         
375         // check that there is a reader available
376
reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
377         assertNotNull("No reader available for node", reader);
378         String JavaDoc contentCheck = reader.getContentString();
379         assertEquals("Content fetched doesn't match that written", SOME_CONTENT, contentCheck);
380
381         // check that the content data was set
382
contentData = (ContentData) nodeService.getProperty(
383                 contentNodeRef,
384                 ContentModel.PROP_CONTENT);
385         assertNotNull("Content data not set", contentData);
386         assertEquals("Mismatched URL between writer and node",
387                 writer.getContentUrl(), contentData.getContentUrl());
388         
389         // check that the content size was set
390
assertEquals("Reader content length and node content length different",
391                 reader.getSize(), contentData.getSize());
392         
393         // check that the mimetype was set
394
assertEquals("Mimetype not set on content data", "text/plain", contentData.getMimetype());
395         // check encoding
396
assertEquals("Encoding not set", "UTF-16", contentData.getEncoding());
397     }
398     
399     /**
400      * Checks that multiple writes can occur to the same node outside of any transactions.
401      * <p>
402      * It is only when the streams are closed that the node is updated.
403      */

404     public void testConcurrentWritesNoTxn() throws Exception JavaDoc
405     {
406         // ensure that the transaction is ended - ofcourse, we need to force a commit
407
setComplete();
408         endTransaction();
409         
410         ContentWriter writer1 = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true);
411         ContentWriter writer2 = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true);
412         ContentWriter writer3 = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true);
413         
414         writer1.putContent("writer1 wrote this");
415         writer2.putContent("writer2 wrote this");
416         writer3.putContent("writer3 wrote this");
417
418         // get the content
419
ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
420         String JavaDoc contentCheck = reader.getContentString();
421         assertEquals("Content check failed", "writer3 wrote this", contentCheck);
422     }
423     
424     public void testConcurrentWritesWithSingleTxn() throws Exception JavaDoc
425     {
426         // want to operate in a user transaction
427
setComplete();
428         endTransaction();
429         
430         UserTransaction JavaDoc txn = getUserTransaction();
431         txn.begin();
432         txn.setRollbackOnly();
433
434         ContentWriter writer1 = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true);
435         ContentWriter writer2 = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true);
436         ContentWriter writer3 = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true);
437         
438         writer1.putContent("writer1 wrote this");
439         writer2.putContent("writer2 wrote this");
440         writer3.putContent("writer3 wrote this");
441
442         // get the content
443
ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
444         String JavaDoc contentCheck = reader.getContentString();
445         assertEquals("Content check failed", "writer3 wrote this", contentCheck);
446         
447         try
448         {
449             txn.commit();
450             fail("Transaction has been marked for rollback");
451         }
452         catch (RollbackException JavaDoc e)
453         {
454             // expected
455
}
456         
457         // rollback and check that the content has 'disappeared'
458
txn.rollback();
459         
460         // need a new transaction
461
txn = getUserTransaction();
462         txn.begin();
463         txn.setRollbackOnly();
464
465         reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
466         assertNull("Transaction was rolled back - no content should be visible", reader);
467         
468         txn.rollback();
469     }
470     
471     public synchronized void testConcurrentWritesWithMultipleTxns() throws Exception JavaDoc
472     {
473         // commit node so that threads can see node
474
setComplete();
475         endTransaction();
476         
477         UserTransaction JavaDoc txn = getUserTransaction();
478         txn.begin();
479         
480         // ensure that there is no content to read on the node
481
ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
482         assertNull("Reader should not be available", reader);
483         
484         ContentWriter threadWriter = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true);
485         String JavaDoc threadContent = "Thread content";
486         WriteThread thread = new WriteThread(threadWriter, threadContent);
487         // kick off thread
488
thread.start();
489         // wait for thread to get to its wait points
490
while (!thread.isWaiting())
491         {
492             wait(10);
493         }
494         
495         // write to the content
496
ContentWriter writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true);
497         writer.putContent(SOME_CONTENT);
498         
499         // fire thread up again
500
synchronized(threadWriter)
501         {
502             threadWriter.notifyAll();
503         }
504         // thread is released - but we have to wait for it to complete
505
while (!thread.isDone())
506         {
507             wait(10);
508         }
509
510         // the thread has finished and has committed its changes - check the visibility
511
reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
512         assertNotNull("Reader should now be available", reader);
513         String JavaDoc checkContent = reader.getContentString();
514         assertEquals("Content check failed", SOME_CONTENT, checkContent);
515         
516         // rollback the txn
517
txn.rollback();
518         
519         // check content has taken on thread's content
520
reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
521         assertNotNull("Reader should now be available", reader);
522         checkContent = reader.getContentString();
523         assertEquals("Content check failed", threadContent, checkContent);
524     }
525     
526     public void testTransformation() throws Exception JavaDoc
527     {
528         // commit node so that threads can see node
529
setComplete();
530         endTransaction();
531         
532         UserTransaction JavaDoc txn = getUserTransaction();
533         txn.begin();
534         txn.setRollbackOnly();
535         
536         // get a regular writer
537
ContentWriter writer = contentService.getTempWriter();
538         writer.setMimetype("text/xml");
539         // write some stuff
540
String JavaDoc content = "<blah></blah>";
541         writer.putContent(content);
542         // get a reader onto the content
543
ContentReader reader = writer.getReader();
544         
545         // get a new writer for the transformation
546
writer = contentService.getTempWriter();
547         writer.setMimetype("audio/x-wav"); // no such conversion possible
548
try
549         {
550             contentService.transform(reader, writer);
551             fail("Transformation attempted with invalid mimetype");
552         }
553         catch (NoTransformerException e)
554         {
555             // expected
556
}
557         
558         // at this point, the transaction is unusable
559
txn.rollback();
560         
561         txn = getUserTransaction();
562         txn.begin();
563         txn.setRollbackOnly();
564         
565         writer.setMimetype("text/plain");
566         contentService.transform(reader, writer);
567         // get the content from the writer
568
reader = writer.getReader();
569         assertEquals("Mimetype of target reader incorrect",
570                 writer.getMimetype(), reader.getMimetype());
571         String JavaDoc contentCheck = reader.getContentString();
572         assertEquals("Content check failed", content, contentCheck);
573         
574         txn.rollback();
575     }
576     
577     /**
578      * Writes some content to the writer's output stream and then aquires
579      * a lock on the writer, waits until notified and then closes the
580      * output stream before terminating.
581      * <p>
582      * When firing thread up, be sure to call <code>notify</code> on the
583      * writer in order to let the thread run to completion.
584      */

585     private class WriteThread extends Thread JavaDoc
586     {
587         private ContentWriter writer;
588         private String JavaDoc content;
589         private boolean isWaiting;
590         private boolean isDone;
591         
592         public WriteThread(ContentWriter writer, String JavaDoc content)
593         {
594             this.writer = writer;
595             this.content = content;
596             isWaiting = false;
597             isDone = false;
598         }
599         
600         public boolean isWaiting()
601         {
602             return isWaiting;
603         }
604         
605         public boolean isDone()
606         {
607             return isDone;
608         }
609
610         public void run()
611         {
612             authenticationComponent.setSystemUserAsCurrentUser();
613             
614             isWaiting = false;
615             isDone = false;
616             UserTransaction JavaDoc txn = getUserTransaction();
617             OutputStream JavaDoc os = writer.getContentOutputStream();
618             try
619             {
620                 txn.begin(); // not testing transactions - this is not a safe pattern
621
// put the content
622
if (writer.getEncoding() == null)
623                 {
624                     os.write(content.getBytes());
625                 }
626                 else
627                 {
628                     os.write(content.getBytes(writer.getEncoding()));
629                 }
630                 synchronized (writer)
631                 {
632                     isWaiting = true;
633                     writer.wait(); // wait until notified
634
}
635                 os.close();
636                 os = null;
637                 txn.commit();
638             }
639             catch (Throwable JavaDoc e)
640             {
641                 try {txn.rollback(); } catch (Exception JavaDoc ee) {}
642                 e.printStackTrace();
643                 throw new RuntimeException JavaDoc("Failed writing to output stream for writer: " + writer, e);
644             }
645             finally
646             {
647                 if (os != null)
648                 {
649                     try { os.close(); } catch (IOException JavaDoc e) {}
650                 }
651                 isDone = true;
652             }
653         }
654     }
655 }
656
Popular Tags