/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.tomee.embedded.junit;
import org.apache.openejb.util.NetworkUtil;
import org.apache.tomee.embedded.Configuration;
import org.apache.tomee.embedded.Container;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import java.io.File;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import static java.util.Arrays.asList;
public class TomEEEmbeddedRule implements TestRule {
private final Configuration configuration;
private final File docBase;
private boolean resetSystemProperties = true;
private final String context;
private final Collection<Object> injects = new LinkedList<>();
public TomEEEmbeddedRule() {
this(new Configuration().http(NetworkUtil.getNextAvailablePort()).dir(autoDir()), "");
}
public TomEEEmbeddedRule(final Configuration configuration, final String context) {
this.configuration = configuration;
this.context = context;
final File mvnDocBase = new File("src/main/webapp");
if (mvnDocBase.isDirectory()) {
docBase = mvnDocBase;
} else {
docBase = null;
}
}
public TomEEEmbeddedRule(final Configuration configuration, final String context, final File docBase) {
this.configuration = configuration;
this.docBase = docBase;
this.context = context;
}
public TomEEEmbeddedRule injectOn(final Object instance) {
this.injects.add(instance);
return this;
}
public TomEEEmbeddedRule resetSystemPropertiesAfter(final boolean value) {
resetSystemProperties = value;
return this;
}
public TomEEEmbeddedRule stopInjectionOn(final Object instance) {
this.injects.remove(instance);
return this;
}
public Configuration getConfiguration() {
return configuration;
}
public int getPort() {
return configuration.getHttpPort();
}
@Override
public Statement apply(final Statement statement, Description description) {
if (configuration.getDir() == null) {
configuration.dir(autoDir());
}
return new Statement() {
@Override
public void evaluate() throws Throwable {
final Properties properties = new Properties();
if (resetSystemProperties) {
properties.putAll(System.getProperties());
}
try (final Container container = new Container(configuration)
.deployClasspathAsWebApp(context, docBase, toCallers())) {
for (final Object o : injects) {
container.inject(o);
}
statement.evaluate();
} finally {
if (resetSystemProperties) { // issue is we set System Properties like default loader which breaks other tests
System.getProperties().clear();
System.getProperties().putAll(properties);
}
}
}
};
}
private List<String> toCallers() {
if (injects.isEmpty()) {
return null;
}
final Collection<String> callers = new HashSet<>();
for (final Object o : injects) {
callers.add(o.getClass().getName());
}
return new LinkedList<>(callers);
}
private static String autoDir() {
for (final String test : asList("target", "../target", "workdir")) {
final File dir = new File(test);
if (dir.isDirectory()) {
return new File(dir, "tomee-embedded_" + System.identityHashCode(test)).getAbsolutePath();
}
}
return null;
}
}