Permalink
Browse files

added missing plugins for plugin-views spec

  • Loading branch information...
1 parent f818173 commit 84ee8fab60eed6c43a630f25674d9109aed0c962 @graemerocher graemerocher committed Jan 20, 2012
Showing with 653 additions and 0 deletions.
  1. +53 −0 plugins/grails-db-util/DbUtilGrailsPlugin.groovy
  2. +7 −0 plugins/grails-db-util/grails-app/conf/BootStrap.groovy
  3. +1 −0 plugins/grails-db-util/grails-app/conf/BuildConfig.groovy
  4. +5 −0 plugins/grails-db-util/grails-app/conf/Config.groovy
  5. +5 −0 plugins/grails-db-util/grails-app/conf/UrlMappings.groovy
  6. +192 −0 ...-db-util/grails-app/controllers/org/codehaus/groovy/grails/plugins/dbutil/DbUtilController.groovy
  7. 0 plugins/grails-db-util/grails-app/i18n/messages.properties
  8. +40 −0 plugins/grails-db-util/grails-app/views/dbUtil/data.gsp
  9. +47 −0 plugins/grails-db-util/grails-app/views/dbUtil/info.gsp
  10. +37 −0 plugins/grails-db-util/grails-app/views/dbUtil/sql.gsp
  11. +37 −0 plugins/grails-db-util/grails-app/views/dbUtil/testWithPluginLayout.gsp
  12. +25 −0 plugins/grails-db-util/grails-app/views/layouts/full.gsp
  13. BIN plugins/grails-db-util/lib/commons-dbutils-1.1.jar
  14. +10 −0 plugins/grails-db-util/scripts/_Install.groovy
  15. +5 −0 plugins/grails-db-util/scripts/_Uninstall.groovy
  16. +10 −0 plugins/grails-db-util/scripts/_Upgrade.groovy
  17. +50 −0 plugins/resources-to-copy/ResourcesToCopyGrailsPlugin.groovy
  18. +32 −0 plugins/resources-to-copy/grails-app/conf/DataSource.groovy
  19. +11 −0 plugins/resources-to-copy/grails-app/conf/UrlMappings.groovy
  20. +2 −0 plugins/resources-to-copy/grails-app/conf/foo/plugin-bar.xml
  21. +2 −0 plugins/resources-to-copy/grails-app/conf/hibernate/custom-hib/my-plugin-config.xml
  22. +54 −0 plugins/resources-to-copy/grails-app/views/error.gsp
  23. +10 −0 plugins/resources-to-copy/scripts/_Install.groovy
  24. +5 −0 plugins/resources-to-copy/scripts/_Uninstall.groovy
  25. +10 −0 plugins/resources-to-copy/scripts/_Upgrade.groovy
  26. +1 −0 plugins/resources-to-copy/src/groovy/org/grails/resources-plugin/groovy-readme.txt
  27. +2 −0 plugins/resources-to-copy/src/java/resources-plugin/readme.txt
