001: /* ====================================================================
002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003: *
004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by Jcorporate Ltd.
021: * (http://www.jcorporate.com/)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. "Jcorporate" and product names such as "Expresso" must
026: * not be used to endorse or promote products derived from this
027: * software without prior written permission. For written permission,
028: * please contact info@jcorporate.com.
029: *
030: * 5. Products derived from this software may not be called "Expresso",
031: * or other Jcorporate product names; nor may "Expresso" or other
032: * Jcorporate product names appear in their name, without prior
033: * written permission of Jcorporate Ltd.
034: *
035: * 6. No product derived from this software may compete in the same
036: * market space, i.e. framework, without prior written permission
037: * of Jcorporate Ltd. For written permission, please contact
038: * partners@jcorporate.com.
039: *
040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051: * SUCH DAMAGE.
052: * ====================================================================
053: *
054: * This software consists of voluntary contributions made by many
055: * individuals on behalf of the Jcorporate Ltd. Contributions back
056: * to the project(s) are encouraged when you make modifications.
057: * Please send them to support@jcorporate.com. For more information
058: * on Jcorporate Ltd. and its products, please see
059: * <http://www.jcorporate.com/>.
060: *
061: * Portions of this software are based upon other open source
062: * products and are subject to their respective licenses.
063: */
064:
065: /**
066: * XMLController
067: *
068: * Copyright 2000, 2001 Jcorporate Ltd.
069: */package com.jcorporate.expresso.ext.xml.controller;
070:
071: import com.jcorporate.expresso.core.controller.ControllerException;
072: import com.jcorporate.expresso.core.controller.ControllerRequest;
073: import com.jcorporate.expresso.core.controller.ControllerResponse;
074: import com.jcorporate.expresso.core.controller.DBController;
075: import com.jcorporate.expresso.core.controller.Input;
076: import com.jcorporate.expresso.core.controller.NonHandleableException;
077: import com.jcorporate.expresso.core.controller.Output;
078: import com.jcorporate.expresso.core.controller.State;
079: import com.jcorporate.expresso.core.controller.Transition;
080: import com.jcorporate.expresso.core.db.DBException;
081: import com.jcorporate.expresso.core.dbobj.DBObject;
082: import com.jcorporate.expresso.core.dbobj.Schema;
083: import com.jcorporate.expresso.core.dbobj.SchemaFactory;
084: import com.jcorporate.expresso.core.dbobj.SecuredDBObject;
085: import com.jcorporate.expresso.core.dbobj.ValidValue;
086: import com.jcorporate.expresso.ext.xml.dbobj.XMLDBObject;
087: import com.jcorporate.expresso.services.dbobj.SchemaList;
088: import org.apache.log4j.Logger;
089:
090: import java.io.BufferedOutputStream;
091: import java.io.FileOutputStream;
092: import java.io.IOException;
093: import java.io.PrintStream;
094: import java.util.Enumeration;
095: import java.util.Iterator;
096: import java.util.Vector;
097:
098: /**
099: * The XML transaction allows authorized users to easily
100: * import and export DBObject contents to XML formats
101: *
102: * @author Michael Nash
103: */
104: public class XMLController extends DBController {
105:
106: private static Logger log = Logger.getLogger(XMLController.class);
107:
108: /**
109: * Our constructor declares the states this transaction supports
110: */
111: public XMLController() {
112: State promptForSchema = new State("promptForSchema",
113: "Prompt for Schema");
114: addState(promptForSchema);
115: setInitialState("promptForSchema");
116:
117: State promptImport = new State("promptImport",
118: "Prompt for Parameters for Import");
119: addState(promptImport);
120:
121: State promptFileImport = new State("promptFileImport",
122: "Prompt for Parameters for File Import");
123: addState(promptFileImport);
124:
125: State promptFileExport = new State("promptFileExport",
126: "Prompt for Parameters for File Export");
127: addState(promptFileExport);
128:
129: /* Given a schema, prompt the user to select a database object
130:
131: * and then select import or export
132:
133: */
134: State selDBObj = new State("selDBObj", "Select Database Object");
135: selDBObj.addRequiredParameter("SchemaClass");
136: addState(selDBObj);
137:
138: State doFileExport = new State("doFileExport",
139: "Export Data to a File");
140: doFileExport.addRequiredParameter("FileName");
141: doFileExport.addRequiredParameter("DBObjectClass");
142: addState(doFileExport);
143:
144: State doFileImport = new State("doFileImport",
145: "Import Data from a File");
146: doFileImport.addRequiredParameter("FileName");
147: addState(doFileImport);
148:
149: State doImport = new State("doImport",
150: "Import Data from remote Server");
151: doImport.addRequiredParameter("DBObjectName");
152: doImport.addRequiredParameter("Server");
153: doImport.addRequiredParameter("Login");
154: doImport.addRequiredParameter("Password");
155: addState(doImport);
156: } /* XMLController() */
157:
158: /**
159: * @param req The <code>ControllerRequest</code> object given
160: * to us by the framework.
161: * @param res The <code>ControllerResponse</code> object to populate
162: * with Inputs/Outputs and Blocks.
163: */
164: private void doFileExportState(ControllerRequest req,
165: ControllerResponse res) throws ControllerException {
166: String fileName = req.getParameter("FileName") + ".xml";
167: int objectCount = 0;
168:
169: try {
170: FileOutputStream fout = new FileOutputStream(fileName,
171: false);
172: BufferedOutputStream bout = new BufferedOutputStream(fout);
173: PrintStream XMLFileStream = new PrintStream(bout);
174: XMLFileStream
175: .println("<?xml version=\"1.0\" standalone=\"no\"?>");
176: XMLFileStream.println("<!DOCTYPE ExpressoData [");
177: XMLFileStream.println("<!ELEMENT DBObjects (DBObject+)>");
178: XMLFileStream
179: .println("<!ELEMENT DBObject (ObjectName, TableName, Data)>");
180: XMLFileStream.println("<!ELEMENT ObjectName (#PCDATA)>");
181: XMLFileStream.println("<!ELEMENT TableName (#PCDATA)>");
182: XMLFileStream.println("<!ELEMENT Data (DataRecord+)>");
183: XMLFileStream.println("<!ELEMENT DataRecord (Field)>");
184: XMLFileStream
185: .println("<!ELEMENT Field (FieldName, FieldValue)>");
186: XMLFileStream.println("<!ELEMENT FieldName (#PCDATA)>");
187: XMLFileStream.println("<!ELEMENT FieldValue (#PCDATA)>");
188: XMLFileStream.println("]>");
189: XMLFileStream.println("<DBObjects>");
190: XMLFileStream.flush();
191: XMLFileStream.close();
192:
193: DBObject oneDBObject = null;
194: String dbObjClassName = req.getParameter("DBObjectClass");
195:
196: if (dbObjClassName.equals("All")) {
197: Schema mySchema = getSchema(req
198: .getParameter("SchemaClass"));
199:
200: for (Enumeration e = mySchema.getMembers(); e
201: .hasMoreElements();) {
202: oneDBObject = (DBObject) e.nextElement();
203: oneDBObject.setDataContext(req.getDataContext());
204:
205: XMLDBObject myXMLObj = new XMLDBObject(oneDBObject);
206: myXMLObj.exportToFile(req.getParameter("FileName"));
207: objectCount++;
208: }
209: } else {
210: oneDBObject = getDBObject(dbObjClassName);
211: oneDBObject.setDataContext(req.getDataContext());
212:
213: XMLDBObject myXMLObj = new XMLDBObject(oneDBObject);
214: myXMLObj.exportToFile(req.getParameter("FileName"));
215: objectCount++;
216: }
217:
218: FileOutputStream fout2 = new FileOutputStream(fileName,
219: true);
220: BufferedOutputStream bout2 = new BufferedOutputStream(fout2);
221: PrintStream XMLFileStream2 = new PrintStream(bout2);
222: XMLFileStream2.println("</DBObjects>");
223: XMLFileStream2.flush();
224: XMLFileStream2.close();
225: } catch (Exception de) {
226: throw new ControllerException(de.getMessage());
227: }
228:
229: res.addOutput(new Output("Exported " + objectCount
230: + " objects."));
231: } /* doFileExportState() */
232:
233: /**
234: * @param req The <code>ControllerRequest</code> object given
235: * to us by the framework.
236: * @param res The <code>ControllerResponse</code> object to populate
237: * with Inputs/Outputs and Blocks.
238: */
239: private void doFileImportState(ControllerRequest req,
240: ControllerResponse res) throws ControllerException {
241: int errorCount = 0;
242:
243: try {
244: XMLDBObject myXMLObj = new XMLDBObject();
245: myXMLObj.setDBName(req.getDataContext());
246: myXMLObj.importFromFile(req.getParameter("FileName"));
247:
248: Exception ex = null;
249:
250: for (Enumeration e = myXMLObj.getErrorList().elements(); e
251: .hasMoreElements();) {
252: errorCount++;
253: ex = (Exception) e.nextElement();
254: res.addOutput(new Output(ex.getMessage()));
255: }
256: } catch (DBException de) {
257: throw new ControllerException(de.getMessage());
258: }
259:
260: res.addOutput(new Output("Import Complete - " + errorCount
261: + " errors."));
262: } /* doFileImportState() */
263:
264: /**
265: * @param req The <code>ControllerRequest</code> object given
266: * to us by the framework.
267: */
268: private void doImportState(ControllerRequest req)
269: throws ControllerException {
270: String importURL = ("http://" + req.getParameter("Server")
271: + "/servlet/Export?dbobj="
272: + req.getParameter("DBObjectName") + "&UserName="
273: + req.getParameter("Login") + "&Password=" + req
274: .getParameter("Password"));
275:
276: try {
277: XMLDBObject myXMLObj = new XMLDBObject();
278: myXMLObj.importFromURL(importURL);
279: } catch (DBException de) {
280: throw new ControllerException(de.getMessage());
281: }
282: } /* doImportState() */
283:
284: /**
285: * @param dbObjName The Object to load.
286: * @return A Schema object instantiated from the class named by the
287: * 'SchemaClass' parameter
288: */
289: private DBObject getDBObject(String dbObjName)
290: throws ControllerException {
291: try {
292: return (DBObject) Class.forName(dbObjName).newInstance();
293: } catch (IllegalAccessException ie) {
294: throw new ControllerException("Illegal Access "
295: + "Exception loading DBObject class " + dbObjName,
296: ie);
297: } catch (InstantiationException ie) {
298: throw new ControllerException("Can't instantiate "
299: + "DBObject class " + dbObjName, ie);
300: } catch (ClassNotFoundException se) {
301: throw new ControllerException("Can't find a DBObject "
302: + "class called " + dbObjName, se);
303: } catch (Exception eo) {
304: throw new ControllerException("Exception loading "
305: + "DBObject " + dbObjName, eo);
306: }
307: } /* getDBObject() */
308:
309: /**
310: * Instantiate & return the schema class given in the current parameter
311: *
312: * @param schemaName the class-name of the schema to load.
313: * @return A Schema object instantiated from the class named by the
314: * 'SchemaClass' parameter
315: */
316: private Schema getSchema(String schemaName)
317: throws ControllerException {
318: Schema mySchema = SchemaFactory.getInstance().getSchema(
319: schemaName);
320: if (mySchema == null) {
321: throw new ControllerException(
322: "Can't instantiate Schema class " + schemaName
323: + ". See log for details");
324:
325: }
326:
327: return mySchema;
328: } /* getSchema(String) */
329:
330: /**
331: * Return the title of this Transaction
332: *
333: * @return java.lang.String The Title of the controller
334: */
335: public String getTitle() {
336: return "Database Object XML Import/Export";
337: } /* getTitle() */
338:
339: /**
340: * Old-Style State switching method.
341: *
342: * @param req The <code>ControllerRequest</code> object given
343: * to us by the framework.
344: * @param newState the new state to transition into.
345: * @return ControllerResponse.
346: * @throws ControllerException upon error.
347: * @throws NonHandleableException upon fatal error.
348: */
349: public ControllerResponse newState(String newState,
350: ControllerRequest req) throws ControllerException,
351: NonHandleableException {
352: ControllerResponse res = super .newState(newState, req);
353:
354: if (newState.equals("promptImport")) {
355: promptImportState(res);
356: } else if (newState.equals("doImport")) {
357: doImportState(req);
358: } else if (newState.equals("promptFileExport")) {
359: promptFileExportState(req, res);
360: } else if (newState.equals("doFileExport")) {
361: doFileExportState(req, res);
362: } else if (newState.equals("doFileImport")) {
363: doFileImportState(req, res);
364: } else if (newState.equals("promptForSchema")) {
365: promptForSchema(req, res);
366: } else if (newState.equals("selDBObj")) {
367: selDBObj(req, res);
368: } else if (newState.equals("promptFileImport")) {
369: promptFileImportState(res);
370: }
371:
372: log.debug("State currently '" + newState + "'");
373:
374: if ((!newState.equals("promptForSchema"))
375: && (!newState.equals(""))) {
376: Transition again = new Transition("Start Again", getClass()
377: .getName());
378: again.setName("again");
379: again.addParam(STATE_PARAM_KEY, "promptForSchema");
380: res.addTransition(again);
381: }
382:
383: return res;
384: } /* newState(String) */
385:
386: /**
387: * @param req The <code>ControllerRequest</code> object given
388: * to us by the framework.
389: * @param res The <code>ControllerResponse</code> object to populate
390: * with Inputs/Outputs and Blocks.
391: */
392: private void promptFileExportState(ControllerRequest req,
393: ControllerResponse res) throws ControllerException {
394: try {
395: Schema mySchema = getSchema(req.getParameter("Schema"));
396:
397: for (Enumeration e = mySchema.getMembers(); e
398: .hasMoreElements();) {
399: XMLDBObject myXMLObj = new XMLDBObject((DBObject) e
400: .nextElement());
401: myXMLObj.exportToFile(req.getParameter("FileName"));
402: }
403: } catch (DBException de) {
404: throw new ControllerException(de);
405: } catch (IOException ie) {
406: throw new ControllerException(ie);
407: }
408:
409: Input fileName = new Input("FileName");
410: fileName.setLabel("XML File Name (no extension)");
411: res.addInput(fileName);
412:
413: Input schemaName = new Input("Schema");
414: schemaName.setLabel("Schema Object Name");
415: res.addInput(schemaName);
416: } /* promptFileExportState() */
417:
418: /**
419: * @param res The <code>ControllerResponse</code> object to populate
420: * with Inputs/Outputs and Blocks.
421: */
422: private void promptFileImportState(ControllerResponse res)
423: throws ControllerException {
424: Input fileName = new Input("FileName");
425: fileName.setLabel("XML File Name (no extension)");
426: res.addInput(fileName);
427:
428: /* now the actions */
429: Transition doImport = new Transition("Begin Import", getClass()
430: .getName());
431: doImport.setName("doFileImport");
432: doImport.addParam(STATE_PARAM_KEY, "doFileImport");
433: res.addTransition(doImport);
434: } /* promptFileImportState() */
435:
436: /**
437: * @param res The <code>ControllerResponse</code> object to populate
438: * with Inputs/Outputs and Blocks.
439: */
440: private void promptImportState(ControllerResponse res)
441: throws ControllerException {
442: Input server = new Input("Server");
443: server.setLabel("Server Name");
444: res.addInput(server);
445:
446: Input dbobjName = new Input("DBObjectName");
447: dbobjName.setLabel("Database Object:");
448: res.addInput(dbobjName);
449:
450: dbobjName.setLabel("Login:");
451: res.addInput(dbobjName);
452:
453: Input password = new Input("Password");
454: password.setLabel("Password:");
455: res.addInput(password);
456: } /* promptImportState() */
457:
458: /**
459: * @param req The <code>ControllerRequest</code> object given
460: * to us by the framework.
461: * @param res The <code>ControllerResponse</code> object to populate
462: * with Inputs/Outputs and Blocks.
463: */
464: private void promptForSchema(ControllerRequest req,
465: ControllerResponse res) throws ControllerException {
466: log.debug("Begin state promptForSchema");
467:
468: Input chooseSchema = new Input();
469: chooseSchema.setLabel("Choose Schema");
470: chooseSchema.setName("SchemaClass");
471:
472: Vector v2 = new Vector(2);
473: v2.addElement(new ValidValue("com.jcorporate.expresso."
474: + "core.ExpressoSchema", "General"));
475:
476: try {
477: SchemaList sl = new SchemaList(
478: SecuredDBObject.SYSTEM_ACCOUNT);
479: sl.setDataContext(req.getDataContext());
480:
481: SchemaList oneSchema = null;
482:
483: for (Iterator i = sl.searchAndRetrieveList("Descrip")
484: .iterator(); i.hasNext();) {
485: oneSchema = (SchemaList) i.next();
486: v2.addElement(new ValidValue(oneSchema
487: .getField("SchemaClass"), oneSchema
488: .getField("Descrip")));
489: }
490: } catch (DBException de) {
491: throw new ControllerException(de);
492: }
493:
494: chooseSchema.setValidValues(v2);
495: res.addInput(chooseSchema);
496:
497: /* now the actions */
498: Transition promptImport = new Transition("Import from File",
499: getClass().getName());
500: promptImport.setName("promptFileImport");
501: promptImport.addParam(STATE_PARAM_KEY, "promptFileImport");
502: res.addTransition(promptImport);
503:
504: /* now the actions */
505: Transition promptImport2 = new Transition("Import from Server",
506: getClass().getName());
507: promptImport2.setName("promptImport");
508: promptImport2.addParam(STATE_PARAM_KEY, "promptImport");
509: res.addTransition(promptImport2);
510:
511: /* now the actions */
512: Transition selDBObj = new Transition("Select Database Object",
513: getClass().getName());
514: selDBObj.setName("selDBObj");
515: selDBObj.addParam(STATE_PARAM_KEY, "selDBObj");
516: res.addTransition(selDBObj);
517: }
518:
519: /* Prompt for a database object to import/export from the specified schema */
520: private void selDBObj(ControllerRequest req, ControllerResponse res)
521: throws ControllerException {
522: Input chooseDBobj = new Input();
523: chooseDBobj.setLabel("Choose Database Object");
524: chooseDBobj.setName("DBObjectClass");
525:
526: Vector v2 = new Vector(2);
527: v2.addElement(new ValidValue("All",
528: "All Objects in this Schema"));
529:
530: DBObject oneDBObject = null;
531: Schema mySchema = getSchema(req.getParameter("SchemaClass"));
532:
533: for (Enumeration e = mySchema.getMembers(); e.hasMoreElements();) {
534: oneDBObject = (DBObject) e.nextElement();
535: v2.addElement(new ValidValue(oneDBObject.getClass()
536: .getName(), oneDBObject.getMetaData()
537: .getDescription(req.getLocale())));
538: }
539:
540: chooseDBobj.setValidValues(v2);
541: res.addInput(chooseDBobj);
542: log.debug("Just added chooseDBObj");
543:
544: Input fileName = new Input("FileName");
545: fileName.setLabel("XML File Name (no extension)");
546: res.addInput(fileName);
547:
548: Transition doExport = new Transition("Export", getClass()
549: .getName());
550: doExport.setName("doFileExport");
551: doExport.addParam(STATE_PARAM_KEY, "doFileExport");
552: doExport.addParam("SchemaClass", req
553: .getParameter("SchemaClass"));
554: res.addTransition(doExport);
555: } /* selDBObj(ControllerRequest, ControllerResponse) */
556:
557: } /* XMLController */
|