001    package biz.hammurapi.remoting;
002    
003    import java.io.Serializable;
004    
005    import org.apache.xmlbeans.XmlObject;
006    import org.w3c.dom.Element;
007    import org.w3c.dom.Node;
008    
009    import biz.hammurapi.invocation.Invocation.Arg;
010    import biz.hammurapi.invocation.Invocation.State;
011    import biz.hammurapi.xml.dom.AbstractDomObject;
012    import biz.hammurapi.xml.dom.CompositeDomSerializer;
013    import biz.hammurapi.xml.dom.DOMUtils;
014    import biz.hammurapi.xml.dom.DomSerializable;
015    import biz.hammurapi.xmlbeans.XmlObjectSerializable;
016    
017    /**
018     * Method invocation.
019     * @author Pavel
020     */
021    public class Invocation implements DomSerializable, Serializable, XmlObjectSerializable {
022    
023            private Object state;
024            private String methodName;
025            private String[] parameterTypes;
026            private Object[] args;
027            private String declaringClass;
028    
029            public Invocation(Object state, String declaringClass, String methodName, String[] parameterTypes,      Object[] args) {
030                    this.state = state;
031                    this.declaringClass = declaringClass;
032                    this.methodName = methodName;
033                    this.parameterTypes = parameterTypes;
034                    this.args = args;
035            }
036            
037            public Object getState() {
038                    return state;
039            }
040            
041            public String getMethodName() {
042                    return methodName;
043            }
044            
045            public String[] getParameterTypes() {
046                    return parameterTypes;
047            }
048            
049            public Object[] getArguments() {
050                    return args;
051            }
052            
053            public void toDom(Element holder) {
054                    holder.setAttribute("method-name", methodName);
055                    if (declaringClass!=null) {
056                            holder.setAttribute("declaring-class", declaringClass);
057                    }
058                    holder.setAttribute("type", getClass().getName());
059                    
060                    if (state!=null) {
061                            DOMUtils.toDom(state, "state", holder);
062                    }
063                    
064                    if (parameterTypes!=null) {
065                            for (int i=0; i<parameterTypes.length; ++i) {
066                                    AbstractDomObject.addTextElement(holder, "parameter-type", parameterTypes[i]);                          
067                            }
068                    }
069                    
070                    if (args!=null) {
071                            for (int i=0; i<args.length; ++i) {
072                                    if (args[i]==null) {
073                                            AbstractDomObject.addElement(holder, "argument").setAttribute("is-null", "true");
074                                    } else {
075                                            DOMUtils.toDom(args[i], "argument", holder);
076                                    }
077                            }
078                    }
079                    
080            }
081            
082            public XmlObject toXmlObject() {
083                    biz.hammurapi.invocation.InvocationDocument ret = biz.hammurapi.invocation.InvocationDocument.Factory.newInstance();
084                    biz.hammurapi.invocation.Invocation invocation = ret.addNewInvocation();
085                    if (declaringClass!=null) {
086                            invocation.setDeclaringClass(declaringClass);                   
087                    }
088                    
089                    invocation.setMethodName(methodName);
090                    
091                    if (parameterTypes!=null) {
092                            for (int i=0; i<parameterTypes.length; ++i) {
093                                    invocation.addParameterType(parameterTypes[i]);
094                            }
095                    }
096                    
097                    if (state!=null) {
098                            State xmlState = invocation.addNewState();
099                            if (state instanceof XmlObject) {
100                                    xmlState.set((XmlObject) state);
101                            } else {
102                                    Node domNode = xmlState.getDomNode();
103                                    CompositeDomSerializer.getThreadInstance().toDomSerializable(state).toDom((Element) domNode);                           
104                            }
105                    }
106                    
107                    if (args!=null) {
108                            for (int i=0; i<args.length; ++i) {
109                                    Arg arg = invocation.addNewArg();
110                                    if (args[i] instanceof XmlObject) {
111                                            arg.set((XmlObject) args[i]);
112                                    } else {
113                                            Node domNode = arg.getDomNode();
114                                            CompositeDomSerializer.getThreadInstance().toDomSerializable(args[i]).toDom((Element) domNode);                         
115                                    }
116                            }                       
117                    }
118                            
119                    return ret;
120            }
121            
122            /**
123             * Finds method to invoke.
124             * @param invocation
125             * @param classLoader Classloader, can be null.
126             * @return
127             * @throws ClassNotFoundException 
128             */
129            public static java.lang.reflect.Method findMethod(biz.hammurapi.invocation.Invocation invocation, ClassLoader classLoader) throws ClassNotFoundException, NoSuchMethodException {
130                    Class declaringClass = classLoader==null ? Class.forName(invocation.getDeclaringClass()) : classLoader.loadClass(invocation.getDeclaringClass());
131                    String[] pta = invocation.getParameterTypeArray();
132                    Class[] parameterTypes = new Class[pta.length];
133                    for (int i=0; i<pta.length; ++i) {
134                            if ("int".equals(pta[i])) {
135                                    parameterTypes[i] = int.class;
136                            } else if ("short".equals(pta[i])) {
137                                    parameterTypes[i] = short.class;
138                            } else if ("long".equals(pta[i])) {
139                                    parameterTypes[i] = long.class;
140                            } else if ("boolean".equals(pta[i])) {
141                                    parameterTypes[i] = boolean.class;
142                            } else if ("byte".equals(pta[i])) {
143                                    parameterTypes[i] = byte.class;
144                            } else if ("double".equals(pta[i])) {
145                                    parameterTypes[i] = double.class;
146                            } else if ("float".equals(pta[i])) {
147                                    parameterTypes[i] = float.class;
148                            } else if ("char".equals(pta[i])) {
149                                    parameterTypes[i] = char.class;
150                            } else {
151                                    parameterTypes[i] = classLoader==null ? Class.forName(pta[i]) : classLoader.loadClass(pta[i]);
152                            }
153                    }
154                    return declaringClass.getMethod(invocation.getMethodName(), parameterTypes);
155            }
156    }