1 21 22 package org.apache.derby.iapi.types; 23 24 import org.apache.derby.iapi.error.StandardException; 25 26 import org.apache.derby.iapi.services.cache.ClassSize; 27 import org.apache.derby.iapi.services.io.ArrayInputStream; 28 import org.apache.derby.iapi.services.io.StoredFormatIds; 29 import org.apache.derby.iapi.services.io.StreamStorable; 30 import org.apache.derby.iapi.services.io.Storable; 31 import org.apache.derby.iapi.services.io.TypedFormat; 32 import org.apache.derby.iapi.services.loader.ClassInspector; 33 import org.apache.derby.iapi.services.sanity.SanityManager; 34 35 import org.apache.derby.iapi.types.DataValueDescriptor; 36 import org.apache.derby.iapi.types.StringDataValue; 37 import org.apache.derby.iapi.types.BooleanDataValue; 38 39 import org.apache.derby.iapi.reference.SQLState; 40 41 import java.sql.ResultSet ; 42 import java.sql.SQLException ; 43 import java.sql.Types ; 44 45 import java.io.InputStream ; 46 import java.io.IOException ; 47 import java.io.ObjectOutput ; 48 import java.io.ObjectInput ; 49 import java.io.StringReader ; 50 51 import java.util.ArrayList ; 52 53 72 public class XML 73 extends DataType implements XMLDataValue, StreamStorable 74 { 75 protected static final short UTF8_IMPL_ID = 0; 78 79 private static final int BASE_MEMORY_USAGE = 81 ClassSize.estimateBaseFromCatalog(XML.class); 82 83 public static final short XQ_PASS_BY_REF = 1; 86 public static final short XQ_PASS_BY_VALUE = 2; 87 public static final short XQ_RETURN_SEQUENCE = 3; 88 public static final short XQ_RETURN_CONTENT = 4; 89 public static final short XQ_EMPTY_ON_EMPTY = 5; 90 public static final short XQ_NULL_ON_EMPTY = 6; 91 92 112 public static final int XML_DOC_ANY = 0; 113 public static final int XML_SEQUENCE = 1; 114 115 private int xType; 117 118 private SQLChar xmlStringValue; 126 127 131 private static String xmlReqCheck = null; 132 133 140 private boolean containsTopLevelAttr; 141 142 145 public XML() 146 { 147 xmlStringValue = null; 148 xType = -1; 149 containsTopLevelAttr = false; 150 } 151 152 163 private XML(SQLChar val, int xmlType, boolean seqWithAttr) 164 { 165 xmlStringValue = (val == null ? null : (SQLChar)val.getClone()); 166 setXType(xmlType); 167 if (seqWithAttr) 168 markAsHavingTopLevelAttr(); 169 } 170 171 174 175 178 public DataValueDescriptor getClone() 179 { 180 return new XML(xmlStringValue, getXType(), hasTopLevelAttr()); 181 } 182 183 186 public DataValueDescriptor getNewNull() 187 { 188 return new XML(); 189 } 190 191 194 public String getTypeName() 195 { 196 return TypeId.XML_NAME; 197 } 198 199 202 public int typePrecedence() 203 { 204 return TypeId.XML_PRECEDENCE; 205 } 206 207 210 public String getString() throws StandardException 211 { 212 return (xmlStringValue == null) ? null : xmlStringValue.getString(); 213 } 214 215 218 public int getLength() throws StandardException 219 { 220 return ((xmlStringValue == null) ? 0 : xmlStringValue.getLength()); 221 } 222 223 226 public int estimateMemoryUsage() 227 { 228 int sz = BASE_MEMORY_USAGE; 229 if (xmlStringValue != null) 230 sz += xmlStringValue.estimateMemoryUsage(); 231 return sz; 232 } 233 234 237 public void readExternalFromArray(ArrayInputStream in) 238 throws IOException 239 { 240 if (xmlStringValue == null) 241 xmlStringValue = new SQLChar(); 242 243 in.readShort(); 249 250 xmlStringValue.readExternalFromArray(in); 252 253 setXType(XML_DOC_ANY); 257 } 258 259 262 protected void setFrom(DataValueDescriptor theValue) 263 throws StandardException 264 { 265 String strVal = theValue.getString(); 266 if (strVal == null) 267 { 268 xmlStringValue = null; 269 270 setXType(XML_DOC_ANY); 272 return; 273 } 274 275 if (xmlStringValue == null) 277 xmlStringValue = new SQLChar(); 278 xmlStringValue.setValue(strVal); 279 280 289 if (theValue instanceof XMLDataValue) 290 { 291 setXType(((XMLDataValue)theValue).getXType()); 292 if (((XMLDataValue)theValue).hasTopLevelAttr()) 293 markAsHavingTopLevelAttr(); 294 } 295 } 296 297 300 public final void setValueFromResultSet( 301 ResultSet resultSet, int colNumber, boolean isNullable) 302 throws SQLException 303 { 304 if (xmlStringValue == null) 305 xmlStringValue = new SQLChar(); 306 xmlStringValue.setValue(resultSet.getString(colNumber)); 307 } 308 309 328 public int compare(DataValueDescriptor other) 329 throws StandardException 330 { 331 if (SanityManager.DEBUG) { 332 SanityManager.ASSERT(other instanceof XMLDataValue, 333 "Store should NOT have tried to compare an XML value " + 334 "with a non-XML value."); 335 } 336 337 if (isNull()) { 338 if (other.isNull()) 339 return 0; 341 return -1; 343 } 344 345 if (other.isNull()) 346 return 1; 348 349 if (SanityManager.DEBUG) { 353 SanityManager.THROWASSERT( 354 "Store tried to compare two non-null XML values, " + 355 "which isn't allowed."); 356 } 357 return 0; 358 } 359 360 374 public void normalize( 375 DataTypeDescriptor desiredType, 376 DataValueDescriptor source) 377 throws StandardException 378 { 379 if (SanityManager.DEBUG) { 380 SanityManager.ASSERT(source instanceof XMLDataValue, 381 "Tried to store non-XML value into XML column; " + 382 "should have thrown error at compile time."); 383 } 384 385 if (((XMLDataValue)source).getXType() != XML_DOC_ANY) { 386 throw StandardException.newException( 387 SQLState.LANG_NOT_AN_XML_DOCUMENT); 388 } 389 390 ((DataValueDescriptor) this).setValue(source); 391 return; 392 393 } 394 395 398 399 405 public int getTypeFormatId() { 406 return StoredFormatIds.XML_ID; 407 } 408 409 412 public boolean isNull() 413 { 414 return ((xmlStringValue == null) || xmlStringValue.isNull()); 415 } 416 417 420 public void restoreToNull() 421 { 422 if (xmlStringValue != null) 423 xmlStringValue.restoreToNull(); 424 } 425 426 430 public void readExternal(ObjectInput in) throws IOException 431 { 432 if (xmlStringValue == null) 433 xmlStringValue = new SQLChar(); 434 435 in.readShort(); 441 442 xmlStringValue.readExternal(in); 444 445 setXType(XML_DOC_ANY); 449 } 450 451 455 public void writeExternal(ObjectOutput out) throws IOException 456 { 457 if (SanityManager.DEBUG) 459 SanityManager.ASSERT(!isNull()); 460 461 out.writeShort(UTF8_IMPL_ID); 463 464 xmlStringValue.writeExternal(out); 466 } 467 468 471 472 475 public InputStream returnStream() 476 { 477 return 478 (xmlStringValue == null) ? null : xmlStringValue.returnStream(); 479 } 480 481 484 public void setStream(InputStream newStream) 485 { 486 if (xmlStringValue == null) 487 xmlStringValue = new SQLChar(); 488 489 try { 498 newStream.read(); 500 newStream.read(); 501 } catch (Exception e) { 502 if (SanityManager.DEBUG) 503 SanityManager.THROWASSERT("Failed to read impl id" + 504 "bytes in setStream."); 505 } 506 507 xmlStringValue.setStream(newStream); 509 510 setXType(XML_DOC_ANY); 514 } 515 516 519 public void loadStream() throws StandardException 520 { 521 getString(); 522 } 523 524 527 528 544 public XMLDataValue XMLParse(String text, boolean preserveWS, 545 SqlXmlUtil sqlxUtil) throws StandardException 546 { 547 try { 548 549 if (preserveWS) { 550 text = sqlxUtil.serializeToString(text); 556 } 557 else { 558 if (SanityManager.DEBUG) 561 SanityManager.THROWASSERT("Tried to STRIP whitespace " + 562 "but we shouldn't have made it this far"); 563 } 564 565 } catch (Throwable t) { 566 579 throw StandardException.newException( 580 SQLState.LANG_INVALID_XML_DOCUMENT, t, t.getMessage()); 581 582 } 583 584 setXType(XML_DOC_ANY); 587 if (xmlStringValue == null) 588 xmlStringValue = new SQLChar(); 589 xmlStringValue.setValue(text); 590 return this; 591 } 592 593 609 public StringDataValue XMLSerialize(StringDataValue result, 610 int targetType, int targetWidth) throws StandardException 611 { 612 if (result == null) { 613 switch (targetType) 614 { 615 case Types.CHAR: result = new SQLChar(); break; 616 case Types.VARCHAR: result = new SQLVarchar(); break; 617 case Types.LONGVARCHAR: result = new SQLLongvarchar(); break; 618 case Types.CLOB: result = new SQLClob(); break; 619 default: 620 623 if (SanityManager.DEBUG) { 624 SanityManager.THROWASSERT( 625 "Should NOT have made it to XMLSerialize " + 626 "with a non-string target type: " + targetType); 627 } 628 return null; 629 } 630 } 631 632 639 if (this.isNull()) { 640 result.setToNull(); 643 return result; 644 } 645 646 656 if (this.hasTopLevelAttr()) 657 { 658 throw StandardException.newException( 659 SQLState.LANG_XQUERY_SERIALIZATION_ERROR); 660 } 661 662 result.setValue(getString()); 666 667 result.setWidth(targetWidth, 0, true); 671 return result; 672 } 673 674 690 public BooleanDataValue XMLExists(SqlXmlUtil sqlxUtil) 691 throws StandardException 692 { 693 if (this.isNull()) { 694 return SQLBoolean.unknownTruthValue(); 699 } 700 701 if (SanityManager.DEBUG) { 704 SanityManager.ASSERT( 705 sqlxUtil != null, 706 "Tried to evaluate XML xquery, but no XML objects were loaded."); 707 } 708 709 try { 710 711 return new SQLBoolean(null != 712 sqlxUtil.evalXQExpression(this, false, new int[1])); 713 714 } catch (StandardException se) { 715 716 throw se; 718 719 } catch (Throwable xe) { 720 732 throw StandardException.newException( 733 SQLState.LANG_XML_QUERY_ERROR, xe, 734 "XMLEXISTS", xe.getMessage()); 735 } 736 } 737 738 755 public XMLDataValue XMLQuery(XMLDataValue result, 756 SqlXmlUtil sqlxUtil) throws StandardException 757 { 758 if (this.isNull()) { 759 if (result == null) 762 result = (XMLDataValue)getNewNull(); 763 else 764 result.setToNull(); 765 return result; 766 } 767 768 try { 769 770 int [] xType = new int[1]; 773 ArrayList itemRefs = sqlxUtil.evalXQExpression( 774 this, true, xType); 775 776 if (result == null) 777 result = new XML(); 778 String strResult = sqlxUtil.serializeToString(itemRefs, result); 779 result.setValue(new SQLChar(strResult)); 780 781 result.setXType(xType[0]); 784 785 return result; 787 788 } catch (StandardException se) { 789 790 throw se; 792 793 } catch (Throwable xe) { 794 806 throw StandardException.newException( 807 SQLState.LANG_XML_QUERY_ERROR, xe, 808 "XMLQUERY", xe.getMessage()); 809 } 810 } 811 812 815 816 819 public void setXType(int xtype) 820 { 821 this.xType = xtype; 822 823 831 if (xtype == XML_DOC_ANY) 832 containsTopLevelAttr = false; 833 } 834 835 838 public int getXType() 839 { 840 return xType; 841 } 842 843 847 public void markAsHavingTopLevelAttr() 848 { 849 this.containsTopLevelAttr = true; 850 } 851 852 856 public boolean hasTopLevelAttr() 857 { 858 return containsTopLevelAttr; 859 } 860 861 879 public static void checkXMLRequirements() 880 throws StandardException 881 { 882 if (xmlReqCheck == null) 884 { 885 xmlReqCheck = ""; 886 887 901 if (!ClassInspector.classIsLoadable("org.w3c.dom.Document")) 902 xmlReqCheck = "JAXP"; 903 904 913 else if (!ClassInspector.classIsLoadable("org.apache.xpath.XPath")) 914 xmlReqCheck = "Xalan"; 915 } 916 917 if (xmlReqCheck.length() != 0) 918 { 919 throw StandardException.newException( 920 SQLState.LANG_MISSING_XML_CLASSES, xmlReqCheck); 921 } 922 923 return; 924 } 925 926 } 927 | Popular Tags |