View Javadoc

1   /*
2    * Copyright 2012-2013 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.properties.spi.core.util;
17  
18  import java.io.IOException;
19  import java.io.ObjectInputStream;
20  import java.io.ObjectOutputStream;
21  import java.io.Serializable;
22  import java.lang.reflect.Method;
23  
24  import javax.annotation.CheckForNull;
25  
26  import org.apache.commons.lang.ObjectUtils;
27  
28  /**
29   * Wrapper to serialize {@link Method}s.
30   */
31  public final class SerializableMethod implements Serializable
32  {
33    // ********************************* Fields *********************************
34  
35    // --- constants ------------------------------------------------------------
36  
37    /**
38     * The class version identifier.
39     */
40    private static final long serialVersionUID = 1L;
41  
42    // --- members --------------------------------------------------------------
43  
44    /**
45     * The wrapped method. The method may be <code>null</code>.
46     */
47    private transient volatile Method method;
48  
49    /**
50     * Default constructor.
51     *
52     * @param method the wrapped method. The method may be <code>null</code>.
53     */
54    public SerializableMethod(final Method method)
55    {
56      this.method = method;
57    }
58  
59    // ****************************** Initializer *******************************
60  
61    // ****************************** Constructors ******************************
62  
63    // ****************************** Inner Classes *****************************
64  
65    // ********************************* Methods ********************************
66  
67    // --- init -----------------------------------------------------------------
68  
69    // --- get&set --------------------------------------------------------------
70  
71    /**
72     * Returns the wrapped method.
73     *
74     * @return the wrapped method. The method may be <code>null</code>.
75     */
76    @CheckForNull
77    public Method getMethod()
78    {
79      return method;
80    }
81  
82    // --- business -------------------------------------------------------------
83  
84    // --- object basics --------------------------------------------------------
85  
86    /**
87     * Method to write the object to the stream.
88     *
89     * @param out the stream to write to.
90     * @throws IOException on any write problem.
91     */
92    private void writeObject(final ObjectOutputStream out) throws IOException
93    {
94      out.defaultWriteObject();
95  
96      if (method != null)
97      {
98        final Class<?> declaringType = method.getDeclaringClass();
99        final String methodName = method.getName();
100       final Class<?>[] parameterTypes = method.getParameterTypes();
101 
102       out.writeObject(declaringType);
103       out.writeObject(methodName);
104       out.writeObject(parameterTypes);
105     }
106     else
107     {
108       out.writeObject(null);
109     }
110   }
111 
112   /**
113    * Reads the object from the given stream.
114    *
115    * @param in the stream to read from.
116    * @throws IOException on read problems.
117    * @throws ClassNotFoundException if a class cannot be found.
118    */
119   private void readObject(final ObjectInputStream in) throws IOException,
120     ClassNotFoundException
121   {
122     in.defaultReadObject();
123 
124     final Class<?> declaringType = (Class<?>) in.readObject();
125     if (declaringType != null)
126     {
127       final String methodName = (String) in.readObject();
128       final Class<?>[] parameterTypes = (Class<?>[]) in.readObject();
129 
130       try
131       {
132         this.method =
133             declaringType.getDeclaredMethod(methodName, parameterTypes);
134       }
135       catch (final Exception e)
136       {
137         final String message =
138             message(declaringType, methodName, parameterTypes);
139         throw new IOException(message, e);
140       }
141     }
142     else
143     {
144       method = null;
145     }
146   }
147 
148   private static String message(final Class<?> declaringType,
149       final String methodName, final Class<?>[] parameterTypes)
150   {
151     final StringBuilder buffer = new StringBuilder(256);
152 
153     buffer.append("Cannot recreate method ").append(declaringType.getName())
154         .append('.').append(methodName).append('(');
155     int counter = parameterTypes.length;
156     for (final Class<?> parameterType : parameterTypes)
157     {
158       buffer.append(parameterType.getName());
159 
160       if (--counter > 0)
161       {
162         buffer.append(", ");
163       }
164     }
165     buffer.append(").");
166 
167     return buffer.toString();
168   }
169 
170   @Override
171   public String toString()
172   {
173     return ObjectUtils.toString(method, null);
174   }
175 }