001: /*
002: * This program is free software; you can redistribute it and/or modify
003: * it under the terms of the GNU General Public License as published by
004: * the Free Software Foundation; either version 2 of the License, or
005: * (at your option) any later version.
006: *
007: * This program is distributed in the hope that it will be useful,
008: * but WITHOUT ANY WARRANTY; without even the implied warranty of
009: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
010: * GNU General Public License for more details.
011: *
012: * You should have received a copy of the GNU General Public License
013: * along with this program; if not, write to the Free Software
014: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
015: */
016:
017: /*
018: * SerializationHelper.java
019: * Copyright (C) 2007 University of Waikato, Hamilton, New Zealand
020: */
021:
022: package weka.core;
023:
024: import java.io.FileInputStream;
025: import java.io.FileOutputStream;
026: import java.io.InputStream;
027: import java.io.ObjectInputStream;
028: import java.io.ObjectOutputStream;
029: import java.io.ObjectStreamClass;
030: import java.io.OutputStream;
031: import java.io.Serializable;
032:
033: /**
034: * A helper class for determining serialVersionUIDs and checking whether
035: * classes contain one and/or need one. One can also serialize and deserialize
036: * objects to and fro files or streams.
037: *
038: * @author fracpete (fracpete at waikato dot ac dot nz)
039: * @version $Revision: 1.1 $
040: */
041: public class SerializationHelper {
042:
043: /** the field name of serialVersionUID */
044: public final static String SERIAL_VERSION_UID = "serialVersionUID";
045:
046: /**
047: * checks whether a class is serializable
048: *
049: * @param classname the class to check
050: * @return true if the class or one of its ancestors implements
051: * the Serializable interface, otherwise false (also if
052: * the class cannot be loaded)
053: */
054: public static boolean isSerializable(String classname) {
055: boolean result;
056:
057: try {
058: result = isSerializable(Class.forName(classname));
059: } catch (Exception e) {
060: result = false;
061: }
062:
063: return result;
064: }
065:
066: /**
067: * checks whether a class is serializable
068: *
069: * @param c the class to check
070: * @return true if the class or one of its ancestors implements
071: * the Serializable interface, otherwise false
072: */
073: public static boolean isSerializable(Class c) {
074: return ClassDiscovery.hasInterface(Serializable.class, c);
075: }
076:
077: /**
078: * checks whether the given class contains a serialVersionUID
079: *
080: * @param classname the class to check
081: * @return true if the class contains a serialVersionUID,
082: * otherwise false (also if the class is not
083: * implementing serializable or cannot be loaded)
084: */
085: public static boolean hasUID(String classname) {
086: boolean result;
087:
088: try {
089: result = hasUID(Class.forName(classname));
090: } catch (Exception e) {
091: result = false;
092: }
093:
094: return result;
095: }
096:
097: /**
098: * checks whether the given class contains a serialVersionUID
099: *
100: * @param c the class to check
101: * @return true if the class contains a serialVersionUID,
102: * otherwise false (also if the class is not
103: * implementing serializable)
104: */
105: public static boolean hasUID(Class c) {
106: boolean result;
107:
108: result = false;
109:
110: if (isSerializable(c)) {
111: try {
112: c.getDeclaredField(SERIAL_VERSION_UID);
113: result = true;
114: } catch (Exception e) {
115: result = false;
116: }
117: }
118:
119: return result;
120: }
121:
122: /**
123: * checks whether a class needs to declare a serialVersionUID, i.e., it
124: * implements the java.io.Serializable interface but doesn't declare a
125: * serialVersionUID.
126: *
127: * @param classname the class to check
128: * @return true if the class needs to declare one, false otherwise
129: * (also if the class cannot be loaded!)
130: */
131: public static boolean needsUID(String classname) {
132: boolean result;
133:
134: try {
135: result = needsUID(Class.forName(classname));
136: } catch (Exception e) {
137: result = false;
138: }
139:
140: return result;
141: }
142:
143: /**
144: * checks whether a class needs to declare a serialVersionUID, i.e., it
145: * implements the java.io.Serializable interface but doesn't declare a
146: * serialVersionUID.
147: *
148: * @param c the class to check
149: * @return true if the class needs to declare one, false otherwise
150: */
151: public static boolean needsUID(Class c) {
152: boolean result;
153:
154: if (isSerializable(c))
155: result = !hasUID(c);
156: else
157: result = false;
158:
159: return result;
160: }
161:
162: /**
163: * reads or creates the serialVersionUID for the given class
164: *
165: * @param classname the class to get the serialVersionUID for
166: * @return the UID, 0L for non-serializable classes (or if the
167: * class cannot be loaded)
168: */
169: public static long getUID(String classname) {
170: long result;
171:
172: try {
173: result = getUID(Class.forName(classname));
174: } catch (Exception e) {
175: result = 0L;
176: }
177:
178: return result;
179: }
180:
181: /**
182: * reads or creates the serialVersionUID for the given class
183: *
184: * @param c the class to get the serialVersionUID for
185: * @return the UID, 0L for non-serializable classes
186: */
187: public static long getUID(Class c) {
188: return ObjectStreamClass.lookup(c).getSerialVersionUID();
189: }
190:
191: /**
192: * serializes the given object to the specified file
193: *
194: * @param filename the file to write the object to
195: * @param o the object to serialize
196: * @throws Exception if serialization fails
197: */
198: public static void write(String filename, Object o)
199: throws Exception {
200: write(new FileOutputStream(filename), o);
201: }
202:
203: /**
204: * serializes the given object to the specified stream
205: *
206: * @param stream the stream to write the object to
207: * @param o the object to serialize
208: * @throws Exception if serialization fails
209: */
210: public static void write(OutputStream stream, Object o)
211: throws Exception {
212: ObjectOutputStream oos;
213:
214: oos = new ObjectOutputStream(stream);
215: oos.writeObject(o);
216: oos.flush();
217: oos.close();
218: }
219:
220: /**
221: * deserializes the given file and returns the object from it
222: *
223: * @param filename the file to deserialize from
224: * @return the deserialized object
225: * @throws Exception if deserialization fails
226: */
227: public static Object read(String filename) throws Exception {
228: return read(new FileInputStream(filename));
229: }
230:
231: /**
232: * deserializes from the given stream and returns the object from it
233: *
234: * @param stream the stream to deserialize from
235: * @return the deserialized object
236: * @throws Exception if deserialization fails
237: */
238: public static Object read(InputStream stream) throws Exception {
239: ObjectInputStream ois;
240: Object result;
241:
242: ois = new ObjectInputStream(stream);
243: result = ois.readObject();
244: ois.close();
245:
246: return result;
247: }
248:
249: /**
250: * Outputs information about a class on the commandline, takes class
251: * name as arguments
252: *
253: * @param args the classnames to check
254: */
255: public static void main(String[] args) {
256: if (args.length == 0) {
257: System.out.println("\nUsage: "
258: + SerializationHelper.class.getName()
259: + " classname [classname [classname [...]]]\n");
260: System.exit(1);
261: }
262:
263: // check all the classes
264: System.out.println();
265: for (int i = 0; i < args.length; i++) {
266: System.out.println(args[i]);
267: System.out.println("- is serializable: "
268: + isSerializable(args[i]));
269: System.out.println("- has " + SERIAL_VERSION_UID + ": "
270: + hasUID(args[i]));
271: System.out.println("- needs " + SERIAL_VERSION_UID + ": "
272: + needsUID(args[i]));
273: System.out.println("- " + SERIAL_VERSION_UID
274: + ": private static final long serialVersionUID = "
275: + getUID(args[i]) + "L;");
276: System.out.println();
277: }
278: }
279: }
|