View Javadoc
1   /*
2    *
3    * The DbUnit Database Testing Framework
4    * Copyright (C)2002-2024, DbUnit.org
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License as published by the Free Software Foundation; either
9    * version 2.1 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, write to the Free Software
18   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19   *
20   */
21  
22  package org.dbunit.ant.adapter;
23  
24  import java.io.File;
25  import java.io.OutputStream;
26  import java.io.PrintStream;
27  import java.nio.file.Paths;
28  import org.apache.tools.ant.BuildEvent;
29  import org.apache.tools.ant.BuildException;
30  import org.apache.tools.ant.BuildListener;
31  import org.apache.tools.ant.Project;
32  import org.apache.tools.ant.ProjectHelper;
33  import org.apache.tools.ant.util.ProcessUtil;
34  import org.junit.jupiter.api.extension.AfterEachCallback;
35  import org.junit.jupiter.api.extension.ExtensionContext;
36  
37  /**
38   * The BuildFileExtension class provides functionality to configure and execute Apache Ant build
39   * files for testing purposes. It has been ported over from the ant-testutils.jar which only
40   * supports junit4. See BuildFileRule for comparison.
41   *
42   * @author Andrew Johnson
43   * @author Last changed by: $Author$
44   * @version $Revision$ $Date$
45   * @see "org.apache.tools.ant.BuildFileRule, the JUnit 4 ant-testutils rule this extension replaces"
46   * @since Sep 21, 2024
47   */
48  public class BuildFileExtension implements AfterEachCallback {
49  
50  	private Project project;
51  	private StringBuilder logBuffer;
52  	private StringBuilder fullLogBuffer;
53  	private StringBuilder outputBuffer;
54  	private StringBuilder errorBuffer;
55  
56  	public BuildFileExtension() {
57  	}
58  
59  	protected void after() {
60  		if (this.project != null) {
61  			String tearDown = "tearDown";
62  			if (this.project.getTargets().containsKey("tearDown")) {
63  				this.project.executeTarget("tearDown");
64  			}
65  
66  		}
67  	}
68  
69  	public String getLog() {
70  		return this.logBuffer.toString();
71  	}
72  
73  	public String getFullLog() {
74  		return this.fullLogBuffer.toString();
75  	}
76  
77  	public String getOutput() {
78  		return this.cleanBuffer(this.outputBuffer);
79  	}
80  
81  	public String getError() {
82  		return this.cleanBuffer(this.errorBuffer);
83  	}
84  
85  	private String cleanBuffer(StringBuilder buffer) {
86  		StringBuilder cleanedBuffer = new StringBuilder();
87  
88  		for (int i = 0; i < buffer.length(); ++i) {
89  			char ch = buffer.charAt(i);
90  			if (ch != '\r') {
91  				cleanedBuffer.append(ch);
92  			}
93  		}
94  
95  		return cleanedBuffer.toString();
96  	}
97  
98  	public void configureProject(String filename) throws BuildException {
99  		this.configureProject(filename, 4);
100 	}
101 
102 	public void configureProject(String filename, int logLevel) throws BuildException {
103 		this.logBuffer = new StringBuilder();
104 		this.fullLogBuffer = new StringBuilder();
105 		this.project = new Project();
106 		if (Boolean.getBoolean("ant.test.basedir.ignore")) {
107 			System.clearProperty("basedir");
108 		}
109 
110 		this.project.init();
111 		final String root = System.getProperty("root");
112 		File antFile = root != null ? Paths.get(root, filename).toFile() : Paths.get(filename).toFile();
113 		this.project.setProperty("ant.processid", ProcessUtil.getProcessId("<Process>"));
114 		this.project.setProperty("ant.threadname", Thread.currentThread().getName());
115 		this.project.setUserProperty("ant.file", antFile.getAbsolutePath());
116 		this.project.addBuildListener(new AntTestListener(logLevel));
117 		ProjectHelper.configureProject(this.project, antFile);
118 	}
119 
120 	public void executeTarget(String targetName) {
121 		this.outputBuffer = new StringBuilder();
122 		PrintStream out = new PrintStream(
123 				new AntOutputStream(this.outputBuffer));
124 		this.errorBuffer = new StringBuilder();
125 		PrintStream err = new PrintStream(
126 				new AntOutputStream(this.errorBuffer));
127 		this.logBuffer = new StringBuilder();
128 		this.fullLogBuffer = new StringBuilder();
129 		synchronized (System.out) {
130 			PrintStream sysOut = System.out;
131 			PrintStream sysErr = System.err;
132 			sysOut.flush();
133 			sysErr.flush();
134 
135 			try {
136 				System.setOut(out);
137 				System.setErr(err);
138 				this.project.executeTarget(targetName);
139 			} finally {
140 				System.setOut(sysOut);
141 				System.setErr(sysErr);
142 			}
143 
144 		}
145 	}
146 
147 	public Project getProject() {
148 		return this.project;
149 	}
150 
151 	public File getOutputDir() {
152 		return Paths.get(this.getProject().getProperty("output")).toFile();
153 	}
154 
155 	@Override
156 	public void afterEach(ExtensionContext context) throws Exception {
157 		after();
158 	}
159 
160 	protected static class AntOutputStream extends OutputStream {
161 
162 		private StringBuilder buffer;
163 
164 		public AntOutputStream(StringBuilder buffer) {
165 			this.buffer = buffer;
166 		}
167 
168 		public void write(int b) {
169 			this.buffer.append((char) b);
170 		}
171 	}
172 
173 	private class AntTestListener implements BuildListener {
174 
175 		private int logLevel;
176 
177 		public AntTestListener(int logLevel) {
178 			this.logLevel = logLevel;
179 		}
180 
181 		public void buildStarted(BuildEvent event) {
182 		}
183 
184 		public void buildFinished(BuildEvent event) {
185 		}
186 
187 		public void targetStarted(BuildEvent event) {
188 		}
189 
190 		public void targetFinished(BuildEvent event) {
191 		}
192 
193 		public void taskStarted(BuildEvent event) {
194 		}
195 
196 		public void taskFinished(BuildEvent event) {
197 		}
198 
199 		public void messageLogged(BuildEvent event) {
200 			if (event.getPriority() <= this.logLevel) {
201 				if (event.getPriority() == 2 || event.getPriority() == 1 || event.getPriority() == 0) {
202 					logBuffer.append(event.getMessage());
203 				}
204 
205 				fullLogBuffer.append(event.getMessage());
206 			}
207 		}
208 	}
209 }