001: /*
002: * $Id: EntitySaxReader.java,v 1.3 2004/01/28 13:35:40 jonesde Exp $
003: *
004: * Copyright (c) 2001, 2002 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: *
024: */
025: package org.ofbiz.entity.util;
026:
027: import java.io.ByteArrayInputStream;
028: import java.io.InputStream;
029: import java.net.URL;
030: import java.util.ArrayList;
031: import java.util.List;
032:
033: import javax.xml.parsers.SAXParser;
034: import javax.xml.parsers.SAXParserFactory;
035:
036: import org.ofbiz.base.util.Debug;
037: import org.ofbiz.entity.GenericDelegator;
038: import org.ofbiz.entity.GenericEntityException;
039: import org.ofbiz.entity.GenericValue;
040: import org.ofbiz.entity.transaction.GenericTransactionException;
041: import org.ofbiz.entity.transaction.TransactionUtil;
042: import org.xml.sax.ErrorHandler;
043: import org.xml.sax.InputSource;
044: import org.xml.sax.SAXException;
045: import org.xml.sax.XMLReader;
046:
047: /**
048: * SAX XML Parser Content Handler for Entity Engine XML files
049: *
050: * @author <a href="mailto:jonesde@ofbiz.org">David E. Jones</a>
051: * @version $Revision: 1.3 $
052: * @since 2.0
053: */
054: public class EntitySaxReader implements org.xml.sax.ContentHandler,
055: ErrorHandler {
056:
057: public static final String module = EntitySaxReader.class.getName();
058:
059: protected org.xml.sax.Locator locator;
060: protected GenericDelegator delegator;
061: protected GenericValue currentValue = null;
062: protected String currentFieldName = null;
063: protected String currentFieldValue = null;
064: protected long numberRead = 0;
065:
066: protected int valuesPerWrite = 100;
067: protected int valuesPerMessage = 1000;
068: protected int transactionTimeout = 7200;
069: boolean useTryInsertMethod = false;
070:
071: protected List valuesToWrite = new ArrayList(valuesPerWrite);
072:
073: protected EntitySaxReader() {
074: }
075:
076: public EntitySaxReader(GenericDelegator delegator) {
077: this .delegator = delegator;
078: }
079:
080: public int getValuesPerWrite() {
081: return this .valuesPerWrite;
082: }
083:
084: public void setValuesPerWrite(int valuesPerWrite) {
085: this .valuesPerWrite = valuesPerWrite;
086: }
087:
088: public int getValuesPerMessage() {
089: return this .valuesPerMessage;
090: }
091:
092: public void setValuesPerMessage(int valuesPerMessage) {
093: this .valuesPerMessage = valuesPerMessage;
094: }
095:
096: public int getTransactionTimeout() {
097: return this .transactionTimeout;
098: }
099:
100: public void setUseTryInsertMethod(boolean value) {
101: this .useTryInsertMethod = value;
102: }
103:
104: public void setTransactionTimeout(int transactionTimeout)
105: throws GenericTransactionException {
106: if (this .transactionTimeout != transactionTimeout) {
107: TransactionUtil.setTransactionTimeout(transactionTimeout);
108: this .transactionTimeout = transactionTimeout;
109: }
110: }
111:
112: public long parse(String content) throws SAXException,
113: java.io.IOException {
114: if (content == null) {
115: Debug.logWarning("content was null, doing nothing", module);
116: return 0;
117: }
118: ByteArrayInputStream bis = new ByteArrayInputStream(content
119: .getBytes());
120:
121: return this .parse(bis, "Internal Content");
122: }
123:
124: public long parse(URL location) throws SAXException,
125: java.io.IOException {
126: if (location == null) {
127: Debug.logWarning("location URL was null, doing nothing",
128: module);
129: return 0;
130: }
131: return this .parse(location.openStream(), location.toString());
132: }
133:
134: public long parse(InputStream is, String docDescription)
135: throws SAXException, java.io.IOException {
136:
137: /* NOTE: this method is not used because it doesn't work with various parsers...
138: String orgXmlSaxDriver = System.getProperty("org.xml.sax.driver");
139: if (UtilValidate.isEmpty(orgXmlSaxDriver)) orgXmlSaxDriver = "org.apache.xerces.parsers.SAXParser";
140: XMLReader reader = XMLReaderFactory.createXMLReader(orgXmlSaxDriver);
141: */
142:
143: XMLReader reader = null;
144:
145: try {
146: SAXParserFactory parserFactory = SAXParserFactory
147: .newInstance();
148: SAXParser parser = parserFactory.newSAXParser();
149:
150: reader = parser.getXMLReader();
151: } catch (javax.xml.parsers.ParserConfigurationException e) {
152: Debug.logError(e, "Failed to get a SAX XML parser", module);
153: throw new IllegalStateException(
154: "Failed to get a SAX XML parser");
155: }
156:
157: reader.setContentHandler(this );
158: reader.setErrorHandler(this );
159: // LocalResolver lr = new UtilXml.LocalResolver(new DefaultHandler());
160: // reader.setEntityResolver(lr);
161:
162: numberRead = 0;
163: try {
164: boolean beganTransaction = TransactionUtil
165: .begin(transactionTimeout);
166: Debug.logImportant("Transaction Timeout set to "
167: + transactionTimeout / 3600 + " hours ("
168: + transactionTimeout + " seconds)", module);
169: try {
170: reader.parse(new InputSource(is));
171: // make sure all of the values to write got written...
172: if (valuesToWrite.size() > 0) {
173: delegator.storeAll(valuesToWrite);
174: valuesToWrite.clear();
175: }
176: TransactionUtil.commit(beganTransaction);
177: } catch (Exception e) {
178: Debug
179: .logError(
180: e,
181: "An error occurred saving the data, rolling back transaction",
182: module);
183: TransactionUtil.rollback(beganTransaction);
184: throw new SAXException(
185: "A transaction error occurred reading data", e);
186: }
187: } catch (GenericTransactionException e) {
188: throw new SAXException(
189: "A transaction error occurred reading data", e);
190: }
191: Debug.logImportant("Finished writing " + numberRead
192: + " values to the database from " + docDescription,
193: module);
194: return numberRead;
195: }
196:
197: public void characters(char[] values, int offset, int count)
198: throws org.xml.sax.SAXException {
199: if (currentValue != null && currentFieldName != null) {
200: String value = new String(values, offset, count);
201:
202: // Debug.logInfo("characters: value=" + value, module);
203: if (currentFieldValue == null) {
204: currentFieldValue = value;
205: } else {
206: currentFieldValue += value;
207: }
208: }
209: }
210:
211: public void endDocument() throws org.xml.sax.SAXException {
212: }
213:
214: public void endElement(String namespaceURI, String localName,
215: String fullName) throws org.xml.sax.SAXException {
216: // Debug.logInfo("endElement: localName=" + localName + ", fullName=" + fullName + ", numberRead=" + numberRead, module);
217: if ("entity-engine-xml".equals(fullName)) {
218: return;
219: }
220: if (currentValue != null) {
221: if (currentFieldName != null) {
222: if (currentFieldValue != null
223: && currentFieldValue.length() > 0) {
224: currentValue.setString(currentFieldName,
225: currentFieldValue);
226: currentFieldValue = null;
227: }
228: currentFieldName = null;
229: } else {
230: try {
231: if (useTryInsertMethod) {
232: // this technique is faster for data sets where most, if not all, values do not already exist in the database
233: try {
234: currentValue.create();
235: } catch (GenericEntityException e1) {
236: // create failed, try a store, if that fails too we have a real error and the catch outside of this should handle it
237: currentValue.store();
238: }
239: } else {
240: valuesToWrite.add(currentValue);
241: if (valuesToWrite.size() >= valuesPerWrite) {
242: delegator.storeAll(valuesToWrite);
243: valuesToWrite.clear();
244: }
245: }
246: numberRead++;
247: if ((numberRead % valuesPerMessage) == 0) {
248: Debug.logImportant("Another "
249: + valuesPerMessage
250: + " values imported: now up to "
251: + numberRead, module);
252: }
253: currentValue = null;
254: } catch (GenericEntityException e) {
255: throw new SAXException("Error storing value", e);
256: }
257: }
258: }
259: }
260:
261: public void endPrefixMapping(String prefix)
262: throws org.xml.sax.SAXException {
263: }
264:
265: public void ignorableWhitespace(char[] values, int offset, int count)
266: throws org.xml.sax.SAXException {
267: // String value = new String(values, offset, count);
268: // Debug.logInfo("ignorableWhitespace: value=" + value, module);
269: }
270:
271: public void processingInstruction(String target, String instruction)
272: throws org.xml.sax.SAXException {
273: }
274:
275: public void setDocumentLocator(org.xml.sax.Locator locator) {
276: this .locator = locator;
277: }
278:
279: public void skippedEntity(String name)
280: throws org.xml.sax.SAXException {
281: }
282:
283: public void startDocument() throws org.xml.sax.SAXException {
284: }
285:
286: public void startElement(String namepsaceURI, String localName,
287: String fullName, org.xml.sax.Attributes attributes)
288: throws org.xml.sax.SAXException {
289: // Debug.logInfo("startElement: localName=" + localName + ", fullName=" + fullName + ", attributes=" + attributes, module);
290: if ("entity-engine-xml".equals(fullName)) {
291: return;
292: }
293: if (currentValue != null) {
294: // we have a nested value/CDATA element
295: currentFieldName = fullName;
296: } else {
297: String entityName = fullName;
298:
299: // if a dash or colon is in the tag name, grab what is after it
300: if (entityName.indexOf('-') > 0) {
301: entityName = entityName.substring(entityName
302: .indexOf('-') + 1);
303: }
304: if (entityName.indexOf(':') > 0) {
305: entityName = entityName.substring(entityName
306: .indexOf(':') + 1);
307: }
308:
309: try {
310: currentValue = delegator.makeValue(entityName, null);
311: currentValue.setIsFromEntitySync(true);
312: } catch (Exception e) {
313: Debug.logError(e, module);
314: }
315:
316: if (currentValue != null) {
317: int length = attributes.getLength();
318:
319: for (int i = 0; i < length; i++) {
320: String name = attributes.getLocalName(i);
321: String value = attributes.getValue(i);
322:
323: if (name == null || name.length() == 0) {
324: name = attributes.getQName(i);
325: }
326: try {
327: // treat empty strings as nulls
328: if (value != null && value.length() > 0) {
329: currentValue.setString(name, value);
330: }
331: } catch (Exception e) {
332: Debug.logWarning(e, "Could not set field "
333: + name + " to the value " + value,
334: module);
335: }
336: }
337: }
338: }
339: }
340:
341: public void startPrefixMapping(String prefix, String uri)
342: throws org.xml.sax.SAXException {
343: }
344:
345: // ======== ErrorHandler interface implementations ========
346:
347: public void error(org.xml.sax.SAXParseException exception)
348: throws org.xml.sax.SAXException {
349: Debug.logWarning(exception, "Error reading XML on line "
350: + exception.getLineNumber() + ", column "
351: + exception.getColumnNumber(), module);
352: }
353:
354: public void fatalError(org.xml.sax.SAXParseException exception)
355: throws org.xml.sax.SAXException {
356: Debug.logError(exception, "Fatal Error reading XML on line "
357: + exception.getLineNumber() + ", column "
358: + exception.getColumnNumber(), module);
359: throw new SAXException("Fatal Error reading XML on line "
360: + exception.getLineNumber() + ", column "
361: + exception.getColumnNumber(), exception);
362: }
363:
364: public void warning(org.xml.sax.SAXParseException exception)
365: throws org.xml.sax.SAXException {
366: Debug.logWarning(exception, "Warning reading XML on line "
367: + exception.getLineNumber() + ", column "
368: + exception.getColumnNumber(), module);
369: }
370: }
|