001 /******************************************************************************* 002 * Portions created by Sebastian Thomschke are copyright (c) 2005-2011 Sebastian 003 * Thomschke. 004 * 005 * All Rights Reserved. This program and the accompanying materials 006 * are made available under the terms of the Eclipse Public License v1.0 007 * which accompanies this distribution, and is available at 008 * http://www.eclipse.org/legal/epl-v10.html 009 * 010 * Contributors: 011 * Sebastian Thomschke - initial implementation. 012 *******************************************************************************/ 013 package net.sf.oval.configuration.xml; 014 015 import java.io.BufferedInputStream; 016 import java.io.File; 017 import java.io.FileInputStream; 018 import java.io.IOException; 019 import java.io.InputStream; 020 import java.io.OutputStream; 021 import java.io.Reader; 022 import java.io.Writer; 023 import java.lang.annotation.Annotation; 024 import java.lang.reflect.Method; 025 import java.lang.reflect.ParameterizedType; 026 import java.lang.reflect.Type; 027 import java.util.ArrayList; 028 import java.util.List; 029 import java.util.Set; 030 import java.util.regex.Pattern; 031 032 import net.sf.oval.AbstractCheck; 033 import net.sf.oval.Check; 034 import net.sf.oval.CheckExclusion; 035 import net.sf.oval.ConstraintTarget; 036 import net.sf.oval.Validator; 037 import net.sf.oval.configuration.CheckInitializationListener; 038 import net.sf.oval.configuration.Configurer; 039 import net.sf.oval.configuration.annotation.AbstractAnnotationCheck; 040 import net.sf.oval.configuration.annotation.Constraint; 041 import net.sf.oval.configuration.pojo.POJOConfigurer; 042 import net.sf.oval.configuration.pojo.elements.ClassConfiguration; 043 import net.sf.oval.configuration.pojo.elements.ConstraintSetConfiguration; 044 import net.sf.oval.configuration.pojo.elements.ConstructorConfiguration; 045 import net.sf.oval.configuration.pojo.elements.FieldConfiguration; 046 import net.sf.oval.configuration.pojo.elements.MethodConfiguration; 047 import net.sf.oval.configuration.pojo.elements.MethodPostExecutionConfiguration; 048 import net.sf.oval.configuration.pojo.elements.MethodPreExecutionConfiguration; 049 import net.sf.oval.configuration.pojo.elements.MethodReturnValueConfiguration; 050 import net.sf.oval.configuration.pojo.elements.ObjectConfiguration; 051 import net.sf.oval.configuration.pojo.elements.ParameterConfiguration; 052 import net.sf.oval.constraint.AssertCheck; 053 import net.sf.oval.constraint.AssertConstraintSetCheck; 054 import net.sf.oval.constraint.AssertFalseCheck; 055 import net.sf.oval.constraint.AssertFieldConstraintsCheck; 056 import net.sf.oval.constraint.AssertNullCheck; 057 import net.sf.oval.constraint.AssertTrueCheck; 058 import net.sf.oval.constraint.AssertURLCheck; 059 import net.sf.oval.constraint.AssertURLCheck.URIScheme; 060 import net.sf.oval.constraint.AssertValidCheck; 061 import net.sf.oval.constraint.CheckWithCheck; 062 import net.sf.oval.constraint.CheckWithCheck.SimpleCheck; 063 import net.sf.oval.constraint.DateRangeCheck; 064 import net.sf.oval.constraint.DigitsCheck; 065 import net.sf.oval.constraint.EmailCheck; 066 import net.sf.oval.constraint.EqualToFieldCheck; 067 import net.sf.oval.constraint.FutureCheck; 068 import net.sf.oval.constraint.HasSubstringCheck; 069 import net.sf.oval.constraint.InstanceOfAnyCheck; 070 import net.sf.oval.constraint.InstanceOfCheck; 071 import net.sf.oval.constraint.LengthCheck; 072 import net.sf.oval.constraint.MatchPatternCheck; 073 import net.sf.oval.constraint.MaxCheck; 074 import net.sf.oval.constraint.MaxLengthCheck; 075 import net.sf.oval.constraint.MaxSizeCheck; 076 import net.sf.oval.constraint.MemberOfCheck; 077 import net.sf.oval.constraint.MinCheck; 078 import net.sf.oval.constraint.MinLengthCheck; 079 import net.sf.oval.constraint.MinSizeCheck; 080 import net.sf.oval.constraint.NoSelfReferenceCheck; 081 import net.sf.oval.constraint.NotBlankCheck; 082 import net.sf.oval.constraint.NotEmptyCheck; 083 import net.sf.oval.constraint.NotEqualCheck; 084 import net.sf.oval.constraint.NotEqualToFieldCheck; 085 import net.sf.oval.constraint.NotMatchPatternCheck; 086 import net.sf.oval.constraint.NotMemberOfCheck; 087 import net.sf.oval.constraint.NotNegativeCheck; 088 import net.sf.oval.constraint.NotNullCheck; 089 import net.sf.oval.constraint.PastCheck; 090 import net.sf.oval.constraint.RangeCheck; 091 import net.sf.oval.constraint.SizeCheck; 092 import net.sf.oval.constraint.ValidateWithMethodCheck; 093 import net.sf.oval.constraint.exclusion.NullableExclusion; 094 import net.sf.oval.exception.InvalidConfigurationException; 095 import net.sf.oval.guard.PostCheck; 096 import net.sf.oval.guard.PreCheck; 097 import net.sf.oval.internal.Log; 098 import net.sf.oval.internal.util.Assert; 099 import net.sf.oval.internal.util.LinkedSet; 100 import net.sf.oval.internal.util.ReflectionUtils; 101 102 import com.thoughtworks.xstream.XStream; 103 import com.thoughtworks.xstream.converters.Converter; 104 import com.thoughtworks.xstream.converters.MarshallingContext; 105 import com.thoughtworks.xstream.converters.UnmarshallingContext; 106 import com.thoughtworks.xstream.converters.collections.CollectionConverter; 107 import com.thoughtworks.xstream.converters.reflection.ReflectionConverter; 108 import com.thoughtworks.xstream.converters.reflection.Sun14ReflectionProvider; 109 import com.thoughtworks.xstream.io.HierarchicalStreamDriver; 110 import com.thoughtworks.xstream.io.HierarchicalStreamReader; 111 import com.thoughtworks.xstream.io.HierarchicalStreamWriter; 112 import com.thoughtworks.xstream.io.xml.DomDriver; 113 import com.thoughtworks.xstream.io.xml.StaxDriver; 114 import com.thoughtworks.xstream.io.xml.XppDriver; 115 import com.thoughtworks.xstream.mapper.Mapper; 116 117 /** 118 * XStream (http://xstream.codehaus.org/) based XML configuration class. 119 * 120 * @author Sebastian Thomschke 121 */ 122 public class XMLConfigurer implements Configurer 123 { 124 /** 125 * The converter is needed to allow the rendering of Assert's expr attribute value as an XML node value and not an XML attribute 126 * <code><assert><expr>...</expr></assert></code> instead of <code><assert expr="..."></code> 127 * This allows users to write complex, multi-line expressions. 128 */ 129 protected final class AssertCheckConverter implements Converter 130 { 131 /** 132 * {@inheritDoc} 133 */ 134 public boolean canConvert(@SuppressWarnings("rawtypes") final Class clazz) 135 { 136 return clazz.equals(AssertCheck.class); 137 } 138 139 /** 140 * {@inheritDoc} 141 */ 142 public void marshal(final Object value, final HierarchicalStreamWriter writer, final MarshallingContext context) 143 { 144 final AssertCheck assertCheck = (AssertCheck) value; 145 writer.addAttribute("lang", assertCheck.getLang()); 146 if (!"net.sf.oval.constraint.Assert.violated".equals(assertCheck.getMessage())) 147 writer.addAttribute("message", assertCheck.getMessage()); 148 if (!"net.sf.oval.constraint.Assert".equals(assertCheck.getErrorCode())) 149 writer.addAttribute("errorCode", assertCheck.getErrorCode()); 150 writer.addAttribute("severity", Integer.toString(assertCheck.getSeverity())); 151 if (assertCheck.getWhen() != null) writer.addAttribute("when", assertCheck.getWhen()); 152 writer.startNode("expr"); 153 writer.setValue(assertCheck.getExpr()); 154 writer.endNode(); 155 final String[] profiles = assertCheck.getProfiles(); 156 if (profiles != null && profiles.length > 0) 157 { 158 writer.startNode("profiles"); 159 for (final String profile : profiles) 160 { 161 writer.startNode("string"); 162 writer.setValue(profile); 163 writer.endNode(); 164 } 165 writer.endNode(); 166 } 167 final ConstraintTarget[] appliesTo = assertCheck.getAppliesTo(); 168 if (appliesTo != null && appliesTo.length > 0) 169 { 170 writer.startNode("appliesTo"); 171 for (final ConstraintTarget ctarget : appliesTo) 172 { 173 writer.startNode("constraintTarget"); 174 writer.setValue(ctarget.name()); 175 writer.endNode(); 176 } 177 writer.endNode(); 178 } 179 } 180 181 /** 182 * {@inheritDoc} 183 */ 184 public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) 185 { 186 final AssertCheck assertCheck = new AssertCheck(); 187 assertCheck.setLang(reader.getAttribute("lang")); 188 assertCheck.setMessage(reader.getAttribute("message")); 189 assertCheck.setErrorCode(reader.getAttribute("errorCode")); 190 if (reader.getAttribute("severity") != null) 191 assertCheck.setSeverity(Integer.parseInt(reader.getAttribute("severity"))); 192 assertCheck.setTarget(reader.getAttribute("target")); 193 assertCheck.setWhen(reader.getAttribute("when")); 194 195 reader.moveDown(); 196 assertCheck.setExpr(reader.getValue()); 197 reader.moveUp(); 198 if (reader.hasMoreChildren()) 199 { 200 reader.moveDown(); 201 if ("appliesTo".equals(reader.getNodeName())) 202 { 203 final List<ConstraintTarget> targets = new ArrayList<ConstraintTarget>(2); 204 while (reader.hasMoreChildren()) 205 { 206 reader.moveDown(); 207 if ("constraintTarget".equals(reader.getNodeName())) 208 targets.add(ConstraintTarget.valueOf(reader.getValue())); 209 reader.moveUp(); 210 } 211 assertCheck.setAppliesTo(targets.toArray(new ConstraintTarget[targets.size()])); 212 } 213 else if ("profiles".equals(reader.getNodeName())) 214 { 215 final List<String> profiles = new ArrayList<String>(4); 216 while (reader.hasMoreChildren()) 217 { 218 reader.moveDown(); 219 if ("string".equals(reader.getNodeName())) profiles.add(reader.getValue()); 220 reader.moveUp(); 221 } 222 assertCheck.setProfiles(profiles.toArray(new String[profiles.size()])); 223 } 224 reader.moveUp(); 225 } 226 for (final CheckInitializationListener listener : listeners) 227 listener.onCheckInitialized(assertCheck); 228 return assertCheck; 229 } 230 } 231 232 private static final class ListConverter extends CollectionConverter 233 { 234 protected ListConverter(final Mapper mapper) 235 { 236 super(mapper); 237 } 238 239 /** 240 * {@inheritDoc} 241 */ 242 @Override 243 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) 244 { 245 return List.class.isAssignableFrom(type); 246 } 247 } 248 249 /** 250 * This reflection provider applies default values declared on constraint annotations to the corresponding check class 251 */ 252 protected static final class XStreamReflectionProvider extends Sun14ReflectionProvider 253 { 254 @SuppressWarnings("unchecked") 255 @Override 256 public Object newInstance(@SuppressWarnings("rawtypes") final Class type) 257 { 258 final Object instance = super.newInstance(type); 259 260 // test if a AnnotationCheck instance is requested 261 if (instance instanceof AbstractAnnotationCheck) 262 { 263 // determine the constraint annotation 264 Class<Annotation> constraintAnnotation = null; 265 final ParameterizedType genericSuperclass = (ParameterizedType) type.getGenericSuperclass(); 266 for (final Type genericType : genericSuperclass.getActualTypeArguments()) 267 { 268 final Class< ? > genericClass = (Class< ? >) genericType; 269 if (genericClass.isAnnotation() && genericClass.isAnnotationPresent(Constraint.class)) 270 { 271 constraintAnnotation = (Class<Annotation>) genericClass; 272 break; 273 } 274 } 275 // in case we could determine the constraint annotation, read the attributes and 276 // apply the declared default values to the check instance 277 if (constraintAnnotation != null) for (final Method m : constraintAnnotation.getMethods()) 278 { 279 final Object defaultValue = m.getDefaultValue(); 280 if (defaultValue != null) ReflectionUtils.setViaSetter(instance, m.getName(), defaultValue); 281 } 282 } 283 return instance; 284 } 285 } 286 287 private static final Log LOG = Log.getLog(Validator.class); 288 289 protected final Set<CheckInitializationListener> listeners = new LinkedSet<CheckInitializationListener>(2); 290 private POJOConfigurer pojoConfigurer = new POJOConfigurer(); 291 private final XStream xStream; 292 293 /** 294 * creates an XMLConfigurer instance backed by a new XStream instance 295 * using the com.thoughtworks.xstream.io.xml.StaxDriver for XML parsing 296 * if the StAX API is available 297 * @see com.thoughtworks.xstream.io.xml.StaxDriver 298 */ 299 public XMLConfigurer() 300 { 301 final HierarchicalStreamDriver xmlDriver = // 302 ReflectionUtils.isClassPresent("javax.xml.stream.XMLStreamReader") ? new StaxDriver() : // 303 ReflectionUtils.isClassPresent("org.xmlpull.mxp1.MXParser") ? new XppDriver() : // 304 new DomDriver(); 305 LOG.info("XML driver implementation: {1}", xmlDriver.getClass().getName()); 306 xStream = new XStream(new XStreamReflectionProvider(), xmlDriver); 307 configureXStream(); 308 } 309 310 public XMLConfigurer(final File xmlConfigFile) throws IOException 311 { 312 this(); 313 fromXML(xmlConfigFile); 314 } 315 316 public XMLConfigurer(final InputStream xmlConfigStream) 317 { 318 this(); 319 fromXML(xmlConfigStream); 320 } 321 322 public XMLConfigurer(final Reader xmlConfigReader) 323 { 324 this(); 325 fromXML(xmlConfigReader); 326 } 327 328 public XMLConfigurer(final String xmlConfigAsString) 329 { 330 this(); 331 fromXML(xmlConfigAsString); 332 } 333 334 public boolean addCheckInitializationListener(final CheckInitializationListener listener) 335 { 336 Assert.argumentNotNull("listener", listener); 337 return listeners.add(listener); 338 } 339 340 private void configureXStream() 341 { 342 xStream.registerConverter(new ReflectionConverter(xStream.getMapper(), xStream.getReflectionProvider()) 343 { 344 @Override 345 public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) 346 { 347 final Object instance = super.unmarshal(reader, context); 348 if (instance instanceof Check) // 349 for (final CheckInitializationListener listener : listeners) 350 listener.onCheckInitialized((Check) instance); 351 return instance; 352 } 353 }, XStream.PRIORITY_VERY_LOW); 354 xStream.registerConverter(new ListConverter(xStream.getMapper())); 355 xStream.registerConverter(new AssertCheckConverter()); 356 357 xStream.omitField(AbstractCheck.class, "messageVariablesUpToDate"); 358 359 xStream.useAttributeFor(Class.class); 360 xStream.useAttributeFor(boolean.class); 361 xStream.useAttributeFor(byte.class); 362 xStream.useAttributeFor(char.class); 363 xStream.useAttributeFor(double.class); 364 xStream.useAttributeFor(float.class); 365 xStream.useAttributeFor(int.class); 366 xStream.useAttributeFor(long.class); 367 xStream.useAttributeFor(Boolean.class); 368 xStream.useAttributeFor(Byte.class); 369 xStream.useAttributeFor(Character.class); 370 xStream.useAttributeFor(Double.class); 371 xStream.useAttributeFor(Float.class); 372 xStream.useAttributeFor(Integer.class); 373 xStream.useAttributeFor(Long.class); 374 xStream.useAttributeFor(String.class); 375 376 xStream.alias("java-type", Class.class); 377 xStream.alias("constraintTarget", ConstraintTarget.class); 378 379 // constraint check short forms 380 xStream.alias("assert", AssertCheck.class); 381 xStream.alias("assertConstraintSet", AssertConstraintSetCheck.class); 382 xStream.alias("assertFalse", AssertFalseCheck.class); 383 xStream.alias("assertFieldConstraints", AssertFieldConstraintsCheck.class); 384 xStream.alias("assertNull", AssertNullCheck.class); 385 xStream.alias("assertTrue", AssertTrueCheck.class); 386 { 387 xStream.alias("assertURL", AssertURLCheck.class); 388 xStream.alias("permittedURIScheme", URIScheme.class); 389 xStream.addImplicitCollection(AssertURLCheck.class, "permittedURISchemes", URIScheme.class); 390 } 391 xStream.alias("assertValid", AssertValidCheck.class); 392 xStream.alias("checkWith", CheckWithCheck.class); 393 xStream.alias("dateRange", DateRangeCheck.class); 394 xStream.alias("digits", DigitsCheck.class); 395 xStream.alias("email", EmailCheck.class); 396 xStream.alias("equalToField", EqualToFieldCheck.class); 397 xStream.alias("future", FutureCheck.class); 398 xStream.alias("hasSubstring", HasSubstringCheck.class); 399 xStream.alias("instanceOf", InstanceOfCheck.class); 400 xStream.alias("instanceOfAny", InstanceOfAnyCheck.class); 401 xStream.alias("length", LengthCheck.class); 402 { 403 xStream.alias("matchPattern", MatchPatternCheck.class); 404 xStream.alias("pattern", Pattern.class); 405 xStream.addImplicitCollection(MatchPatternCheck.class, "patterns", Pattern.class); 406 } 407 xStream.alias("max", MaxCheck.class); 408 xStream.alias("maxLength", MaxLengthCheck.class); 409 xStream.alias("maxSize", MaxSizeCheck.class); 410 xStream.alias("memberOf", MemberOfCheck.class); 411 xStream.alias("min", MinCheck.class); 412 xStream.alias("minLength", MinLengthCheck.class); 413 xStream.alias("minSize", MinSizeCheck.class); 414 xStream.alias("noSelfReference", NoSelfReferenceCheck.class); 415 xStream.alias("notBlank", NotBlankCheck.class); 416 xStream.alias("notEmpty", NotEmptyCheck.class); 417 xStream.alias("notEqual", NotEqualCheck.class); 418 xStream.alias("notEqualToField", NotEqualToFieldCheck.class); 419 { 420 xStream.alias("notMatchPattern", NotMatchPatternCheck.class); 421 xStream.addImplicitCollection(NotMatchPatternCheck.class, "patterns", Pattern.class); 422 } 423 xStream.alias("notMemberOf", NotMemberOfCheck.class); 424 xStream.alias("notNegative", NotNegativeCheck.class); 425 xStream.alias("notNull", NotNullCheck.class); 426 xStream.alias("past", PastCheck.class); 427 xStream.alias("range", RangeCheck.class); 428 xStream.alias("simpleCheck", SimpleCheck.class); 429 xStream.alias("size", SizeCheck.class); 430 xStream.alias("validateWithMethod", ValidateWithMethodCheck.class); 431 432 // check exclusions short forms 433 xStream.alias("nullable", NullableExclusion.class); 434 435 // <oval> -> net.sf.oval.configuration.POJOConfigurer 436 xStream.alias("oval", POJOConfigurer.class); 437 { 438 // <constraintSet> -> net.sf.oval.configuration.elements.ConstraintSetConfiguration 439 xStream.addImplicitCollection(POJOConfigurer.class, "constraintSetConfigurations", 440 ConstraintSetConfiguration.class); 441 xStream.alias("constraintSet", ConstraintSetConfiguration.class); 442 xStream.addImplicitCollection(ConstraintSetConfiguration.class, "checks"); 443 444 // <class> -> net.sf.oval.configuration.elements.ClassConfiguration 445 xStream.addImplicitCollection(POJOConfigurer.class, "classConfigurations", ClassConfiguration.class); 446 xStream.alias("class", ClassConfiguration.class); 447 { 448 // <object> -> net.sf.oval.configuration.elements.ObjectConfiguration 449 xStream.aliasField("object", ClassConfiguration.class, "objectConfiguration"); 450 { 451 xStream.addImplicitCollection(ObjectConfiguration.class, "checks"); 452 } 453 // <field> -> net.sf.oval.configuration.elements.FieldConfiguration 454 xStream.addImplicitCollection(ClassConfiguration.class, "fieldConfigurations", FieldConfiguration.class); 455 xStream.alias("field", FieldConfiguration.class); 456 xStream.addImplicitCollection(FieldConfiguration.class, "checks"); 457 458 // <parameter> -> net.sf.oval.configuration.elements.ParameterConfiguration 459 // used within ConstructorConfiguration and MethodConfiguration 460 xStream.alias("parameter", ParameterConfiguration.class); 461 xStream.addImplicitCollection(ParameterConfiguration.class, "checks", Check.class); 462 xStream.addImplicitCollection(ParameterConfiguration.class, "checkExclusions", CheckExclusion.class); 463 464 // <constructor> -> net.sf.oval.configuration.elements.ConstructorConfiguration 465 xStream.addImplicitCollection(ClassConfiguration.class, "constructorConfigurations", 466 ConstructorConfiguration.class); 467 xStream.alias("constructor", ConstructorConfiguration.class); 468 { 469 // <parameter> -> net.sf.oval.configuration.elements.ParameterConfiguration 470 xStream.addImplicitCollection(ConstructorConfiguration.class, "parameterConfigurations", 471 ParameterConfiguration.class); 472 } 473 474 // <method> -> net.sf.oval.configuration.elements.MethodConfiguration 475 xStream.addImplicitCollection(ClassConfiguration.class, "methodConfigurations", 476 MethodConfiguration.class); 477 xStream.alias("method", MethodConfiguration.class); 478 { 479 // <parameter> -> net.sf.oval.configuration.elements.ParameterConfiguration 480 xStream.addImplicitCollection(MethodConfiguration.class, "parameterConfigurations", 481 ParameterConfiguration.class); 482 483 // <returnValue> -> net.sf.oval.configuration.elements.MethodConfiguration.returnValueConfiguration 484 // -> MethodReturnValueConfiguration 485 xStream.aliasField("returnValue", MethodConfiguration.class, "returnValueConfiguration"); 486 xStream.addImplicitCollection(MethodReturnValueConfiguration.class, "checks", Check.class); 487 488 // <pre> -> net.sf.oval.configuration.elements.MethodConfiguration.preExecutionConfiguration -> 489 // MethodPreExecutionConfiguration 490 xStream.aliasField("preExecution", MethodConfiguration.class, "preExecutionConfiguration"); 491 xStream.addImplicitCollection(MethodPreExecutionConfiguration.class, "checks", PreCheck.class); 492 xStream.alias("pre", PreCheck.class); 493 494 // <post> -> net.sf.oval.configuration.elements.MethodConfiguration.postExecutionConfiguration -> 495 // MethodPostExecutionConfiguration 496 xStream.aliasField("postExecution", MethodConfiguration.class, "postExecutionConfiguration"); 497 xStream.addImplicitCollection(MethodPostExecutionConfiguration.class, "checks", PostCheck.class); 498 xStream.alias("post", PostCheck.class); 499 } 500 } 501 } 502 } 503 504 public void fromXML(final File input) throws IOException 505 { 506 final BufferedInputStream bis = new BufferedInputStream(new FileInputStream(input)); 507 try 508 { 509 fromXML(bis); 510 } 511 finally 512 { 513 bis.close(); 514 } 515 } 516 517 public void fromXML(final InputStream input) 518 { 519 pojoConfigurer = (POJOConfigurer) xStream.fromXML(input); 520 } 521 522 public void fromXML(final Reader input) 523 { 524 pojoConfigurer = (POJOConfigurer) xStream.fromXML(input); 525 } 526 527 public void fromXML(final String input) 528 { 529 pojoConfigurer = (POJOConfigurer) xStream.fromXML(input); 530 } 531 532 /** 533 * {@inheritDoc} 534 */ 535 public ClassConfiguration getClassConfiguration(final Class< ? > clazz) throws InvalidConfigurationException 536 { 537 return pojoConfigurer.getClassConfiguration(clazz); 538 } 539 540 /** 541 * {@inheritDoc} 542 */ 543 public ConstraintSetConfiguration getConstraintSetConfiguration(final String constraintSetId) 544 throws InvalidConfigurationException 545 { 546 return pojoConfigurer.getConstraintSetConfiguration(constraintSetId); 547 } 548 549 /** 550 * @return the pojoConfigurer 551 */ 552 public POJOConfigurer getPojoConfigurer() 553 { 554 return pojoConfigurer; 555 } 556 557 /** 558 * @return the xStream 559 */ 560 public XStream getXStream() 561 { 562 return xStream; 563 } 564 565 public boolean removeCheckInitializationListener(final CheckInitializationListener listener) 566 { 567 return listeners.remove(listener); 568 } 569 570 /** 571 * @param pojoConfigurer the pojoConfigurer to set 572 */ 573 public void setPojoConfigurer(final POJOConfigurer pojoConfigurer) 574 { 575 this.pojoConfigurer = pojoConfigurer; 576 } 577 578 public synchronized String toXML() 579 { 580 return xStream.toXML(pojoConfigurer); 581 } 582 583 public synchronized void toXML(final OutputStream out) 584 { 585 xStream.toXML(pojoConfigurer, out); 586 } 587 588 public synchronized void toXML(final Writer out) 589 { 590 xStream.toXML(pojoConfigurer, out); 591 } 592 }