3434import java .io .File ;
3535import java .io .IOException ;
3636import java .net .URL ;
37+ import java .util .AbstractMap ;
38+ import java .util .Map ;
3739
3840import org .scijava .util .ClassUtils ;
3941import org .scijava .util .FileUtils ;
@@ -58,7 +60,8 @@ public class TestUtils {
5860 * @throws IOException
5961 */
6062 public static File createTemporaryDirectory (final String prefix ) throws IOException {
61- return createTemporaryDirectory (prefix , getCallingClass (null ));
63+ final Map .Entry <Class <?>, String > calling = getCallingCodeLocation (null );
64+ return createTemporaryDirectory (prefix , calling .getKey (), calling .getValue ());
6265 }
6366
6467 /**
@@ -77,18 +80,41 @@ public static File createTemporaryDirectory(final String prefix) throws IOExcept
7780 */
7881 public static File createTemporaryDirectory (final String prefix ,
7982 final Class <?> forClass ) throws IOException
83+ {
84+ return createTemporaryDirectory (prefix , forClass , "" );
85+ }
86+
87+ /**
88+ * Makes a temporary directory for use with unit tests.
89+ * <p>
90+ * When the unit test runs in a Maven context, the temporary directory will be
91+ * created in the corresponding <i>target/</i> directory instead of
92+ * <i>/tmp/</i>.
93+ * </p>
94+ *
95+ * @param prefix the prefix for the directory's name
96+ * @param forClass the class for context (to determine whether there's a
97+ * <i>target/<i> directory)
98+ * @param suffix the suffix for the directory's name
99+ * @return the reference to the newly-created temporary directory
100+ * @throws IOException
101+ */
102+ public static File createTemporaryDirectory (final String prefix ,
103+ final Class <?> forClass , final String suffix ) throws IOException
80104 {
81105 final URL directory = ClassUtils .getLocation (forClass );
82106 if (directory != null && "file" .equals (directory .getProtocol ())) {
83107 final String path = directory .getPath ();
84108 if (path != null && path .endsWith ("/target/test-classes/" )) {
85109 final File baseDirectory =
86110 new File (path .substring (0 , path .length () - 13 ));
87- final File file = File .createTempFile (prefix , "" , baseDirectory );
88- if (file .delete () && file .mkdir ()) return file ;
111+ final File file = new File (baseDirectory , prefix + suffix );
112+ if (file .exists ()) FileUtils .deleteRecursively (file );
113+ if (!file .mkdir ()) throw new IOException ("Could not make directory " + file );
114+ return file ;
89115 }
90116 }
91- return FileUtils .createTemporaryDirectory (prefix , "" );
117+ return FileUtils .createTemporaryDirectory (prefix , suffix );
92118 }
93119
94120 /**
@@ -104,6 +130,22 @@ public static File createTemporaryDirectory(final String prefix,
104130 * @return the class of the caller
105131 */
106132 public static Class <?> getCallingClass (final Class <?> excluding ) {
133+ return getCallingCodeLocation (excluding ).getKey ();
134+ }
135+
136+ /**
137+ * Returns the class and the method/line number of the caller (excluding the specified class).
138+ * <p>
139+ * Sometimes it is convenient to determine the caller's context, e.g. to
140+ * determine whether running in a maven-surefire-plugin context (in which case
141+ * the location of the caller's class would end in
142+ * <i>target/test-classes/</i>).
143+ * </p>
144+ *
145+ * @param excluding the class to exclude (or null)
146+ * @return the class of the caller and the method and line number
147+ */
148+ public static Map .Entry <Class <?>, String > getCallingCodeLocation (final Class <?> excluding ) {
107149 final String thisClassName = TestUtils .class .getName ();
108150 final String thisClassName2 = excluding == null ? null : excluding .getName ();
109151 final Thread currentThread = Thread .currentThread ();
@@ -115,14 +157,17 @@ public static Class<?> getCallingClass(final Class<?> excluding) {
115157 continue ;
116158 }
117159 final ClassLoader loader = currentThread .getContextClassLoader ();
160+ final Class <?> clazz ;
118161 try {
119- return loader .loadClass (element .getClassName ());
162+ clazz = loader .loadClass (element .getClassName ());
120163 }
121164 catch (ClassNotFoundException e ) {
122165 throw new UnsupportedOperationException ("Could not load " +
123166 element .getClassName () + " with the current context class loader (" +
124167 loader + ")!" );
125168 }
169+ final String suffix = element .getMethodName () + "-L" + element .getLineNumber ();
170+ return new AbstractMap .SimpleEntry <Class <?>, String >(clazz , suffix );
126171 }
127172 throw new UnsupportedOperationException ("No calling class outside " + thisClassName + " found!" );
128173 }
0 commit comments