/******************************************************************************* * * Copyright (c) 2004-2009 Oracle Corporation. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * * Kohsuke Kawaguchi * * *******************************************************************************/ package org.jvnet.hudson.test; import hudson.FilePath; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; /** * Controls how a {@link HudsonTestCase} initializes <tt>HUDSON_HOME</tt>. * * @author Kohsuke Kawaguchi */ public interface HudsonHomeLoader { /** * Returns a directory to be used as <tt>HUDSON_HOME</tt> * * @throws Exception to cause a test to fail. */ File allocate() throws Exception; /** * Allocates a new empty directory, meaning this will emulate the fresh * Hudson installation. */ public static final HudsonHomeLoader NEW = new HudsonHomeLoader() { public File allocate() throws IOException { return TestEnvironment.get().temporaryDirectoryAllocator.allocate(); } }; /** * Allocates a new directory by copying from an existing directory, or * unzipping from a zip file. */ public static final class CopyExisting implements HudsonHomeLoader { private final URL source; /** * Either a zip file or a directory that contains the home image. */ public CopyExisting(File source) throws MalformedURLException { this(source.toURI().toURL()); } /** * Extracts from a zip file in the resource. * * <p> This is useful in case you want to have a test data in the * resources. Only file URL is supported. */ public CopyExisting(URL source) { this.source = source; } public File allocate() throws Exception { File target = NEW.allocate(); if (source.getProtocol().equals("file")) { File src = new File(source.toURI()); if (src.isDirectory()) { new FilePath(src).copyRecursiveTo("**/*", new FilePath(target)); } else if (src.getName().endsWith(".zip")) { new FilePath(src).unzip(new FilePath(target)); } } else { File tmp = File.createTempFile("hudson", "zip"); try { FileUtils.copyURLToFile(source, tmp); new FilePath(tmp).unzip(new FilePath(target)); } finally { tmp.delete(); } } return target; } } /** * Allocates a new directory by copying from a test resource */ public static final class Local implements HudsonHomeLoader { private final Method testMethod; public Local(Method testMethod) { this.testMethod = testMethod; } public File allocate() throws Exception { URL res = findDataResource(); if (!res.getProtocol().equals("file")) { throw new AssertionError("Test data is not available in the file system: " + res); } // if we picked up a directory, it's one level above config.xml File home = new File(res.toURI()); if (!home.getName().endsWith(".zip")) { home = home.getParentFile(); } return new CopyExisting(home).allocate(); } private URL findDataResource() { // first, check method specific resource Class<?> clazz = testMethod.getDeclaringClass(); for (String middle : new String[]{'/' + testMethod.getName(), ""}) { for (String suffix : SUFFIXES) { URL res = clazz.getResource(clazz.getSimpleName() + middle + suffix); if (res != null) { return res; } } } throw new AssertionError("No test resource was found for " + testMethod); } private static final String[] SUFFIXES = {"/config.xml", ".zip"}; } }