org.eclipse.mylyn.commons.sdk.util.CommonTestUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.mylyn.commons.sdk.util.CommonTestUtil.java

Source

/*******************************************************************************
 * Copyright (c) 2011, 2012 Tasktop Technologies and others.
 * 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:
 *     Tasktop Technologies - initial API and implementation
 *******************************************************************************/

package org.eclipse.mylyn.commons.sdk.util;

import static com.google.common.base.Preconditions.checkNotNull;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import junit.framework.AssertionFailedError;

import org.apache.commons.lang.reflect.MethodUtils;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.mylyn.commons.core.CoreUtil;
import org.eclipse.mylyn.commons.core.net.NetUtil;
import org.eclipse.mylyn.commons.net.WebUtil;
import org.eclipse.mylyn.commons.repositories.core.auth.CertificateCredentials;
import org.eclipse.mylyn.commons.repositories.core.auth.UserCredentials;
import org.eclipse.mylyn.internal.commons.net.CommonsNetPlugin;
import org.eclipse.osgi.service.resolver.VersionRange;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Bundle;

/**
 * @author Steffen Pingel
 */
@SuppressWarnings("restriction")
public class CommonTestUtil {

    public enum PrivilegeLevel {
        ADMIN, ANONYMOUS, GUEST, READ_ONLY, USER
    }

    public static final String KEY_CREDENTIALS_FILE = "mylyn.credentials";

    private static final String KEY_IGNORE_LOCAL_SERVICES = "org.eclipse.mylyn.tests.ignore.local.services";

    private final static int MAX_RETRY = 5;

    /**
     * Returns the given file path with its separator character changed from the given old separator to the given new
     * separator.
     *
     * @param path
     *            a file path
     * @param oldSeparator
     *            a path separator character
     * @param newSeparator
     *            a path separator character
     * @return the file path with its separator character changed from the given old separator to the given new
     *         separator
     */
    public static String changeSeparator(String path, char oldSeparator, char newSeparator) {
        return path.replace(oldSeparator, newSeparator);
    }

    /**
     * Copies the given source file to the given destination file.
     */
    public static void copy(File source, File dest) throws IOException {
        InputStream in = new FileInputStream(source);
        try {
            OutputStream out = new FileOutputStream(dest);
            try {
                transferData(in, out);
            } finally {
                out.close();
            }
        } finally {
            in.close();
        }
    }

    /**
     * Copies all files in the current data directory to the specified folder. Will overwrite.
     */
    public static void copyFolder(File sourceFolder, File targetFolder) throws IOException {
        for (File sourceFile : sourceFolder.listFiles()) {
            if (sourceFile.isFile()) {
                File destFile = new File(targetFolder, sourceFile.getName());
                copy(sourceFile, destFile);
            }
        }
    }

    /**
     * Copies all files in the current data directory to the specified folder. Will overwrite.
     */
    public static void copyFolderRecursively(File sourceFolder, File targetFolder) throws IOException {
        for (File sourceFile : sourceFolder.listFiles()) {
            if (sourceFile.isFile()) {
                File destFile = new File(targetFolder, sourceFile.getName());
                copy(sourceFile, destFile);
            } else if (sourceFile.isDirectory()) {
                File destDir = new File(targetFolder, sourceFile.getName());
                if (!destDir.exists()) {
                    if (!destDir.mkdir()) {
                        throw new IOException("Unable to create destination folder: " + destDir.getAbsolutePath());
                    }
                }
                copyFolderRecursively(sourceFile, destDir);
            }
        }
    }

    public static File createTempFileInPlugin(Plugin plugin, IPath path) {
        IPath stateLocation = plugin.getStateLocation();
        stateLocation = stateLocation.append(path);
        return stateLocation.toFile();
    }

    public static File createTempFolder(String prefix) throws IOException {
        File location = File.createTempFile(prefix, null);
        location.delete();
        location.mkdirs();
        return location;
    }

    public static void delete(File file) {
        if (file.exists()) {
            for (int i = 0; i < MAX_RETRY; i++) {
                if (file.delete()) {
                    i = MAX_RETRY;
                } else {
                    try {
                        Thread.sleep(1000); // sleep a second
                    } catch (InterruptedException e) {
                        // don't need to catch this
                    }
                }
            }
        }
    }

    public static void deleteFolder(File path) {
        if (path.isDirectory()) {
            for (File file : path.listFiles()) {
                file.delete();
            }
            path.delete();
        }
    }

