1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 package com.sun.star.wizards.web;
24 
25 import java.io.File;
26 import java.io.FileOutputStream;
27 import java.io.IOException;
28 import java.util.Hashtable;
29 import java.util.Iterator;
30 import java.util.Map;
31 
32 import javax.xml.transform.Templates;
33 import javax.xml.transform.Transformer;
34 import javax.xml.transform.dom.DOMSource;
35 import javax.xml.transform.stream.StreamResult;
36 
37 import org.w3c.dom.Document;
38 
39 import com.sun.star.lang.XMultiServiceFactory;
40 import com.sun.star.wizards.common.ConfigSet;
41 import com.sun.star.wizards.common.FileAccess;
42 import com.sun.star.wizards.common.PropertyNames;
43 import com.sun.star.wizards.common.UCB;
44 import com.sun.star.wizards.ui.event.Task;
45 import com.sun.star.wizards.web.data.CGContent;
46 import com.sun.star.wizards.web.data.CGDocument;
47 import com.sun.star.wizards.web.data.CGExporter;
48 import com.sun.star.wizards.web.data.CGLayout;
49 import com.sun.star.wizards.web.data.CGPublish;
50 import com.sun.star.wizards.web.data.CGSettings;
51 import com.sun.star.wizards.web.export.Exporter;
52 
53 /**
54  * @author rpiterman
55  * This class is used to process a CGSession object
56  * and generate a site. </br>
57  * it does the following: <br/>
58  * 1. create a temporary directory.<br/>
59  * 2. export documents to the temporary directory.<br/>
60  * 3. generate the TOC page, includes copying images from the
61  * web wizard work directory and other layout files.<br/>
62  * 4. publish, or copy, from the temporary directory to
63  * different destinations.<br/>
64  * 5. delete the temporary directory.<br/>
65  * <br/>
66  * to follow up the status/errors it uses a TaskListener object,
67  * and an ErrorHandler. <br/>
68  * in practice, the TaskListener is the status dialog,
69  * and the Errorhandler does the interaction with the user,
70  * if something goes wrong.<br/>
71  * Note that this class takes it in count that
72  * the given session object is prepared for it -
73  * all preparations are done in WWD_Events.finishWizard methods.
74  * <br/>
75  * <br/>
76  *
77  * note on error handling: <br/>
78  * on "catch" clauses I tries to decide whether the
79  * exception is fatal or not. For fatal exception an error message
80  * is displayed (or rather: the errorHandler is being called...)
81  * and a false is returned.
82  * In less-fatal errors, the errorHandler "should decide" which means,
83  * the user is given the option to "OK" or to "Cancel" and depending
84  * on that interaction I cary on.
85  */
86 public class Process implements WebWizardConst, ProcessErrors
87 {
88 
89     private static final int TASKS_PER_DOC = 5;
90     private static final int TASKS_PER_XSL = 2;
91     private static final int TASKS_PER_PUBLISH = 2;
92     private static final int TASKS_IN_PREPARE = 1;
93     private static final int TASKS_IN_EXPORT = 2;
94     private static final int TASKS_IN_GENERATE = 2;
95     private static final int TASKS_IN_PUBLISH = 2;
96     private static final int TASKS_IN_FINISHUP = 1;
97     private CGSettings settings;
98     private XMultiServiceFactory xmsf;
99     private ErrorHandler errorHandler;
100     private String tempDir;
101     private FileAccess fileAccess;
102     private UCB ucb;
103     public Task myTask;
104     /**
105      * This is a cache for exporters, so I do not need to
106      * instanciate the same exporter more than once.
107      */
108     private Map exporters = new Hashtable(3);
109     private boolean result;
110 
Process( CGSettings settings, XMultiServiceFactory xmsf, ErrorHandler er)111     public Process(
112             CGSettings settings,
113             XMultiServiceFactory xmsf,
114             ErrorHandler er)
115             throws Exception
116     {
117         this.xmsf = xmsf;
118         this.settings = settings;
119         fileAccess = new FileAccess(xmsf);
120         errorHandler = er;
121 
122         ucb = new UCB(xmsf);
123 
124         int taskSteps = getTaskSteps();
125         myTask = new Task(TASK, TASK_PREPARE, taskSteps);
126 
127     }
128 
129     /**
130      * @return to how many destinations should the
131      * generated site be published.
132      */
countPublish()133     private int countPublish()
134     {
135         int count = 0;
136         ConfigSet publishers = settings.cp_DefaultSession.cp_Publishing;
137         for (int i = 0; i < publishers.getSize(); i++)
138         {
139             if (((CGPublish) publishers.getElementAt(i)).cp_Publish)
140             {
141                 count++;
142             }
143         }
144         return count;
145     }
146 
147     /**
148      * @return the number of task steps that this
149      * session should have
150      */
getTaskSteps()151     private int getTaskSteps()
152     {
153         int docs = settings.cp_DefaultSession.cp_Content.cp_Documents.getSize();
154         int xsl = 0;
155         try
156         {
157             xsl = settings.cp_DefaultSession.getLayout().getTemplates(xmsf).size();
158         }
159         catch (Exception ex)
160         {
161         }
162         int publish = countPublish();
163         return
164                 TASKS_IN_PREPARE +
165                 TASKS_IN_EXPORT + docs * TASKS_PER_DOC +
166                 TASKS_IN_GENERATE + xsl * TASKS_PER_XSL +
167                 TASKS_IN_PUBLISH + publish * TASKS_PER_PUBLISH +
168                 TASKS_IN_FINISHUP;
169     }
170 
171     /**
172      * does the job
173      */
runProcess()174     public void runProcess()
175     {
176         myTask.start();
177         try
178         {
179             try
180             {
181                 /*
182                  * I use here '&&' so if one of the
183                  * methods returns false, the next
184                  * will not be called.
185                  */
186                 result = createTempDir(myTask) && export(myTask) && generate(tempDir, myTask) && publish(tempDir, myTask);
187 
188             }
189             finally
190             {
191                 //cleanup must be called.
192                 result = result & cleanup(myTask);
193             }
194         }
195         catch (Exception ex)
196         {
197             result = false;
198         }
199 
200         if (!result)
201         {
202             myTask.fail();        //this is a bug protection.
203         }
204         while (myTask.getStatus() < myTask.getMax())
205         {
206             myTask.advance(true);
207         }
208     }
209 
210     /**
211      * creates a temporary directory.
212      * @param task
213      * @return true should continue
214      */
createTempDir(Task task)215     private boolean createTempDir(Task task)
216     {
217 
218         tempDir = fileAccess.createNewDir(getSOTempDir(xmsf), "wwiztemp");
219         if (tempDir == null)
220         {
221             error(null, null, ERROR_MKDIR, ErrorHandler.ERROR_PROCESS_FATAL);
222             return false;
223         }
224         else
225         {
226             task.advance(true);
227             return true;
228         }
229     }
230 
231     /**
232      * @param xmsf
233      * @return the staroffice /openoffice temporary directory
234      */
getSOTempDir(XMultiServiceFactory xmsf)235     static String getSOTempDir(XMultiServiceFactory xmsf)
236     {
237         try
238         {
239             return FileAccess.getOfficePath(xmsf, "Temp", PropertyNames.EMPTY_STRING, PropertyNames.EMPTY_STRING);
240         }
241         catch (Exception e)
242         {
243         }
244         return null;
245     }
246 
247     // CLEANUP
248     /**
249      * delete the temporary directory
250      * @return true should continue
251      */
cleanup(Task task)252     private boolean cleanup(Task task)
253     {
254 
255         task.setSubtaskName(TASK_FINISH);
256         boolean b = fileAccess.delete(tempDir);
257         if (!b)
258         {
259             error(null, null, ERROR_CLEANUP, ErrorHandler.ERROR_WARNING);
260         }
261         task.advance(b);
262         return b;
263     }
264 
265 //  /**
266 //   * deletes the given directory
267 //   * @param dir the directory to delete
268 //   * @return true if should continue
269 //   */
270 //  private boolean cleanup(String dir) {
271 //
272 //      boolean success = true;
273 //
274 //      if (dir != null && fileAccess.exists(dir,false)) {
275 //
276 //          String[] files = fileAccess.listFiles(dir,true);
277 //
278 //          for (int i = 0; i < files.length; i++) {
279 //              if (fileAccess.isDirectory(files[i]))
280 //                  success = success && cleanup(files[i]);
281 //              else
282 //                  success = success && fileAccess.delete(files[i]);
283 //
284 //          }
285 //      }
286 //      return success && fileAccess.delete(dir);
287 //  }
288     /**
289      * This method is used to copy style files to a target
290      * Directory: css and background.
291      * Note that this method is static since it is
292      * also used when displaying a "preview"
293      */
copyMedia(UCB copy, CGSettings settings, String targetDir, Task task)294     public static void copyMedia(UCB copy, CGSettings settings, String targetDir, Task task) throws Exception
295     {
296 
297         //1. .css
298         String sourceDir = FileAccess.connectURLs(settings.workPath, "styles");
299         String filename = settings.cp_DefaultSession.getStyle().cp_CssHref;
300         copy.copy(sourceDir, filename, targetDir, "style.css");
301 
302         task.advance(true);
303 
304         //2. background image
305         String background = settings.cp_DefaultSession.cp_Design.cp_BackgroundImage;
306         if (background != null && !background.equals(PropertyNames.EMPTY_STRING))
307         {
308             sourceDir = FileAccess.getParentDir(background);
309             filename = background.substring(sourceDir.length());
310             copy.copy(sourceDir, filename, targetDir + "/images", "background.gif");
311         }
312 
313         task.advance(true);
314     }
315 
316     /**
317      * Copy "static" files (which are always the same,
318      * thus not user-input-dependant) to a target directory.
319      * Note that this method is static since it is
320      * also used when displaying a "preview"
321      * @param copy
322      * @param settings
323      * @param targetDir
324      * @throws Exception
325      */
copyStaticImages(UCB copy, CGSettings settings, String targetDir)326     public static void copyStaticImages(UCB copy, CGSettings settings, String targetDir)
327             throws Exception
328     {
329         copy.copy(FileAccess.connectURLs(settings.workPath, "images"), targetDir + "/images");
330     }
331 
332     /**
333      * publish the given directory.
334      * @param dir the source directory to publish from
335      * @param task task tracking.
336      * @return true if should continue
337      */
publish(String dir, Task task)338     private boolean publish(String dir, Task task)
339     {
340         task.setSubtaskName(TASK_PUBLISH_PREPARE);
341         ConfigSet set = settings.cp_DefaultSession.cp_Publishing;
342         try
343         {
344 
345             copyMedia(ucb, settings, dir, task);
346             copyStaticImages(ucb, settings, dir);
347             task.advance(true);
348         }
349         catch (Exception ex)
350         {
351             //error in copying media
352             error(ex, PropertyNames.EMPTY_STRING, ERROR_PUBLISH_MEDIA, ErrorHandler.ERROR_PROCESS_FATAL);
353             return false;
354         }
355 
356         boolean result = true;
357 
358         for (int i = 0; i < set.getSize(); i++)
359         {
360 
361             CGPublish p = (CGPublish) set.getElementAt(i);
362 
363             if (p.cp_Publish)
364             {
365 
366                 String key = (String) set.getKey(p);
367                 task.setSubtaskName(key);
368 
369                 if (key.equals(ZIP_PUBLISHER))
370                 {
371                     fileAccess.delete(p.cp_URL);
372                 }
373                 if (!publish(dir, p, ucb, task))
374                 {
375                     return false;
376                 }
377 
378             }
379         }
380 
381         return result;
382     }
383 
384     /**
385      * publish the given directory to the
386      * given target CGPublish.
387      * @param dir the dir to copy from
388      * @param publish the object that specifies the target
389      * @param copy ucb encapsulation
390      * @param task task tracking
391      * @return true if should continue
392      */
publish(String dir, CGPublish publish, UCB copy, Task task)393     private boolean publish(String dir, CGPublish publish, UCB copy, Task task)
394     {
395         try
396         {
397             //copy.deleteDirContent(publish.url);
398             task.advance(true);
399             copy.copy(dir, publish.url);
400             task.advance(true);
401             return true;
402         }
403         catch (Exception e)
404         {
405             task.advance(false);
406             return error(e, publish, ERROR_PUBLISH, ErrorHandler.ERROR_NORMAL_IGNORE);
407         }
408     }
409     //GENERATING METHODS
410     /**
411      * Generates the TOC pages for the current session.
412      * @param targetDir generating to this directory.
413      */
generate(String targetDir, Task task)414     public boolean generate(String targetDir, Task task)
415     {
416         boolean result = false;
417         task.setSubtaskName(TASK_GENERATE_PREPARE);
418 
419 
420         CGLayout layout = settings.cp_DefaultSession.getLayout();
421 
422         try
423         {
424             /*
425              * here I create the DOM of the TOC to pass to the XSL
426              */
427             Document doc = (Document) settings.cp_DefaultSession.createDOM();
428             generate(xmsf, layout, doc, fileAccess, targetDir, task);
429 
430         }
431         catch (Exception ex)
432         {
433             error(ex, PropertyNames.EMPTY_STRING, ERROR_GENERATE_XSLT, ErrorHandler.ERROR_PROCESS_FATAL);
434             return false;
435         }
436 
437         /* copy files which are not xsl from layout directory to
438          * website root.
439          */
440         try
441         {
442 
443             task.setSubtaskName(TASK_GENERATE_COPY);
444 
445             copyLayoutFiles(ucb, fileAccess, settings, layout, targetDir);
446 
447             task.advance(true);
448 
449             result = true;
450         }
451         catch (Exception ex)
452         {
453             task.advance(false);
454             return error(ex, null, ERROR_GENERATE_COPY, ErrorHandler.ERROR_NORMAL_ABORT);
455         }
456 
457 
458 
459         return result;
460 
461     }
462 
463     /**
464      * copies layout files which are not .xsl files
465      * to the target directory.
466      * @param ucb UCB encapsulatzion object
467      * @param fileAccess filaAccess encapsulation object
468      * @param settings web wizard settings
469      * @param layout the layout object
470      * @param targetDir the target directory to copy to
471      * @throws Exception
472      */
copyLayoutFiles(UCB ucb, FileAccess fileAccess, CGSettings settings, CGLayout layout, String targetDir)473     public static void copyLayoutFiles(UCB ucb, FileAccess fileAccess, CGSettings settings, CGLayout layout, String targetDir)
474             throws Exception
475     {
476         String filesPath = fileAccess.getURL(
477                 FileAccess.connectURLs(settings.workPath, "layouts/"), layout.cp_FSName);
478         ucb.copy(filesPath, targetDir, new ExtensionVerifier("xsl"));
479 
480     }
481 
482     /**
483      * generates the TOC page for the given layout.
484      * This method might generate more than one file, depending
485      * on how many .xsl files are in the
486      * directory specifies by the given layout object.
487      * @param xmsf
488      * @param layout specifies the layout to use.
489      * @param doc the DOM representation of the web wizard session
490      * @param fileAccess encapsulation of FileAccess
491      * @param targetPath target directory
492      * @param task
493      * @throws Exception
494      */
generate( XMultiServiceFactory xmsf, CGLayout layout, Document doc, FileAccess fileAccess, String targetPath, Task task)495     public static void generate(
496             XMultiServiceFactory xmsf,
497             CGLayout layout,
498             Document doc,
499             FileAccess fileAccess,
500             String targetPath,
501             Task task)
502             throws Exception
503     {
504         /*
505          * a map that contains xsl templates. the keys are the xsl file names.
506          */
507         Map templates = layout.getTemplates(xmsf);
508 
509         task.advance(true, TASK_GENERATE_XSL);
510 
511         /*
512          * each template generates a page.
513          */
514         for (Iterator i = templates.keySet().iterator(); i.hasNext();)
515         {
516 
517             String key = PropertyNames.EMPTY_STRING;
518 
519             key = (String) i.next();
520 
521             Transformer transformer = ((Templates) templates.get(key)).newTransformer();
522 
523             doc.normalize();
524             task.advance(true);
525 
526             /*
527              * The target file name is like the xsl template filename
528              * without the .xsl extension.
529              */
530             String fn = fileAccess.getPath(targetPath, key.substring(0, key.length() - 4));
531             File f = new File(fn);
532             FileOutputStream oStream = new FileOutputStream(f);
533             // Due to a problem occurring when using Xalan-Java 2.6.0 and
534             // Java 1.5.0, wrap f in a FileOutputStream here (otherwise, the
535             // StreamResult's getSystemId would return a "file:/..." URL while
536             // the Xalan code expects a "file:///..." URL):
537             transformer.transform(
538                     new DOMSource(doc), new StreamResult(oStream));
539             oStream.close();
540             task.advance(true);
541         }
542     }
543 
544     /**
545      * I broke the export method to two methods
546      * in a time where a tree with more than one contents was planned.
547      * I left it that way, because it may be used in the future.
548      * @param task
549      * @return
550      */
export(Task task)551     private boolean export(Task task)
552     {
553 
554         return export(settings.cp_DefaultSession.cp_Content, tempDir, task);
555 
556     }
557 
558     /**
559      * This method could actually, with light modification, use recursion.
560      * In the present situation, where we only use a "flat" list of
561      * documents, instead of the original plan to use a tree,
562      * the recursion is not implemented.
563      * @param content the content ( directory-like, contains documents)
564      * @param dir (target directory for exporting this content.
565      * @param task
566      * @return true if should continue
567      */
export(CGContent content, String dir, Task task)568     private boolean export(CGContent content, String dir, Task task)
569     {
570         int toPerform = 1;
571         String contentDir = dir;
572 
573         try
574         {
575 
576             task.setSubtaskName(TASK_EXPORT_PREPARE);
577 
578             /* 1. create a content directory.
579              * each content (at the moment there is only one :-( )
580              * is created in its own directory.
581              * faileure here is fatal.
582              */
583             contentDir = fileAccess.createNewDir(dir, content.cp_Name);
584             if (contentDir == null || contentDir.equals(PropertyNames.EMPTY_STRING))
585             {
586                 throw new IOException("Directory " + dir + " could not be created.");
587             }
588             content.dirName = FileAccess.getFilename(contentDir);
589 
590             task.advance(true, TASK_EXPORT_DOCUMENTS);
591             toPerform--;
592 
593             /*2. export all documents and sub contents.
594              * (at the moment, only documents, no subcontents)
595              */
596             Object item = null;
597             for (int i = 0; i < content.cp_Documents.getSize(); i++)
598             {
599                 try
600                 {
601                     item = content.cp_Documents.getElementAt(i);
602                     /*
603                      * In present this is always the case.
604                      * may be in the future, when
605                      * a tree is used, it will be abit different.
606                      */
607                     if (item instanceof CGDocument)
608                     {
609                         if (!export((CGDocument) item, contentDir, task))
610                         {
611                             return false;
612                         }
613                     }
614                     else /*
615                      * we never get here since we
616                      * did not implement sub-contents.
617                      */ if (!export((CGContent) item, contentDir, task))
618                     {
619                         return false;
620                     }
621                 }
622                 catch (SecurityException sx)
623                 {
624                     // nonfatal
625                     if (!error(sx, item, ERROR_EXPORT_SECURITY, ErrorHandler.ERROR_NORMAL_IGNORE))
626                     {
627                         return false;
628                     }
629                     result = false;
630                 }
631             }
632         }
633         catch (IOException iox)
634         {
635             //nonfatal
636             return error(iox, content, ERROR_EXPORT_IO, ErrorHandler.ERROR_NORMAL_IGNORE);
637 
638         }
639         catch (SecurityException se)
640         {
641             //nonfatal
642             return error(se, content, ERROR_EXPORT_SECURITY, ErrorHandler.ERROR_NORMAL_IGNORE);
643         }
644         failTask(task, toPerform);
645         return true;
646 
647     }
648 
649     /**
650      * exports a single document
651      * @param doc the document to export
652      * @param dir the target directory
653      * @param task task tracking
654      * @return true if should continue
655      */
export(CGDocument doc, String dir, Task task)656     private boolean export(CGDocument doc, String dir, Task task)
657     {
658 
659         //first I check if the document was already validated...
660         if (!doc.valid)
661         {
662             try
663             {
664                 doc.validate(xmsf, null);
665             }
666             catch (Exception ex)
667             {
668                 //fatal
669                 error(ex, doc, ERROR_DOC_VALIDATE, ErrorHandler.ERROR_PROCESS_FATAL);
670                 return false;
671             }
672         //get the exporter specified for this document
673         }
674         CGExporter exporter = (CGExporter) settings.cp_Exporters.getElement(doc.cp_Exporter);
675 
676 
677         try
678         {
679 
680             /*
681              * here I calculate the destination filename.
682              * I take the original filename (docFilename), subtract the extension, (docExt) -> (fn)
683              * and find an available filename which starts with
684              * this filename, but with the new extension. (destExt)
685              */
686             String docFilename = FileAccess.getFilename(doc.cp_URL);
687 
688             String docExt = FileAccess.getExtension(docFilename);
689             String fn = doc.localFilename.substring(0, doc.localFilename.length() - docExt.length() - 1); //filename without extension
690 
691             /*
692              * the copyExporter does not change
693              * the extension of the target...
694              */
695             String destExt = (exporter.cp_Extension.equals(PropertyNames.EMPTY_STRING)
696                     ? FileAccess.getExtension(docFilename)
697                     : exporter.cp_Extension);
698 
699             /* if this filter needs to export to its own directory...
700              * this is the case in, for example, impress html export
701              */
702             if (exporter.cp_OwnDirectory)
703             { //+++
704                 dir = fileAccess.createNewDir(dir, fn);
705                 doc.dirName = FileAccess.getFilename(dir);
706             }
707 
708             /*
709              * if two files with the same name
710              * need to be exported ? So here
711              * i get a new filename, so I do not
712              * overwrite files...
713              */
714             String file = fileAccess.getNewFile(dir, fn, destExt);
715 
716 
717             /* set filename with extension.
718              * this will be used by the exporter,
719              * and to generate the TOC.
720              */
721             doc.urlFilename = FileAccess.getFilename(file);
722 
723             task.advance(true);
724 
725             try
726             {
727                 //export
728                 getExporter(exporter).export(doc, file, xmsf, task);
729                 task.advance(true);
730             }
731             /*
732              * getExporter(..) throws
733              * IllegalAccessException, InstantiationException, ClassNotFoundException
734              * export() throws Exception
735              */
736             catch (Exception ex)
737             {
738                 //nonfatal
739                 if (!error(ex, doc, ERROR_EXPORT, ErrorHandler.ERROR_NORMAL_IGNORE))
740                 {
741                     return false;
742                 }
743             }
744         }
745         catch (Exception ex)
746         {
747             //nonfatal
748             if (!error(ex, doc, ERROR_EXPORT_MKDIR, ErrorHandler.ERROR_NORMAL_ABORT))
749             {
750                 return false;
751             }
752         }
753 
754         return true;
755 
756     }
757 
758     /**
759      * submit an error.
760      * @param ex the exception
761      * @param arg1 error argument
762      * @param arg2 error argument 2
763      * @param errType error type
764      * @return the interaction result
765      */
error(Exception ex, Object arg1, int arg2, int errType)766     private boolean error(Exception ex, Object arg1, int arg2, int errType)
767     {
768         result = false;
769         return errorHandler.error(ex, arg1, arg2, errType);
770     }
771 
772     /**
773      * advances the given task in the given count of steps,
774      * marked as failed.
775      * @param task the task to advance
776      * @param count the number of steps to advance
777      */
failTask(Task task, int count)778     private void failTask(Task task, int count)
779     {
780         while (count-- > 0)
781         {
782             task.advance(false);
783         }
784     }
785 
786     /**
787      * creates an instance of the exporter class
788      * as specified by the
789      * exporter object.
790      * @param export specifies the exporter to be created
791      * @return the Exporter instance
792      * @throws ClassNotFoundException
793      * @throws IllegalAccessException
794      * @throws InstantiationException
795      */
createExporter(CGExporter export)796     private Exporter createExporter(CGExporter export)
797             throws ClassNotFoundException,
798             IllegalAccessException,
799             InstantiationException
800     {
801         Exporter e = (Exporter) Class.forName(export.cp_ExporterClass).newInstance();
802         e.init(export);
803         return e;
804     }
805 
806     /**
807      * searches the an exporter for the given CGExporter object
808      * in the cache.
809      * If its not there, creates it, stores it in the cache and
810      * returns it.
811      * @param export specifies the needed exporter.
812      * @return an Exporter instance
813      * @throws ClassNotFoundException thrown when using Class.forName(string)
814      * @throws IllegalAccessException thrown when using Class.forName(string)
815      * @throws InstantiationException thrown when using Class.forName(string)
816      */
getExporter(CGExporter export)817     private Exporter getExporter(CGExporter export)
818             throws ClassNotFoundException,
819             IllegalAccessException,
820             InstantiationException
821     {
822         Exporter exp = (Exporter) exporters.get(export);
823         if (exp == null)
824         {
825             exp = createExporter(export);
826             exporters.put(export, exp);
827         }
828         return exp;
829     }
830 
831     /**
832      * @return tru if everything went smooth, false
833      * if error(s) accured.
834      */
getResult()835     public boolean getResult()
836     {
837         return (myTask.getFailed() == 0) && result;
838     }
839 }
840