📄 dumpmetadatatask.java
字号:
package org.apache.ddlutils.task;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.File;
import java.io.FileOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import org.apache.commons.collections.set.ListOrderedSet;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.dom4j.Document;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
/**
* A simple helper task that dumps information about a database using JDBC.
*
* @version $Revision: 289996 $
* @ant.task name="dumpMetadata"
*/
public class DumpMetadataTask extends Task
{
/** Methods that are filtered when enumerating the properties. */
private static final String[] IGNORED_PROPERTY_METHODS = { "getConnection", "getCatalogs", "getSchemas" };
/** The data source to use for accessing the database. */
private BasicDataSource _dataSource;
/** The file to write the dump to. */
private File _outputFile = null;
/** The encoding of the XML output file. */
private String _outputEncoding = "UTF-8";
/** The database catalog(s) to read. */
private String _catalogPattern = "%";
/** The database schema(s) to read. */
private String _schemaPattern = "%";
/** The pattern for reading all tables. */
private String _tablePattern = "%";
/** The pattern for reading all procedures. */
private String _procedurePattern = "%";
/** The pattern for reading all columns. */
private String _columnPattern = "%";
/** The tables types to read; <code>null</code> or an empty list means that we shall read every type. */
private String[] _tableTypes = null;
/** Whether to read tables. */
private boolean _dumpTables = true;
/** Whether to read procedures. */
private boolean _dumpProcedures = true;
/**
* Adds the data source to use for accessing the database.
*
* @param dataSource The data source
*/
public void addConfiguredDatabase(BasicDataSource dataSource)
{
_dataSource = dataSource;
}
/**
* Specifies the output file to which the database metadata is written to.
*
* @param outputFile The output file
* @ant.required
*/
public void setOutputFile(File outputFile)
{
_outputFile = outputFile;
}
/**
* Specifies the encoding of the output file.
*
* @param encoding The encoding
* @ant.not-required Per default, <code>UTF-8</code> is used.
*/
public void setOutputEncoding(String encoding)
{
_outputEncoding = encoding;
}
/**
* Sets the catalog pattern used when accessing the database.
*
* @param catalogPattern The catalog pattern
* @ant.not-required Per default, no specific catalog is used (value <code>%</code>).
*/
public void setCatalogPattern(String catalogPattern)
{
_catalogPattern = ((catalogPattern == null) || (catalogPattern.length() == 0) ? null : catalogPattern);
}
/**
* Sets the schema pattern used when accessing the database.
*
* @param schemaPattern The schema pattern
* @ant.not-required Per default, no specific schema is used (value <code>%</code>).
*/
public void setSchemaPattern(String schemaPattern)
{
_schemaPattern = ((schemaPattern == null) || (schemaPattern.length() == 0) ? null : schemaPattern);
}
/**
* Specifies the table to be processed. For details see
* <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/sql/DatabaseMetaData.html#getTables(java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String[])">java.sql.DatabaseMetaData#getTables</a>.
*
* @param tablePattern The table pattern
* @ant.not-required By default, all tables are read (value <code>%</code>).
*/
public void setTablePattern(String tablePattern)
{
_tablePattern = ((tablePattern == null) || (tablePattern.length() == 0) ? null : tablePattern);
}
/**
* Specifies the procedures to be processed. For details and typical table types see
* <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/sql/DatabaseMetaData.html#getProcedures(java.lang.String,%20java.lang.String,%20java.lang.String)">java.sql.DatabaseMetaData#getProcedures</a>.
*
* @param procedurePattern The procedure pattern
* @ant.not-required By default, all procedures are read (value <code>%</code>).
*/
public void setProcedurePattern(String procedurePattern)
{
_procedurePattern = ((procedurePattern == null) || (procedurePattern.length() == 0) ? null : procedurePattern);
}
/**
* Specifies the columns to be processed. For details and typical table types see
* <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/sql/DatabaseMetaData.html#getColumns(java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String[])">java.sql.DatabaseMetaData#getColumns</a>.
*
* @param columnPattern The column pattern
* @ant.not-required By default, all columns are read (value <code>%</code>).
*/
public void setColumnPattern(String columnPattern)
{
_columnPattern = ((columnPattern == null) || (columnPattern.length() == 0) ? null : columnPattern);
}
/**
* Specifies the table types to be processed. For details and typical table types see
* <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/sql/DatabaseMetaData.html#getTables(java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String[])">java.sql.DatabaseMetaData#getTables</a>.
*
* @param tableTypes The table types to read
* @ant.not-required By default, all types of tables are read.
*/
public void setTableTypes(String tableTypes)
{
ArrayList types = new ArrayList();
if (tableTypes != null)
{
StringTokenizer tokenizer = new StringTokenizer(tableTypes, ",");
while (tokenizer.hasMoreTokens())
{
String token = tokenizer.nextToken().trim();
if (token.length() > 0)
{
types.add(token);
}
}
}
_tableTypes = (String[])types.toArray(new String[types.size()]);
}
/**
* Specifies whether procedures shall be read from the database.
*
* @param readProcedures <code>true</code> if procedures shall be read
* @ant.not-required By default, procedures are read.
*/
public void setDumpProcedures(boolean readProcedures)
{
_dumpProcedures = readProcedures;
}
/**
* Specifies whether tables shall be read from the database.
*
* @param readTables <code>true</code> if tables shall be read
* @ant.not-required By default, tables are read.
*/
public void setDumpTables(boolean readTables)
{
_dumpTables = readTables;
}
/**
* {@inheritDoc}
*/
public void execute() throws BuildException
{
if (_dataSource == null)
{
log("No data source specified, so there is nothing to do.", Project.MSG_INFO);
return;
}
Connection connection = null;
try
{
Document document = DocumentFactory.getInstance().createDocument();
Element root = document.addElement("metadata");
root.addAttribute("driverClassName", _dataSource.getDriverClassName());
connection = _dataSource.getConnection();
dumpMetaData(root, connection.getMetaData());
OutputFormat outputFormat = OutputFormat.createPrettyPrint();
XMLWriter xmlWriter = null;
outputFormat.setEncoding(_outputEncoding);
if (_outputFile == null)
{
xmlWriter = new XMLWriter(System.out, outputFormat);
}
else
{
xmlWriter = new XMLWriter(new FileOutputStream(_outputFile), outputFormat);
}
xmlWriter.write(document);
xmlWriter.close();
}
catch (Exception ex)
{
throw new BuildException(ex);
}
finally
{
if (connection != null)
{
try
{
connection.close();
}
catch (SQLException ex)
{}
}
}
}
/**
* Dumps the database meta data into XML elements under the given element.
*
* @param element The XML element
* @param metaData The meta data
*/
private void dumpMetaData(Element element, DatabaseMetaData metaData) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException
{
// We rather iterate over the methods because most metadata properties
// do not follow the bean naming standard
Method[] methods = metaData.getClass().getMethods();
Set filtered = new HashSet(Arrays.asList(IGNORED_PROPERTY_METHODS));
for (int idx = 0; idx < methods.length; idx++)
{
// only no-arg methods that return something and that are not defined in Object
// we also filter certain methods
if ((methods[idx].getParameterTypes().length == 0) &&
(methods[idx].getReturnType() != null) &&
(Object.class != methods[idx].getDeclaringClass()) &&
!filtered.contains(methods[idx].getName()))
{
dumpProperty(element, metaData, methods[idx]);
}
}
dumpCatalogsAndSchemas(element, metaData);
if (_dumpTables)
{
dumpTables(element, metaData);
}
if (_dumpProcedures)
{
dumpProcedures(element, metaData);
}
}
/**
* Dumps the property represented by the given method.
*
* @param parent The parent XML element
* @param obj The application we're working on
* @param propGetter The method for accessing the property
*/
private void dumpProperty(Element parent, Object obj, Method propGetter)
{
try
{
addProperty(parent, getPropertyName(propGetter.getName()), propGetter.invoke(obj, null));
}
catch (Throwable ex)
{
log("Could not dump property "+propGetter.getName()+" because of "+ex.getMessage(), Project.MSG_WARN);
}
}
/**
* Adds a property to the given element, either as an attribute (primitive value or
* string) or as a sub element.
*
* @param element The XML element
* @param name The name of the property
* @param value The value of the property
*/
private void addProperty(Element element, String name, Object value)
{
if (value != null)
{
if (value.getClass().isArray())
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -