blob: 512dbcf169f3c9daaabfc7cad6a18b1394ce4853 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1996-2005 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.tools.serialver;
27
28import java.io.*;
29import java.awt.*;
30import java.applet.*;
31import java.io.ObjectStreamClass;
32import java.util.Properties;
33import java.text.MessageFormat;
34import java.util.ResourceBundle;
35import java.util.MissingResourceException;
36import java.net.URLClassLoader;
37import java.net.URL;
38import java.net.MalformedURLException;
39import java.util.StringTokenizer;
40import sun.net.www.ParseUtil;
41
42public class SerialVer extends Applet {
43 GridBagLayout gb;
44 TextField classname_t;
45 Button show_b;
46 TextField serialversion_t;
47 Label footer_l;
48
49 private static final long serialVersionUID = 7666909783837760853L;
50
51 public synchronized void init() {
52 gb = new GridBagLayout();
53 setLayout(gb);
54
55 GridBagConstraints c = new GridBagConstraints();
56 c.fill = GridBagConstraints.BOTH;
57
58 Label l1 = new Label(Res.getText("FullClassName"));
59 l1.setAlignment(Label.RIGHT);
60 gb.setConstraints(l1, c);
61 add(l1);
62
63 classname_t = new TextField(20);
64 c.gridwidth = GridBagConstraints.RELATIVE;
65 c.weightx = 1.0;
66 gb.setConstraints(classname_t, c);
67 add(classname_t);
68
69 show_b = new Button(Res.getText("Show"));
70 c.gridwidth = GridBagConstraints.REMAINDER;
71 c.weightx = 0.0; /* Don't grow the button */
72 gb.setConstraints(show_b, c);
73 add(show_b);
74
75 Label l2 = new Label(Res.getText("SerialVersion"));
76 l2.setAlignment(Label.RIGHT);
77 c.gridwidth = 1;
78 gb.setConstraints(l2, c);
79 add(l2);
80
81 serialversion_t = new TextField(50);
82 serialversion_t.setEditable(false);
83 c.gridwidth = GridBagConstraints.REMAINDER;
84 gb.setConstraints(serialversion_t, c);
85 add(serialversion_t);
86
87 footer_l = new Label();
88 c.gridwidth = GridBagConstraints.REMAINDER;
89 gb.setConstraints(footer_l, c);
90 add(footer_l);
91
92 /* Give the focus to the type-in area */
93 classname_t.requestFocus();
94 }
95
96 public void start() {
97 /* Give the focus to the type-in area */
98 classname_t.requestFocus();
99 }
100
101 public boolean action(Event ev, Object obj) {
102 if (ev.target == classname_t) {
103 show((String)ev.arg);
104 return true;
105 } else if (ev.target == show_b) {
106 show(classname_t.getText());
107 return true;
108 }
109 return false;
110 }
111
112
113 public boolean handleEvent(Event ev) {
114 boolean rc = super.handleEvent(ev);
115 return rc;
116 }
117
118 /**
119 * Lookup the specified classname and display it.
120 */
121 void show(String classname) {
122 try {
123 footer_l.setText(""); // Clear the message
124 serialversion_t.setText(""); // clear the last value
125
126 if (classname.equals("")) {
127 return;
128 }
129
130 String s = serialSyntax(classname);
131 if (s != null) {
132 serialversion_t.setText(s);
133 } else {
134 footer_l.setText(Res.getText("NotSerializable", classname));
135 }
136 } catch (ClassNotFoundException cnf) {
137 footer_l.setText(Res.getText("ClassNotFound", classname));
138 }
139 }
140
141 /*
142 * A class loader that will load from the CLASSPATH environment
143 * variable set by the user.
144 */
145 static URLClassLoader loader = null;
146
147 /*
148 * Create a URL class loader that will load classes from the
149 * specified classpath.
150 */
151 static void initializeLoader(String cp)
152 throws MalformedURLException, IOException {
153 URL[] urls;
154 StringTokenizer st = new StringTokenizer(cp, File.pathSeparator);
155 int count = st.countTokens();
156 urls = new URL[count];
157 for (int i = 0; i < count; i++) {
158 urls[i] = ParseUtil.fileToEncodedURL(
159 new File(new File(st.nextToken()).getCanonicalPath()));
160 }
161 loader = new URLClassLoader(urls);
162 }
163
164 /*
165 * From the classname find the serialVersionUID string formatted
166 * for to be copied to a java class.
167 */
168 static String serialSyntax(String classname) throws ClassNotFoundException {
169 String ret = null;
170 boolean classFound = false;
171
172 // If using old style of qualifyling inner classes with '$'s.
173 if (classname.indexOf('$') != -1) {
174 ret = resolveClass(classname);
175 } else {
176 /* Try to resolve the fully qualified name and if that fails, start
177 * replacing the '.'s with '$'s starting from the last '.', until
178 * the class is resolved.
179 */
180 try {
181 ret = resolveClass(classname);
182 classFound = true;
183 } catch (ClassNotFoundException e) {
184 /* Class not found so far */
185 }
186 if (!classFound) {
187 StringBuffer workBuffer = new StringBuffer(classname);
188 String workName = workBuffer.toString();
189 int i;
190 while ((i = workName.lastIndexOf('.')) != -1 && !classFound) {
191 workBuffer.setCharAt(i, '$');
192 try {
193 workName = workBuffer.toString();
194 ret = resolveClass(workName);
195 classFound = true;
196 } catch (ClassNotFoundException e) {
197 /* Continue searching */
198 }
199 }
200 }
201 if (!classFound) {
202 throw new ClassNotFoundException();
203 }
204 }
205 return ret;
206 }
207
208 static String resolveClass(String classname) throws ClassNotFoundException {
209 Class cl = Class.forName(classname, false, loader);
210 ObjectStreamClass desc = ObjectStreamClass.lookup(cl);
211 if (desc != null) {
212 return " static final long serialVersionUID = " +
213 desc.getSerialVersionUID() + "L;";
214 } else {
215 return null;
216 }
217 }
218
219
220 public static void main(String[] args) {
221 boolean show = false;
222 String envcp = null;
223 int i = 0;
224
225 if (args.length == 0) {
226 usage();
227 System.exit(1);
228 }
229
230 for (i = 0; i < args.length; i++) {
231 if (args[i].equals("-show")) {
232 show = true;
233 } else if (args[i].equals("-classpath")) {
234 if ((i+1 == args.length) || args[i+1].startsWith("-")) {
235 System.err.println(Res.getText("error.missing.classpath"));
236 usage();
237 System.exit(1);
238 }
239 envcp = new String(args[i+1]);
240 i++;
241 } else if (args[i].startsWith("-")) {
242 System.err.println(Res.getText("invalid.flag", args[i]));
243 usage();
244 System.exit(1);
245 } else {
246 break; // drop into processing class names
247 }
248 }
249
250
251 /*
252 * Get user's CLASSPATH environment variable, if the -classpath option
253 * is not defined, and make a loader that can read from that path.
254 */
255 if (envcp == null) {
256 envcp = System.getProperty("env.class.path");
257 /*
258 * If environment variable not set, add current directory to path.
259 */
260 if (envcp == null) {
261 envcp = ".";
262 }
263 }
264
265 try {
266 initializeLoader(envcp);
267 } catch (MalformedURLException mue) {
268 System.err.println(Res.getText("error.parsing.classpath", envcp));
269 System.exit(2);
270 } catch (IOException ioe) {
271 System.err.println(Res.getText("error.parsing.classpath", envcp));
272 System.exit(3);
273 }
274
275 if (!show) {
276 /*
277 * Check if there are any class names specified, if it is not a
278 * invocation with the -show option.
279 */
280 if (i == args.length) {
281 usage();
282 System.exit(1);
283 }
284
285 /*
286 * The rest of the parameters are classnames.
287 */
288 boolean exitFlag = false;
289 for (i = i; i < args.length; i++ ) {
290 try {
291 String syntax = serialSyntax(args[i]);
292 if (syntax != null)
293 System.out.println(args[i] + ":" + syntax);
294 else {
295 System.err.println(Res.getText("NotSerializable",
296 args[i]));
297 exitFlag = true;
298 }
299 } catch (ClassNotFoundException cnf) {
300 System.err.println(Res.getText("ClassNotFound", args[i]));
301 exitFlag = true;
302 }
303 }
304 if (exitFlag) {
305 System.exit(1);
306 }
307 } else {
308 if (i < args.length) {
309 System.err.println(Res.getText("ignoring.classes"));
310 System.exit(1);
311 }
312 Frame f = new SerialVerFrame();
313 // f.setLayout(new FlowLayout());
314 SerialVer sv = new SerialVer();
315 sv.init();
316
317 f.add("Center", sv);
318 f.pack();
319 f.show();
320 }
321 }
322
323
324 /**
325 * Usage
326 */
327 public static void usage() {
328 System.err.println(Res.getText("usage"));
329 }
330
331}
332
333/**
334 * Top level frame so serialVer can be run as an main program
335 * and have an exit menu item.
336 */
337class SerialVerFrame extends Frame {
338 MenuBar menu_mb;
339 Menu file_m;
340 MenuItem exit_i;
341
342 private static final long serialVersionUID = -7248105987187532533L;
343
344 /*
345 * Construct a new Frame with title and menu.
346 */
347 SerialVerFrame() {
348 super(Res.getText("SerialVersionInspector"));
349
350 /* Create the file menu */
351 file_m = new Menu(Res.getText("File"));
352 file_m.add(exit_i = new MenuItem(Res.getText("Exit")));
353
354 /* Now add the file menu to the menu bar */
355 menu_mb = new MenuBar();
356 menu_mb.add(file_m);
357
358 /* Add the menubar to the frame */
359 // Bug in JDK1.1 setMenuBar(menu_mb);
360 }
361
362 /*
363 * Handle a window destroy event by exiting.
364 */
365 public boolean handleEvent(Event e) {
366 if (e.id == Event.WINDOW_DESTROY) {
367 exit(0);
368 }
369 return super.handleEvent(e);
370 }
371 /*
372 * Handle an Exit event by exiting.
373 */
374 public boolean action(Event ev, Object obj) {
375 if (ev.target == exit_i) {
376 exit(0);
377 }
378 return false;
379 }
380
381 /*
382 * Cleanup and exit.
383 */
384 void exit(int ret) {
385 System.exit(ret);
386 }
387
388}
389
390/**
391 * Utility for integrating with serialver and for localization.
392 * Handle Resources. Access to error and warning counts.
393 * Message formatting.
394 *
395 * @see java.util.ResourceBundle
396 * @see java.text.MessageFormat
397 */
398class Res {
399
400 private static ResourceBundle messageRB;
401
402 /**
403 * Initialize ResourceBundle
404 */
405 static void initResource() {
406 try {
407 messageRB =
408 ResourceBundle.getBundle("sun.tools.serialver.resources.serialver");
409 } catch (MissingResourceException e) {
410 throw new Error("Fatal: Resource for serialver is missing");
411 }
412 }
413
414 /**
415 * get and format message string from resource
416 *
417 * @param key selects message from resource
418 */
419 static String getText(String key) {
420 return getText(key, (String)null);
421 }
422
423 /**
424 * get and format message string from resource
425 *
426 * @param key selects message from resource
427 * @param a1 first argument
428 */
429 static String getText(String key, String a1) {
430 return getText(key, a1, null);
431 }
432
433 /**
434 * get and format message string from resource
435 *
436 * @param key selects message from resource
437 * @param a1 first argument
438 * @param a2 second argument
439 */
440 static String getText(String key, String a1, String a2) {
441 return getText(key, a1, a2, null);
442 }
443
444 /**
445 * get and format message string from resource
446 *
447 * @param key selects message from resource
448 * @param a1 first argument
449 * @param a2 second argument
450 * @param a3 third argument
451 */
452 static String getText(String key, String a1, String a2, String a3) {
453 if (messageRB == null) {
454 initResource();
455 }
456 try {
457 String message = messageRB.getString(key);
458 String[] args = new String[3];
459 args[0] = a1;
460 args[1] = a2;
461 args[2] = a3;
462 return MessageFormat.format(message, args);
463 } catch (MissingResourceException e) {
464 throw new Error("Fatal: Resource for serialver is broken. There is no " + key + " key in resource.");
465 }
466 }
467}