You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Rmic.java 24 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package org.apache.tools.ant.taskdefs;
  19. import java.io.File;
  20. import java.io.IOException;
  21. import java.rmi.Remote;
  22. import java.util.Vector;
  23. import org.apache.tools.ant.BuildException;
  24. import org.apache.tools.ant.DirectoryScanner;
  25. import org.apache.tools.ant.Project;
  26. import org.apache.tools.ant.taskdefs.rmic.RmicAdapter;
  27. import org.apache.tools.ant.taskdefs.rmic.RmicAdapterFactory;
  28. import org.apache.tools.ant.types.FilterSetCollection;
  29. import org.apache.tools.ant.types.Path;
  30. import org.apache.tools.ant.types.Reference;
  31. import org.apache.tools.ant.util.FileNameMapper;
  32. import org.apache.tools.ant.util.FileUtils;
  33. import org.apache.tools.ant.util.SourceFileScanner;
  34. import org.apache.tools.ant.util.facade.FacadeTaskHelper;
  35. /**
  36. * Runs the rmic compiler against classes.</p>
  37. * <p>Rmic can be run on a single class (as specified with the classname
  38. * attribute) or a number of classes at once (all classes below base that
  39. * are neither _Stub nor _Skel classes). If you want to rmic a single
  40. * class and this class is a class nested into another class, you have to
  41. * specify the classname in the form <code>Outer$$Inner</code> instead of
  42. * <code>Outer.Inner</code>.</p>
  43. * <p>It is possible to refine the set of files that are being rmiced. This can
  44. * be done with the <i>includes</i>, <i>includesfile</i>, <i>excludes</i>,
  45. * <i>excludesfile</i> and <i>defaultexcludes</i>
  46. * attributes. With the <i>includes</i> or <i>includesfile</i> attribute you
  47. * specify the files you want to have included by using patterns. The
  48. * <i>exclude</i> or <i>excludesfile</i> attribute is used to specify
  49. * the files you want to have excluded. This is also done with patterns. And
  50. * finally with the <i>defaultexcludes</i> attribute, you can specify whether
  51. * you want to use default exclusions or not. See the section on
  52. * directory based tasks</a>, on how the
  53. * inclusion/exclusion of files works, and how to write patterns.</p>
  54. * <p>This task forms an implicit FileSet and
  55. * supports all attributes of <code>&lt;fileset&gt;</code>
  56. * (<code>dir</code> becomes <code>base</code>) as well as the nested
  57. * <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code> and
  58. * <code>&lt;patternset&gt;</code> elements.</p>
  59. * <p>It is possible to use different compilers. This can be selected
  60. * with the &quot;build.rmic&quot; property or the <code>compiler</code>
  61. * attribute. <a name="compilervalues">There are three choices</a>:</p>
  62. * <ul>
  63. * <li>sun (the standard compiler of the JDK)</li>
  64. * <li>kaffe (the standard compiler of
  65. * {@link <a href="http://www.kaffe.org">Kaffe</a>})</li>
  66. * <li>weblogic</li>
  67. * </ul>
  68. *
  69. * <p> The <a href="http://dione.zcu.cz/~toman40/miniRMI/">miniRMI</a>
  70. * project contains a compiler implementation for this task as well,
  71. * please consult miniRMI's documentation to learn how to use it.</p>
  72. *
  73. * @since Ant 1.1
  74. *
  75. * @ant.task category="java"
  76. */
  77. public class Rmic extends MatchingTask {
  78. /** rmic failed message */
  79. public static final String ERROR_RMIC_FAILED
  80. = "Rmic failed; see the compiler error output for details.";
  81. private File baseDir;
  82. private String classname;
  83. private File sourceBase;
  84. private String stubVersion;
  85. private Path compileClasspath;
  86. private Path extDirs;
  87. private boolean verify = false;
  88. private boolean filtering = false;
  89. private boolean iiop = false;
  90. private String iiopOpts;
  91. private boolean idl = false;
  92. private String idlOpts;
  93. private boolean debug = false;
  94. private boolean includeAntRuntime = true;
  95. private boolean includeJavaRuntime = false;
  96. private Vector compileList = new Vector();
  97. private ClassLoader loader = null;
  98. private FacadeTaskHelper facade;
  99. /** unable to verify message */
  100. public static final String ERROR_UNABLE_TO_VERIFY_CLASS = "Unable to verify class ";
  101. /** could not be found message */
  102. public static final String ERROR_NOT_FOUND = ". It could not be found.";
  103. /** not defined message */
  104. public static final String ERROR_NOT_DEFINED = ". It is not defined.";
  105. /** loaded error message */
  106. public static final String ERROR_LOADING_CAUSED_EXCEPTION = ". Loading caused Exception: ";
  107. /** base not exists message */
  108. public static final String ERROR_NO_BASE_EXISTS = "base does not exist: ";
  109. /** base not a directory message */
  110. public static final String ERROR_NOT_A_DIR = "base is not a directory:";
  111. /** base attribute not set message */
  112. public static final String ERROR_BASE_NOT_SET = "base attribute must be set!";
  113. private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
  114. /**
  115. * Constructor for Rmic.
  116. */
  117. public Rmic() {
  118. facade = new FacadeTaskHelper(RmicAdapterFactory.DEFAULT_COMPILER);
  119. }
  120. /**
  121. * Sets the location to store the compiled files; required
  122. * @param base the location to store the compiled files
  123. */
  124. public void setBase(File base) {
  125. this.baseDir = base;
  126. }
  127. /**
  128. * Gets the base directory to output generated class.
  129. * @return the location of the compiled files
  130. */
  131. public File getBase() {
  132. return this.baseDir;
  133. }
  134. /**
  135. * Sets the class to run <code>rmic</code> against;
  136. * optional
  137. * @param classname the name of the class for rmic to create code for
  138. */
  139. public void setClassname(String classname) {
  140. this.classname = classname;
  141. }
  142. /**
  143. * Gets the class name to compile.
  144. * @return the name of the class to compile
  145. */
  146. public String getClassname() {
  147. return classname;
  148. }
  149. /**
  150. * optional directory to save generated source files to.
  151. * @param sourceBase the directory to save source files to.
  152. */
  153. public void setSourceBase(File sourceBase) {
  154. this.sourceBase = sourceBase;
  155. }
  156. /**
  157. * Gets the source dirs to find the source java files.
  158. * @return sourceBase the directory containing the source files.
  159. */
  160. public File getSourceBase() {
  161. return sourceBase;
  162. }
  163. /**
  164. * Specify the JDK version for the generated stub code.
  165. * Specify &quot;1.1&quot; to pass the &quot;-v1.1&quot; option to rmic.</td>
  166. * @param stubVersion the JDK version
  167. */
  168. public void setStubVersion(String stubVersion) {
  169. this.stubVersion = stubVersion;
  170. }
  171. /**
  172. * Gets the JDK version for the generated stub code.
  173. * @return stubVersion
  174. */
  175. public String getStubVersion() {
  176. return stubVersion;
  177. }
  178. /**
  179. * Sets token filtering [optional], default=false
  180. * @param filter turn on token filtering
  181. */
  182. public void setFiltering(boolean filter) {
  183. this.filtering = filter;
  184. }
  185. /**
  186. * Gets whether token filtering is set
  187. * @return filtering
  188. */
  189. public boolean getFiltering() {
  190. return filtering;
  191. }
  192. /**
  193. * Generate debug info (passes -g to rmic);
  194. * optional, defaults to false
  195. * @param debug turn on debug info
  196. */
  197. public void setDebug(boolean debug) {
  198. this.debug = debug;
  199. }
  200. /**
  201. * Gets the debug flag.
  202. * @return debug
  203. */
  204. public boolean getDebug() {
  205. return debug;
  206. }
  207. /**
  208. * Set the classpath to be used for this compilation.
  209. * @param classpath the classpath used for this compilation
  210. */
  211. public void setClasspath(Path classpath) {
  212. if (compileClasspath == null) {
  213. compileClasspath = classpath;
  214. } else {
  215. compileClasspath.append(classpath);
  216. }
  217. }
  218. /**
  219. * Creates a nested classpath element.
  220. * @return classpath
  221. */
  222. public Path createClasspath() {
  223. if (compileClasspath == null) {
  224. compileClasspath = new Path(getProject());
  225. }
  226. return compileClasspath.createPath();
  227. }
  228. /**
  229. * Adds to the classpath a reference to
  230. * a &lt;path&gt; defined elsewhere.
  231. * @param pathRef the reference to add to the classpath
  232. */
  233. public void setClasspathRef(Reference pathRef) {
  234. createClasspath().setRefid(pathRef);
  235. }
  236. /**
  237. * Gets the classpath.
  238. * @return the classpath
  239. */
  240. public Path getClasspath() {
  241. return compileClasspath;
  242. }
  243. /**
  244. * Flag to enable verification so that the classes
  245. * found by the directory match are
  246. * checked to see if they implement java.rmi.Remote.
  247. * optional; This defaults to false if not set.
  248. * @param verify turn on verification for classes
  249. */
  250. public void setVerify(boolean verify) {
  251. this.verify = verify;
  252. }
  253. /**
  254. * Get verify flag.
  255. * @return verify
  256. */
  257. public boolean getVerify() {
  258. return verify;
  259. }
  260. /**
  261. * Indicates that IIOP compatible stubs should
  262. * be generated; optional, defaults to false
  263. * if not set.
  264. * @param iiop generate IIOP compatible stubs
  265. */
  266. public void setIiop(boolean iiop) {
  267. this.iiop = iiop;
  268. }
  269. /**
  270. * Gets iiop flags.
  271. * @return iiop
  272. */
  273. public boolean getIiop() {
  274. return iiop;
  275. }
  276. /**
  277. * Set additional arguments for iiop
  278. * @param iiopOpts additional arguments for iiop
  279. */
  280. public void setIiopopts(String iiopOpts) {
  281. this.iiopOpts = iiopOpts;
  282. }
  283. /**
  284. * Gets additional arguments for iiop.
  285. * @return iiopOpts
  286. */
  287. public String getIiopopts() {
  288. return iiopOpts;
  289. }
  290. /**
  291. * Indicates that IDL output should be
  292. * generated. This defaults to false
  293. * if not set.
  294. * @param idl generate IDL output
  295. */
  296. public void setIdl(boolean idl) {
  297. this.idl = idl;
  298. }
  299. /**
  300. * Gets IDL flags.
  301. * @return the idl flag
  302. */
  303. public boolean getIdl() {
  304. return idl;
  305. }
  306. /**
  307. * pass additional arguments for IDL compile
  308. * @param idlOpts additional IDL arguments
  309. */
  310. public void setIdlopts(String idlOpts) {
  311. this.idlOpts = idlOpts;
  312. }
  313. /**
  314. * Gets additional arguments for idl compile.
  315. * @return the idl options
  316. */
  317. public String getIdlopts() {
  318. return idlOpts;
  319. }
  320. /**
  321. * Gets file list to compile.
  322. * @return the list of files to compile.
  323. */
  324. public Vector getFileList() {
  325. return compileList;
  326. }
  327. /**
  328. * Sets whether or not to include ant's own classpath in this task's
  329. * classpath.
  330. * Optional; default is <code>true</code>.
  331. * @param include if true include ant's classpath
  332. */
  333. public void setIncludeantruntime(boolean include) {
  334. includeAntRuntime = include;
  335. }
  336. /**
  337. * Gets whether or not the ant classpath is to be included in the
  338. * task's classpath.
  339. * @return true if ant's classpath is to be included
  340. */
  341. public boolean getIncludeantruntime() {
  342. return includeAntRuntime;
  343. }
  344. /**
  345. * task's classpath.
  346. * Enables or disables including the default run-time
  347. * libraries from the executing VM; optional,
  348. * defaults to false
  349. * @param include if true include default run-time libraries
  350. */
  351. public void setIncludejavaruntime(boolean include) {
  352. includeJavaRuntime = include;
  353. }
  354. /**
  355. * Gets whether or not the java runtime should be included in this
  356. * task's classpath.
  357. * @return true if default run-time libraries are included
  358. */
  359. public boolean getIncludejavaruntime() {
  360. return includeJavaRuntime;
  361. }
  362. /**
  363. * Sets the extension directories that will be used during the
  364. * compilation; optional.
  365. * @param extDirs the extension directories to be used
  366. */
  367. public void setExtdirs(Path extDirs) {
  368. if (this.extDirs == null) {
  369. this.extDirs = extDirs;
  370. } else {
  371. this.extDirs.append(extDirs);
  372. }
  373. }
  374. /**
  375. * Maybe creates a nested extdirs element.
  376. * @return path object to be configured with the extension directories
  377. */
  378. public Path createExtdirs() {
  379. if (extDirs == null) {
  380. extDirs = new Path(getProject());
  381. }
  382. return extDirs.createPath();
  383. }
  384. /**
  385. * Gets the extension directories that will be used during the
  386. * compilation.
  387. * @return the extension directories to be used
  388. */
  389. public Path getExtdirs() {
  390. return extDirs;
  391. }
  392. /**
  393. * @return the compile list.
  394. */
  395. public Vector getCompileList() {
  396. return compileList;
  397. }
  398. /**
  399. * Sets the compiler implementation to use; optional,
  400. * defaults to the value of the <code>build.rmic</code> property,
  401. * or failing that, default compiler for the current VM
  402. * @param compiler the compiler implemention to use
  403. * @since Ant 1.5
  404. */
  405. public void setCompiler(String compiler) {
  406. if (compiler.length() > 0) {
  407. facade.setImplementation(compiler);
  408. }
  409. }
  410. /**
  411. * get the name of the current compiler
  412. * @return the name of the compiler
  413. * @since Ant 1.5
  414. */
  415. public String getCompiler() {
  416. facade.setMagicValue(getProject().getProperty("build.rmic"));
  417. return facade.getImplementation();
  418. }
  419. /**
  420. * Adds an implementation specific command line argument.
  421. * @return an object to be configured with a command line argument
  422. * @since Ant 1.5
  423. */
  424. public ImplementationSpecificArgument createCompilerArg() {
  425. ImplementationSpecificArgument arg =
  426. new ImplementationSpecificArgument();
  427. facade.addImplementationArgument(arg);
  428. return arg;
  429. }
  430. /**
  431. * Get the additional implementation specific command line arguments.
  432. * @return array of command line arguments, guaranteed to be non-null.
  433. * @since Ant 1.5
  434. */
  435. public String[] getCurrentCompilerArgs() {
  436. getCompiler();
  437. return facade.getArgs();
  438. }
  439. /**
  440. * execute by creating an instance of an implementation
  441. * class and getting to do the work
  442. * @throws org.apache.tools.ant.BuildException
  443. * if there's a problem with baseDir or RMIC
  444. */
  445. public void execute() throws BuildException {
  446. if (baseDir == null) {
  447. throw new BuildException(ERROR_BASE_NOT_SET, getLocation());
  448. }
  449. if (!baseDir.exists()) {
  450. throw new BuildException(ERROR_NO_BASE_EXISTS + baseDir, getLocation());
  451. }
  452. if (!baseDir.isDirectory()) {
  453. throw new BuildException(ERROR_NOT_A_DIR + baseDir, getLocation());
  454. }
  455. if (verify) {
  456. log("Verify has been turned on.", Project.MSG_VERBOSE);
  457. }
  458. RmicAdapter adapter = RmicAdapterFactory.getRmic(getCompiler(), this);
  459. // now we need to populate the compiler adapter
  460. adapter.setRmic(this);
  461. Path classpath = adapter.getClasspath();
  462. loader = getProject().createClassLoader(classpath);
  463. try {
  464. // scan base dirs to build up compile lists only if a
  465. // specific classname is not given
  466. if (classname == null) {
  467. DirectoryScanner ds = this.getDirectoryScanner(baseDir);
  468. String[] files = ds.getIncludedFiles();
  469. scanDir(baseDir, files, adapter.getMapper());
  470. } else {
  471. // otherwise perform a timestamp comparison - at least
  472. scanDir(baseDir,
  473. new String[] {classname.replace('.',
  474. File.separatorChar)
  475. + ".class"},
  476. adapter.getMapper());
  477. }
  478. int fileCount = compileList.size();
  479. if (fileCount > 0) {
  480. log("RMI Compiling " + fileCount
  481. + " class" + (fileCount > 1 ? "es" : "") + " to " + baseDir,
  482. Project.MSG_INFO);
  483. // finally, lets execute the compiler!!
  484. if (!adapter.execute()) {
  485. throw new BuildException(ERROR_RMIC_FAILED, getLocation());
  486. }
  487. }
  488. /*
  489. * Move the generated source file to the base directory. If
  490. * base directory and sourcebase are the same, the generated
  491. * sources are already in place.
  492. */
  493. if (null != sourceBase && !baseDir.equals(sourceBase)
  494. && fileCount > 0) {
  495. if (idl) {
  496. log("Cannot determine sourcefiles in idl mode, ",
  497. Project.MSG_WARN);
  498. log("sourcebase attribute will be ignored.",
  499. Project.MSG_WARN);
  500. } else {
  501. for (int j = 0; j < fileCount; j++) {
  502. moveGeneratedFile(baseDir, sourceBase,
  503. (String) compileList.elementAt(j),
  504. adapter);
  505. }
  506. }
  507. }
  508. } finally {
  509. compileList.removeAllElements();
  510. }
  511. }
  512. /**
  513. * Move the generated source file(s) to the base directory
  514. *
  515. * @throws org.apache.tools.ant.BuildException When error
  516. * copying/removing files.
  517. */
  518. private void moveGeneratedFile (File baseDir, File sourceBaseFile,
  519. String classname,
  520. RmicAdapter adapter)
  521. throws BuildException {
  522. String classFileName =
  523. classname.replace('.', File.separatorChar) + ".class";
  524. String[] generatedFiles =
  525. adapter.getMapper().mapFileName(classFileName);
  526. for (int i = 0; i < generatedFiles.length; i++) {
  527. final String generatedFile = generatedFiles[i];
  528. if (!generatedFile.endsWith(".class")) {
  529. // don't know how to handle that - a IDL file doesn't
  530. // have a corresponding Java source for example.
  531. continue;
  532. }
  533. final int pos = generatedFile.length() - ".class".length();
  534. String sourceFileName =
  535. generatedFile.substring(0, pos) + ".java";
  536. File oldFile = new File(baseDir, sourceFileName);
  537. if (!oldFile.exists()) {
  538. // no source file generated, nothing to move
  539. continue;
  540. }
  541. File newFile = new File(sourceBaseFile, sourceFileName);
  542. try {
  543. if (filtering) {
  544. FILE_UTILS.copyFile(oldFile, newFile,
  545. new FilterSetCollection(getProject()
  546. .getGlobalFilterSet()));
  547. } else {
  548. FILE_UTILS.copyFile(oldFile, newFile);
  549. }
  550. oldFile.delete();
  551. } catch (IOException ioe) {
  552. String msg = "Failed to copy " + oldFile + " to "
  553. + newFile + " due to " + ioe.getMessage();
  554. throw new BuildException(msg, ioe, getLocation());
  555. }
  556. }
  557. }
  558. /**
  559. * Scans the directory looking for class files to be compiled.
  560. * The result is returned in the class variable compileList.
  561. * @param baseDir the base direction
  562. * @param files the list of files to scan
  563. * @param mapper the mapper of files to target files
  564. */
  565. protected void scanDir(File baseDir, String[] files,
  566. FileNameMapper mapper) {
  567. String[] newFiles = files;
  568. if (idl) {
  569. log("will leave uptodate test to rmic implementation in idl mode.",
  570. Project.MSG_VERBOSE);
  571. } else if (iiop
  572. && iiopOpts != null && iiopOpts.indexOf("-always") > -1) {
  573. log("no uptodate test as -always option has been specified",
  574. Project.MSG_VERBOSE);
  575. } else {
  576. SourceFileScanner sfs = new SourceFileScanner(this);
  577. newFiles = sfs.restrict(files, baseDir, baseDir, mapper);
  578. }
  579. for (int i = 0; i < newFiles.length; i++) {
  580. String name = newFiles[i].replace(File.separatorChar, '.');
  581. name = name.substring(0, name.lastIndexOf(".class"));
  582. compileList.addElement(name);
  583. }
  584. }
  585. /**
  586. * Load named class and test whether it can be rmic'ed
  587. * @param classname the name of the class to be tested
  588. * @return true if the class can be rmic'ed
  589. */
  590. public boolean isValidRmiRemote(String classname) {
  591. try {
  592. Class testClass = loader.loadClass(classname);
  593. // One cannot RMIC an interface for "classic" RMI (JRMP)
  594. if (testClass.isInterface() && !iiop && !idl) {
  595. return false;
  596. }
  597. return isValidRmiRemote(testClass);
  598. } catch (ClassNotFoundException e) {
  599. log(ERROR_UNABLE_TO_VERIFY_CLASS + classname
  600. + ERROR_NOT_FOUND, Project.MSG_WARN);
  601. } catch (NoClassDefFoundError e) {
  602. log(ERROR_UNABLE_TO_VERIFY_CLASS + classname
  603. + ERROR_NOT_DEFINED, Project.MSG_WARN);
  604. } catch (Throwable t) {
  605. log(ERROR_UNABLE_TO_VERIFY_CLASS + classname
  606. + ERROR_LOADING_CAUSED_EXCEPTION
  607. + t.getMessage(), Project.MSG_WARN);
  608. }
  609. // we only get here if an exception has been thrown
  610. return false;
  611. }
  612. /**
  613. * Returns the topmost interface that extends Remote for a given
  614. * class - if one exists.
  615. * @param testClass the class to be tested
  616. * @return the topmost interface that extends Remote, or null if there
  617. * is none.
  618. */
  619. public Class getRemoteInterface(Class testClass) {
  620. if (Remote.class.isAssignableFrom(testClass)) {
  621. Class [] interfaces = testClass.getInterfaces();
  622. if (interfaces != null) {
  623. for (int i = 0; i < interfaces.length; i++) {
  624. if (Remote.class.isAssignableFrom(interfaces[i])) {
  625. return interfaces[i];
  626. }
  627. }
  628. }
  629. }
  630. return null;
  631. }
  632. /**
  633. * Check to see if the class or (super)interfaces implement
  634. * java.rmi.Remote.
  635. */
  636. private boolean isValidRmiRemote (Class testClass) {
  637. return getRemoteInterface(testClass) != null;
  638. }
  639. /**
  640. * Classloader for the user-specified classpath.
  641. * @return the classloader
  642. */
  643. public ClassLoader getLoader() {
  644. return loader;
  645. }
  646. /**
  647. * Adds an "compiler" attribute to Commandline$Attribute used to
  648. * filter command line attributes based on the current
  649. * implementation.
  650. */
  651. public class ImplementationSpecificArgument extends
  652. org.apache.tools.ant.util.facade.ImplementationSpecificArgument {
  653. /**
  654. * Only pass the specified argument if the
  655. * chosen compiler implementation matches the
  656. * value of this attribute. Legal values are
  657. * the same as those in the above list of
  658. * valid compilers.)
  659. * @param impl the compiler to be used.
  660. */
  661. public void setCompiler(String impl) {
  662. super.setImplementation(impl);
  663. }
  664. }
  665. }