    public static void deleteFolderRecursively(File path) {
        File[] files = path.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    deleteFolderRecursively(file);
                } else {
                    file.delete();
                }
            }
        }
        path.delete();
    }

    public static CertificateCredentials getCertificateCredentials() {
        File keyStoreFile;
        try {
            keyStoreFile = CommonTestUtil.getFile(CommonTestUtil.class, "testdata/keystore");
            String password = CommonTestUtil.getUserCredentials().getPassword();
            return new CertificateCredentials(keyStoreFile.getAbsolutePath(), password, null);
        } catch (IOException cause) {
            AssertionFailedError e = new AssertionFailedError("Failed to load keystore file");
            e.initCause(cause);
            throw e;
        }
    }

    public static boolean hasCredentials(PrivilegeLevel level) {
        try {
            CommonTestUtil.getCredentials(level);
            return true;
        } catch (AssertionFailedError error) {
            return false;
        }
    }

    public static UserCredentials getCredentials(PrivilegeLevel level) {
        return getCredentials(level, null);
    }

    public static UserCredentials getCredentials(PrivilegeLevel level, String realm) {
        Properties properties = new Properties();
        try {
            File file;
            String filename = System.getProperty(KEY_CREDENTIALS_FILE);
            if (filename != null) {
                // 1. use user specified file
                file = new File(filename);
            } else {
                // 2. check in home directory
                file = new File(new File(System.getProperty("user.home"), ".mylyn"), "credentials.properties");
                if (!file.exists()) {
                    // 3. fall back to included credentials file
                    file = getFile(CommonTestUtil.class, "testdata/credentials.properties");
                }
            }
            properties.load(new FileInputStream(file));
        } catch (Exception e) {
            AssertionFailedError error = new AssertionFailedError(
                    "must define credentials in $HOME/.mylyn/credentials.properties");
            error.initCause(e);
            throw error;
        }

        String defaultPassword = properties.getProperty("pass");

        realm = (realm != null) ? realm + "." : "";
        switch (level) {
        case ANONYMOUS:
            return createCredentials(properties, realm + "anon.", "", "");
        case GUEST:
            return createCredentials(properties, realm + "guest.", "guest@mylyn.eclipse.org", defaultPassword);
        case USER:
            return createCredentials(properties, realm, "tests@mylyn.eclipse.org", defaultPassword);
        case READ_ONLY:
            return createCredentials(properties, realm, "read-only@mylyn.eclipse.org", defaultPassword);
        case ADMIN:
            return createCredentials(properties, realm + "admin.", "admin@mylyn.eclipse.org", null);
        }

        throw new AssertionFailedError("invalid privilege level");
    }

    private static boolean isOsgiVersion310orNewer(ClassLoader classLoader) {
        return classLoader.getClass().getName().equals("org.eclipse.osgi.internal.loader.ModuleClassLoader") // user before 4.4M4
                || classLoader.getClass().getName().equals("org.eclipse.osgi.internal.loader.EquinoxClassLoader");
    }

    public static File getFile(Object source, String filename) throws IOException {
        Class<?> clazz = (source instanceof Class<?>) ? (Class<?>) source : source.getClass();
        if (Platform.isRunning()) {
            ClassLoader classLoader = clazz.getClassLoader();
            try {
                if (isOsgiVersion310orNewer(classLoader)) {
                    return checkNotNull(getFileFromClassLoader4Luna(filename, classLoader));
                } else {
                    return checkNotNull(getFileFromClassLoaderBeforeLuna(filename, classLoader));
                }
            } catch (Exception e) {
                AssertionFailedError exception = new AssertionFailedError(
                        NLS.bind("Could not locate {0} using classloader for {1}", filename, clazz));
                exception.initCause(e);
                throw exception;
            }
        } else {
            return getFileFromNotRunningPlatform(filename, clazz);
        }
    }

    private static File getFileFromNotRunningPlatform(String filename, Class<?> clazz)
            throws UnsupportedEncodingException, IOException {
        URL localURL = clazz.getResource("");
        String path = URLDecoder.decode(localURL.getFile(), Charset.defaultCharset().name());
        int i = path.indexOf("!");
        if (i != -1) {
            int j = path.lastIndexOf(File.separatorChar, i);
            if (j != -1) {
                path = path.substring(0, j) + File.separator;
            } else {
                throw new AssertionFailedError(
                        "Unable to determine location for '" + filename + "' at '" + path + "'");
            }
            // class file is nested in jar, use jar path as base
            if (path.startsWith("file:")) {
                path = path.substring(5);
            }
            return new File(path + filename);
        } else {
            // remove all package segments from name
            String directory = clazz.getName().replaceAll("[^.]", "");
            directory = directory.replaceAll(".", "../");
            if (path.contains("/bin/")) {
                // account for bin/ when running from Eclipse workspace
                directory += "../";
            } else if (path.contains("/target/classes/")) {
                // account for bin/ when running from Eclipse workspace
                directory += "../../";
            }
            filename = path + (directory + filename).replaceAll("/", Matcher.quoteReplacement(File.separator));
            return new File(filename).getCanonicalFile();
        }
    }

    private static File getFileFromClassLoaderBeforeLuna(String filename, ClassLoader classLoader)
            throws Exception {
        Object classpathManager = MethodUtils.invokeExactMethod(classLoader, "getClasspathManager", null);
        Object baseData = MethodUtils.invokeExactMethod(classpathManager, "getBaseData", null);
        Bundle bundle = (Bundle) MethodUtils.invokeExactMethod(baseData, "getBundle", null);
        URL localURL = FileLocator.toFileURL(bundle.getEntry(filename));
        return new File(localURL.getFile());
    }

    private static File getFileFromClassLoader4Luna(String filename, ClassLoader classLoader) throws Exception {
        Object classpathManager = MethodUtils.invokeExactMethod(classLoader, "getClasspathManager", null);
        Object generation = MethodUtils.invokeExactMethod(classpathManager, "getGeneration", null);
        Object bundleFile = MethodUtils.invokeExactMethod(generation, "getBundleFile", null);
        File file = (File) MethodUtils.invokeExactMethod(bundleFile, "getFile", new Object[] { filename, true },
                new Class[] { String.class, boolean.class });
        return file;
    }

    public static InputStream getResource(Object source, String filename) throws IOException {
        Class<?> clazz = (source instanceof Class<?>) ? (Class<?>) source : source.getClass();
        ClassLoader classLoader = clazz.getClassLoader();
        InputStream in = classLoader.getResourceAsStream(filename);
        if (in == null) {
            File file = getFile(source, filename);
            if (file != null) {
                return new FileInputStream(file);
            }
        }
        if (in == null) {
            throw new IOException(NLS.bind("Failed to locate ''{0}'' for ''{1}''", filename, clazz.getName()));
        }
        return in;
    }

    public static UserCredentials getUserCredentials() {
        return getCredentials(PrivilegeLevel.USER, null);
    }

    public static String read(File source) throws IOException {
        InputStream in = new FileInputStream(source);
        try {
            StringBuilder sb = new StringBuilder();
            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0) {
                sb.append(new String(buf, 0, len));
            }
            return sb.toString();
        } finally {
            in.close();
        }
    }

    /**
     * Returns whether to run a limited suite of tests. Returns true, unless a system property has been set to force
     * running of all tests.
     */
    public static boolean runHeartbeatTestsOnly() {
        return !Boolean.parseBoolean(System.getProperty("org.eclipse.mylyn.tests.all"));
    }

    /**
     * Unzips the given zip file to the given destination directory extracting only those entries the pass through the
     * given filter.
     *
     * @param zipFile
     *            the zip file to unzip
     * @param dstDir
     *            the destination directory
     * @throws IOException
     *             in case of problem
     */
    public static void unzip(ZipFile zipFile, File dstDir) throws IOException {
        unzip(zipFile, dstDir, dstDir, 0);
    }

    public static void write(String fileName, StringBuffer content) throws IOException {
        Writer writer = new FileWriter(fileName);
        try {
            writer.write(content.toString());
        } finally {
            try {
                writer.close();
            } catch (IOException e) {
                // don't need to catch this
            }
        }
    }

    private static UserCredentials createCredentials(Properties properties, String prefix, String defaultUsername,
            String defaultPassword) {
        String username = properties.getProperty(prefix + "user");
        String password = properties.getProperty(prefix + "pass");

        if (username == null) {
            username = defaultUsername;
        }

        if (password == null) {
            password = defaultPassword;
        }

        if (username == null || password == null) {
            throw new AssertionFailedError("username or password not found for " + prefix
                    + " in <plug-in dir>/credentials.properties, make sure file is valid");
        }

        return new UserCredentials(username, password);
    }

    /**
     * Copies all bytes in the given source stream to the given destination stream. Neither streams are closed.
     *
     * @param source
     *            the given source stream
     * @param destination
     *            the given destination stream
     * @throws IOException
     *             in case of error
     */
    private static void transferData(InputStream in, OutputStream out) throws IOException {
        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
    }

    private static void unzip(ZipFile zipFile, File rootDstDir, File dstDir, int depth) throws IOException {

        Enumeration<? extends ZipEntry> entries = zipFile.entries();

        try {
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                if (entry.isDirectory()) {
                    continue;
                }
                String entryName = entry.getName();
                File file = new File(dstDir, changeSeparator(entryName, '/', File.separatorChar));
                file.getParentFile().mkdirs();
                InputStream src = null;
                OutputStream dst = null;
                try {
                    src = zipFile.getInputStream(entry);
                    dst = new FileOutputStream(file);
                    transferData(src, dst);
                } finally {
                    if (dst != null) {
                        try {
                            dst.close();
                        } catch (IOException e) {
                            // don't need to catch this
                        }
                    }
                    if (src != null) {
                        try {
                            src.close();
                        } catch (IOException e) {
                            // don't need to catch this
                        }
                    }
                }
            }
        } finally {
            try {
                zipFile.close();
            } catch (IOException e) {
                // don't need to catch this
            }
        }
    }

    public static boolean isCertificateAuthBroken() {
        // not entirely correct since 1.6.0_3 would also satisfy this check but it should be sufficient in reality
        return new VersionRange("[0.0.0,1.6.0.25]").isIncluded(CoreUtil.getRuntimeVersion());
    }

    public static boolean hasCertificateCredentials() {
        try {
            CommonTestUtil.getCertificateCredentials();
            return true;
        } catch (AssertionFailedError error) {
            return false;
        }
    }

    public static String getShortUserName(UserCredentials credentials) {
        String username = credentials.getUserName();
        if (username.contains("@")) {
            return username.substring(0, username.indexOf("@"));
        }
        return username;
    }

    /**
     * Activates manual proxy configuration in the Ecipse proxy service if system proxy support is not available. This
     * sets proxy configuration to Java system properties.
     * <p>
     * This work around is required on e3.5/gtk.x86_64 where system proxy settings get enabled but the proxy
     * configuration is not actually detected resulting in a broken configuration.
     * <p>
     * Please note that this only works for http proxies. The https proxy system property is ignored.
     *
     * @see #isHttpsProxyBroken()
     */
    public static boolean fixProxyConfiguration() {
        if (Platform.isRunning() && CommonsNetPlugin.getProxyService() != null
                && CommonsNetPlugin.getProxyService().isSystemProxiesEnabled()
                && !CommonsNetPlugin.getProxyService().hasSystemProxies()) {
            System.err.println("Forcing manual proxy configuration");
            CommonsNetPlugin.getProxyService().setSystemProxiesEnabled(false);
            CommonsNetPlugin.getProxyService().setProxiesEnabled(true);
            return true;
        }
        return false;
    }

    public static void dumpSystemInfo(PrintStream out) {
        Properties p = System.getProperties();
        if (Platform.isRunning()) {
            p.put("build.system", Platform.getOS() + "-" + Platform.getOSArch() + "-" + Platform.getWS());
        } else {
            p.put("build.system", "standalone");
        }
        String info = "System: ${os.name} ${os.version} (${os.arch}) / ${build.system} / ${java.vendor} ${java.vm.name} ${java.version}";
        for (Entry<Object, Object> entry : p.entrySet()) {
            info = info.replaceFirst(Pattern.quote("${" + entry.getKey() + "}"), entry.getValue().toString());
        }
        out.println(info);
        out.print("HTTP Proxy : " + WebUtil.getProxyForUrl("http://mylyn.org") + " (Platform)");
        try {
            out.print(" / " + ProxySelector.getDefault().select(new URI("http://mylyn.org")) + " (Java)");
        } catch (URISyntaxException e) {
            // ignore
        }
        out.println();
        out.print("HTTPS Proxy : " + WebUtil.getProxyForUrl("https://mylyn.org") + " (Platform)");
        try {
            out.print(" / " + ProxySelector.getDefault().select(new URI("https://mylyn.org")) + " (Java)");
        } catch (URISyntaxException e) {
            // ignore
        }
        out.println();
        out.println();
    }

    public static boolean isEclipse4() {
        return Platform.getBundle("org.eclipse.e4.core.commands") != null;
    }

    /**
     * If Eclipse proxy configuration is set to manual https proxies aren't detected and hence tests that rely on https
     * connections may fail. Use this method to detect whether https is configured correctly.
     *
     * @see #fixProxyConfiguration()
     */
    public static boolean isHttpsProxyBroken() {
        // checks if http and https proxy configuration matches
        Proxy httpProxy = WebUtil.getProxyForUrl("http://mylyn.org");
        Proxy httpsProxy = WebUtil.getProxyForUrl("https://mylyn.org");
        return CoreUtil.areEqual(httpProxy, httpsProxy);
    }

    /**
     * Returns whether to run on local services if present. Returns false, unless a system property has been set to
     * force to ignore local running services.
     */
    public static boolean ignoreLocalTestServices() {
        return Boolean.parseBoolean(System.getProperty(KEY_IGNORE_LOCAL_SERVICES));
    }

    public static boolean isBehindProxy() {
        return NetUtil.getProxyForUrl("https://mylyn.org/secure/index.txt") != null;
    }

    public static boolean skipBrowserTests() {
        return Boolean.parseBoolean(System.getProperty("mylyn.test.skipBrowserTests"));
    }

    public static boolean bundleWithNameIsPresent(String name) {
        Bundle bundle = Platform.getBundle(name);
        return bundle != null;
    }

}