View Javadoc
1   /*
2    *
3    * The DbUnit Database Testing Framework
4    * Copyright (C)2002-2008, 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  package org.dbunit.dataset.sqlloader;
22  
23  import java.io.File;
24  import java.io.IOException;
25  import java.util.Iterator;
26  import java.util.List;
27  
28  import org.dbunit.dataset.Column;
29  import org.dbunit.dataset.DataSetException;
30  import org.dbunit.dataset.DefaultTableMetaData;
31  import org.dbunit.dataset.IDataSet;
32  import org.dbunit.dataset.ITableMetaData;
33  import org.dbunit.dataset.common.handlers.IllegalInputCharacterException;
34  import org.dbunit.dataset.common.handlers.PipelineException;
35  import org.dbunit.dataset.datatype.DataType;
36  import org.dbunit.dataset.stream.DefaultConsumer;
37  import org.dbunit.dataset.stream.IDataSetConsumer;
38  import org.dbunit.dataset.stream.IDataSetProducer;
39  import org.dbunit.util.FileHelper;
40  import org.slf4j.Logger;
41  import org.slf4j.LoggerFactory;
42  
43  /**
44   * Producer that creates an {@link IDataSet} using SQLLoader style '.ctl' files.
45   * 
46   * @author Stephan Strittmatter (stritti AT users.sourceforge.net), gommma (gommma AT users.sourceforge.net)
47   * @author Last changed by: $Author$
48   * @version $Revision$ $Date$
49   * @since 2.4.0
50   */
51  public class SqlLoaderControlProducer implements IDataSetProducer {
52  
53      /**
54       * Logger for this class
55       */
56      private static final Logger logger = LoggerFactory.getLogger(SqlLoaderControlProducer.class);
57  
58      private static final String TMP_TABLE_LIST_FILENAME = "table-list.txt";
59  
60  
61      /** The Constant NULL. */
62      public static final String NULL = "null";
63  
64      /** The Constant EMPTY_CONSUMER. */
65      private static final IDataSetConsumer EMPTY_CONSUMER = new DefaultConsumer();
66  
67      /** The consumer. */
68      private IDataSetConsumer consumer = EMPTY_CONSUMER;
69  
70      /** The control files directory */
71      private final File controlFilesDir;
72  
73      /**
74       * String list of the ordered table names
75       */
76      private List orderedTableNames;
77  
78  
79      /**
80       * The Constructor.
81       * 
82       * @param controlFilesDir the control files directory
83       * @param tableOrderFile the table order file
84       * @throws DataSetException 
85       */
86      public SqlLoaderControlProducer(String controlFilesDir, String tableOrderFile) 
87      throws DataSetException 
88      {
89          this(new File(controlFilesDir), new File(tableOrderFile));
90      }
91  
92      /**
93       * The Constructor.
94       * 
95       * @param controlFilesDir the control files directory
96       * @param tableOrderFile the table order file
97       * @throws DataSetException 
98       */
99      public SqlLoaderControlProducer(File controlFilesDir, File tableOrderFile) 
100     throws DataSetException 
101     {
102         this.controlFilesDir = controlFilesDir;
103         
104         try {
105             this.orderedTableNames = SqlLoaderControlProducer.getTables(controlFilesDir, tableOrderFile);
106         }
107         catch (IOException e) {
108             throw new DataSetException("error getting list of tables from file '" + tableOrderFile + "'", e);
109         }
110     }
111 
112     /**
113      * The Constructor.
114      * 
115      * @param controlFilesDir the control files directory
116      * @param orderedTableNames a list of strings that contains the ordered table names
117      */
118     public SqlLoaderControlProducer(File controlFilesDir, List orderedTableNames) {
119         this.controlFilesDir = controlFilesDir;
120         this.orderedTableNames = orderedTableNames;
121     }
122 
123     /**
124      * @see org.dbunit.dataset.stream.IDataSetProducer#setConsumer(org.dbunit.dataset.stream.IDataSetConsumer)
125      */
126     public void setConsumer(IDataSetConsumer consumer) throws DataSetException {
127         this.consumer = consumer;
128     }
129 
130     /**
131      * @see org.dbunit.dataset.stream.IDataSetProducer#produce()
132      */
133     public void produce() throws DataSetException {
134         logger.debug("produce() - start");
135 
136         File dir = this.controlFilesDir;
137 
138         if (!this.controlFilesDir.isDirectory()) {
139             throw new DataSetException("'"
140                     + this.controlFilesDir + "' should be a directory of the control files");
141         }
142 
143         this.consumer.startDataSet();
144         
145         for (Iterator tableIter = this.orderedTableNames.iterator(); tableIter.hasNext();) {
146             String table = (String) tableIter.next();
147             try {
148                 File ctlFile = new File(dir, table + ".ctl");
149                 produceFromControlFile(ctlFile);
150             }
151             catch (SqlLoaderControlParserException e) {
152                 throw new DataSetException("error producing dataset for table '" + table + "'", e);
153             }
154             catch (DataSetException e) {
155                 throw new DataSetException("error producing dataset for table '" + table + "'", e);
156             }
157 
158         }
159         this.consumer.endDataSet();
160     }
161 
162     /**
163      * Produce from control file.
164      * 
165      * @param controlFile the control file
166      * 
167      * @throws DataSetException the data set exception
168      * @throws SqlLoaderControlParserException the oracle control parser exception
169      */
170     private void produceFromControlFile(File controlFile) throws DataSetException,
171     SqlLoaderControlParserException 
172     {
173         logger.debug("produceFromControlFile(controlFile={}) - start", controlFile);
174 
175         try {
176             SqlLoaderControlParser parser = new SqlLoaderControlParserImpl();
177             List readData = parser.parse(controlFile);
178             List readColumns = ((List) readData.get(0));
179             Column[] columns = new Column[readColumns.size()];
180 
181             for (int i = 0; i < readColumns.size(); i++) {
182                 columns[i] = new Column((String) readColumns.get(i), DataType.UNKNOWN);
183             }
184 
185             String tableName = parser.getTableName();
186             ITableMetaData metaData = new DefaultTableMetaData(tableName, columns);
187             this.consumer.startTable(metaData);
188             for (int i = 1; i < readData.size(); i++) {
189                 List rowList = (List) readData.get(i);
190                 Object[] row = rowList.toArray();
191                 for (int col = 0; col < row.length; col++) {
192                     row[col] = row[col].equals(NULL) ? null : row[col];
193                 }
194                 this.consumer.row(row);
195             }
196             this.consumer.endTable();
197         }
198         catch (PipelineException e) {
199             throw new DataSetException(e);
200         }
201         catch (IllegalInputCharacterException e) {
202             throw new DataSetException(e);
203         }
204         catch (IOException e) {
205             throw new DataSetException(e);
206         }
207     }
208 
209     /**
210      * Get a list of tables that this producer will create.
211      * 
212      * @param controlFilesDir the base directory
213      * @param tableList the table list
214      * 
215      * @return a list of Strings, where each item is a CSV file relative to the base URL
216      * 
217      * @throws IOException when IO on the base URL has issues.
218      */
219     public static List getTables(File controlFilesDir, File tableList) throws IOException 
220     {
221         logger.debug("getTables(controlFilesDir={}, tableList={}) - start", controlFilesDir, tableList);
222 
223         // Copy file into the control directory
224         File tmpTableList = new File(controlFilesDir, TMP_TABLE_LIST_FILENAME);
225         FileHelper.copyFile(tableList, tmpTableList);
226 
227         List orderedNames;
228         try {
229             orderedNames = FileHelper.readLines(tmpTableList);
230         }
231         finally {
232             boolean success = tmpTableList.delete();
233             if (!success) {
234                 throw new IOException("Deletion of temorary file failed: " + tmpTableList);
235             }
236         }
237         return orderedNames;
238     }
239 
240 }