1 4 package com.tc.config.schema.repository; 5 6 import org.apache.commons.lang.ClassUtils; 7 import org.apache.xmlbeans.SchemaType; 8 import org.apache.xmlbeans.XmlException; 9 import org.apache.xmlbeans.XmlObject; 10 import org.apache.xmlbeans.XmlOptions; 11 12 import com.tc.config.schema.listen.ConfigurationChangeListener; 13 import com.tc.config.schema.listen.ConfigurationChangeListenerSet; 14 import com.tc.config.schema.validate.ConfigurationValidator; 15 import com.tc.util.Assert; 16 17 import java.lang.reflect.Field ; 18 import java.lang.reflect.Modifier ; 19 import java.util.ArrayList ; 20 import java.util.HashSet ; 21 import java.util.Iterator ; 22 import java.util.List ; 23 import java.util.Set ; 24 25 28 public class StandardBeanRepository implements MutableBeanRepository { 29 30 private final Class requiredClass; 31 private final ConfigurationChangeListenerSet listenerSet; 32 private final Set validators; 33 private XmlObject bean; 34 35 private XmlObject preMutateCopy; 36 37 public StandardBeanRepository(Class requiredClass) { 38 Assert.assertNotNull(requiredClass); 39 40 this.requiredClass = requiredClass; 41 this.listenerSet = new ConfigurationChangeListenerSet(); 42 this.validators = new HashSet (); 43 this.bean = null; 44 } 45 46 public void ensureBeanIsOfClass(Class theClass) { 47 if (!theClass.isAssignableFrom(this.requiredClass)) { 48 throw Assert.failure("You're making sure this repository requires at least " + theClass + ", but it requires " 50 + this.requiredClass + ", which isn't that class or a subclass thereof."); 51 } 52 } 53 54 public void saveCopyOfBeanInAnticipationOfFutureMutation() { 55 Assert.eval(this.preMutateCopy == null); 56 this.preMutateCopy = this.bean.copy(); 57 } 58 59 public void didMutateBean() { 60 Assert.eval(this.preMutateCopy != null); 61 this.listenerSet.configurationChanged(this.preMutateCopy, this.bean); 62 this.preMutateCopy = null; 63 } 64 65 public synchronized XmlObject bean() { 66 return this.bean; 67 } 68 69 static SchemaType getTypeFieldFrom(Class theClass) { 70 try { 71 Field typeField = theClass.getField("type"); 72 73 Assert.eval(typeField.getType().equals(SchemaType.class)); 74 75 int modifiers = typeField.getModifiers(); 76 Assert.eval(Modifier.isPublic(modifiers)); 77 Assert.eval(Modifier.isStatic(modifiers)); 78 Assert.eval(Modifier.isFinal(modifiers)); 79 80 return (SchemaType) typeField.get(null); 81 } catch (NoSuchFieldException nsfe) { 82 throw Assert.failure("Class " + theClass.getName() 83 + ", doesn't have a 'public static final SchemaType type' field?", nsfe); 84 } catch (IllegalArgumentException iae) { 85 throw Assert.failure("Unable to get 'public static final SchemaType type' from class " + theClass.getName(), iae); 86 } catch (IllegalAccessException iae) { 87 throw Assert.failure("Unable to get 'public static final SchemaType type' from class " + theClass.getName(), iae); 88 } 89 } 90 91 public SchemaType rootBeanSchemaType() { 92 return getTypeFieldFrom(this.requiredClass); 93 } 94 95 public synchronized void setBean(XmlObject bean, String sourceDescription) throws XmlException { 96 Assert.assertNotBlank(sourceDescription); 97 Assert.eval(bean == null || this.requiredClass.isInstance(bean)); 98 99 if (this.bean == bean) return; 100 101 if (bean != null) { 102 throwExceptionIfSchemaValidationFails(bean, sourceDescription); 103 104 Iterator iter = this.validators.iterator(); 105 while (iter.hasNext()) { 106 ((ConfigurationValidator) iter.next()).validate(bean); 107 } 108 } 109 110 XmlObject oldBean = this.bean; 111 this.bean = bean; 112 this.listenerSet.configurationChanged(oldBean, bean); 113 } 114 115 private void throwExceptionIfSchemaValidationFails(XmlObject theBean, String sourceDescription) throws XmlException { 116 List errors = new ArrayList (); 117 XmlOptions options = new XmlOptions(); 118 options = options.setLoadLineNumbers(); 119 options = options.setErrorListener(errors); 120 options = options.setDocumentSourceName(sourceDescription); 121 122 boolean validated = theBean.validate(options); 123 124 if (errors.size() > 0 || (!validated)) { 125 StringBuffer descrip = new StringBuffer (); 126 127 descrip.append("The configuration from '" + sourceDescription + "' is invalid; it has " + errors.size() 128 + " error" + (errors.size() == 1 ? "" : "s") + ":\n"); 129 130 int pos = 1; 131 Iterator iter = errors.iterator(); 132 while (iter.hasNext()) { 133 descrip.append(" " + pos + ": " + iter.next().toString() + "\n"); 134 pos++; 135 } 136 137 throw new XmlException(descrip.toString()); 138 } 139 } 140 141 public void addListener(ConfigurationChangeListener listener) { 142 Assert.assertNotNull(listener); 143 this.listenerSet.addListener(listener); 144 } 145 146 public void addValidator(ConfigurationValidator validator) { 147 Assert.assertNotNull(validator); 148 this.validators.add(validator); 149 } 150 151 public String toString() { 152 return "<Repository for bean of class " + ClassUtils.getShortClassName(this.requiredClass) + "; have bean? " 153 + (this.bean != null) + ">"; 154 } 155 156 } 157 | Popular Tags |