1. /*
  2. * Copyright 2000-2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. package org.apache.tools.ant.taskdefs.optional.dotnet;
  18. import org.apache.tools.ant.Task;
  19. import org.apache.tools.ant.BuildException;
  20. import org.apache.tools.ant.Project;
  21. import org.apache.tools.ant.util.FileUtils;
  22. import java.io.File;
  23. /**
  24. * Import a COM type library into the .NET framework.
  25. * <p>
  26. *
  27. * This task is a wrapper to .NET's tlbimport; it imports a tlb file to a NET assembly
  28. * by generating a binary assembly (.dll) that contains all the binding
  29. * metadata. It uses date timestamps to minimise rebuilds.
  30. * <p>
  31. * Example
  32. * <pre>
  33. * <importtypelib
  34. * srcfile="xerces.tlb"
  35. * destfile="xerces.dll"
  36. * namespace="Apache.Xerces"/>
  37. * </pre>
  38. * @since Ant 1.6
  39. * @ant.task category="dotnet"
  40. */
  41. public class ImportTypelib extends Task {
  42. /**
  43. * input file; precedes options
  44. */
  45. private File srcFile;
  46. /**
  47. * /out:file
  48. */
  49. private File destFile;
  50. /**
  51. * /namespace:[string]
  52. */
  53. private String namespace;
  54. /**
  55. * /sysarray
  56. */
  57. private boolean useSysArray = false;
  58. /**
  59. * /unsafe
  60. */
  61. private boolean unsafe = false;
  62. /**
  63. * extra commands?
  64. */
  65. private String extraOptions = null;
  66. /**
  67. * This method names the output file.
  68. *
  69. * This is an operation which is required to have been performed.
  70. * @param destFile
  71. */
  72. public void setDestFile(File destFile) {
  73. this.destFile = destFile;
  74. }
  75. /**
  76. * This method sets what namespace the typelib is to be in.
  77. * This is an operation which is required to have been performed.
  78. * @param namespace
  79. */
  80. public void setNamespace(String namespace) {
  81. this.namespace = namespace;
  82. }
  83. /**
  84. * This method sets which is the source .tlb file.
  85. * This is an operation which is required to have been performed.
  86. * @param srcFile
  87. */
  88. public void setSrcFile(File srcFile) {
  89. this.srcFile = srcFile;
  90. }
  91. /**
  92. * do you want unsafe code.
  93. * @param unsafe
  94. */
  95. public void setUnsafe(boolean unsafe) {
  96. this.unsafe = unsafe;
  97. }
  98. /**
  99. * set this to map a COM SafeArray to the System.Array class
  100. * @param useSysArray
  101. */
  102. public void setUseSysArray(boolean useSysArray) {
  103. this.useSysArray = useSysArray;
  104. }
  105. /**
  106. * set any extra options that are not yet supported by this task.
  107. * @param extraOptions
  108. */
  109. public void setExtraOptions(String extraOptions) {
  110. this.extraOptions = extraOptions;
  111. }
  112. /**
  113. * validation code
  114. * @throws BuildException if validation failed
  115. */
  116. protected void validate()
  117. throws BuildException {
  118. if (destFile == null) {
  119. throw new BuildException("destination file must be specified");
  120. }
  121. if (destFile.isDirectory()) {
  122. throw new BuildException(
  123. "destination file is a directory");
  124. }
  125. if (srcFile == null || !srcFile.exists()) {
  126. throw new BuildException(
  127. "source file does not exist");
  128. }
  129. if (srcFile.isDirectory()) {
  130. throw new BuildException(
  131. "source file is a directory");
  132. }
  133. if (namespace == null) {
  134. throw new BuildException("No namespace");
  135. }
  136. }
  137. /**
  138. * Test for disassembly being needed; use existence and granularity
  139. * correct date stamps
  140. * @return true iff a rebuild is required.
  141. */
  142. private boolean isExecuteNeeded() {
  143. if (!destFile.exists()) {
  144. log("Destination file does not exist: a build is required",
  145. Project.MSG_VERBOSE);
  146. return true;
  147. }
  148. long sourceTime = srcFile.lastModified();
  149. long destTime = destFile.lastModified();
  150. if (sourceTime > (destTime + FileUtils.newFileUtils().getFileTimestampGranularity())) {
  151. log("Source file is newer than the dest file: a rebuild is required",
  152. Project.MSG_VERBOSE);
  153. return true;
  154. } else {
  155. log("The output file is up to date", Project.MSG_VERBOSE);
  156. return false;
  157. }
  158. }
  159. /**
  160. * Create a typelib command
  161. * @exception BuildException if something goes wrong with the build
  162. */
  163. public void execute() throws BuildException {
  164. validate();
  165. log("Importing typelib " + srcFile
  166. + " to assembly " + destFile
  167. + " in namespace " + namespace, Project.MSG_VERBOSE);
  168. //rebuild unless the dest file is newer than the source file
  169. if(!isExecuteNeeded()) {
  170. return;
  171. }
  172. NetCommand command = new NetCommand(this, "ImportTypelib", "tlbimp");
  173. command.setFailOnError(true);
  174. command.addArgument(srcFile.toString());
  175. //fill in args
  176. command.addArgument("/nologo");
  177. command.addArgument("/out:" + destFile);
  178. command.addArgument("/namespace:", namespace);
  179. if (useSysArray) {
  180. command.addArgument("/sysarray");
  181. }
  182. if (unsafe) {
  183. command.addArgument("/unsafe");
  184. }
  185. command.addArgument(extraOptions);
  186. command.runCommand();
  187. }
  188. }