diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..707a647 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +*.jar +*.war +*.ear + +target +.idea +*.iml +*.ipr +*.iws diff --git a/README.md b/README.md new file mode 100644 index 0000000..4f72ee0 --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +# BeanLoader + +[![release](http://github-release-version.herokuapp.com/github/yandex-qatools/beanloader/release.svg?style=flat)](https://github.com/yandex-qatools/beanloader/releases/latest) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/ru.yandex.qatools.beanloader/beanloader/badge.svg?style=flat)](https://maven-badges.herokuapp.com/maven-central/ru.yandex.qatools.beanloader/beanloader) + +This small library provides an easy fluent API to load xml beans +from different sources via JAXB, giving some of them higher priority +than to the others. + +### Maven + +```xml + + ru.yandex.qatools.beanloader + beanloader + 1.0-SNAPSHOT + +``` + +### Usage + +```java +import static ru.qatools.beanloader.BeanLoaderStrategies.*; +import static ru.qatools.beanloader.BeanLoader.*; + +BeanLoader beanLoader = load(Bean.class) + .from(resource("bean.xml")) + .from(url("http://example.com?get-my-bean-dawg")) + .from(file("~/beans/bean.xml")) + .from(fileWithWatcher("/etc/beans/", "bean.xml")); + +// load bean iterating over the given strategies +// until one of the returns a non-null bean +Bean bean = beanLoader.getBean(); +makeSomeStuff(bean); + +// reload the bean, if reloads are specified for any strategy +// returns the same object if no reloads are specified +bean = beanLoader.getBean(); +makeAnotherStuff(bean); + +``` diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..e1c004d --- /dev/null +++ b/pom.xml @@ -0,0 +1,139 @@ + + + 4.0.0 + + + org.sonatype.oss + oss-parent + 7 + + + ru.yandex.qatools.beanloader + beanloader + 1.0-SNAPSHOT + Yandex QATools BeanLoader + + + scm:git:git@github.com:yandex-qatools/beanloader.git + scm:git:git@github.com:yandex-qatools/beanloader.git + https://github.com/yandex-qatools/beanloader + + + https://github.com/yandex-qatools/beanloader + + + UTF-8 + 1.7 + + + + Yandex + http://company.yandex.com + + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + GitHub Issue Tracker + https://github.com/yandex-qatools/beanloader/issues + + + + Jenkins + http://jenkins.qatools.ru/ + + + + + innokenty + Innokenty Shuvalov + innokenty@yandex-team.ru + Yandex + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.0 + + ${java.version} + ${java.version} + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar + + + + + + org.codehaus.mojo + jaxb2-maven-plugin + 1.6 + + + generate test bean + + testXjc + + + + + ru.qatools.beanloader + src/test/resources + + + + + + + + org.slf4j + slf4j-log4j12 + 1.7.7 + + + junit + junit + 4.11 + test + + + org.hamcrest + hamcrest-all + 1.3 + test + + + ru.yandex.qatools.matchers + matcher-decorators + 1.0 + test + + + com.googlecode.lambdaj + lambdaj + 2.3.3 + test + + + + diff --git a/src/main/java/ru/qatools/beanloader/BeanLoader.java b/src/main/java/ru/qatools/beanloader/BeanLoader.java new file mode 100644 index 0000000..165f68a --- /dev/null +++ b/src/main/java/ru/qatools/beanloader/BeanLoader.java @@ -0,0 +1,40 @@ +package ru.qatools.beanloader; + +import ru.qatools.beanloader.internal.BeanLoadStrategy; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Innokenty Shuvalov innokenty@yandex-team.ru + */ +public class BeanLoader { + + private final List strategies = new ArrayList<>(); + + private final Class beanClass; + + private BeanLoader(Class beanClass) { + this.beanClass = beanClass; + } + + public static BeanLoader load(Class beanClass) { + return new BeanLoader<>(beanClass); + } + + public BeanLoader from(BeanLoadStrategy strategy) { + strategies.add(strategy); + return this; + } + + public T getBean() { + for (BeanLoadStrategy strategy : strategies) { + @SuppressWarnings("unchecked") + T bean = (T) strategy.getBeanAs(beanClass); + if (bean != null) { + return bean; + } + } + return null; + } +} diff --git a/src/main/java/ru/qatools/beanloader/BeanLoaderStrategies.java b/src/main/java/ru/qatools/beanloader/BeanLoaderStrategies.java new file mode 100644 index 0000000..395a2b4 --- /dev/null +++ b/src/main/java/ru/qatools/beanloader/BeanLoaderStrategies.java @@ -0,0 +1,49 @@ +package ru.qatools.beanloader; + +import ru.qatools.beanloader.internal.*; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; + +/** + * @author Innokenty Shuvalov innokenty@yandex-team.ru + */ +public abstract class BeanLoaderStrategies { + + public static FileLoadStrategy file(String filename) { + return file(filename, false); + } + + public static FileLoadStrategy file(String filename, boolean reloadEveryTime) { + return file(new File(filename), reloadEveryTime); + } + + public static FileLoadStrategy file(File file, boolean reloadEveryTime) { + return new FileLoadStrategy(file, reloadEveryTime); + } + + public static FileWithWatcherLoadStrategy fileWithWatcher(String directoryToWatch, String fileToWatch) { + return new FileWithWatcherLoadStrategy(directoryToWatch, fileToWatch); + } + + public static UrlLoadStrategy url(URL url) { + return url(url, false); + } + + static BeanLoadStrategy url(String url) throws MalformedURLException { + return url(new URL(url)); + } + + static BeanLoadStrategy url(String url, boolean reloadEveryTime) throws MalformedURLException { + return url(new URL(url), reloadEveryTime); + } + + public static UrlLoadStrategy url(URL url, boolean reloadEveryTime) { + return new UrlLoadStrategy(url, reloadEveryTime); + } + + public static ResourceLoadStrategy resource(String resource) { + return new ResourceLoadStrategy(resource); + } +} diff --git a/src/main/java/ru/qatools/beanloader/internal/BeanLoadStrategy.java b/src/main/java/ru/qatools/beanloader/internal/BeanLoadStrategy.java new file mode 100644 index 0000000..129443f --- /dev/null +++ b/src/main/java/ru/qatools/beanloader/internal/BeanLoadStrategy.java @@ -0,0 +1,61 @@ +package ru.qatools.beanloader.internal; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.bind.DataBindingException; + +/** + * This class could be generified but it is not. The purpose of that is + * to increase the 'fluency' of the {@link ru.qatools.beanloader.BeanLoader} API. Note that + * with the proper usage through BeanLoader this code can not lead to any + * ClassCastExceptions, although it is not fully generified and has class casts + * in the code. This is fine because the BeanLoader itself is generified properly. + * + * @author Innokenty Shuvalov innokenty@yandex-team.ru + */ +public abstract class BeanLoadStrategy { + + protected final Logger logger = LoggerFactory.getLogger(getClass()); + + private Object bean; + private boolean loaded; + + public Object getBeanAs(Class beanClass) { + if (!loaded || reloadEveryTime()) { + loadBean(beanClass); + } + return bean; + } + + protected void loadBean(Class beanClass) { + loaded = true; + logger.trace("trying to load bean from " + getSourceDescription()); + if (!canUnmarshal()) { + logger.trace("source does not exist, aborting"); + return; + } + + try { + logger.trace("source exists, trying to unmarshal"); + bean = performUnmarshal(beanClass); + logger.trace("successfully unmarshalled"); + } catch (DataBindingException e) { + logUnmarshallingException(e, getSourceDescription()); + } + } + + private void logUnmarshallingException(Exception e, String sourceDescription) { + if (logger.isDebugEnabled()) { + logger.error("exception caught while unmarshalling from " + sourceDescription, e); + } else { + logger.error(String.format("exception caught while unmarshalling from %s: %s", + sourceDescription, e.getMessage())); + } + } + + protected abstract boolean canUnmarshal(); + protected abstract boolean reloadEveryTime(); + protected abstract Object performUnmarshal(Class beanClass); + protected abstract String getSourceDescription(); +} diff --git a/src/main/java/ru/qatools/beanloader/internal/FileLoadStrategy.java b/src/main/java/ru/qatools/beanloader/internal/FileLoadStrategy.java new file mode 100644 index 0000000..a74609b --- /dev/null +++ b/src/main/java/ru/qatools/beanloader/internal/FileLoadStrategy.java @@ -0,0 +1,38 @@ +package ru.qatools.beanloader.internal; + +import javax.xml.bind.JAXB; +import java.io.File; + +/** + * @author Innokenty Shuvalov innokenty@yandex-team.ru + */ +public class FileLoadStrategy extends BeanLoadStrategy { + + private final File file; + private final boolean reload; + + public FileLoadStrategy(File file, boolean reload) { + super(); + this.file = file; + this.reload = reload; + } + + @Override + protected boolean canUnmarshal() { + return file.exists(); + } + + protected boolean reloadEveryTime() { + return reload; + } + + @Override + protected Object performUnmarshal(Class beanClass) { + return JAXB.unmarshal(file, beanClass); + } + + @Override + protected String getSourceDescription() { + return "file '" + file.getPath() + "'"; + } +} diff --git a/src/main/java/ru/qatools/beanloader/internal/FileWatcher.java b/src/main/java/ru/qatools/beanloader/internal/FileWatcher.java new file mode 100644 index 0000000..38c552e --- /dev/null +++ b/src/main/java/ru/qatools/beanloader/internal/FileWatcher.java @@ -0,0 +1,66 @@ +package ru.qatools.beanloader.internal; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.file.*; + +/** + * @author Innokenty Shuvalov innokenty@yandex-team.ru + * @author Dmitry Baev charlie@yandex-team.ru + */ +public class FileWatcher implements Runnable { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final BeanLoadStrategy loadStrategy; + private final Class beanClass; + private final String directory; + private final String file; + + public FileWatcher(BeanLoadStrategy loadStrategy, Class beanClass, + String directory, String file) { + this.loadStrategy = loadStrategy; + this.beanClass = beanClass; + this.directory = directory; + this.file = file; + } + + @Override + public void run() { + Path directory = Paths.get(this.directory); + try (WatchService service = FileSystems.getDefault().newWatchService()) { + directory.register(service, StandardWatchEventKinds.ENTRY_MODIFY); + watch(service); + } catch (IOException e) { + logger.error("Can't create watch service for directory " + this.directory, e); + } catch (InterruptedException e) { + logger.warn("oops, thread was interrupted"); + } + } + + private void watch(WatchService service) throws InterruptedException { + logger.info("Watching for changes in directory " + directory); + //noinspection all + while (true) { + WatchKey key = service.take(); + handleKey(key); + key.reset(); + } + } + + private void handleKey(WatchKey key) { + for (WatchEvent event : key.pollEvents()) { + Path path = (Path) event.context(); + if (path.toAbsolutePath().endsWith(file)) { + logger.info("file '" + file + "' changed"); + invokeFileReload(); + } + } + } + + protected void invokeFileReload() { + loadStrategy.loadBean(beanClass); + } +} diff --git a/src/main/java/ru/qatools/beanloader/internal/FileWithWatcherLoadStrategy.java b/src/main/java/ru/qatools/beanloader/internal/FileWithWatcherLoadStrategy.java new file mode 100644 index 0000000..e9e0f56 --- /dev/null +++ b/src/main/java/ru/qatools/beanloader/internal/FileWithWatcherLoadStrategy.java @@ -0,0 +1,47 @@ +package ru.qatools.beanloader.internal; + +import java.io.File; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @author Innokenty Shuvalov innokenty@yandex-team.ru + */ +public class FileWithWatcherLoadStrategy extends FileLoadStrategy { + + private final String directory; + private final String file; + + private boolean fileWatcherInitialized; + + private ExecutorService executor; + + public FileWithWatcherLoadStrategy(String directory, String file) { + super(new File(directory, file), false); + this.directory = directory; + this.file = file; + } + + @Override + protected synchronized void loadBean(Class beanClass) { + super.loadBean(beanClass); + if (!fileWatcherInitialized) { + initFileWatcher(beanClass); + fileWatcherInitialized = true; + } + } + + private void initFileWatcher(Class beanClass) { + executor = Executors.newSingleThreadExecutor(); + executor.execute(new FileWatcher(this, beanClass, directory, file)); + executor.shutdown(); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + if (executor != null) { + executor.shutdownNow(); + } + } +} diff --git a/src/main/java/ru/qatools/beanloader/internal/ResourceLoadStrategy.java b/src/main/java/ru/qatools/beanloader/internal/ResourceLoadStrategy.java new file mode 100644 index 0000000..d93daaa --- /dev/null +++ b/src/main/java/ru/qatools/beanloader/internal/ResourceLoadStrategy.java @@ -0,0 +1,19 @@ +package ru.qatools.beanloader.internal; + +/** + * @author Innokenty Shuvalov innokenty@yandex-team.ru + */ +public class ResourceLoadStrategy extends UrlLoadStrategy { + + private final String resource; + + public ResourceLoadStrategy(String resource) { + super(ResourceLoadStrategy.class.getClassLoader().getResource(resource), false); + this.resource = resource; + } + + @Override + protected String getSourceDescription() { + return "resource '" + resource + "'"; + } +} diff --git a/src/main/java/ru/qatools/beanloader/internal/UrlLoadStrategy.java b/src/main/java/ru/qatools/beanloader/internal/UrlLoadStrategy.java new file mode 100644 index 0000000..1eafd3a --- /dev/null +++ b/src/main/java/ru/qatools/beanloader/internal/UrlLoadStrategy.java @@ -0,0 +1,37 @@ +package ru.qatools.beanloader.internal; + +import javax.xml.bind.JAXB; +import java.net.URL; + +/** + * @author Innokenty Shuvalov innokenty@yandex-team.ru + */ +public class UrlLoadStrategy extends BeanLoadStrategy { + + protected final URL url; + private final boolean reload; + + public UrlLoadStrategy(URL url, boolean reload) { + super(); + this.url = url; + this.reload = reload; + } + + protected boolean canUnmarshal() { + return url != null; + } + + protected boolean reloadEveryTime() { + return reload; + } + + @Override + protected Object performUnmarshal(Class beanClass) { + return JAXB.unmarshal(url, beanClass); + } + + @Override + protected String getSourceDescription() { + return url.toString(); + } +} diff --git a/src/test/java/ru/qatools/beanloader/BeanAssert.java b/src/test/java/ru/qatools/beanloader/BeanAssert.java new file mode 100644 index 0000000..85d0cb8 --- /dev/null +++ b/src/test/java/ru/qatools/beanloader/BeanAssert.java @@ -0,0 +1,95 @@ +package ru.qatools.beanloader; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; +import ru.qatools.beanloader.internal.BeanLoadStrategy; + +import java.io.File; + +import static javax.xml.bind.JAXB.marshal; +import static javax.xml.bind.JAXB.unmarshal; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.assertThat; +import static ru.qatools.beanloader.BeanLoader.load; +import static ru.yandex.qatools.matchers.decorators.MatcherDecorators.should; +import static ru.yandex.qatools.matchers.decorators.MatcherDecorators.timeoutHasExpired; + +/** + * @author Innokenty Shuvalov innokenty@yandex-team.ru + */ +public class BeanAssert { + + public static final String RESOURCES_DIR = "src/test/resources/"; + public static final String BEAN_XML_NAME = "bean.xml"; + public static final String BEAN_XML_PATH = RESOURCES_DIR + BEAN_XML_NAME; + public static final String BEAN_XML_URL = "file:" + BEAN_XML_PATH; + public static final File BEAN_XML_FILE = new File(BEAN_XML_PATH); + + private final String actualValue = getActualValue(); + + private final BeanLoader loader; + + public BeanAssert(BeanLoadStrategy strategy) { + this(load(Bean.class).from(strategy)); + } + + public BeanAssert(BeanLoader beanLoader) { + loader = beanLoader; + } + + public static String getActualValue() { + return unmarshal(BEAN_XML_FILE, Bean.class).getValue(); + } + + public static void setActualValue(String value) { + setActualValue(value, BEAN_XML_FILE); + } + + public static void setActualValue(String value, File file) { + Bean bean = new Bean(); + bean.setValue(value); + marshal(bean, file); + } + + public void isNull() { + assertThat(loader.getBean(), is(nullValue())); + } + + public void valueIsEqualTo(String value) { + assertThat(loader.getBean().getValue(), equalTo(value)); + } + + public void valueIsEqualToActual() { + valueIsEqualTo(actualValue); + } + + public void valueHasNotChanged() { + valueIsEqualToActual(); + } + + public void waitUntilValueIsEqualTo(String value) { + assertThat(loader, should(haveBeanWith(value)) + .whileWaitingUntil(timeoutHasExpired(60000))); + } + + private Matcher> haveBeanWith(final String value) { + return new TypeSafeMatcher>() { + + @Override + protected boolean matchesSafely(BeanLoader item) { + return item.getBean().getValue().equals(value); + } + + @Override + protected void describeMismatchSafely(BeanLoader item, Description description) { + description.appendText("bean with value = " + item.getBean().getValue()); + } + + @Override + public void describeTo(Description description) { + description.appendText("bean with value = " + value); + } + }; + } +} diff --git a/src/test/java/ru/qatools/beanloader/BeanChangingTest.java b/src/test/java/ru/qatools/beanloader/BeanChangingTest.java new file mode 100644 index 0000000..d843862 --- /dev/null +++ b/src/test/java/ru/qatools/beanloader/BeanChangingTest.java @@ -0,0 +1,25 @@ +package ru.qatools.beanloader; + +import org.junit.After; +import org.junit.Before; + +import static ru.qatools.beanloader.BeanAssert.getActualValue; +import static ru.qatools.beanloader.BeanAssert.setActualValue; + +/** + * @author Innokenty Shuvalov innokenty@yandex-team.ru + */ +public abstract class BeanChangingTest { + + private String actualValueAtTheBeginningOfTheTest; + + @Before + public void setUp() throws Exception { + actualValueAtTheBeginningOfTheTest = getActualValue(); + } + + @After + public void tearDown() throws Exception { + setActualValue(actualValueAtTheBeginningOfTheTest); + } +} diff --git a/src/test/java/ru/qatools/beanloader/BeanLoaderTest.java b/src/test/java/ru/qatools/beanloader/BeanLoaderTest.java new file mode 100644 index 0000000..bb248b9 --- /dev/null +++ b/src/test/java/ru/qatools/beanloader/BeanLoaderTest.java @@ -0,0 +1,61 @@ +package ru.qatools.beanloader; + +import org.junit.Test; + +import java.io.File; + +import static ru.qatools.beanloader.BeanAssert.*; +import static ru.qatools.beanloader.BeanLoader.load; +import static ru.qatools.beanloader.BeanLoaderStrategies.*; + +/** + * @author Innokenty Shuvalov innokenty@yandex-team.ru + */ +public class BeanLoaderTest { + + @Test + public void testLoadFromTheFirstStrategy() { + BeanAssert assertBean = new BeanAssert(load(Bean.class) + .from(resource(BEAN_XML_NAME)) + .from(file("non existing file"))); + assertBean.valueIsEqualToActual(); + assertBean.valueIsEqualToActual(); + } + + @Test + public void testLoadFromTheSecondStrategy() { + BeanAssert assertBean = new BeanAssert(load(Bean.class) + .from(resource("non existing resource")) + .from(file(BEAN_XML_PATH))); + assertBean.valueIsEqualToActual(); + assertBean.valueIsEqualToActual(); + } + + @Test + public void testLoadWhenAllStrategiesFail() throws Exception { + BeanAssert assertBean = new BeanAssert(load(Bean.class) + .from(url("file:non existing file")) + .from(resource("non existing resource")) + .from(file("non existing file"))); + assertBean.isNull(); + assertBean.isNull(); + } + + @Test + public void testReloadFromDifferentStrategy() { + File anotherFile = new File(RESOURCES_DIR + "bean1.xml"); + + BeanAssert assertBean = new BeanAssert(load(Bean.class) + .from(file(anotherFile, true)) + .from(resource(BEAN_XML_NAME))); + assertBean.valueIsEqualToActual(); + assertBean.valueIsEqualToActual(); + + String anotherValue = "another value"; + setActualValue(anotherValue, anotherFile); + anotherFile.deleteOnExit(); + + assertBean.valueIsEqualTo(anotherValue); + assertBean.valueIsEqualTo(anotherValue); + } +} diff --git a/src/test/java/ru/qatools/beanloader/FileWatcherTest.java b/src/test/java/ru/qatools/beanloader/FileWatcherTest.java new file mode 100644 index 0000000..fd825a4 --- /dev/null +++ b/src/test/java/ru/qatools/beanloader/FileWatcherTest.java @@ -0,0 +1,54 @@ +package ru.qatools.beanloader; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; +import org.junit.Test; +import ru.qatools.beanloader.internal.FileWatcher; + +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static ru.qatools.beanloader.BeanAssert.*; +import static ru.yandex.qatools.matchers.decorators.MatcherDecorators.should; +import static ru.yandex.qatools.matchers.decorators.MatcherDecorators.timeoutHasExpired; + +/** + * @author Innokenty Shuvalov innokenty@yandex-team.ru + */ +public class FileWatcherTest extends BeanChangingTest { + + @Test + public void testFileWatcher() throws Exception { + final AtomicBoolean unmarshalInvoked = new AtomicBoolean(false); + FileWatcher watcher = new FileWatcher(null, null, RESOURCES_DIR, BEAN_XML_NAME) { + @Override + protected void invokeFileReload() { + unmarshalInvoked.getAndSet(true); + } + }; + Executors.newSingleThreadExecutor().submit(watcher); + + Thread.sleep(1000); + assertFalse(unmarshalInvoked.get()); + setActualValue("another " + getActualValue()); + assertThat(unmarshalInvoked, should(beTrue()) + .whileWaitingUntil(timeoutHasExpired(60000))); + } + + private static Matcher beTrue() { + return new TypeSafeMatcher() { + @Override + protected boolean matchesSafely(AtomicBoolean item) { + return item.get(); + } + + @Override + public void describeTo(Description description) { + description.appendText(""); + } + }; + } +} diff --git a/src/test/java/ru/qatools/beanloader/FileWithWatcherLoadStrategyTest.java b/src/test/java/ru/qatools/beanloader/FileWithWatcherLoadStrategyTest.java new file mode 100644 index 0000000..999deaa --- /dev/null +++ b/src/test/java/ru/qatools/beanloader/FileWithWatcherLoadStrategyTest.java @@ -0,0 +1,25 @@ +package ru.qatools.beanloader; + +import org.junit.Test; + +import static ru.qatools.beanloader.BeanAssert.*; +import static ru.qatools.beanloader.BeanLoaderStrategies.fileWithWatcher; + +/** + * @author Innokenty Shuvalov innokenty@yandex-team.ru + */ +public class FileWithWatcherLoadStrategyTest extends BeanChangingTest { + + @Test + public void testFileWatcher() throws Exception { + BeanAssert assertBean + = new BeanAssert(fileWithWatcher(RESOURCES_DIR, BEAN_XML_NAME)); + + assertBean.valueIsEqualToActual(); + Thread.sleep(1000); + String newValue = "another " + getActualValue(); + setActualValue(newValue); + assertBean.valueHasNotChanged(); + assertBean.waitUntilValueIsEqualTo(newValue); + } +} diff --git a/src/test/java/ru/qatools/beanloader/LoadStrategiesTest.java b/src/test/java/ru/qatools/beanloader/LoadStrategiesTest.java new file mode 100644 index 0000000..762d9a4 --- /dev/null +++ b/src/test/java/ru/qatools/beanloader/LoadStrategiesTest.java @@ -0,0 +1,79 @@ +package ru.qatools.beanloader; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import ru.qatools.beanloader.internal.*; + +import java.net.MalformedURLException; +import java.util.Arrays; +import java.util.Collection; + +import static ru.qatools.beanloader.BeanAssert.*; +import static ru.qatools.beanloader.BeanLoaderStrategies.*; + +/** + * @author Innokenty Shuvalov innokenty@yandex-team.ru + */ +@RunWith(Parameterized.class) +public class LoadStrategiesTest { + + @Parameters(name = "{2}") + public static Collection data() throws MalformedURLException { + return Arrays.asList(new Object[][]{ + { + resource(BEAN_XML_NAME), + resource("non existing file"), + ResourceLoadStrategy.class.getSimpleName() + }, + { + file(BEAN_XML_PATH), + file("non existing file"), + FileLoadStrategy.class.getSimpleName() + }, + { + file(BEAN_XML_PATH, true), + file("non existing file", true), + FileLoadStrategy.class.getSimpleName() + " with reload" + }, + { + fileWithWatcher(RESOURCES_DIR, BEAN_XML_NAME), + fileWithWatcher("non existing directory", "non existing file"), + FileWithWatcherLoadStrategy.class.getSimpleName() + }, + { + url(BEAN_XML_URL), + url("file:non existing file"), + UrlLoadStrategy.class.getSimpleName() + }, + { + url(BEAN_XML_URL, true), + url("file:non existing file", true), + UrlLoadStrategy.class.getSimpleName() + " with reload" + }, + }); + } + + private final BeanAssert assertExistingBean; + private final BeanAssert assertAbsentBean; + + public LoadStrategiesTest(BeanLoadStrategy existingBeanStrategy, + BeanLoadStrategy absentBeanStrategy, + @SuppressWarnings("UnusedParameters") String name) { + assertExistingBean = new BeanAssert(existingBeanStrategy); + assertAbsentBean = new BeanAssert(absentBeanStrategy); + } + + @Test + public void testWithExistingBean() { + assertExistingBean.valueIsEqualToActual(); + assertExistingBean.valueIsEqualToActual(); + } + + @Test + public void testWithNotExistingBean() { + assertAbsentBean.isNull(); + assertAbsentBean.isNull(); + } +} diff --git a/src/test/java/ru/qatools/beanloader/ReloadStrategiesTest.java b/src/test/java/ru/qatools/beanloader/ReloadStrategiesTest.java new file mode 100644 index 0000000..dd1de12 --- /dev/null +++ b/src/test/java/ru/qatools/beanloader/ReloadStrategiesTest.java @@ -0,0 +1,81 @@ +package ru.qatools.beanloader; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import ru.qatools.beanloader.internal.*; + +import java.net.MalformedURLException; +import java.util.Arrays; +import java.util.Collection; + +import static ru.qatools.beanloader.BeanAssert.*; +import static ru.qatools.beanloader.BeanLoaderStrategies.*; + +/** + * @author Innokenty Shuvalov innokenty@yandex-team.ru + */ +@RunWith(Parameterized.class) +public class ReloadStrategiesTest extends BeanChangingTest { + + @Parameters(name = "{2}") + public static Collection data() throws MalformedURLException { + return Arrays.asList(new Object[][]{ + { + resource(BEAN_XML_NAME), + false, + ResourceLoadStrategy.class.getSimpleName() + }, + { + file(BEAN_XML_PATH), + false, + FileLoadStrategy.class.getSimpleName() + }, + { + file(BEAN_XML_PATH, true), + true, + FileLoadStrategy.class.getSimpleName() + " with reload" + }, + { + fileWithWatcher(RESOURCES_DIR, BEAN_XML_NAME), + false, + FileWithWatcherLoadStrategy.class.getSimpleName() + }, + { + url(BEAN_XML_URL), + false, + UrlLoadStrategy.class.getSimpleName() + }, + { + url(BEAN_XML_URL, true), + true, + UrlLoadStrategy.class.getSimpleName() + " with reload" + }, + }); + } + + private final BeanAssert assertBean; + private final boolean mustUpdate; + + public ReloadStrategiesTest(BeanLoadStrategy existingBeanStrategy, + boolean mustUpdate, + @SuppressWarnings("UnusedParameters") String name) { + this.mustUpdate = mustUpdate; + this.assertBean = new BeanAssert(existingBeanStrategy); + } + + @Test + public void testBeanUpdates() { + assertBean.valueIsEqualToActual(); + String newValue = "another " + getActualValue(); + setActualValue(newValue); + if (mustUpdate) { + assertBean.valueIsEqualTo(newValue); + assertBean.valueIsEqualTo(newValue); + } else { + assertBean.valueHasNotChanged(); + assertBean.valueHasNotChanged(); + } + } +} diff --git a/src/test/resources/bean.xml b/src/test/resources/bean.xml new file mode 100644 index 0000000..3364c49 --- /dev/null +++ b/src/test/resources/bean.xml @@ -0,0 +1,2 @@ + + diff --git a/src/test/resources/bean.xsd b/src/test/resources/bean.xsd new file mode 100644 index 0000000..5d79244 --- /dev/null +++ b/src/test/resources/bean.xsd @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties new file mode 100644 index 0000000..f7aab7c --- /dev/null +++ b/src/test/resources/log4j.properties @@ -0,0 +1,9 @@ +# suppress inspection "UnusedProperty" for whole file +log4j.rootLogger = TRACE, CONSOLE + +log4j.category.org.apache.commons.beanutils = WARN + +# CONSOLE +log4j.appender.CONSOLE = org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.layout = org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.ConversionPattern = %-4r %-5p %c %x - %m%n