001: /* Copyright 2002 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal.car;
007:
008: import java.io.PrintWriter;
009: import java.io.StringWriter;
010: import java.net.URL;
011:
012: import org.apache.commons.logging.Log;
013: import org.apache.commons.logging.LogFactory;
014: import org.jasig.portal.tools.dbloader.Configuration;
015: import org.jasig.portal.tools.dbloader.DbLoader;
016: import org.xml.sax.Attributes;
017: import org.xml.sax.SAXException;
018: import org.xml.sax.helpers.DefaultHandler;
019:
020: /**
021: * Processes the database tag looking for two element that should each
022: * contain a file path suitable for loading via classloader.findResource().
023: * The "tables" tag should point to a file having the appropriate format for
024: * creating tables in the portal's database using DbLoader and hence should be
025: * structured identically to uPortal's default data structure definition file
026: * tables.xml. The "data" tag is optional but if included should point to file
027: * having the appropriate format for loading with DbLoader the tables created
028: * by tables.xml and hence should be structured identically to uPortal's
029: * default data set file data.xml.
030: *
031: * @author Mark Boyd {@link <a href="mailto:mark.boyd@engineer.com">mark.boyd@engineer.com</a>}
032: * @version $Revision: 36690 $ $Date: 2006-08-25 14:03:25 -0700 (Fri, 25 Aug 2006) $
033: */
034: public class DatabaseTagHandler extends DefaultHandler {
035: private static final Log log = LogFactory
036: .getLog(DatabaseTagHandler.class);
037: private boolean CREATE_SCRPT_DFLT = false;
038: private boolean POP_TBL_DFLT = true;
039: private boolean CREATE_TBL_DFLT = true;
040: private boolean DROP_TBL_DFLT = false;
041:
042: private boolean createScript;
043: private boolean populateTables;
044: private boolean createTables;
045: private boolean dropTables;
046:
047: private ParsingContext ctx = null;
048: private String tables = null;
049: private String data = null;
050: private StringBuffer chars = null;
051:
052: /**
053: * Construct a DatabaseHandler that receives events from parsing
054: * a channel archive deployment descriptor but only for any contained
055: * database elements and their children.
056: *
057: * @param ctx
058: */
059: DatabaseTagHandler(ParsingContext ctx) {
060: this .ctx = ctx;
061: resetValues();
062: }
063:
064: ///////////////////// Content Handler Implementations //////////////////
065:
066: /**
067: * Handle start element events.
068: */
069: public void startElement(String namespaceURI, String localName,
070: String qName, Attributes atts) throws SAXException {
071: this .chars = new StringBuffer();
072: }
073:
074: /**
075: * Handle the characters event to capture textual content for elements.
076: */
077: public void characters(char[] ch, int start, int length)
078: throws SAXException {
079: chars.append(ch, start, length);
080: }
081:
082: /**
083: * Handle the closing element event.
084: */
085: public void endElement(String namespaceURI, String localName,
086: String qName) throws SAXException {
087: if (qName.equals("tables"))
088: this .tables = this .chars.toString();
089: else if (qName.equals("data"))
090: this .data = this .chars.toString();
091: else if (qName.equals("drop-tables"))
092: this .dropTables = getBoolean(chars.toString(),
093: DROP_TBL_DFLT);
094: else if (qName.equals("create-tables"))
095: this .createTables = getBoolean(chars.toString(),
096: CREATE_TBL_DFLT);
097: else if (qName.equals("populate-tables"))
098: this .populateTables = getBoolean(chars.toString(),
099: POP_TBL_DFLT);
100: else if (qName.equals("create-script"))
101: this .createScript = getBoolean(chars.toString(),
102: CREATE_SCRPT_DFLT);
103: else if (qName.equals(DescriptorHandler.DATABASE_TAG_NAME)
104: && ctx.getPath().equals(DescriptorHandler.DBDEFS)) {
105: // leaving block so run dbloader for acquired tables and data files
106: loadDatabase();
107:
108: // reset all values for next database element if any
109: resetValues();
110: }
111: }
112:
113: /**
114: * @param string
115: * @return
116: */
117: private boolean getBoolean(String string, boolean deflt) {
118: if (string == null)
119: return deflt;
120: if (string.equals("false"))
121: return false;
122: if (string.equals("true"))
123: return true;
124: return deflt;
125: }
126:
127: /**
128: *
129: */
130: private void resetValues() {
131: tables = null;
132: data = null;
133: dropTables = DROP_TBL_DFLT;
134: createTables = CREATE_TBL_DFLT;
135: createScript = CREATE_SCRPT_DFLT;
136: populateTables = POP_TBL_DFLT;
137: }
138:
139: /**
140: * Load the database using DbLoader.
141: */
142: private void loadDatabase() {
143: if (tables == null) {
144: log
145: .error("A database declaration in a channel deployment descriptor "
146: + "must contain a non-empty <tables> element to "
147: + "successfully create tables for the channel and populate "
148: + "them with data. Declaration ignored.");
149: return;
150: }
151: try {
152: ClassLoader cl = CarResources.getInstance()
153: .getClassLoader();
154: URL dataURL = null;
155:
156: if (data != null) {
157: dataURL = cl.getResource(data);
158:
159: if (dataURL == null) {
160: log.error("JAR file = '"
161: + ctx.getJarFile().getName()
162: + "' unable to find specified data file '"
163: + data + "'");
164: }
165: }
166: URL tablesURL = cl.getResource(tables);
167:
168: if (tablesURL == null) {
169: log.error("JAR file = '" + ctx.getJarFile().getName()
170: + "' unable to find specified tables file '"
171: + tables + "'");
172: }
173: if ((data != null && dataURL == null) || tablesURL == null)
174: return;
175:
176: // set up log buffers for capturing DbLoader output.
177:
178: Configuration config = new Configuration();
179: StringWriter logBfr = new StringWriter();
180: PrintWriter logWriter = new PrintWriter(logBfr);
181: config.setLog(logWriter);
182:
183: StringWriter scriptLog = null;
184:
185: if (createScript) {
186: scriptLog = new StringWriter();
187: PrintWriter scriptWriter = new PrintWriter(scriptLog);
188: config.setScriptWriter(scriptWriter);
189: }
190:
191: // load default config
192: DbLoader.loadConfiguration(config);
193:
194: // set overrides for car table loading
195: config.setCreateTables(createTables);
196: config.setDropTables(dropTables);
197: config.setPopulateTables(populateTables);
198: config.setTablesURL(tablesURL);
199: config.setDataURL(dataURL);
200:
201: DbLoader loader = new DbLoader(config);
202:
203: String dataString = "(no data definition)";
204: if (dataURL != null) {
205: dataString = dataURL.toString();
206: }
207:
208: try {
209: loader.process();
210: logWriter.flush();
211: if (config.getScriptWriter() != null)
212: config.getScriptWriter().flush();
213: if (log.isInfoEnabled())
214: log
215: .info("***** Successfully processed *****\n"
216: + tablesURL
217: + " and \n"
218: + dataString
219: + ".\nLogged Output:\n---------------------\n"
220: + logBfr
221: + (createScript ? "\nDatabase Script:\n---------------------\n"
222: + scriptLog
223: : ""));
224: } catch (Exception e) {
225: log
226: .error(
227: "***** Failure during processing ***** \n"
228: + tablesURL
229: + " and \n"
230: + dataString
231: + ".\nLogged Output:\n---------------------\n"
232: + logBfr
233: + (createScript ? "\nDatabase Script:\n---------------------\n"
234: + scriptLog
235: : ""), e);
236: }
237: } catch (Exception e) {
238: log
239: .error(
240: "Problem occurred while loading database from CAR.",
241: e);
242: }
243: }
244: }
|