001: /*
002: * Copyright (C) 2004, 2005 Joe Walnes.
003: * Copyright (C) 2006, 2007 XStream Committers.
004: * All rights reserved.
005: *
006: * The software in this package is published under the terms of the BSD
007: * style license a copy of which has been included with this distribution in
008: * the LICENSE.txt file.
009: *
010: * Created on 25. March 2004 by Joe Walnes
011: */
012: package com.thoughtworks.xstream.converters.extended;
013:
014: import com.thoughtworks.xstream.converters.ConversionException;
015: import com.thoughtworks.xstream.converters.Converter;
016: import com.thoughtworks.xstream.converters.MarshallingContext;
017: import com.thoughtworks.xstream.converters.UnmarshallingContext;
018: import com.thoughtworks.xstream.io.HierarchicalStreamReader;
019: import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
020: import com.thoughtworks.xstream.mapper.DynamicProxyMapper;
021: import com.thoughtworks.xstream.mapper.Mapper;
022:
023: import java.lang.reflect.InvocationHandler;
024: import java.lang.reflect.Proxy;
025: import java.util.ArrayList;
026: import java.util.List;
027:
028: /**
029: * Converts a dynamic proxy to XML, storing the implemented
030: * interfaces and handler.
031: *
032: * @author Joe Walnes
033: */
034: public class DynamicProxyConverter implements Converter {
035:
036: private ClassLoader classLoader;
037: private Mapper mapper;
038:
039: public DynamicProxyConverter(Mapper mapper) {
040: this (mapper, DynamicProxyConverter.class.getClassLoader());
041: }
042:
043: public DynamicProxyConverter(Mapper mapper, ClassLoader classLoader) {
044: this .classLoader = classLoader;
045: this .mapper = mapper;
046: }
047:
048: public boolean canConvert(Class type) {
049: return type.equals(DynamicProxyMapper.DynamicProxy.class)
050: || Proxy.isProxyClass(type);
051: }
052:
053: public void marshal(Object source, HierarchicalStreamWriter writer,
054: MarshallingContext context) {
055: InvocationHandler invocationHandler = Proxy
056: .getInvocationHandler(source);
057: addInterfacesToXml(source, writer);
058: writer.startNode("handler");
059: writer.addAttribute("class", mapper
060: .serializedClass(invocationHandler.getClass()));
061: context.convertAnother(invocationHandler);
062: writer.endNode();
063: }
064:
065: private void addInterfacesToXml(Object source,
066: HierarchicalStreamWriter writer) {
067: Class[] interfaces = source.getClass().getInterfaces();
068: for (int i = 0; i < interfaces.length; i++) {
069: Class currentInterface = interfaces[i];
070: writer.startNode("interface");
071: writer.setValue(mapper.serializedClass(currentInterface));
072: writer.endNode();
073: }
074: }
075:
076: public Object unmarshal(HierarchicalStreamReader reader,
077: UnmarshallingContext context) {
078: List interfaces = new ArrayList();
079: InvocationHandler handler = null;
080: while (reader.hasMoreChildren()) {
081: reader.moveDown();
082: String elementName = reader.getNodeName();
083: if (elementName.equals("interface")) {
084: interfaces.add(mapper.realClass(reader.getValue()));
085: } else if (elementName.equals("handler")) {
086: Class handlerType = mapper.realClass(reader
087: .getAttribute("class"));
088: handler = (InvocationHandler) context.convertAnother(
089: null, handlerType);
090: }
091: reader.moveUp();
092: }
093: if (handler == null) {
094: throw new ConversionException(
095: "No InvocationHandler specified for dynamic proxy");
096: }
097: Class[] interfacesAsArray = new Class[interfaces.size()];
098: interfaces.toArray(interfacesAsArray);
099: return Proxy.newProxyInstance(classLoader, interfacesAsArray,
100: handler);
101: }
102: }
|