1. /*
  2. * Copyright 2001-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.junit;
  18. import java.io.BufferedOutputStream;
  19. import java.io.ByteArrayOutputStream;
  20. import java.io.File;
  21. import java.io.FileOutputStream;
  22. import java.io.IOException;
  23. import java.io.OutputStream;
  24. import java.io.PrintWriter;
  25. import java.io.StringWriter;
  26. import java.lang.reflect.Field;
  27. import org.apache.tools.ant.BuildException;
  28. import org.apache.tools.ant.Project;
  29. import org.apache.tools.ant.util.JavaEnvUtils;
  30. /**
  31. * Command class that encapsulate specific behavior for each
  32. * Xalan version. The right executor will be instantiated at
  33. * runtime via class lookup. For instance, it will check first
  34. * for Xalan2/XSLTC, then for Xalan1.
  35. */
  36. abstract class XalanExecutor {
  37. private static final String pack =
  38. "org.apache.tools.ant.taskdefs.optional.junit.";
  39. /** the transformer caller */
  40. protected AggregateTransformer caller;
  41. /** set the caller for this object. */
  42. private final void setCaller(AggregateTransformer caller) {
  43. this.caller = caller;
  44. }
  45. /** get the appropriate stream based on the format (frames/noframes) */
  46. protected final OutputStream getOutputStream() throws IOException {
  47. if (AggregateTransformer.FRAMES.equals(caller.format)) {
  48. // dummy output for the framed report
  49. // it's all done by extension...
  50. return new ByteArrayOutputStream();
  51. } else {
  52. return new BufferedOutputStream(new FileOutputStream(new File(caller.toDir, "junit-noframes.html")));
  53. }
  54. }
  55. /** override to perform transformation */
  56. abstract void execute() throws Exception;
  57. /**
  58. * Create a valid Xalan executor. It checks first if Xalan2 is
  59. * present, if not it checks for xalan1. If none is available, it
  60. * fails.
  61. * @param caller object containing the transformation information.
  62. * @throws BuildException thrown if it could not find a valid xalan
  63. * executor.
  64. */
  65. static XalanExecutor newInstance(AggregateTransformer caller)
  66. throws BuildException {
  67. XalanExecutor executor = null;
  68. try {
  69. Class clazz = Class.forName(pack + "Xalan2Executor");
  70. executor = (XalanExecutor)clazz.newInstance();
  71. } catch (Exception xsltcApacheMissing){
  72. caller.task.log(xsltcApacheMissing.toString());
  73. try {
  74. Class clazz = Class.forName(pack + "Xalan1Executor");
  75. executor = (XalanExecutor) clazz.newInstance();
  76. } catch (Exception xalan1Missing){
  77. caller.task.log(xalan1Missing.toString());
  78. throw new BuildException("Could not find xstlc nor xalan2 nor "
  79. + "xalan1 in the classpath. Check "
  80. + "http://xml.apache.org/xalan-j");
  81. }
  82. }
  83. String classNameImpl = executor.getImplementation();
  84. String version = executor.getProcVersion(classNameImpl);
  85. caller.task.log("Using " + version, Project.MSG_VERBOSE);
  86. executor.setCaller(caller);
  87. return executor;
  88. }
  89. /**
  90. * This methods should return the classname implementation of the
  91. * underlying xslt processor
  92. * @return the classname of the implementation, for example:
  93. * org.apache.xalan.processor.TransformerFactoryImpl
  94. * @see #getProcVersion(String)
  95. */
  96. protected abstract String getImplementation();
  97. /**
  98. * Try to discover the xslt processor version based on the
  99. * className. There is nothing carved in stone and it can change
  100. * anytime, so this is just for the sake of giving additional
  101. * information if we can find it.
  102. * @param classNameImpl the classname of the underlying xslt processor
  103. * @return a string representing the implementation version.
  104. * @throws BuildException
  105. */
  106. protected abstract String getProcVersion(String classNameImpl)
  107. throws BuildException;
  108. /** a bit simplistic but xsltc data are conveniently private non final */
  109. protected final String getXSLTCVersion(String procVersionClassName)
  110. throws ClassNotFoundException {
  111. // there's a convenient xsltc class version but data are
  112. // private so use package information
  113. Class procVersion = Class.forName(procVersionClassName);
  114. Package pkg = procVersion.getPackage();
  115. return pkg.getName() + " " + pkg.getImplementationTitle()
  116. + " " + pkg.getImplementationVersion();
  117. }
  118. /** pretty useful data (Xalan version information) to display. */
  119. protected final String getXalanVersion(String procVersionClassName)
  120. throws ClassNotFoundException {
  121. Class procVersion = Class.forName(procVersionClassName);
  122. String pkg = procVersion.getPackage().getName();
  123. try {
  124. Field f = procVersion.getField("S_VERSION");
  125. return pkg + " " + f.get(null).toString();
  126. } catch (Exception e) {
  127. return pkg + " ?.?";
  128. }
  129. }
  130. }