001    /*******************************************************************************
002     * Portions created by Sebastian Thomschke are copyright (c) 2005-2015 Sebastian
003     * Thomschke.
004     *
005     * All Rights Reserved. This program and the accompanying materials
006     * are made available under the terms of the Eclipse Public License v1.0
007     * which accompanies this distribution, and is available at
008     * http://www.eclipse.org/legal/epl-v10.html
009     *
010     * Contributors:
011     *     Sebastian Thomschke - initial implementation.
012     *******************************************************************************/
013    package net.sf.oval.internal.util;
014    
015    import java.io.IOException;
016    import java.io.Serializable;
017    import java.lang.reflect.Constructor;
018    import java.util.WeakHashMap;
019    
020    import net.sf.oval.internal.Log;
021    
022    /**
023     * Serializable Wrapper for java.lang.reflect.Constructor objects since they do not implement Serializable
024     *
025     * @author Sebastian Thomschke
026     */
027    public final class SerializableConstructor implements Serializable
028    {
029            private static final Log LOG = Log.getLog(SerializableConstructor.class);
030    
031            private static final WeakHashMap<Constructor< ? >, SerializableConstructor> CACHE = //
032            new WeakHashMap<Constructor< ? >, SerializableConstructor>();
033    
034            private static final long serialVersionUID = 1L;
035    
036            public static SerializableConstructor getInstance(final Constructor< ? > constructor)
037            {
038                    synchronized (CACHE)
039                    {
040                            SerializableConstructor sm = CACHE.get(constructor);
041                            if (sm == null)
042                            {
043                                    sm = new SerializableConstructor(constructor);
044                                    CACHE.put(constructor, sm);
045                            }
046                            return sm;
047                    }
048            }
049    
050            private transient Constructor< ? > constructor;
051    
052            private final Class< ? > declaringClass;
053    
054            private final Class< ? >[] parameterTypes;
055    
056            private SerializableConstructor(final Constructor< ? > constructor)
057            {
058                    this.constructor = constructor;
059                    parameterTypes = constructor.getParameterTypes();
060                    declaringClass = constructor.getDeclaringClass();
061            }
062    
063            /**
064             * @return the constructor
065             */
066            public Constructor< ? > getConstructor()
067            {
068                    return constructor;
069            }
070    
071            /**
072             * @return the declaringClass
073             */
074            public Class< ? > getDeclaringClass()
075            {
076                    return declaringClass;
077            }
078    
079            /**
080             * @return the parameterTypes
081             */
082            public Class< ? >[] getParameterTypes()
083            {
084                    return parameterTypes;
085            }
086    
087            private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
088            {
089                    in.defaultReadObject();
090                    try
091                    {
092                            constructor = declaringClass.getDeclaredConstructor(parameterTypes);
093                    }
094                    catch (final NoSuchMethodException ex)
095                    {
096                            LOG.debug("Unexpected NoSuchMethodException occured", ex);
097                            throw new IOException(ex.getMessage());
098                    }
099            }
100    }