001: /*
002: * The contents of this file are subject to the Mozilla Public License
003: * Version 1.1 (the "License"); you may not use this file except in
004: * compliance with the License. You may obtain a copy of the License at
005: * http://www.mozilla.org/MPL/
006: *
007: * Software distributed under the License is distributed on an "AS IS"
008: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
009: * License for the specific language governing rights and limitations
010: * under the License.
011: *
012: * The Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
013: *
014: * The Initial Developer of the Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
015: * Portions created by Mark A. Kobold are Copyright (C) 2000-2007. All Rights Reserved.
016: *
017: * Contributor(s):
018: * Mark A. Kobold [mkobold <at> isqlviewer <dot> com].
019: *
020: * If you didn't download this code from the following link, you should check
021: * if you aren't using an obsolete version: http://www.isqlviewer.com
022: */
023: package org.isqlviewer.xml;
024:
025: import java.io.OutputStream;
026: import java.io.OutputStreamWriter;
027: import java.io.PrintWriter;
028: import java.io.StringWriter;
029: import java.nio.charset.Charset;
030: import java.sql.Timestamp;
031: import java.util.Date;
032: import java.util.Enumeration;
033:
034: import org.isqlviewer.BindVariable;
035: import org.isqlviewer.bookmarks.Bookmark;
036: import org.isqlviewer.bookmarks.BookmarkFolder;
037: import org.isqlviewer.util.BasicUtilities;
038: import org.isqlviewer.util.IsqlToolkit;
039: import org.isqlviewer.util.StringUtilities;
040: import org.xml.sax.Attributes;
041: import org.xml.sax.EntityResolver;
042: import org.xml.sax.InputSource;
043: import org.xml.sax.SAXException;
044: import org.xml.sax.XMLReader;
045: import org.xml.sax.helpers.DefaultHandler;
046:
047: /**
048: * XML Handler for parsing iSQL-Viewer bookmarks via SAX.
049: * <p>
050: * This class is primarily retained for compatability purposes within iSQL-Viewer such that bookmarks from previous
051: * versions can be retrieved and impoted into newer versions of iSQL-Viewer that do not store bookmarks in an XML
052: * format.
053: *
054: * @author Mark A. Kobold <mkobold at isqlviewer dot com>
055: * @version 1.0
056: */
057: public class BookmarkDigester extends DefaultHandler {
058:
059: private static final String DTD_DECLARATION = "<!DOCTYPE isql-bookmarks PUBLIC \"-//iSQL-Viewer.org.//DTD JDBC Bookmarks 2.1.8//EN\" \"http://isqlviewer.org/dtd/bookmarks.dtd\">";
060:
061: private static final String TAG_ROOT_BOOKMARK = "isql-bookmarks";
062: private static final String TAG_BOOKMARK = "bookmark";
063: private static final String TAG_PARAMETER = "parameter";
064: private static final String TAG_FOLDER = "folder";
065: private static final String ATTR_NAME = "name";
066:
067: private static String ATTR_BM_EPOCH = "created";
068: private static String ATTR_BM_LAST = "last";
069: private static String ATTR_BM_COUNT = "count";
070: private static String ATTR_BM_EPOCH_OLD = "epoch";
071: private static String ATTR_BM_LAST_OLD = "last_query";
072: private static String ATTR_BM_COUNT_OLD = "use_count";
073:
074: private static String ATTR_PARAM_TYPE = "type";
075: private static String ATTR_PARAM_VALUE = "value";
076: private static String ATTR_PARAM_OPTIONS = "options";
077: private static String ATTR_PARAM_INDEX = "index";
078:
079: private StringBuffer cdataBuffer = new StringBuffer("");
080: private BookmarkFolder rootFolder = null;
081: private Bookmark currentBookmark = null;
082: private BookmarkFolder currentFolder = null;
083:
084: public static BookmarkFolder parseBookmarks(InputSource source)
085: throws Exception {
086:
087: return parseBookmarks(source, IsqlToolkit
088: .getSharedEntityResolver());
089: }
090:
091: public static BookmarkFolder parseBookmarks(InputSource source,
092: EntityResolver resolver) throws Exception {
093:
094: XMLReader xmlreader = BasicUtilities.createXMLReader(false,
095: true);
096: BookmarkFolder root = BookmarkFolder.createRootFolder();
097: BookmarkDigester digester = new BookmarkDigester(root);
098: if (resolver != null) {
099: xmlreader.setEntityResolver(resolver);
100: }
101: xmlreader.setContentHandler(digester);
102: xmlreader.setErrorHandler(digester);
103: xmlreader.parse(source);
104: return root;
105: }
106:
107: public static void writeBookmarkFolder(OutputStream out,
108: BookmarkFolder bookmarkFolder) {
109:
110: writeBookmarkFolder(out, bookmarkFolder, Charset
111: .forName("UTF-8"));
112: }
113:
114: public static void writeBookmarkFolder(OutputStream out,
115: BookmarkFolder bookmarkFolder, Charset cs) {
116:
117: OutputStreamWriter osw = new OutputStreamWriter(out, cs);
118: PrintWriter pw = new PrintWriter(osw, false);
119: pw.print("<?xml version=\"1.0\" encoding=\"");
120: pw.print(cs.name());
121: pw.println("\" ?>");
122: try {
123: pw.println(DTD_DECLARATION);
124: pw.print('<');
125: pw.print(TAG_ROOT_BOOKMARK);
126: pw.println('>');
127: printBookmarkFolder(pw, bookmarkFolder, 1);
128: pw.print("</");
129: pw.print(TAG_ROOT_BOOKMARK);
130: pw.println('>');
131: } finally {
132: pw.flush();
133: pw.close();
134: pw = null;
135: osw = null;
136: }
137: }
138:
139: private BookmarkDigester(BookmarkFolder rootFolder) {
140:
141: this .rootFolder = rootFolder;
142: }
143:
144: @Override
145: public void startDocument() throws SAXException {
146:
147: currentFolder = rootFolder;
148: }
149:
150: @Override
151: public void characters(char[] ch, int start, int length)
152: throws SAXException {
153:
154: cdataBuffer.append(new String(ch, start, length).trim());
155: }
156:
157: @Override
158: public void startElement(String uri, String localName,
159: String qName, Attributes attributes) throws SAXException {
160:
161: String tag = qName.toLowerCase().trim();
162: if (TAG_FOLDER.equals(tag)) {
163: BookmarkFolder childFolder = currentFolder
164: .addChildFolder(attributes.getValue(ATTR_NAME));
165: currentFolder = childFolder;
166: } else if (TAG_BOOKMARK.equals(tag)) {
167: currentBookmark = new Bookmark();
168: currentBookmark.setName(attributes.getValue(ATTR_NAME));
169: int idx = attributes.getIndex(ATTR_BM_EPOCH_OLD);
170: if (idx >= 0) {
171: long timestamp = Long.parseLong(attributes
172: .getValue(idx));
173: currentBookmark.setCreationTime(new Date(timestamp));
174: } else {
175: long timestamp = Long.parseLong(attributes
176: .getValue(attributes.getIndex(ATTR_BM_EPOCH)));
177: currentBookmark.setCreationTime(new Date(timestamp));
178: }
179:
180: idx = attributes.getIndex(ATTR_BM_LAST_OLD);
181: if (idx >= 0) {
182: long timestamp = Long.parseLong(attributes
183: .getValue(idx));
184: currentBookmark.setLastAccess(new Date(timestamp));
185: } else {
186: long timestamp = Long.parseLong(attributes
187: .getValue(attributes.getIndex(ATTR_BM_LAST)));
188: currentBookmark.setLastAccess(new Timestamp(timestamp));
189: }
190: idx = attributes.getIndex(ATTR_BM_COUNT_OLD);
191: if (idx >= 0) {
192: currentBookmark.setUseCount(Long.parseLong(attributes
193: .getValue(idx)));
194: } else {
195: int useCount = Integer.parseInt(attributes
196: .getValue(attributes.getIndex(ATTR_BM_COUNT)));
197: currentBookmark.setUseCount(useCount);
198: }
199: currentFolder.addBookmark(currentBookmark);
200: } else if (TAG_PARAMETER.equals(tag)) {
201: BindVariable bpd = new BindVariable();
202: bpd.setFormatOptions(attributes.getValue(ATTR_PARAM_VALUE));
203: bpd.setUserData(attributes.getValue(ATTR_PARAM_VALUE));
204: bpd.setType(Integer.parseInt(attributes
205: .getValue(ATTR_PARAM_TYPE)));
206: currentBookmark.add(bpd);
207: }
208: }
209:
210: @Override
211: public void endElement(String uri, String localName, String qName) {
212:
213: String tag = qName.toLowerCase().trim();
214: if (TAG_FOLDER.equals(tag)) {
215: if (currentFolder != rootFolder) {
216: currentFolder = currentFolder.getParentFolder();
217: }
218: } else if (TAG_BOOKMARK.equals(tag)) {
219: String sql = StringUtilities.decodeBase64(cdataBuffer
220: .toString().trim());
221: currentBookmark.setCommandText(sql);
222: }
223: cdataBuffer.setLength(0);
224: }
225:
226: private static void createTabdepth(PrintWriter out, int size) {
227:
228: for (int i = 0; i < size; i++) {
229: out.print('\t');
230: }
231: }
232:
233: private static void printBookmarkFolder(PrintWriter out,
234: BookmarkFolder folder, int depth) {
235:
236: Enumeration childElements = folder.childElements();
237: boolean isRoot = folder.getParentFolder() == null;
238: if (!isRoot) {
239: createTabdepth(out, depth - 1);
240: out.print('<');
241: out.print(TAG_FOLDER);
242: out.print(' ');
243: out.print(ATTR_NAME);
244: out.print("=\"");
245: out.print(StringUtilities.encodeXMLEntities(folder
246: .getName()));
247: out.println("\">");
248: }
249: while (childElements.hasMoreElements()) {
250: Object child = childElements.nextElement();
251: if (child instanceof BookmarkFolder) {
252: printBookmarkFolder(out, (BookmarkFolder) child,
253: depth + 1);
254: } else if (child instanceof Bookmark) {
255: printBookmark(out, (Bookmark) child, depth);
256: }
257: }
258: if (!isRoot) {
259: createTabdepth(out, depth - 1);
260: out.print("</");
261: out.print(TAG_FOLDER);
262: out.println('>');
263: }
264: }
265:
266: private static void printBookmark(PrintWriter out,
267: Bookmark bookmark, int depth) {
268:
269: createTabdepth(out, depth);
270: out.print('<');
271: out.print(TAG_BOOKMARK);
272: out.print(' ');
273: out.print(ATTR_NAME);
274: out.print("=\"");
275: out
276: .print(StringUtilities.encodeXMLEntities(bookmark
277: .getName()));
278: out.print("\" ");
279: out.print(ATTR_BM_COUNT);
280: out.print("=\"");
281: out.print(Long.toString(bookmark.getUseCount()));
282: out.print("\" ");
283: out.print(ATTR_BM_LAST);
284: out.print("=\"");
285: Date timestamp = null;
286: timestamp = bookmark.getLastAccess();
287: out.print(Long.toString(timestamp == null ? 0 : timestamp
288: .getTime()));
289: out.print("\" ");
290: out.print(ATTR_BM_EPOCH);
291: out.print("=\"");
292: timestamp = bookmark.getCreationTime();
293: out.print(Long.toString(timestamp == null ? 0 : timestamp
294: .getTime()));
295: out.println("\">");
296: if (bookmark.containsParameters()) {
297: Enumeration<BindVariable> elements = bookmark.variables();
298: while (elements.hasMoreElements()) {
299: BindVariable next = elements.nextElement();
300: createTabdepth(out, depth + 1);
301: out.print(TAG_PARAMETER);
302: out.print(" ");
303: out.print(ATTR_PARAM_INDEX);
304: out.print("=\"");
305: out.print(Integer.toString(next.getType()));
306: out.print("\" ");
307: out.print(ATTR_PARAM_TYPE);
308: out.print("=\"");
309: out.print(Integer.toString(next.getType()));
310: out.print("\" ");
311: out.print(ATTR_PARAM_VALUE);
312: out.print("=\"");
313: out.print(StringUtilities.encodeXMLEntities(next
314: .getUserData()));
315: out.print("\" ");
316: out.print(ATTR_PARAM_OPTIONS);
317: out.print("=\"");
318: out.print(StringUtilities.encodeXMLEntities(next
319: .getFormatOptions()));
320: out.print("\"/>");
321: }
322: }
323:
324: StringWriter sw = new StringWriter();
325: PrintWriter pw = new PrintWriter(sw, true);
326: createTabdepth(pw, depth);
327: pw.flush();
328: sw.append(' ');
329: createTabdepth(out, depth);
330: out.print(' ');
331:
332: String encoded = StringUtilities.encodeBase64(bookmark
333: .getCommandText());
334: out.println(StringUtilities.formatBreak(80, encoded, sw
335: .toString(), false));
336: createTabdepth(out, depth);
337: out.print("</");
338: out.print(TAG_BOOKMARK);
339: out.println('>');
340: }
341: }
|