001    //$HeadURL: svn+ssh://developername@svn.wald.intevation.org/deegree/base/trunk/src/org/deegree/tools/datastore/DBSchemaToDatastoreConf.java $
002    /*----------------------------------------------------------------------------
003     This file is part of deegree, http://deegree.org/
004     Copyright (C) 2001-2009 by:
005     Department of Geography, University of Bonn
006     and
007     lat/lon GmbH
008    
009     This library is free software; you can redistribute it and/or modify it under
010     the terms of the GNU Lesser General Public License as published by the Free
011     Software Foundation; either version 2.1 of the License, or (at your option)
012     any later version.
013     This library is distributed in the hope that it will be useful, but WITHOUT
014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016     details.
017     You should have received a copy of the GNU Lesser General Public License
018     along with this library; if not, write to the Free Software Foundation, Inc.,
019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020    
021     Contact information:
022    
023     lat/lon GmbH
024     Aennchenstr. 19, 53177 Bonn
025     Germany
026     http://lat-lon.de/
027    
028     Department of Geography, University of Bonn
029     Prof. Dr. Klaus Greve
030     Postfach 1147, 53001 Bonn
031     Germany
032     http://www.geographie.uni-bonn.de/deegree/
033    
034     e-mail: info@deegree.org
035     ----------------------------------------------------------------------------*/
036    package org.deegree.tools.datastore;
037    
038    import java.io.BufferedReader;
039    import java.io.File;
040    import java.io.FileOutputStream;
041    import java.io.IOException;
042    import java.io.InputStreamReader;
043    import java.io.StringReader;
044    import java.net.URL;
045    import java.security.InvalidParameterException;
046    import java.sql.Connection;
047    import java.sql.ResultSet;
048    import java.sql.ResultSetMetaData;
049    import java.sql.SQLException;
050    import java.sql.Statement;
051    import java.util.HashMap;
052    import java.util.Map;
053    
054    import javax.xml.transform.TransformerException;
055    
056    import org.deegree.datatypes.Types;
057    import org.deegree.datatypes.UnknownTypeException;
058    import org.deegree.framework.log.ILogger;
059    import org.deegree.framework.log.LoggerFactory;
060    import org.deegree.framework.util.FileUtils;
061    import org.deegree.framework.util.StringTools;
062    import org.deegree.framework.xml.XMLFragment;
063    import org.deegree.io.DBConnectionPool;
064    import org.deegree.io.DBPoolException;
065    import org.deegree.io.dbaseapi.DBaseException;
066    import org.deegree.io.shpapi.HasNoDBaseFileException;
067    import org.deegree.io.shpapi.ShapeFile;
068    import org.xml.sax.SAXException;
069    
070    /**
071     * Example: java -classpath .;deegree.jar;$databasedriver.jar
072     * org.deegree.tools.datastore.DBSchemaToDatastoreConf -tables mytable,myothertable -user dev
073     * -password dev -driver oracle.jdbc.OracleDriver -url jdbc:oracle:thin:@localhost:1521:devs -output
074     * e:/temp/schema.xsd<br>
075     * or for shapefile:<br>
076     * java -classpath .;deegree.jar org.deegree.tools.datastore.DBSchemaToDatastoreConf -url
077     * c:/data/myshape -driver SHAPE -output e:/temp/schema.xsd<br>
078     * 
079     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
080     * @author last edited by: $Author: apoth $
081     * 
082     * @version $Revision: 8049 $, $Date: 2007-08-23 10:19:28 +0200 (Do, 23 Aug 2007) $
083     */
084    public class DBSchemaToDatastoreConf {
085    
086        private static final ILogger LOG = LoggerFactory.getLogger( DBSchemaToDatastoreConf.class );
087    
088        private String[] tables;
089    
090        private String user;
091    
092        private String pw;
093    
094        private String driver;
095    
096        private String logon;
097    
098        private String backend;
099    
100        private String vendor;
101    
102        private String srs;
103    
104        private String defaultPKey;
105    
106        private String insert;
107    
108        private String update;
109    
110        private String delete;
111    
112        private String idGenerator;
113    
114        private String sequence;
115    
116        private Integer defaultSRID;
117    
118        private String omitFidAsProperty;
119    
120        /**
121         * 
122         * @param tables
123         *            list of table names used for one featuretype
124         * @param user
125         *            database user
126         * @param pw
127         *            users password
128         * @param driver
129         *            database driver
130         * @param logon
131         *            database URL/logon
132         * @param srs
133         * @throws IOException
134         */
135        public DBSchemaToDatastoreConf( String[] tables, String user, String pw, String driver, String logon, String srs,
136                                        String pkey, Integer srid, String insert, String update, String delete,
137                                        String idGenerator, String sequence, String omitFidAsProperty ) throws IOException {
138            this.driver = driver;
139            this.logon = logon;
140            this.pw = pw;
141            this.user = user;
142            this.tables = tables;
143            if ( srs != null ) {
144                this.srs = srs;
145            } else {
146                this.srs = readUserInput( DBSchemaToDatastoreConfSQLMSGAccess.getMessage( "ENTERSRS" ), false );
147            }
148    
149            if ( driver.toUpperCase().indexOf( "ORACLE" ) > -1 ) {
150                backend = "ORACLE";
151                vendor = backend;
152            } else if ( driver.toUpperCase().indexOf( "POSTGRES" ) > -1 ) {
153                backend = "POSTGIS";
154                vendor = backend;
155            } else if ( driver.toUpperCase().contains( "SHAPE" ) ) {
156                backend = "SHAPE";
157                vendor = backend;
158            } else {
159                backend = "GENERICSQL";
160                vendor = getVendor( driver );
161            }
162            this.defaultPKey = pkey;
163            this.defaultSRID = srid;
164            this.insert = insert;
165            this.delete = delete;
166            this.update = update;
167            this.idGenerator = idGenerator;
168            this.sequence = sequence;
169            this.omitFidAsProperty = omitFidAsProperty;
170        }
171    
172        private String getVendor( String driver ) {
173            // find out which database is used
174            String vendor = null;
175            if ( driver.toUpperCase().contains( "POSTGRES" ) ) {
176                backend = "POSTGRES";
177            } else if ( driver.toUpperCase().contains( "SQLSERVER" ) ) {
178                backend = "SQLSERVER";
179            } else if ( driver.toUpperCase().contains( "INGRES" ) || driver.equals( "ca.edbc.jdbc.EdbcDriver" ) ) {
180                backend = "INGRES";
181            } else if ( driver.toUpperCase().contains( "HSQLDB" ) ) {
182                backend = "HSQLDB";
183            } else {
184                backend = "SHAPE";
185            }
186            return vendor;
187        }
188    
189        /**
190         * creates a schema/datastore configuration for accessin database table through deegree WFS
191         * 
192         * @return a schema/datastore configuration for accessin database table through deegree WFS
193         * @throws Exception
194         */
195        public String run()
196                                throws Exception {
197            StringBuffer sb = new StringBuffer( 5000 );
198    
199            if ( backend.equals( "SHAPE" ) ) {
200                handleShape( sb );
201            } else {
202                handleDatabase( sb );
203            }
204            printFooter( sb );
205    
206            return sb.toString();
207        }
208    
209        /**
210         * creates a datastore configuration for a database backend
211         * 
212         * @param sb
213         * @throws DBPoolException
214         * @throws SQLException
215         * @throws Exception
216         * @throws UnknownTypeException
217         * @throws IOException
218         */
219        private void handleDatabase( StringBuffer sb )
220                                throws DBPoolException, SQLException, Exception, UnknownTypeException, IOException {
221            printHeader( sb );
222    
223            for ( int k = 0; k < tables.length; k++ ) {
224                LOG.logInfo( "Opening JDBC connection with driver: " + driver );
225                LOG.logInfo( "Opening JDBC connection to database : " + logon );
226    
227                Connection con = DBConnectionPool.getInstance().acquireConnection( driver, logon, user, pw );
228                Statement stmt = con.createStatement();
229                // ensure that we do not get a filled resultset because we just
230                // need the metainformation
231                LOG.logDebug( "read table: ", tables[k] );
232                ResultSet rs = stmt.executeQuery( "select * from " + tables[k] + " where 1 = 2" );
233    
234                ResultSetMetaData rsmd = rs.getMetaData();
235                int cols = rsmd.getColumnCount();
236    
237                printComplexHeader( sb, tables[k] );
238                for ( int i = 0; i < cols; i++ ) {
239                    if ( rsmd.getColumnType( i + 1 ) != 2004 ) {
240                        int tp = rsmd.getColumnType( i + 1 );
241                        String tpn = Types.getTypeNameForSQLTypeCode( tp );
242                        LOG.logDebug( tables[k] + '.' + rsmd.getColumnName( i + 1 ) + ": " + tpn + " " + rsmd.getPrecision( i + 1 ) +  " " + rsmd.getScale( i + 1 ) ); 
243                        // add property just if type != BLOB
244                        if ( !"true".equals( omitFidAsProperty )
245                             || !getPKeyName( tables[k] ).equalsIgnoreCase( rsmd.getColumnName( i + 1 ) ) ) {
246                            printProperty( tables[k], rsmd.getColumnName( i + 1 ), rsmd.getColumnType( i + 1 ), tpn,
247                                           rsmd.getPrecision( i + 1 ), rsmd.getScale( i + 1 ), sb );
248                        }
249                    } else {
250                        String msg = StringTools.concat( 200, "skiped: ", tables[k], '.', rsmd.getColumnName( i + 1 ),
251                                                         ": ", rsmd.getColumnTypeName( i + 1 ) );
252                        LOG.logDebug( msg );
253                    }
254                }
255    
256                DBConnectionPool.getInstance().releaseConnection( con, driver, logon, user, pw );
257                printComplexFooter( sb );
258            }
259        }
260    
261        /**
262         * creates a datastore configuration for a shapefile backend
263         * 
264         * @param sb
265         * @throws IOException
266         * @throws Exception
267         * @throws HasNoDBaseFileException
268         * @throws DBaseException
269         * @throws DBPoolException
270         * @throws SQLException
271         * @throws UnknownTypeException
272         */
273        private void handleShape( StringBuffer sb )
274                                throws IOException, Exception, HasNoDBaseFileException, DBaseException, DBPoolException,
275                                SQLException, UnknownTypeException {
276            // TODO throw RE if tbl.len != 1
277    
278            printShapeHeader( sb, tables[0] );
279    
280            File f = new File( tables[0] );
281            ShapeFile shp = new ShapeFile( f.getAbsolutePath() );
282    
283            printComplexHeader( sb, f.getName() );
284    
285            String[] dataTypes = shp.getDataTypes();
286    
287            printProperty( f.getName(), "GEOM", 2002, "GEOM", -9999, -9999, sb );
288    
289            String[] props = shp.getProperties();
290            for ( int i = 0; i < props.length; i++ ) {
291                int sqlCode = toSQLCode( dataTypes[i] ), precision, scale;
292                printProperty( tables[0], props[i], sqlCode, Types.getTypeNameForSQLTypeCode( sqlCode ),
293                               1, toScale( dataTypes[i] ), sb );
294            }
295    
296            printComplexFooter( sb );
297    
298            shp.close();
299        }
300    
301        /**
302         * @return scale for a dBase numerical type
303         * 
304         * @param dbfType
305         */
306        private int toScale( String dbfType ) {
307            int precision = 0;
308    
309            if ( dbfType.equalsIgnoreCase( "I" ) ) {
310                precision = 1;
311            } 
312    
313            return precision;
314        }
315    
316        /**
317         * @return the SQL type code for a dBase type char
318         * 
319         * @param dbfType
320         */
321        private int toSQLCode( String dbfType ) {
322    
323            int type = -9999;
324    
325            if ( dbfType.equalsIgnoreCase( "C" ) ) {
326                type = Types.VARCHAR;
327            } else if ( dbfType.equalsIgnoreCase( "F" ) || dbfType.equalsIgnoreCase( "N" ) 
328                            || dbfType.equalsIgnoreCase( "I" ) ) {
329                type = Types.NUMERIC;
330            } else if ( dbfType.equalsIgnoreCase( "D" ) || dbfType.equalsIgnoreCase( "M" ) ) {
331                type = Types.DATE;
332            } else if ( dbfType.equalsIgnoreCase( "L" ) ) {
333                type = Types.BOOLEAN;
334            } else if ( dbfType.equalsIgnoreCase( "B" ) ) {
335                type = Types.BLOB;
336            }
337    
338            if ( type == -9999 ) {
339                throw new RuntimeException( "Type '" + dbfType + "' is not suported." );
340            }
341    
342            return type;
343        }
344    
345        /**
346         * adds the header of the configuration/schema for a database datastore
347         * 
348         * @param sb
349         */
350        private void printHeader( StringBuffer sb ) {
351    
352            String s = DBSchemaToDatastoreConfSQLXSDAccess.getXSDFragment( "HEADER", backend, srs, driver, logon, user, pw );
353            sb.append( s );
354    
355        }
356    
357        /**
358         * adds the header of the configuration/schema for a shapefile datastore
359         * 
360         * @param sb
361         * @param filename
362         *            path to the shapefile
363         */
364        private void printShapeHeader( StringBuffer sb, String filename ) {
365    
366            String s = DBSchemaToDatastoreConfSQLXSDAccess.getXSDFragment( "SHAPEHEADER", filename, srs );
367            sb.append( s );
368    
369        }
370    
371        /**
372         * adds a header for a feature type to the schema
373         * 
374         * @param sb
375         * @param table
376         *            name of the table the feature type is assigned to
377         * @throws Exception
378         */
379        private void printComplexHeader( StringBuffer sb, String table )
380                                throws Exception {
381            String idField = getPKeyName( table );
382            String tp = "INTEGER";
383            if ( backend.equals( "GENERICSQL" ) ) {
384                tp = "VARCHAR";
385            }
386            String idg = "";
387            if ( "DB_MAX".equalsIgnoreCase( idGenerator ) ) {
388                idg = DBSchemaToDatastoreConfSQLXSDAccess.getXSDFragment( "DB_MAX_IDGENERATOR", table, idField );
389            } else if ( "DB_SEQ".equalsIgnoreCase( idGenerator ) && sequence != null ) {
390                idg = DBSchemaToDatastoreConfSQLXSDAccess.getXSDFragment( "DB_SEQ_IDGENERATOR", sequence );
391            }
392            String s = DBSchemaToDatastoreConfSQLXSDAccess.getXSDFragment( "COMPLEXHEADER", table, table, table, idField,
393                                                                           tp, table, update, delete, insert, idg );
394            sb.append( s );
395    
396        }
397    
398        /**
399         * adds the footer of a feature type definition
400         * 
401         * @param sb
402         */
403        private void printComplexFooter( StringBuffer sb ) {
404            sb.append( DBSchemaToDatastoreConfSQLXSDAccess.getXSDFragment( "COMPLEXFOOTER" ) );
405        }
406    
407        /**
408         * prints XSD footer
409         * 
410         * @param sb
411         */
412        private void printFooter( StringBuffer sb ) {
413            sb.append( DBSchemaToDatastoreConfSQLXSDAccess.getXSDFragment( "FOOTER" ) );
414        }
415    
416        /**
417         * adds a property assigned to a database table field to the schema
418         * 
419         * @param tableName
420         *            table name
421         * @param name
422         *            property name
423         * @param type
424         *            xsd type name
425         * @param typeName
426         *            SQL type name
427         * @param precision
428         *            number precision if type is a number
429         * @param sb
430         * @throws SQLException
431         * @throws DBPoolException
432         * @throws IOException
433         */
434        private void printProperty( String tableName, String name, int type, String typeName, int precision, int scale, StringBuffer sb )
435                                throws DBPoolException, SQLException, IOException {
436    
437            String tp = Types.getXSDTypeForSQLType( type, precision, scale );
438            if ( !tp.startsWith( "gml:" ) ) {
439                tp = "xsd:" + tp;
440            }
441    
442            if ( tp.equals( "gml:GeometryPropertyType" ) ) {
443                int srid = getSRID( tableName, name );
444                String s = DBSchemaToDatastoreConfSQLXSDAccess.getXSDFragment( "GEOMPROPERTY", name.toLowerCase(), tp,
445                                                                               name, "" + srid );
446                sb.append( s );
447            } else {
448                String s = DBSchemaToDatastoreConfSQLXSDAccess.getXSDFragment( "PROPERTY", name.toLowerCase(), tp, name,
449                                                                               typeName.toUpperCase() );
450                sb.append( s );
451            }
452        }
453    
454        private int getSRID( String tableName, String columnName )
455                                throws SQLException, DBPoolException, IOException {
456    
457            if ( defaultSRID != null ) {
458                return defaultSRID;
459            }
460    
461            int srid = -1;
462            String query = DBSchemaToDatastoreConfSQLSQLAccess.getSQLStatement( vendor + "_SRID", tableName.toUpperCase(),
463                                                                                columnName.toUpperCase() );
464            LOG.logInfo( query );
465            Connection con = null;
466            Statement stmt = null;
467            ResultSet rs = null;
468            if ( query != null && query.indexOf( "not found$" ) < 0 ) {
469                try {
470                    con = DBConnectionPool.getInstance().acquireConnection( driver, logon, user, pw );
471                    stmt = con.createStatement();
472                    rs = stmt.executeQuery( query );
473    
474                    while ( rs.next() ) {
475                        srid = rs.getInt( 1 );
476                    }
477    
478                    if ( srid == 0 ) {
479                        srid = -1;
480                    }
481    
482                } catch ( SQLException e ) {
483                    System.out.println( DBSchemaToDatastoreConfSQLMSGAccess.getMessage( "ERRORSRID" ) + e.getMessage() );
484                    System.out.println( DBSchemaToDatastoreConfSQLMSGAccess.getMessage( "ENTERFIELD" ) );
485                } finally {
486                    rs.close();
487                    stmt.close();
488                    DBConnectionPool.getInstance().releaseConnection( con, driver, logon, user, pw );
489                }
490            } else {
491                System.out.println( DBSchemaToDatastoreConfSQLMSGAccess.getMessage( "NOSRIDQUERY" ) );
492            }
493            if ( srid == -1 ) {
494                String tmp = DBSchemaToDatastoreConfSQLMSGAccess.getMessage( "ENTERSRID" );
495                srid = Integer.parseInt( readUserInput( tmp, false ) );
496            }
497            return srid;
498        }
499    
500        /**
501         * returns the name of the primary key of the passed table
502         * 
503         * @param table
504         * @return the name of the primary key of the passed table
505         * @throws DBPoolException
506         * @throws SQLException
507         * @throws IOException
508         */
509        private String getPKeyName( String table )
510                                throws DBPoolException, SQLException, IOException {
511    
512            if ( defaultPKey != null ) {
513                return defaultPKey;
514            }
515    
516            String query = DBSchemaToDatastoreConfSQLSQLAccess.getSQLStatement( vendor + "_ID", table.toUpperCase() );
517            LOG.logInfo( query );
518            Object id = null;
519            Statement stmt = null;
520            ResultSet rs = null;
521            if ( query != null && query.indexOf( "not found$" ) < 0 ) {
522                Connection con = DBConnectionPool.getInstance().acquireConnection( driver, logon, user, pw );
523                try {
524                    stmt = con.createStatement();
525                    rs = stmt.executeQuery( query );
526    
527                    if ( rs.next() ) {
528                        id = rs.getObject( 1 );
529                    }
530                } catch ( Exception e ) {
531                    System.out.println( DBSchemaToDatastoreConfSQLMSGAccess.getMessage( "ERRORPK" ) + e.getMessage() );
532                    System.out.println( DBSchemaToDatastoreConfSQLMSGAccess.getMessage( "ENTERFIELD" ) );
533                } finally {
534                    rs.close();
535                    stmt.close();
536                    DBConnectionPool.getInstance().releaseConnection( con, driver, logon, user, pw );
537                }
538            } else {
539                System.out.println( DBSchemaToDatastoreConfSQLMSGAccess.getMessage( "NOPKQUERY" ) );
540            }
541            if ( id == null ) {
542                id = readUserInput( DBSchemaToDatastoreConfSQLMSGAccess.getMessage( "ENTERPK" ), false );
543            }
544            return id.toString();
545        }
546    
547        private static void validate( Map<String, String> map )
548                                throws InvalidParameterException, IOException {
549            if ( map.get( "-?" ) != null || map.get( "-h" ) != null || map.get( "-help" ) != null ) {
550                printHelp();
551                System.exit( 1 );
552            }
553            if ( map.get( "-tables" ) == null ) {
554                String s = readUserInput( DBSchemaToDatastoreConfSQLMSGAccess.getMessage( "ENTERTABLES" ), false );
555                map.put( "-tables", s );
556            }
557    
558            if ( map.get( "-driver" ) == null ) {
559                String s = readUserInput( DBSchemaToDatastoreConfSQLMSGAccess.getMessage( "ENTERDRIVER" ), false );
560                map.put( "-driver", s );
561            }
562    
563            if ( map.get( "-user" ) == null ) {
564                if ( !"SHAPE".equals( map.get( "-driver" ) ) ) {
565                    String s = readUserInput( DBSchemaToDatastoreConfSQLMSGAccess.getMessage( "ENTERUSER" ), false );
566                    map.put( "-user", s );
567                }
568            }
569    
570            if ( map.get( "-password" ) == null ) {
571                if ( !"SHAPE".equals( map.get( "-driver" ) ) ) {
572                    String s = readUserInput( DBSchemaToDatastoreConfSQLMSGAccess.getMessage( "ENTERPASSWORD" ), false );
573                    map.put( "-password", s );
574                } else {
575                    map.put( "-password", " " );
576                }
577            }
578    
579            if ( map.get( "-url" ) == null && !"SHAPE".equalsIgnoreCase( (String) map.get( "-driver" ) ) ) {
580                String s = readUserInput( DBSchemaToDatastoreConfSQLMSGAccess.getMessage( "ENTERURL" ), false );
581                map.put( "-url", s );
582            }
583            if ( map.get( "-output" ) == null ) {
584                String s = readUserInput( DBSchemaToDatastoreConfSQLMSGAccess.getMessage( "ENTEROUTPUT" ), false );
585                map.put( "-output", s );
586            }
587        }
588    
589        private static void printHelp()
590                                throws IOException {
591            URL url = DBSchemaToDatastoreConf.class.getResource( "DBSchemaToDatastoreConfHelp.txt" );
592            System.out.println( FileUtils.readTextFile( url ) );
593        }
594    
595        /**
596         * @param args
597         * @throws IOException
598         * @throws SAXException
599         * @throws TransformerException
600         * @throws Exception
601         */
602        public static void main( String[] args )
603                                throws Exception {
604    
605            Map<String, String> map = new HashMap<String, String>();
606            for ( int i = 0; i < args.length; ) {
607                String first = args[i++];
608                if ( "?".equals( first ) || "-h".equals( first ) || "-help".equals( first ) ) {
609                    printHelp();
610                    System.exit( 0 );
611                }
612                map.put( first, args[i++] );
613            }
614    
615            try {
616                validate( map );
617            } catch ( InvalidParameterException ipe ) {
618                LOG.logError( ipe.getMessage() );
619                printHelp();
620                System.exit( 1 );
621            }
622            LOG.logDebug( "Resulting commandline arguments and their values {argument=value, ...}: " + map );
623            String tmp = (String) map.get( "-tables" );
624            String[] tables = StringTools.toArray( tmp, ",;|", true );
625            String user = (String) map.get( "-user" );
626            String pw = (String) map.get( "-password" );
627            String driver = (String) map.get( "-driver" );
628            String url = (String) map.get( "-url" );
629            String output = (String) map.get( "-output" );
630            String srs = (String) map.get( "-srs" );
631            String insert = "false";
632            if ( "true".equalsIgnoreCase( map.get( "-insert" ) ) ) {
633                insert = "true";
634            }
635            String delete = "false";
636            if ( "true".equalsIgnoreCase( map.get( "-delete" ) ) ) {
637                delete = "true";
638            }
639            String update = "false";
640            if ( "true".equalsIgnoreCase( map.get( "-update" ) ) ) {
641                update = "true";
642            }
643            String idGenerator = (String) map.get( "-idGenerator" );
644            String sequence = (String) map.get( "-sequence" );
645    
646            String omitFidAsProperty = "false";
647            if ( "true".equalsIgnoreCase( map.get( "-omitFidAsProperty" ) ) ) {
648                omitFidAsProperty = "true";
649            }
650    
651            // hidden parameters to ease bulk processing, if provided, these values determine
652            // primary key column name and srid for all tables
653            String pkey = (String) map.get( "-pkey" );
654            String sridString = (String) map.get( "-srid" );
655            Integer srid = null;
656            if ( sridString != null ) {
657                srid = Integer.parseInt( sridString );
658            }
659    
660            DBSchemaToDatastoreConf stc = new DBSchemaToDatastoreConf( tables, user, pw, driver, url, srs, pkey, srid,
661                                                                       insert, update, delete, idGenerator, sequence,
662                                                                       omitFidAsProperty );
663            String conf = null;
664            try {
665                conf = stc.run();
666            } catch ( Exception e ) {
667                LOG.logError( e.getMessage(), e );
668                System.exit( 1 );
669            }
670            storeSchema( output, conf );
671            System.exit( 0 );
672        }
673    
674        /**
675         * 
676         * @param output
677         * @param conf
678         * @throws IOException
679         * @throws SAXException
680         * @throws TransformerException
681         */
682        private static void storeSchema( String output, String conf )
683                                throws SAXException, IOException, TransformerException {
684            if ( conf != null ) {
685                XMLFragment xml = new XMLFragment();
686                xml.load( new StringReader( conf ), XMLFragment.DEFAULT_URL );
687                FileOutputStream fos = new FileOutputStream( output );
688                xml.prettyPrint( fos );
689                fos.close();
690            }
691        }
692    
693        /**
694         * This function prints a message on the command line and asks the user for an input, returns
695         * the text the User has typed, null otherwise
696         * 
697         * @param describtion
698         *            The message to be displayed to the user asking for a certain text to type
699         * @return the read text, or null if nothing was read
700         * @throws IOException
701         */
702        private static String readUserInput( String describtion, boolean acceptNull )
703                                throws IOException {
704    
705            String result = null;
706            do {
707                System.out.print( describtion );
708                System.out.println( ':' );
709                BufferedReader reader = new BufferedReader( new InputStreamReader( System.in ) );
710                result = reader.readLine();
711            } while ( !acceptNull && ( result == null || result.trim().length() == 0 ) );
712            return result;
713    
714        }
715    }