@@ -0,0 +1,53 @@
+class DbUtilGrailsPlugin {
+ def version = 0.3
+ def dependsOn = [:]
+
+ def author = "Tyler Williams"
+ def authorEmail = "kaerfredoc@gmail.com"
+ def title = "DB Utils - Embedded"
+ def description = '''Embedded dbs, like derby & in-memory HSQL only allow access from within the JVM that is accessing the db. This presents a problem that you cannot run an external db admin tool to work with the db while your grails app is running. To get around this limitation I wrote small plugin (1 controller & 3 gsps) that can be used to admin the db within the running grails' app.
+There are three actions with the following urls described below...
+
+/$appname$/dbUtil/info - Shows info about the db (tables/columns/column type, etc)
+/$appname$/dbUtil/data - Outputs all the actual data alphabetically by table
+/$appname$/dbUtil/sql - Allows free-form select/update/delete commands
+
+Note: I've included commons-dbutils-1.1 from apache in the lib directory.
+
+IMPORTANT: You will definitely want to protect this controller's url from unauthorized access since the sql action can be used to do just about anything.
+
+DbutilController.groovy
+data.gsp
+info.gsp
+sql.gsp'''
+
+ // URL to the plugin's documentation
+ def documentation = "http://grails.org/DbUtil+Plugin"
+
+ def doWithSpring = {
+ // TODO Implement runtime spring config (optional)
+ }
+
+ def doWithApplicationContext = { applicationContext ->
+ // TODO Implement post initialization spring config (optional)
+ }
+
+ def doWithWebDescriptor = { xml ->
+ // TODO Implement additions to web.xml (optional)
+ }
+
+ def doWithDynamicMethods = { ctx ->
+ // TODO Implement registering dynamic methods to classes (optional)
+ }
+
+ def onChange = { event ->
+ // TODO Implement code that is executed when any artefact that this plugin is
+ // watching is modified and reloaded. The event contains: event.source,
+ // event.application, event.manager, event.ctx, and event.plugin.
+ }
+
+ def onConfigChange = { event ->
+ // TODO Implement code that is executed when the project configuration changes.
+ // The event is the same as for 'onChange'.
+ }
+}
@@ -0,0 +1,7 @@
+class BootStrap {
+ def init = { servletContext ->
+ }
+
+ def destroy = {
+ }
+}
@@ -0,0 +1 @@
+grails.project.work.dir = "work"
@@ -0,0 +1,5 @@
+grails.config.locations = []
+
+// The following properties have been added by the Upgrade process...
+grails.views.default.codec="none" // none, html, base64
+grails.views.gsp.encoding="UTF-8"
@@ -0,0 +1,5 @@
+class UrlMappings {
+ static mappings = {
+ "$controller/$action?/$id?"()
+ }
+}
@@ -0,0 +1,192 @@
+package org.codehaus.groovy.grails.plugins.dbutil
+
+import java.sql.*
+import org.apache.commons.dbcp.*
+import javax.sql.*
+import org.apache.commons.dbutils.handlers.MapListHandler
+
+class DbUtilController {
+
+ DataSource dataSource
+ /* Column metadata...
+ COLUMN_NAME String => column name
+ DATA_TYPE int => SQL type from java.sql.Types
+ TYPE_NAME String => Data source dependent type name, for a UDT the type name is fully qualified
+ COLUMN_SIZE int => column size.
+ BUFFER_LENGTH is not used.
+ DECIMAL_DIGITS int => the number of fractional digits. Null is returned for data types where DECIMAL_DIGITS is not applicable.
+ NUM_PREC_RADIX int => Radix (typically either 10 or 2)
+ NULLABLE int => is NULL allowed.
+ columnNoNulls - might not allow NULL values
+ columnNullable - definitely allows NULL values
+ columnNullableUnknown - nullability unknown
+ REMARKS String => comment describing column (may be null)
+ COLUMN_DEF String => default value for the column, which should be interpreted as a string when the value is enclosed in single quotes (may be null)
+ SQL_DATA_TYPE int => unused
+ SQL_DATETIME_SUB int => unused
+ CHAR_OCTET_LENGTH int => for char types the maximum number of bytes in the column
+ ORDINAL_POSITION int => index of column in table (starting at 1)
+ IS_NULLABLE String => ISO rules are used to determine the nullability for a column.
+ YES --- if the parameter can include NULLs
+ NO --- if the parameter cannot include NULLs
+ empty string --- if the nullability for the parameter is unknown
+ SCOPE_CATLOG String => catalog of table that is the scope of a reference attribute (null if DATA_TYPE isn't REF)
+ SCOPE_SCHEMA String => schema of table that is the scope of a reference attribute (null if the DATA_TYPE isn't REF)
+ SCOPE_TABLE String => table name that this the scope of a reference attribure (null if the DATA_TYPE isn't REF)
+ SOURCE_DATA_TYPE short => source type of a distinct type or user-generated Ref type, SQL type from java.sql.Types (null if DATA_TYPE isn't DISTINCT or user-generated REF)
+ IS_AUTOINCREMENT String => Indicates whether this column is auto incremented
+ */
+ def index = {redirect(action: data, params: params)}
+
+ // Display database metadata
+ def info = {
+ def schemas = []
+ def tables = []
+ def columns = [:]
+
+
+ Connection conn = dataSource.getConnection()
+ def rs = conn.getMetaData()
+
+ // Get list of tables
+ def tmd = rs.getTables(null, null, null, null)
+ while (tmd.next()) {
+ if (tmd.getString("TABLE_TYPE") == "TABLE") {
+ schemas << tmd.getString("TABLE_SCHEM")
+ tables << tmd.getString("TABLE_NAME")
+ }
+ }
+
+ // Get list of columns for each table
+ def tableColMap = [:]
+ tables.each {tableName ->
+ def ResultSet colrs = rs.getColumns(null, null, tableName, null)
+ def tableCols = [:]
+ def isFirstRow = true
+ def colLabels = []
+ while (colrs.next()) {
+ if (isFirstRow) {
+ // This should be an arraylist of uppercase column names
+ colLabels = colrs.getMetaData().columnMetaData.columnLabel*.toUpperCase()
+ isFirstRow = false
+ }
+
+ // Check each that each metadata column exists in the result set and assign it to the map
+ def colParamMap = [:]
+ if (colLabels.contains("TYPE_NAME"))
+ colParamMap["TYPE_NAME"] = colrs.getString("TYPE_NAME")
+
+ if (colLabels.contains("COLUMN_SIZE"))
+ colParamMap["COLUMN_SIZE"] = colrs.getString("COLUMN_SIZE")
+
+ if (colLabels.contains("DECIMAL_DIGITS"))
+ colParamMap["DECIMAL_DIGITS"] = colrs.getString("DECIMAL_DIGITS")
+
+ if (colLabels.contains("DEFAULT_VALUE"))
+ colParamMap["DEFAULT_VALUE"] = colrs.getString("COLUMN_DEF")
+
+ if (colLabels.contains("IS_NULLABLE"))
+ colParamMap["IS_NULLABLE"] = colrs.getString("IS_NULLABLE")
+
+ if (colLabels.contains("IS_AUTOINCREMENT"))
+ colParamMap["IS_AUTOINCREMENT"] = colrs.getString("IS_AUTOINCREMENT")
+
+ // If the "COLUMN_NAME" column doesn't exist in the resultset we will get an exception which is fine
+ // since the operation depends on this column
+ tableCols[colrs.getString("COLUMN_NAME")] = colParamMap
+ }
+ // done w/ table
+ tableColMap[tableName] = tableCols
+ }
+
+ conn.close()
+
+ def dbModel = [tableList: tables.sort(), schemaList: schemas.unique().sort(), columnList: tableColMap]
+ render(view: "info", model: dbModel)
+ }
+
+ // Display dump of database tables
+ def data = {
+ def tables = []
+ def data = [:]
+
+ Connection conn = dataSource.getConnection()
+ def rs = conn.getMetaData()
+
+ // Get list of tables
+ def tmd = rs.getTables(null, null, null, null)
+ while (tmd.next()) {
+ if (tmd.getString("TABLE_TYPE") == "TABLE") {
+ tables << tmd.getString("TABLE_NAME")
+ }
+ }
+
+ // Get list of columns for each table
+ def tableColMap = [:]
+ tables.each {tableName ->
+ def cmd = rs.getColumns(null, null, tableName, null)
+ def tableCols = []
+ while (cmd.next()) {
+ tableCols.add(cmd.getString("COLUMN_NAME"))
+ }
+ // done w/ table
+ tableColMap[tableName] = tableCols
+ }
+
+ // get the data
+ def dataRow = [:]
+ tables.sort().each {tableName ->
+ def statement = conn.createStatement()
+ statement.execute("select * from ${tableName}")
+ def dataRs = statement.getResultSet()
+ // get data for each column
+ while (dataRs.next()) {
+ def rowData = []
+ tableColMap[tableName].sort().each {colName ->
+ rowData << dataRs.getString(colName)
+ }
+ if (dataRow[tableName] == null)
+ dataRow[tableName] = []
+
+ dataRow[tableName] << rowData
+ }
+ }
+
+ conn.close()
+
+ def dbModel = [tableList: tables.sort(), dataList: dataRow, columnList: tableColMap]
+ render(view: "data", model: dbModel)
+ }
+
+ def sql = {
+ if (!params.sqlText)
+ return
+ def sql = params.sqlText?.trim()
+ def retList
+ Connection conn = dataSource.getConnection()
+ Statement stmt = conn.createStatement()
+ ResultSet rs
+ if (sql[0..5].equalsIgnoreCase("SELECT")) {
+ rs = stmt.executeQuery(sql)
+ MapListHandler handler = new MapListHandler()
+ retList = handler.handle(rs)
+ }
+ else {
+ try {
+ def cnt = stmt.executeUpdate(sql)
+ retList = ["Rows affected": cnt]
+ }
+ catch (SQLException e) {
+ retList = ["The following error occurred": e.toString()]
+ }
+ }
+ conn.commit();
+ conn.close()
+ render(view: "sql", model: [dataList: retList, sqlText: sql])
+ }
+
+ /**
+ * Custom action for the 'test-plugin' functional tests.
+ */
+ def testWithPluginLayout = {}
+}
@@ -0,0 +1,40 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <meta name="layout" content="full"/>
+ <title>Database Dump</title>
+ <link rel="stylesheet" href="${resource(dir: '', file: 'css/data.css')}"/>
+ <g:javascript src="dojo-anim.js"/>
+</head>
+<body>
+
+<div class="body">
+ <h1>Display Data</h1>
+ <!--Tables-->
+ <g:each var="tableName" in="${tableList.sort()}">
+ <br/>
+ <b>${tableName}</b>
+ <table>
+ <thead>
+ <!--Columns-->
+ <tr>
+ <g:each var="col" in="${columnList[tableName].sort()}">
+ <th title="${col}">${col}</th>
+ </g:each>
+ </tr>
+ </thead>
+ <tbody>
+ <!--Data-->
+ <g:each in="${dataList[tableName]}" var="row">
+ <tr>
+ <g:each in="${row}" var="field">
+ <td>${field?.encodeAsHTML()}</td>
+ </g:each>
+ </tr>
+ </g:each>
+ </tbody>
+ </table>
+ </g:each>
+</div>
+</body>
+</html>
@@ -0,0 +1,47 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <meta name="layout" content="main"/>
+ <title>Database Info</title>
+ <link rel="stylesheet" href="${resource(dir: 'css', file: 'other.css', plugin: 'db-util')}" />
+ <link rel="stylesheet" href="${resource(dir: 'css', file: 'other-2.css')}" />
+ <link rel="stylesheet" href="${resource(dir: pluginContextPath, file: 'css/other-3.css')}" />
+ <g:javascript src="plugin-info.js" />
+</head>
+<body>
+<div class="body">
+ <h1>Database Info</h1>
+ <table>
+ <thead>
+ <tr>
+ <th title="Schema"/>
+ <th title="Table"/>
+ <th title="Column"/>
+ <th title="Parms"/>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>${schemaList[0].encodeAsHTML()}</td>
+ </tr>
+ <!--Tables-->
+ <g:each in="${tableList.sort()}" status="i" var="table">
+ <tr>
+ <td>&nbsp;</td>
+ <td>${table.encodeAsHTML()}</td>
+ </tr>
+ <!--Columns-->
+ <g:each in="${columnList[table]}" status="j" var="column">
+ <tr>
+ <td>&nbsp;</td>
+ <td>&nbsp;</td>
+ <td>${column.key?.encodeAsHTML()}</td>
+ <td>${column.value?.encodeAsHTML()}</td>
+ </tr>
+ </g:each>
+ </g:each>
+ </tbody>
+ </table>
+</div>
+</body>
+</html>
@@ -0,0 +1,37 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <meta name="layout" content="full"/>
+ <title>Execute SQL</title>
+</head>
+<body>
+<div class="body">
+ <h1>Execute SQL</h1>
+ <g:form action="sql" method="post">
+ <div><g:textArea style="width:95%" id="sqlText" cols="1000" rows="10" name='sqlText' value='${sqlText}'/></div>
+ <div><g:submitButton name="run" value='Execute'/></div>
+ </g:form>
+ <table border="1">
+
+ <g:each in="${dataList}" status='i' var="row">
+ <g:if test='${i==0}'>
+ <tr>
+ <g:each in="${row}" var="col">
+ <th>
+ ${col.key}
+ </th>
+ </g:each>
+ </tr>
+ </g:if>
+ <tr>
+ <g:each in="${row}" var="col">
+ <td>
+ ${col.value}
+ </td>
+ </g:each>
+ </tr>
+ </g:each>
+ </table>
+</div>
+</body>
+</html>
Oops, something went wrong.

0 comments on commit 84ee8fa

Please sign in to comment.