001: /*
002: * This file or a portion of this file is licensed under the terms of
003: * the Globus Toolkit Public License, found in file ../GTPL, or at
004: * http://www.globus.org/toolkit/download/license.html. This notice must
005: * appear in redistributions of this file, with or without modification.
006: *
007: * Redistributions of this Software, with or without modification, must
008: * reproduce the GTPL in: (1) the Software, or (2) the Documentation or
009: * some other similar material which is provided with the Software (if
010: * any).
011: *
012: * Copyright 1999-2004 University of Chicago and The University of
013: * Southern California. All rights reserved.
014: */
015: package org.griphyn.vdl.dbschema;
016:
017: import java.sql.*;
018: import java.util.Iterator;
019: import java.util.ListIterator;
020: import java.util.Vector;
021: import java.util.Enumeration;
022: import java.util.ArrayList;
023: import java.util.List;
024: import java.io.*;
025: import java.lang.reflect.*;
026: import java.sql.SQLException;
027: import org.griphyn.common.util.DynamicLoader;
028: import org.griphyn.vdl.util.ChimeraProperties;
029: import org.griphyn.vdl.util.FileHelper;
030: import org.griphyn.vdl.util.Logging;
031: import org.griphyn.vdl.util.LockFileLock;
032: import org.griphyn.vdl.classes.*;
033: import org.griphyn.vdl.parser.*;
034: import org.griphyn.vdl.dbdriver.*;
035:
036: /**
037: * This is a class that falls back not on a real database backend, but
038: * rather on an existing Definitions data structure that are read from
039: * file during construction (or rather, during open), and pushed back
040: * into file at destruction (or rather, during close).<p>
041: * While schemas in general should fall back onto drivers to perform
042: * actions, it is rather difficult to create a JDBC interface to file
043: * operations. Thus, the file operations are sneaked into this class.<p>
044: * This class is thought more for experimental use than production.
045: *
046: * @author Jens-S. Vöckler
047: * @author Yong Zhao
048: * @version $Revision: 50 $
049: * @see org.griphyn.vdl.dbdriver
050: * @see org.griphyn.vdl.classes.Definitions
051: */
052: public class SingleFileSchema extends InMemorySchema {
053: /**
054: * Save the name of the database file, so we can dump our memory.
055: */
056: private String m_filename;
057:
058: /**
059: * Save the file locking helper, once dynaloaded.
060: */
061: private FileHelper m_filehelper;
062:
063: /**
064: * An instance of the VDLx XML parser.
065: */
066: private org.griphyn.vdl.parser.VDLxParser m_parser;
067:
068: /**
069: * Fakes a connect to the database. This class load the memory
070: * database during construction time from the specified file.
071: *
072: * @param hyphen_d is the CLI argument being passed, and ignored for now.
073: */
074: public SingleFileSchema(String hyphen_d)
075: throws ClassNotFoundException, NoSuchMethodException,
076: InstantiationException, IllegalAccessException,
077: InvocationTargetException, SQLException, IOException {
078: super (); // call minimalistic c'tor, no driver loading!
079: ChimeraProperties props = ChimeraProperties.instance();
080: // Start a new set of definitions
081: this .m_memory = new Definitions();
082: this .m_dbschemaprops = props
083: .getDatabaseSchemaProperties(PROPERTY_PREFIX);
084:
085: // obtain the schema location URL from the schema properties:
086: // url is a list of strings representing schema locations. The
087: // content exists in pairs, one of the namespace URI, one of the
088: // location URL.
089: String url = this .m_dbschemaprops.getProperty("xml.url", props
090: .getVDLSchemaLocation());
091: Logging.instance().log("dbschema", 3, "schema=" + url);
092: this .m_parser = new org.griphyn.vdl.parser.VDLxParser(url);
093: Logging.instance().log("dbschema", 3, "created reader");
094:
095: // obtain the file location from the schema properties
096: File db = new File(props.getLocalStateDir(), "vds.db");
097: this .m_filename = this .m_dbschemaprops.getProperty(
098: "file.store", db.getAbsolutePath());
099: Logging.instance().log("dbschema", 3, "filename=" + m_filename);
100:
101: // Determine helper to provide locking functions
102: String locker = m_dbschemaprops.getProperty("file.lock",
103: "LockFileLock");
104: if (locker.indexOf('.') == -1)
105: locker = "org.griphyn.vdl.util." + locker;
106:
107: // dynamically load the file locking helper implementation
108: Logging.instance().log("dbschema", 3,
109: "trying to load " + locker);
110: DynamicLoader dl = new DynamicLoader(locker);
111: String arg[] = new String[1];
112: arg[0] = m_filename;
113: m_filehelper = (FileHelper) dl.instantiate(arg);
114:
115: // FileHelper m_filehelper = new FileHelper2(this.m_filename);
116: File file = m_filehelper.openReader();
117:
118: if (file == null) {
119: Logging.instance().log("dbschema", 3,
120: "openReader returned null");
121: throw new SQLException("Can't lock file " + this .m_memory);
122: }
123:
124: // Does database exist?
125: try {
126: if (file.exists()) {
127: // file exists, read it unless empty
128: if (file.length() > 0) {
129: // parse the complete file (database)
130: this .m_parser.parse(new org.xml.sax.InputSource(
131: new BufferedReader(new FileReader(file))),
132: new NoHassleHandler(this .m_memory));
133: Logging
134: .instance()
135: .log(
136: "app",
137: 1,
138: this .m_memory.getDefinitionCount()
139: + " definitions loaded into main memory");
140: }
141: }
142: } catch (Exception e) {
143: throw new SQLException(e.getMessage());
144: } finally {
145: // always release locks
146: try {
147: m_filehelper.closeReader(file);
148: } catch (Exception e) {
149: throw new SQLException(e.getMessage());
150: }
151: }
152: }
153:
154: /**
155: * Disassociate from the database driver before finishing. In this
156: * case, dump the memory database back to the file that was saved.
157: * Mind that performing this action may throw NullPointerException
158: * in later stages!
159: */
160: public void close() throws SQLException {
161: super .close();
162:
163: // FileHelper m_filehelper = new FileHelper2(this.m_filename);
164: File file = m_filehelper.openWriter();
165:
166: if (file == null) {
167: throw new SQLException("Unable to create file writer!");
168: }
169:
170: try {
171: BufferedWriter bw = new BufferedWriter(new FileWriter(file));
172: this .m_memory.toXML(bw, "");
173: bw.flush();
174: bw.close();
175: } catch (IOException e) {
176: throw new SQLException(e.getMessage());
177: } finally {
178: // always release locks
179: try {
180: m_filehelper.closeWriter(file);
181: } catch (Exception e) {
182: throw new SQLException(e.getMessage());
183: }
184: }
185: }
186: }
|