org.eclipse.che.commons.test.db.PersistTestModuleBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.che.commons.test.db.PersistTestModuleBuilder.java

Source

/*******************************************************************************
 * Copyright (c) 2012-2017 Codenvy, S.A.
 * 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:
 *   Codenvy, S.A. - initial API and implementation
 *******************************************************************************/
package org.eclipse.che.commons.test.db;

import com.google.common.io.Resources;
import com.google.inject.AbstractModule;
import com.google.inject.Module;
import com.google.inject.persist.jpa.JpaPersistModule;

import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.exceptions.ExceptionHandler;
import org.stringtemplate.v4.ST;

import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import static java.nio.charset.StandardCharsets.UTF_8;

/**
 * Helps to build persistence.xml for test purposes.
 * If bound creates META-INF/persistence.xml with generated content.
 *
 * <p>The example of generated content is:
 * <pre>{@code
 *  // for binding
 *  new PersistTestModuleBuilder().setDriver("org.h2.Driver")
 *                                .addEntityClass(MyEntity.class)
 *                                .addEntityClass(MyEntity2.class)
 *                                .setUrl("jdbc:h2:mem:test")
 *                                .setUser("username")
 *                                .setPassword("secret")
 *                                .build();
 *
 *  // generated persistence.xml
 *  <persistence xmlns="http://java.sun.com/xml/ns/persistence"
 *               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 *               xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_1_0.xsd" version="1.0">
 *      <persistence-unit name="test" transaction-type="RESOURCE_LOCAL">
 *          <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
 *          <class>org.eclipse.che.module.MyEntity</class>
 *          <class>org.eclipse.che.module.MyEntity2</class>
 *          <properties>
 *              <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
 *              <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test"/>
 *              <property name="javax.persistence.jdbc.user" value="username"/>
 *              <property name="javax.persistence.jdbc.password" value="secret"/>
 *          </properties>
 *      </persistence-unit>
 * </persistence>
 * }</pre>
 *
 * @author Yevhenii Voevodin
 */
public class PersistTestModuleBuilder {

    private static final String PERSISTENCE_XML_TEMPLATE_RESOURCE_PATH = "org/eclipse/che/commons/test/db/persistence.xml.template";

    private final Map<String, String> properties = new LinkedHashMap<>();
    private final Set<String> entityFqnSet = new LinkedHashSet<>();

    private String persistenceUnit = "test";

    /**
     * Sets url, user and password equal to the values provided by server.
     */
    public PersistTestModuleBuilder runningOn(DBTestServer server) {
        setUrl(server.getUrl());
        setUser(server.getUser());
        setPassword(server.getPassword());
        return this;
    }

    /**
     * Sets the value of {@value PersistenceUnitProperties#JDBC_DRIVER} property.
     */
    public PersistTestModuleBuilder setDriver(String driver) {
        return setProperty(PersistenceUnitProperties.JDBC_DRIVER, driver);
    }

    /**
     * Sets the value of {@value PersistenceUnitProperties#JDBC_DRIVER} property,
     * the value would be equal to class fqn.
     */
    public PersistTestModuleBuilder setDriver(Class<? extends java.sql.Driver> driverClass) {
        return setDriver(driverClass.getName());
    }

    /**
     * Sets the value of {@value PersistenceUnitProperties#JDBC_URL} property.
     */
    public PersistTestModuleBuilder setUrl(String url) {
        return setProperty(PersistenceUnitProperties.JDBC_URL, url);
    }

    /**
     * Sets the value of {@value PersistenceUnitProperties#JDBC_USER} property.
     */
    public PersistTestModuleBuilder setUser(String user) {
        return setProperty(PersistenceUnitProperties.JDBC_USER, user);
    }

    /**
     * Sets the value of {@value PersistenceUnitProperties#JDBC_PASSWORD} property.
     */
    public PersistTestModuleBuilder setPassword(String password) {
        return setProperty(PersistenceUnitProperties.JDBC_PASSWORD, password);
    }

    /**
     * Sets the value of {@value PersistenceUnitProperties#EXCEPTION_HANDLER_CLASS} property.
     */
    public PersistTestModuleBuilder setExceptionHandler(Class<? extends ExceptionHandler> exHandler) {
        return setProperty(PersistenceUnitProperties.EXCEPTION_HANDLER_CLASS, exHandler.getName());
    }

    /**
     * Adds class to the listing of the entities defined by persistence unit.
     */
    public PersistTestModuleBuilder addEntityClass(Class<?> entityClass) {
        entityFqnSet.add(entityClass.getName());
        return this;
    }

    /**
     * Adds class to the listing of the entities defined by persistence unit.
     */
    public PersistTestModuleBuilder addEntityClass(String fqn) {
        entityFqnSet.add(fqn);
        return this;
    }

    /**
     * Batch add of entity classes to the persistence unit listing.
     */
    public PersistTestModuleBuilder addEntityClasses(Class<?>... entityClasses) {
        for (Class<?> entityClass : entityClasses) {
            addEntityClass(entityClass);
        }
        return this;
    }

    /**
     * Sets persistence unit custom property.
     */
    public PersistTestModuleBuilder setProperty(String name, String value) {
        if (name != null && value != null) {
            properties.put(name, value);
        }
        return this;
    }

    /**
     * Sets the the value of {@link PersistenceUnitProperties#LOGGING_LEVEL} property.
     */
    public PersistTestModuleBuilder setLogLevel(String logLevel) {
        return setProperty(PersistenceUnitProperties.LOGGING_LEVEL, logLevel);
    }

    /**
     * Sets the name of persistence unit.
     */
    public PersistTestModuleBuilder setPersistenceUnit(String persistenceUnit) {
        this.persistenceUnit = persistenceUnit;
        return this;
    }

    /**
     * Creates or overrides META-INF/persistence.xml.
     */
    public Path savePersistenceXml() throws IOException, URISyntaxException {
        Path persistenceXmlPath = getOrCreateMetaInf().resolve("persistence.xml");
        URL url = Thread.currentThread().getContextClassLoader()
                .getResource(PERSISTENCE_XML_TEMPLATE_RESOURCE_PATH);
        if (url == null) {
            throw new IOException("Resource '" + PERSISTENCE_XML_TEMPLATE_RESOURCE_PATH + "' doesn't exist");
        }
        ST st = new ST(Resources.toString(url, UTF_8), '$', '$');
        if (persistenceUnit != null) {
            st.add("unit", persistenceUnit);
        }
        if (!entityFqnSet.isEmpty()) {
            st.add("entity_classes", entityFqnSet);
        }
        if (!properties.isEmpty()) {
            st.add("properties", properties);
        }
        Files.write(persistenceXmlPath, st.render().getBytes(UTF_8));
        return persistenceXmlPath;
    }

    /**
     * Creates persistence.xml and builds module for testing.
     */
    public Module build() {
        return new PersistTestModule();
    }

    private class PersistTestModule extends AbstractModule {
        @Override
        protected void configure() {
            try {
                savePersistenceXml();
            } catch (Exception x) {
                throw new RuntimeException(x.getMessage());
            }
            install(new JpaPersistModule(persistenceUnit));
        }
    }

    private Path getOrCreateMetaInf() throws URISyntaxException, IOException {
        Path root = Paths.get(Thread.currentThread().getContextClassLoader().getResource(".").toURI());
        Path metaInf = root.resolve("META-INF");
        if (!Files.exists(metaInf)) {
            Files.createDirectory(metaInf);
        }
        return metaInf;
    }
}