View Javadoc
1   /*
2    *
3    * The DbUnit Database Testing Framework
4    * Copyright (C)2002-2004, DbUnit.org
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License as published by the Free Software Foundation; either
9    * version 2.1 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, write to the Free Software
18   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19   *
20   */
21  
22  package org.dbunit.ant;
23  
24  import java.io.File;
25  import java.io.FileOutputStream;
26  import java.io.IOException;
27  import java.io.OutputStream;
28  import java.nio.charset.Charset;
29  import java.nio.charset.StandardCharsets;
30  import java.sql.SQLException;
31  import java.util.ArrayList;
32  import java.util.Arrays;
33  import java.util.List;
34  
35  import org.apache.tools.ant.Project;
36  import org.dbunit.DatabaseUnitException;
37  import org.dbunit.database.DatabaseSequenceFilter;
38  import org.dbunit.database.IDatabaseConnection;
39  import org.dbunit.dataset.FilteredDataSet;
40  import org.dbunit.dataset.IDataSet;
41  import org.dbunit.dataset.csv.CsvDataSetWriter;
42  import org.dbunit.dataset.excel.XlsDataSet;
43  import org.dbunit.dataset.filter.ITableFilter;
44  import org.dbunit.dataset.xml.FlatDtdDataSet;
45  import org.dbunit.dataset.xml.FlatXmlWriter;
46  import org.dbunit.dataset.xml.XmlDataSet;
47  import org.dbunit.dataset.yaml.YamlDataSet;
48  import org.slf4j.Logger;
49  import org.slf4j.LoggerFactory;
50  
51  /**
52   * The <code>Export</code> class is the step that facilitates exporting
53   * the contents of the database and/or it's corresponding DTD to a file.
54   * The export can be performed on a full dataset or a partial one if
55   * specific table names are identified.
56   *
57   * @author Timothy Ruppert
58   * @author Ben Cox
59   * @version $Revision$
60   * @since Jun 10, 2002
61   * @see DbUnitTaskStep
62   */
63  public class Export extends AbstractStep
64  {
65  
66      /**
67       * Logger for this class
68       */
69      private static final Logger logger = LoggerFactory.getLogger(Export.class);
70  
71      private File _dest;
72      private String _format = FORMAT_FLAT;
73      private String _doctype = null;
74      private Charset _encoding = StandardCharsets.UTF_8; // if no encoding set by script than the default encoding (UTF-8) of the wrietr is used
75      private List _tables = new ArrayList();
76  
77      public Export()
78      {
79      }
80  
81      private String getAbsolutePath(File filename)
82      {
83          return filename != null ? filename.getAbsolutePath() : "null";
84      }
85  
86      public File getDest()
87      {
88          return _dest;
89      }
90  
91      public String getFormat()
92      {
93          return _format;
94      }
95  
96      public List getTables()
97      {
98          return _tables;
99      }
100 
101     public void setDest(File dest)
102     {
103         logger.debug("setDest(dest={}) - start", dest);
104         _dest = dest;
105     }
106 
107     public void setFormat(String format)
108     {
109         logger.debug("setFormat(format={}) - start", format);
110 
111         if (format.equalsIgnoreCase(FORMAT_FLAT)
112                 || format.equalsIgnoreCase(FORMAT_XML)
113                 || format.equalsIgnoreCase(FORMAT_DTD)
114                 || format.equalsIgnoreCase(FORMAT_CSV)
115                 || format.equalsIgnoreCase(FORMAT_XLS)
116                 || format.equalsIgnoreCase(FORMAT_YML))
117         {
118             _format = format;
119         }
120         else
121         {
122             throw new IllegalArgumentException("Type must be one of: 'flat'(default), 'xml', 'dtd', 'xls' or 'yml' but was: " + format);
123         }
124     }
125 
126     /**
127      * Encoding for XML-Output
128      * @return Returns the encoding.
129      */
130     public Charset getEncoding()
131     {
132         return this._encoding;
133     }
134 
135     public void setEncoding(String encoding)
136     {
137         setEncoding(Charset.forName(encoding));
138     }
139 
140     public void setEncoding(Charset encoding)
141     {
142         this._encoding = encoding;
143     }
144 
145     public void addTable(Table table)
146     {
147         logger.debug("addTable(table={}) - start", table);
148         _tables.add(table);
149     }
150 
151     public void addQuery(Query query)
152     {
153         logger.debug("addQuery(query={}) - start", query);
154         _tables.add(query);
155     }
156 
157 	public void addQuerySet(QuerySet querySet) {
158         logger.debug("addQuerySet(querySet={}) - start", querySet);
159         _tables.add(querySet);
160 	}
161 	
162     
163 	public String getDoctype()
164     {
165         return _doctype;
166     }
167 
168     public void setDoctype(String doctype)
169     {
170         logger.debug("setDoctype(doctype={}) - start", doctype);
171         _doctype = doctype;
172     }
173 
174     public void execute(IDatabaseConnection connection) throws DatabaseUnitException
175     {
176         logger.debug("execute(connection={}) - start", connection);
177 
178         try
179         {
180             if (_dest == null)
181             {
182                 throw new DatabaseUnitException("'_dest' is a required attribute of the <export> step.");
183             }
184 
185             IDataSet dataset = getExportDataSet(connection);
186 			log("dataset tables: " + Arrays.asList(dataset.getTableNames()), Project.MSG_VERBOSE);
187 
188 			
189             // Write the dataset
190             if (_format.equals(FORMAT_CSV))
191             {
192                 CsvDataSetWriter.write(dataset, _dest);
193             }
194             else
195             {
196                 OutputStream out = new FileOutputStream(_dest);
197                 try
198                 {
199                     if (_format.equalsIgnoreCase(FORMAT_FLAT))
200                     {
201                         FlatXmlWriter writer = new FlatXmlWriter(out, getEncoding());
202                         writer.setDocType(_doctype);
203                         writer.write(dataset);
204                     }
205                     else if (_format.equalsIgnoreCase(FORMAT_XML))
206                     {
207                         XmlDataSet.write(dataset, out, getEncoding());
208                     }
209                     else if (_format.equalsIgnoreCase(FORMAT_DTD))
210                     {
211                         //TODO Should DTD also support encoding? It is basically an XML file...
212                         FlatDtdDataSet.write(dataset, out);//, getEncoding());
213                     }
214                     else if (_format.equalsIgnoreCase(FORMAT_XLS))
215                     {
216                         XlsDataSet.write(dataset, out);
217                     }
218                     else if (_format.equalsIgnoreCase(FORMAT_YML))
219                     {
220                         YamlDataSet.write(dataset, out);
221                     }
222                     else
223                     {
224                         throw new IllegalArgumentException("The given format '"+_format+"' is not supported.");
225                     }
226                     
227                 }
228                 finally
229                 {
230                     out.close();
231                 }
232             }
233             
234             log("Successfully wrote file '" + _dest + "'", Project.MSG_INFO);
235             
236         }
237         catch (SQLException e)
238         {
239         	throw new DatabaseUnitException(e);
240         }
241         catch (IOException e)
242         {
243             throw new DatabaseUnitException(e);
244         }
245     }
246 
247     /**
248      * Creates the dataset that is finally used for the export
249      * @param connection
250      * @return The final dataset used for the export
251      * @throws DatabaseUnitException
252      * @throws SQLException
253      */
254     protected IDataSet getExportDataSet(IDatabaseConnection connection) 
255     throws DatabaseUnitException, SQLException 
256     {
257         IDataSet dataset = getDatabaseDataSet(connection, this._tables);
258         if (isOrdered()) 
259         {
260         	// Use topologically sorted database
261         	ITableFilter filter = new DatabaseSequenceFilter(connection);  
262         	dataset = new FilteredDataSet(filter, dataset);
263         }
264         return dataset;
265 	}
266 
267 	public String getLogMessage()
268     {
269         return "Executing export: "
270                 + "\n      in format: " + _format
271                 + " to datafile: " + getAbsolutePath(_dest);
272     }
273 
274 
275     public String toString()
276     {
277         final StringBuilder result = new StringBuilder();
278         result.append("Export: ");
279         result.append(" dest=" + getAbsolutePath(_dest));
280         result.append(", format= " + _format);
281         result.append(", doctype= " + _doctype);
282         result.append(", tables= " + _tables);
283 
284         return result.toString();
285     }
286 }