The main class:
public class XStream {
public XStream(
ReflectionProvider reflectionProvider, HierarchicalStreamDriver driver,
ClassLoader classLoader, Mapper mapper, ConverterLookup converterLookup,
ConverterRegistry converterRegistry) {
jvm = new JVM();
if (reflectionProvider == null) {
reflectionProvider = jvm.bestReflectionProvider();
}
this.reflectionProvider = reflectionProvider;
this.hierarchicalStreamDriver = driver;
this.classLoaderReference = classLoader instanceof ClassLoaderReference ? (ClassLoaderReference)classLoader : new ClassLoaderReference(classLoader);
this.converterLookup = converterLookup;
this.converterRegistry = converterRegistry != null
? converterRegistry
: (converterLookup instanceof ConverterRegistry ? (ConverterRegistry)converterLookup : null);
this.mapper = mapper == null ? buildMapper() : mapper;
ReflectionProvider reflectionProvider, HierarchicalStreamDriver driver,
ClassLoader classLoader, Mapper mapper, ConverterLookup converterLookup,
ConverterRegistry converterRegistry) {
jvm = new JVM();
if (reflectionProvider == null) {
reflectionProvider = jvm.bestReflectionProvider();
}
this.reflectionProvider = reflectionProvider;
this.hierarchicalStreamDriver = driver;
this.classLoaderReference = classLoader instanceof ClassLoaderReference ? (ClassLoaderReference)classLoader : new ClassLoaderReference(classLoader);
this.converterLookup = converterLookup;
this.converterRegistry = converterRegistry != null
? converterRegistry
: (converterLookup instanceof ConverterRegistry ? (ConverterRegistry)converterLookup : null);
this.mapper = mapper == null ? buildMapper() : mapper;
setupMappers();
setupAliases();
setupDefaultImplementations();
setupConverters();
setupImmutableTypes();
setMode(XPATH_RELATIVE_REFERENCES);
}
setupAliases();
setupDefaultImplementations();
setupConverters();
setupImmutableTypes();
setMode(XPATH_RELATIVE_REFERENCES);
}
// toXML method is the start for parsing java object to xml
public String toXML(Object obj) {
Writer writer = new StringWriter();
toXML(obj, writer);
return writer.toString();
}
Writer writer = new StringWriter();
toXML(obj, writer);
return writer.toString();
}
public void toXML(Object obj, Writer out) {
HierarchicalStreamWriter writer = hierarchicalStreamDriver.createWriter(out);
marshal(obj, writer);
writer.flush();
}
public void marshal(Object obj, HierarchicalStreamWriter writer) {
marshal(obj, writer, null);
}
marshal(obj, writer, null);
}
public void marshal(Object obj, HierarchicalStreamWriter writer, DataHolder dataHolder) {
marshallingStrategy.marshal(writer, obj, converterLookup, mapper, dataHolder);
}
// the marshallingStrategy is initial by setMode method.
public void setMode(int mode) {
switch (mode) {
case NO_REFERENCES:
setMarshallingStrategy(new TreeMarshallingStrategy());
break;
case ID_REFERENCES:
setMarshallingStrategy(new ReferenceByIdMarshallingStrategy());
break;
switch (mode) {
case NO_REFERENCES:
setMarshallingStrategy(new TreeMarshallingStrategy());
break;
case ID_REFERENCES:
setMarshallingStrategy(new ReferenceByIdMarshallingStrategy());
break;
// ReferenceByXPathMarshallingStrategy is the default strategy
case XPATH_RELATIVE_REFERENCES:
setMarshallingStrategy(new ReferenceByXPathMarshallingStrategy(
ReferenceByXPathMarshallingStrategy.RELATIVE));
break;
case XPATH_ABSOLUTE_REFERENCES:
setMarshallingStrategy(new ReferenceByXPathMarshallingStrategy(
ReferenceByXPathMarshallingStrategy.ABSOLUTE));
break;
default:
throw new IllegalArgumentException("Unknown mode : " + mode);
}
}
case XPATH_RELATIVE_REFERENCES:
setMarshallingStrategy(new ReferenceByXPathMarshallingStrategy(
ReferenceByXPathMarshallingStrategy.RELATIVE));
break;
case XPATH_ABSOLUTE_REFERENCES:
setMarshallingStrategy(new ReferenceByXPathMarshallingStrategy(
ReferenceByXPathMarshallingStrategy.ABSOLUTE));
break;
default:
throw new IllegalArgumentException("Unknown mode : " + mode);
}
}
}
public class ReferenceByXPathMarshallingStrategy extends AbstractTreeMarshallingStrategy {
public ReferenceByXPathMarshallingStrategy(int mode) {
this.mode = mode;
}
this.mode = mode;
}
protected TreeUnmarshaller createUnmarshallingContext(Object root,
HierarchicalStreamReader reader, ConverterLookup converterLookup, Mapper mapper) {
return new ReferenceByXPathUnmarshaller(root, reader, converterLookup, mapper);
}
HierarchicalStreamReader reader, ConverterLookup converterLookup, Mapper mapper) {
return new ReferenceByXPathUnmarshaller(root, reader, converterLookup, mapper);
}
// Override the createMarshallingContext method in AbstractTreeMarshallingStrategy
protected TreeMarshaller createMarshallingContext(
HierarchicalStreamWriter writer, ConverterLookup converterLookup, Mapper mapper) {
return new ReferenceByXPathMarshaller(writer, converterLookup, mapper, mode);
}
}
HierarchicalStreamWriter writer, ConverterLookup converterLookup, Mapper mapper) {
return new ReferenceByXPathMarshaller(writer, converterLookup, mapper, mode);
}
}
public abstract class AbstractTreeMarshallingStrategy implements MarshallingStrategy {
public void marshal(HierarchicalStreamWriter writer, Object obj, ConverterLookup converterLookup, Mapper mapper, DataHolder dataHolder) {
TreeMarshaller context = createMarshallingContext(writer, converterLookup, mapper);
context.start(obj, dataHolder);
}
TreeMarshaller context = createMarshallingContext(writer, converterLookup, mapper);
context.start(obj, dataHolder);
}
protected abstract TreeMarshaller createMarshallingContext(
HierarchicalStreamWriter writer, ConverterLookup converterLookup, Mapper mapper);
HierarchicalStreamWriter writer, ConverterLookup converterLookup, Mapper mapper);
}
public class ReferenceByXPathMarshaller extends AbstractReferenceMarshaller {
public ReferenceByXPathMarshaller(HierarchicalStreamWriter writer, ConverterLookup converterLookup, Mapper mapper, int mode) {
super(writer, converterLookup, mapper);
this.mode = mode;
}
super(writer, converterLookup, mapper);
this.mode = mode;
}
}
public class TreeMarshaller implements MarshallingContext {
public void convertAnother(Object item) {
convertAnother(item, null);
}
convertAnother(item, null);
}
public void convertAnother(Object item, Converter converter) {
if (converter == null) {
converter = converterLookup.lookupConverterForType(item.getClass());
} else {
if (!converter.canConvert(item.getClass())) {
ConversionException e = new ConversionException(
"Explicit selected converter cannot handle item");
e.add("item-type", item.getClass().getName());
e.add("converter-type", converter.getClass().getName());
throw e;
}
}
convert(item, converter);
}
if (converter == null) {
converter = converterLookup.lookupConverterForType(item.getClass());
} else {
if (!converter.canConvert(item.getClass())) {
ConversionException e = new ConversionException(
"Explicit selected converter cannot handle item");
e.add("item-type", item.getClass().getName());
e.add("converter-type", converter.getClass().getName());
throw e;
}
}
convert(item, converter);
}
protected void convert(Object item, Converter converter) {
if (parentObjects.containsId(item)) {
throw new CircularReferenceException();
}
parentObjects.associateId(item, "");
converter.marshal(item, writer, this);
parentObjects.removeId(item);
}
if (parentObjects.containsId(item)) {
throw new CircularReferenceException();
}
parentObjects.associateId(item, "");
converter.marshal(item, writer, this);
parentObjects.removeId(item);
}
public void start(Object item, DataHolder dataHolder) {
this.dataHolder = dataHolder;
if (item == null) {
writer.startNode(mapper.serializedClass(null));
writer.endNode();
} else {
ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper
.serializedClass(item.getClass()), item.getClass());
convertAnother(item);
writer.endNode();
}
}
this.dataHolder = dataHolder;
if (item == null) {
writer.startNode(mapper.serializedClass(null));
writer.endNode();
} else {
ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper
.serializedClass(item.getClass()), item.getClass());
convertAnother(item);
writer.endNode();
}
}
}
public class PureJavaReflectionProvider implements ReflectionProvider {
public void visitSerializableFields(Object object, ReflectionProvider.Visitor visitor) {
for (Iterator iterator = fieldDictionary.fieldsFor(object.getClass()); iterator.hasNext();) {
Field field = (Field) iterator.next();
if (!fieldModifiersSupported(field)) {
continue;
}
validateFieldAccess(field);
try {
Object value = field.get(object);
visitor.visit(field.getName(), field.getType(), field.getDeclaringClass(), value);
} catch (IllegalArgumentException e) {
throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
} catch (IllegalAccessException e) {
throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
}
}
}
for (Iterator iterator = fieldDictionary.fieldsFor(object.getClass()); iterator.hasNext();) {
Field field = (Field) iterator.next();
if (!fieldModifiersSupported(field)) {
continue;
}
validateFieldAccess(field);
try {
Object value = field.get(object);
visitor.visit(field.getName(), field.getType(), field.getDeclaringClass(), value);
} catch (IllegalArgumentException e) {
throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
} catch (IllegalAccessException e) {
throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
}
}
}
public void writeField(Object object, String fieldName, Object value, Class definedIn) {
Field field = fieldDictionary.field(object.getClass(), fieldName, definedIn);
validateFieldAccess(field);
try {
field.set(object, value);
} catch (IllegalArgumentException e) {
throw new ObjectAccessException("Could not set field " + object.getClass() + "." + field.getName(), e);
} catch (IllegalAccessException e) {
throw new ObjectAccessException("Could not set field " + object.getClass() + "." + field.getName(), e);
}
}
Field field = fieldDictionary.field(object.getClass(), fieldName, definedIn);
validateFieldAccess(field);
try {
field.set(object, value);
} catch (IllegalArgumentException e) {
throw new ObjectAccessException("Could not set field " + object.getClass() + "." + field.getName(), e);
} catch (IllegalAccessException e) {
throw new ObjectAccessException("Could not set field " + object.getClass() + "." + field.getName(), e);
}
}
public Class getFieldType(Object object, String fieldName, Class definedIn) {
return fieldDictionary.field(object.getClass(), fieldName, definedIn).getType();
}
return fieldDictionary.field(object.getClass(), fieldName, definedIn).getType();
}
public boolean fieldDefinedInClass(String fieldName, Class type) {
try {
Field field = fieldDictionary.field(type, fieldName, null);
return fieldModifiersSupported(field) || Modifier.isTransient(field.getModifiers());
} catch (ObjectAccessException e) {
return false;
}
}
try {
Field field = fieldDictionary.field(type, fieldName, null);
return fieldModifiersSupported(field) || Modifier.isTransient(field.getModifiers());
} catch (ObjectAccessException e) {
return false;
}
}
protected boolean fieldModifiersSupported(Field field) {
return !(Modifier.isStatic(field.getModifiers())
|| Modifier.isTransient(field.getModifiers()));
}
return !(Modifier.isStatic(field.getModifiers())
|| Modifier.isTransient(field.getModifiers()));
}
protected void validateFieldAccess(Field field) {
if (Modifier.isFinal(field.getModifiers())) {
if (JVM.is15()) {
field.setAccessible(true);
} else {
throw new ObjectAccessException("Invalid final field "
+ field.getDeclaringClass().getName() + "." + field.getName());
}
}
}
if (Modifier.isFinal(field.getModifiers())) {
if (JVM.is15()) {
field.setAccessible(true);
} else {
throw new ObjectAccessException("Invalid final field "
+ field.getDeclaringClass().getName() + "." + field.getName());
}
}
}
public Field getField(Class definedIn, String fieldName) {
return fieldDictionary.field(definedIn, fieldName, null);
}
return fieldDictionary.field(definedIn, fieldName, null);
}
public void setFieldDictionary(FieldDictionary dictionary) {
this.fieldDictionary = dictionary;
}
this.fieldDictionary = dictionary;
}
protected Object readResolve() {
serializedDataCache = Collections.synchronizedMap(new HashMap());
return this;
}
serializedDataCache = Collections.synchronizedMap(new HashMap());
return this;
}
}
Need to append object class type to output xml
public abstract class AbstractReflectionConverter implements Converter {
protected void doMarshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
final Set seenFields = new HashSet();
final Map defaultFieldDefinition = new HashMap();
final Set seenFields = new HashSet();
final Map defaultFieldDefinition = new HashMap();
// Attributes might be preferred to child elements ...
reflectionProvider.visitSerializableFields(source, new ReflectionProvider.Visitor() {
... ...
reflectionProvider.visitSerializableFields(source, new ReflectionProvider.Visitor() {
... ...
});
// Child elements not covered already processed as attributes ...
reflectionProvider.visitSerializableFields(source, new ReflectionProvider.Visitor() {
... ...
reflectionProvider.visitSerializableFields(source, new ReflectionProvider.Visitor() {
... ...
private void writeField(String fieldName, String aliasName, Class fieldType, Class definedIn, Object newObj) {
... ...
... ...
Field field = reflectionProvider.getField(definedIn,fieldName);
writer.addAttribute("type", field.getType.getName);
marshallField(context, newObj, field);
writer.endNode();
}
marshallField(context, newObj, field);
writer.endNode();
}
});
}
}
}






Comments
Write New Comment ▼
Write New Comment
Sorry! This knol's owner(s) have blocked you from editing, making suggestions, or commenting here.