blob: 49e83a4bd0b7a8770213e03004bc8528db7bb143 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-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.rmi.rmic.newrmic.jrmp;
27
28import com.sun.javadoc.ClassDoc;
29import java.io.File;
30import java.io.FileOutputStream;
31import java.io.IOException;
32import java.io.OutputStreamWriter;
33import java.util.Collections;
34import java.util.HashMap;
35import java.util.HashSet;
36import java.util.Map;
37import java.util.Set;
38import sun.rmi.rmic.newrmic.BatchEnvironment;
39import sun.rmi.rmic.newrmic.Generator;
40import sun.rmi.rmic.newrmic.IndentingWriter;
41import sun.rmi.rmic.newrmic.Main;
42import sun.rmi.rmic.newrmic.Resources;
43
44import static sun.rmi.rmic.newrmic.jrmp.Constants.*;
45
46/**
47 * JRMP rmic back end; generates source code for JRMP stub and
48 * skeleton classes.
49 *
50 * WARNING: The contents of this source file are not part of any
51 * supported API. Code that depends on them does so at its own risk:
52 * they are subject to change or removal without notice.
53 *
54 * @author Peter Jones
55 **/
56public class JrmpGenerator implements Generator {
57
58 private static final Map<String,StubVersion> versionOptions =
59 new HashMap<String,StubVersion>();
60 static {
61 versionOptions.put("-v1.1", StubVersion.V1_1);
62 versionOptions.put("-vcompat", StubVersion.VCOMPAT);
63 versionOptions.put("-v1.2", StubVersion.V1_2);
64 }
65
66 private static final Set<String> bootstrapClassNames =
67 new HashSet<String>();
68 static {
69 bootstrapClassNames.add("java.lang.Exception");
70 bootstrapClassNames.add("java.rmi.Remote");
71 bootstrapClassNames.add("java.rmi.RemoteException");
72 bootstrapClassNames.add("java.lang.RuntimeException");
73 };
74
75 /** version of the JRMP stub protocol to generate code for */
76 private StubVersion version = StubVersion.V1_2; // default is -v1.2
77
78 /**
79 * Creates a new JrmpGenerator.
80 **/
81 public JrmpGenerator() { }
82
83 /**
84 * The JRMP generator recognizes command line options for
85 * selecting the JRMP stub protocol version to generate classes
86 * for. Only one such option is allowed.
87 **/
88 public boolean parseArgs(String[] args, Main main) {
89 String explicitVersion = null;
90 for (int i = 0; i < args.length; i++) {
91 String arg = args[i];
92 if (versionOptions.containsKey(arg)) {
93 if (explicitVersion != null && !explicitVersion.equals(arg)) {
94 main.error("rmic.cannot.use.both", explicitVersion, arg);
95 return false;
96 }
97 explicitVersion = arg;
98 version = versionOptions.get(arg);
99 args[i] = null;
100 }
101 }
102 return true;
103 }
104
105 /**
106 * The JRMP generator does not require an environment class more
107 * specific than BatchEnvironment.
108 **/
109 public Class<? extends BatchEnvironment> envClass() {
110 return BatchEnvironment.class;
111 }
112
113 public Set<String> bootstrapClassNames() {
114 return Collections.unmodifiableSet(bootstrapClassNames);
115 }
116
117 /**
118 * Generates the source file(s) for the JRMP stub class and
119 * (optionally) skeleton class for the specified remote
120 * implementation class.
121 **/
122 public void generate(BatchEnvironment env,
123 ClassDoc inputClass,
124 File destDir)
125 {
126 RemoteClass remoteClass = RemoteClass.forClass(env, inputClass);
127 if (remoteClass == null) {
128 return; // an error must have occurred
129 }
130
131 StubSkeletonWriter writer =
132 new StubSkeletonWriter(env, remoteClass, version);
133
134 File stubFile = sourceFileForClass(writer.stubClassName(), destDir);
135 try {
136 IndentingWriter out = new IndentingWriter(
137 new OutputStreamWriter(new FileOutputStream(stubFile)));
138 writer.writeStub(out);
139 out.close();
140 if (env.verbose()) {
141 env.output(Resources.getText("rmic.wrote",
142 stubFile.getPath()));
143 }
144 env.addGeneratedFile(stubFile);
145 } catch (IOException e) {
146 env.error("rmic.cant.write", stubFile.toString());
147 return;
148 }
149
150 File skeletonFile =
151 sourceFileForClass(writer.skeletonClassName(), destDir);
152 if (version == StubVersion.V1_1 ||
153 version == StubVersion.VCOMPAT)
154 {
155 try {
156 IndentingWriter out = new IndentingWriter(
157 new OutputStreamWriter(
158 new FileOutputStream(skeletonFile)));
159 writer.writeSkeleton(out);
160 out.close();
161 if (env.verbose()) {
162 env.output(Resources.getText("rmic.wrote",
163 skeletonFile.getPath()));
164 }
165 env.addGeneratedFile(skeletonFile);
166 } catch (IOException e) {
167 env.error("rmic.cant.write", skeletonFile.toString());
168 return;
169 }
170 } else {
171 /*
172 * If skeleton files are not being generated for this run,
173 * delete old skeleton source or class files for this
174 * remote implementation class that were (presumably) left
175 * over from previous runs, to avoid user confusion from
176 * extraneous or inconsistent generated files.
177 */
178 File skeletonClassFile =
179 classFileForClass(writer.skeletonClassName(), destDir);
180
181 skeletonFile.delete(); // ignore failures (no big deal)
182 skeletonClassFile.delete();
183 }
184 }
185
186
187 /**
188 * Returns the File object to be used as the source file for a
189 * class with the specified binary name, with the specified
190 * destination directory as the top of the package hierarchy.
191 **/
192 private File sourceFileForClass(String binaryName, File destDir) {
193 return fileForClass(binaryName, destDir, ".java");
194 }
195
196 /**
197 * Returns the File object to be used as the class file for a
198 * class with the specified binary name, with the supplied
199 * destination directory as the top of the package hierarchy.
200 **/
201 private File classFileForClass(String binaryName, File destDir) {
202 return fileForClass(binaryName, destDir, ".class");
203 }
204
205 private File fileForClass(String binaryName, File destDir, String ext) {
206 int i = binaryName.lastIndexOf('.');
207 String classFileName = binaryName.substring(i + 1) + ext;
208 if (i != -1) {
209 String packageName = binaryName.substring(0, i);
210 String packagePath = packageName.replace('.', File.separatorChar);
211 File packageDir = new File(destDir, packagePath);
212 /*
213 * Make sure that the directory for this package exists.
214 * We assume that the caller has verified that the top-
215 * level destination directory exists, so we need not
216 * worry about creating it unintentionally.
217 */
218 if (!packageDir.exists()) {
219 packageDir.mkdirs();
220 }
221 return new File(packageDir, classFileName);
222 } else {
223 return new File(destDir, classFileName);
224 }
225 }
226}