001    /*
002     * Copyright 2012 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.student.common.spring;
017    
018    import java.io.Externalizable;
019    import java.io.IOException;
020    import java.io.ObjectInput;
021    import java.io.ObjectOutput;
022    import java.io.Serializable;
023    import java.lang.reflect.InvocationHandler;
024    import java.lang.reflect.Method;
025    
026    import javax.xml.namespace.QName;
027    
028    import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
029    import org.springframework.util.ReflectionUtils;
030    
031    /**
032     * 
033     * A Serializable Proxy Invokation Handler.  This handler is serializable and knows how to look up the service using the GlobalResourceLocator.
034     * 
035     * @author Kuali Student Team
036     * 
037     */
038    public class SerializableProxyInvokationHandler implements InvocationHandler, Externalizable {
039    
040            /**
041             * 
042             */
043            private static final long serialVersionUID = 1L;
044    
045            private transient Object serviceDelegate;
046    
047            private QName serviceName;
048    
049            /**
050             * 
051             */
052            public SerializableProxyInvokationHandler() {
053            }
054    
055            
056            /**
057             * @param serviceName the serviceName to set
058             */
059            public void setServiceName(QName serviceName) {
060                    this.serviceName = serviceName;
061            }
062    
063    
064            /*
065             * (non-Javadoc)
066             * 
067             * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
068             * java.lang.reflect.Method, java.lang.Object[])
069             */
070            @Override
071            public Object invoke(Object proxy, Method method, Object[] args)
072                            throws Throwable {
073    
074                    if (serviceDelegate == null) {
075                            // first time or just after reserialization.
076                            try {
077                        serviceDelegate = GlobalResourceLoader.getService(serviceName);
078                } catch (Exception e) {
079                    
080                    if (method.getName().equals("toString")) {
081                            // fake toString
082                            // spring has an assertion that expects this to work so we will just fake it
083                            // once the delegate is resolved the normal toString method will be used.
084                            return getClass().getName() + " (serviceName=" + serviceName + ")";
085                    }
086                    else
087                            throw e;
088                }
089                    }
090    
091                    // delegate the call to the actual service to fulfill.
092                    return ReflectionUtils.invokeMethod(method, serviceDelegate, args);
093            }
094    
095            /* (non-Javadoc)
096             * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
097             */
098            @Override
099            public void writeExternal(ObjectOutput out) throws IOException {
100                    
101                    QName name = new QName(serviceName.getNamespaceURI(), serviceName.getLocalPart());
102                    
103                    out.writeObject(name);
104                    
105            }
106    
107            /* (non-Javadoc)
108             * @see java.io.Externalizable#readExternal(java.io.ObjectInput)
109             */
110            @Override
111            public void readExternal(ObjectInput in) throws IOException,
112                            ClassNotFoundException {
113                    
114                    QName name = (QName) in.readObject();
115            
116                    this.serviceName = new QName (name.getNamespaceURI(), name.getLocalPart());
117                    
118            }
119            
120            
121    
122    }