001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.taskdefs.rmic;
020:
021: import java.io.File;
022: import java.util.Random;
023: import java.util.Vector;
024: import org.apache.tools.ant.Project;
025: import org.apache.tools.ant.taskdefs.Rmic;
026: import org.apache.tools.ant.types.Commandline;
027: import org.apache.tools.ant.types.Path;
028: import org.apache.tools.ant.util.FileNameMapper;
029:
030: /**
031: * This is the default implementation for the RmicAdapter interface.
032: * Currently, this is a cut-and-paste of the original rmic task and
033: * DefaultCopmpilerAdapter.
034: *
035: * @since Ant 1.4
036: */
037: public abstract class DefaultRmicAdapter implements RmicAdapter {
038:
039: private Rmic attributes;
040: private FileNameMapper mapper;
041: private static final Random RAND = new Random();
042: /** suffix denoting a stub file */
043: public static final String RMI_STUB_SUFFIX = "_Stub";
044: /** suffix denoting a skel file */
045: public static final String RMI_SKEL_SUFFIX = "_Skel";
046: /** suffix denoting a tie file */
047: public static final String RMI_TIE_SUFFIX = "_Tie";
048: /** arg for compat */
049: public static final String STUB_COMPAT = "-vcompat";
050: /** arg for 1.1 */
051: public static final String STUB_1_1 = "-v1.1";
052: /** arg for 1.2 */
053: public static final String STUB_1_2 = "-v1.2";
054:
055: /**
056: * Default constructor
057: */
058: public DefaultRmicAdapter() {
059: }
060:
061: /**
062: * Sets Rmic attributes
063: * @param attributes the rmic attributes
064: */
065: public void setRmic(final Rmic attributes) {
066: this .attributes = attributes;
067: mapper = new RmicFileNameMapper();
068: }
069:
070: /**
071: * Get the Rmic attributes
072: * @return the attributes as a Rmic taskdef
073: */
074: public Rmic getRmic() {
075: return attributes;
076: }
077:
078: /**
079: * Gets the stub class suffix
080: * @return the stub suffix "_Stub"
081: */
082: protected String getStubClassSuffix() {
083: return RMI_STUB_SUFFIX;
084: }
085:
086: /**
087: * Gets the skeleton class suffix
088: * @return the skeleton suffix "_Skel"
089: */
090: protected String getSkelClassSuffix() {
091: return RMI_SKEL_SUFFIX;
092: }
093:
094: /**
095: * Gets the tie class suffix
096: * @return the tie suffix "_Tie"
097: */
098: protected String getTieClassSuffix() {
099: return RMI_TIE_SUFFIX;
100: }
101:
102: /**
103: * This implementation returns a mapper that may return up to two
104: * file names.
105: *
106: * <ul>
107: * <li>for JRMP it will return *_getStubClassSuffix (and
108: * *_getSkelClassSuffix if JDK 1.1 is used)</li>
109: *
110: * <li>for IDL it will return a random name, causing <rmic> to
111: * always recompile.</li>
112: *
113: * <li>for IIOP it will return _*_getStubClassSuffix for
114: * interfaces and _*_getStubClassSuffix for non-interfaces (and
115: * determine the interface and create _*_Stub from that).</li>
116: * </ul>
117: * @return a <code>FileNameMapper</code>
118: */
119: public FileNameMapper getMapper() {
120: return mapper;
121: }
122:
123: /**
124: * Gets the CLASSPATH this rmic process will use.
125: * @return the classpath
126: */
127: public Path getClasspath() {
128: return getCompileClasspath();
129: }
130:
131: /**
132: * Builds the compilation classpath.
133: * @return the classpath
134: */
135: protected Path getCompileClasspath() {
136: Path classpath = new Path(attributes.getProject());
137: // add dest dir to classpath so that previously compiled and
138: // untouched classes are on classpath
139: classpath.setLocation(attributes.getBase());
140:
141: // Combine the build classpath with the system classpath, in an
142: // order determined by the value of build.sysclasspath
143:
144: Path cp = attributes.getClasspath();
145: if (cp == null) {
146: cp = new Path(attributes.getProject());
147: }
148: if (attributes.getIncludeantruntime()) {
149: classpath.addExisting(cp.concatSystemClasspath("last"));
150: } else {
151: classpath.addExisting(cp.concatSystemClasspath("ignore"));
152: }
153:
154: if (attributes.getIncludejavaruntime()) {
155: classpath.addJavaRuntime();
156: }
157: return classpath;
158: }
159:
160: /**
161: * Setup rmic argument for rmic.
162: * @return the command line
163: */
164: protected Commandline setupRmicCommand() {
165: return setupRmicCommand(null);
166: }
167:
168: /**
169: * Setup rmic argument for rmic.
170: * @param options additional parameters needed by a specific
171: * implementation.
172: * @return the command line
173: */
174: protected Commandline setupRmicCommand(String[] options) {
175: Commandline cmd = new Commandline();
176:
177: if (options != null) {
178: for (int i = 0; i < options.length; i++) {
179: cmd.createArgument().setValue(options[i]);
180: }
181: }
182:
183: Path classpath = getCompileClasspath();
184:
185: cmd.createArgument().setValue("-d");
186: cmd.createArgument().setFile(attributes.getBase());
187:
188: if (attributes.getExtdirs() != null) {
189: cmd.createArgument().setValue("-extdirs");
190: cmd.createArgument().setPath(attributes.getExtdirs());
191: }
192:
193: cmd.createArgument().setValue("-classpath");
194: cmd.createArgument().setPath(classpath);
195:
196: //handle the many different stub options.
197: String stubVersion = attributes.getStubVersion();
198: //default is compatibility
199: String stubOption = null;
200: if (null != stubVersion) {
201: if ("1.1".equals(stubVersion)) {
202: stubOption = STUB_1_1;
203: } else if ("1.2".equals(stubVersion)) {
204: stubOption = STUB_1_2;
205: } else if ("compat".equals(stubVersion)) {
206: stubOption = STUB_COMPAT;
207: } else {
208: //anything else
209: attributes.log("Unknown stub option " + stubVersion);
210: //do nothing with the value? or go -v+stubVersion??
211: }
212: }
213: //for java1.5+, we generate compatible stubs, that is, unless
214: //the caller asked for IDL or IIOP support.
215: if (stubOption == null && !attributes.getIiop()
216: && !attributes.getIdl()) {
217: stubOption = STUB_COMPAT;
218: }
219: if (stubOption != null) {
220: //set the non-null stubOption
221: cmd.createArgument().setValue(stubOption);
222: }
223: if (null != attributes.getSourceBase()) {
224: cmd.createArgument().setValue("-keepgenerated");
225: }
226:
227: if (attributes.getIiop()) {
228: attributes
229: .log("IIOP has been turned on.", Project.MSG_INFO);
230: cmd.createArgument().setValue("-iiop");
231: if (attributes.getIiopopts() != null) {
232: attributes.log("IIOP Options: "
233: + attributes.getIiopopts(), Project.MSG_INFO);
234: cmd.createArgument().setValue(attributes.getIiopopts());
235: }
236: }
237:
238: if (attributes.getIdl()) {
239: cmd.createArgument().setValue("-idl");
240: attributes.log("IDL has been turned on.", Project.MSG_INFO);
241: if (attributes.getIdlopts() != null) {
242: cmd.createArgument().setValue(attributes.getIdlopts());
243: attributes.log("IDL Options: "
244: + attributes.getIdlopts(), Project.MSG_INFO);
245: }
246: }
247:
248: if (attributes.getDebug()) {
249: cmd.createArgument().setValue("-g");
250: }
251:
252: cmd.addArguments(attributes.getCurrentCompilerArgs());
253:
254: logAndAddFilesToCompile(cmd);
255: return cmd;
256: }
257:
258: /**
259: * Logs the compilation parameters, adds the files to compile and logs the
260: * "niceSourceList"
261: * @param cmd the commandline args
262: */
263: protected void logAndAddFilesToCompile(Commandline cmd) {
264: Vector compileList = attributes.getCompileList();
265:
266: attributes.log("Compilation " + cmd.describeArguments(),
267: Project.MSG_VERBOSE);
268:
269: StringBuffer niceSourceList = new StringBuffer("File");
270: int cListSize = compileList.size();
271: if (cListSize != 1) {
272: niceSourceList.append("s");
273: }
274: niceSourceList.append(" to be compiled:");
275:
276: for (int i = 0; i < cListSize; i++) {
277: String arg = (String) compileList.elementAt(i);
278: cmd.createArgument().setValue(arg);
279: niceSourceList.append(" ");
280: niceSourceList.append(arg);
281: }
282:
283: attributes.log(niceSourceList.toString(), Project.MSG_VERBOSE);
284: }
285:
286: /**
287: * Mapper that may return up to two file names.
288: *
289: * <ul>
290: * <li>for JRMP it will return *_getStubClassSuffix (and
291: * *_getSkelClassSuffix if JDK 1.1 is used)</li>
292: *
293: * <li>for IDL it will return a random name, causing <rmic> to
294: * always recompile.</li>
295: *
296: * <li>for IIOP it will return _*_getStubClassSuffix for
297: * interfaces and _*_getStubClassSuffix for non-interfaces (and
298: * determine the interface and create _*_Stub from that).</li>
299: * </ul>
300: */
301: private class RmicFileNameMapper implements FileNameMapper {
302:
303: RmicFileNameMapper() {
304: }
305:
306: /**
307: * Empty implementation.
308: */
309: public void setFrom(String s) {
310: }
311:
312: /**
313: * Empty implementation.
314: */
315: public void setTo(String s) {
316: }
317:
318: public String[] mapFileName(String name) {
319: if (name == null || !name.endsWith(".class")
320: || name.endsWith(getStubClassSuffix() + ".class")
321: || name.endsWith(getSkelClassSuffix() + ".class")
322: || name.endsWith(getTieClassSuffix() + ".class")) {
323: // Not a .class file or the one we'd generate
324: return null;
325: }
326:
327: // we know that name.endsWith(".class")
328: String base = name.substring(0, name.length() - 6);
329:
330: String classname = base.replace(File.separatorChar, '.');
331: if (attributes.getVerify()
332: && !attributes.isValidRmiRemote(classname)) {
333: return null;
334: }
335:
336: /*
337: * fallback in case we have trouble loading the class or
338: * don't know how to handle it (there is no easy way to
339: * know what IDL mode would generate.
340: *
341: * This is supposed to make Ant always recompile the
342: * class, as a file of that name should not exist.
343: */
344: String[] target = new String[] { name + ".tmp."
345: + RAND.nextLong() };
346:
347: if (!attributes.getIiop() && !attributes.getIdl()) {
348: // JRMP with simple naming convention
349: if ("1.2".equals(attributes.getStubVersion())) {
350: target = new String[] { base + getStubClassSuffix()
351: + ".class" };
352: } else {
353: target = new String[] {
354: base + getStubClassSuffix() + ".class",
355: base + getSkelClassSuffix() + ".class", };
356: }
357: } else if (!attributes.getIdl()) {
358: int lastSlash = base.lastIndexOf(File.separatorChar);
359:
360: String dirname = "";
361: /*
362: * I know, this is not necessary, but I prefer it explicit (SB)
363: */
364: int index = -1;
365: if (lastSlash == -1) {
366: // no package
367: index = 0;
368: } else {
369: index = lastSlash + 1;
370: dirname = base.substring(0, index);
371: }
372:
373: String filename = base.substring(index);
374:
375: try {
376: Class c = attributes.getLoader().loadClass(
377: classname);
378:
379: if (c.isInterface()) {
380: // only stub, no tie
381: target = new String[] { dirname + "_"
382: + filename + getStubClassSuffix()
383: + ".class" };
384: } else {
385: /*
386: * stub is derived from implementation,
387: * tie from interface name.
388: */
389: Class interf = attributes.getRemoteInterface(c);
390: String iName = interf.getName();
391: String iDir = "";
392: int iIndex = -1;
393: int lastDot = iName.lastIndexOf(".");
394: if (lastDot == -1) {
395: // no package
396: iIndex = 0;
397: } else {
398: iIndex = lastDot + 1;
399: iDir = iName.substring(0, iIndex);
400: iDir = iDir
401: .replace('.', File.separatorChar);
402: }
403:
404: target = new String[] {
405: dirname + "_" + filename
406: + getTieClassSuffix()
407: + ".class",
408: iDir + "_" + iName.substring(iIndex)
409: + getStubClassSuffix()
410: + ".class" };
411: }
412: } catch (ClassNotFoundException e) {
413: attributes.log("Unable to verify class "
414: + classname + ". It could not be found.",
415: Project.MSG_WARN);
416: } catch (NoClassDefFoundError e) {
417: attributes.log("Unable to verify class "
418: + classname + ". It is not defined.",
419: Project.MSG_WARN);
420: } catch (Throwable t) {
421: attributes.log("Unable to verify class "
422: + classname
423: + ". Loading caused Exception: "
424: + t.getMessage(), Project.MSG_WARN);
425: }
426: }
427: return target;
428: }
429: }
430: }
|