org.jboss.as.embedded.EmbeddedStandAloneServerFactory Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source.
* Copyright 2010, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.embedded;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.jboss.as.controller.ModelController;
import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.as.controller.client.helpers.standalone.DeploymentPlan;
import org.jboss.as.controller.client.helpers.standalone.ServerDeploymentManager;
import org.jboss.as.controller.client.helpers.standalone.ServerDeploymentPlanResult;
import org.jboss.as.embedded.logging.EmbeddedLogger;
import org.jboss.as.protocol.StreamUtils;
import org.jboss.as.server.Bootstrap;
import org.jboss.as.server.Main;
import org.jboss.as.server.ServerEnvironment;
import org.jboss.as.server.logging.ServerLogger;
import org.jboss.as.server.Services;
import org.jboss.as.server.deployment.client.ModelControllerServerDeploymentManager;
import org.jboss.modules.ModuleLoader;
import org.jboss.msc.service.ServiceActivator;
import org.jboss.msc.service.ServiceContainer;
import org.jboss.msc.service.ServiceController;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.value.Value;
import org.jboss.vfs.VFS;
import org.jboss.vfs.VFSUtils;
/**
* This is the counter-part of EmbeddedServerFactory which lives behind a module class loader.
*
* ServerFactory that sets up a standalone server using modular classloading.
*
*
* To use this class the jboss.home.dir
system property must be set to the
* application server home directory. By default it will use the directories
* {$jboss.home.dir}/standalone/config
as the configuration directory and
* {$jboss.home.dir}/standalone/data
as the data directory. This can be overridden
* with the ${jboss.server.base.dir}
, ${jboss.server.config.dir}
or ${jboss.server.config.dir}
* system properties as for normal server startup.
*
*
* If a clean run is wanted, you can specify ${jboss.embedded.root}
to an existing directory
* which will copy the contents of the data and configuration directories under a temporary folder. This
* has the effect of this run not polluting later runs of the embedded server.
*
*
* @author Kabir Khan
* @author [email protected]
* @see org.jboss.as.embedded.EmbeddedServerFactory
*/
public class EmbeddedStandAloneServerFactory {
public static final String JBOSS_EMBEDDED_ROOT = "jboss.embedded.root";
private EmbeddedStandAloneServerFactory() {
}
public static StandaloneServer create(final File jbossHomeDir, final ModuleLoader moduleLoader, final Properties systemProps, final Map systemEnv, final String[] cmdargs) {
if (jbossHomeDir == null)
throw EmbeddedLogger.ROOT_LOGGER.nullVar("jbossHomeDir");
if (moduleLoader == null)
throw EmbeddedLogger.ROOT_LOGGER.nullVar("moduleLoader");
if (systemProps == null)
throw EmbeddedLogger.ROOT_LOGGER.nullVar("systemProps");
if (systemEnv == null)
throw EmbeddedLogger.ROOT_LOGGER.nullVar("systemEnv");
if (cmdargs == null)
throw EmbeddedLogger.ROOT_LOGGER.nullVar("cmdargs");
setupCleanDirectories(jbossHomeDir, systemProps);
StandaloneServer standaloneServer = new StandaloneServer() {
private ServiceContainer serviceContainer;
private ServerDeploymentManager serverDeploymentManager;
private Context context;
private ModelControllerClient modelControllerClient;
@Override
public void deploy(File file) throws IOException, ExecutionException, InterruptedException {
// the current deployment manager only accepts jar input stream, so hack one together
final InputStream is = VFSUtils.createJarFileInputStream(VFS.getChild(file.toURI()));
try {
execute(serverDeploymentManager.newDeploymentPlan().add(file.getName(), is).andDeploy().build());
} finally {
if(is != null) try {
is.close();
} catch (IOException ignore) {
//
}
}
}
private ServerDeploymentPlanResult execute(DeploymentPlan deploymentPlan) throws ExecutionException, InterruptedException {
return serverDeploymentManager.execute(deploymentPlan).get();
}
@Override
public Context getContext() {
if (context == null) {
throw ServerLogger.ROOT_LOGGER.namingContextHasNotBeenSet();
}
return context;
}
@Override
public ModelControllerClient getModelControllerClient() {
return modelControllerClient;
}
@Override
public void start() throws ServerStartException {
try {
// Determine the ServerEnvironment
ServerEnvironment serverEnvironment = Main.determineEnvironment(cmdargs, systemProps, systemEnv, ServerEnvironment.LaunchType.EMBEDDED);
Bootstrap bootstrap = Bootstrap.Factory.newInstance();
Bootstrap.Configuration configuration = new Bootstrap.Configuration(serverEnvironment);
/*
* This would setup an {@link TransientConfigurationPersister} which does not persist anything
*
final ExtensionRegistry extensionRegistry = configuration.getExtensionRegistry();
final Bootstrap.ConfigurationPersisterFactory configurationPersisterFactory = new Bootstrap.ConfigurationPersisterFactory() {
@Override
public ExtensibleConfigurationPersister createConfigurationPersister(ServerEnvironment serverEnvironment, ExecutorService executorService) {
final QName rootElement = new QName(Namespace.CURRENT.getUriString(), "server");
final StandaloneXml parser = new StandaloneXml(Module.getBootModuleLoader(), executorService, extensionRegistry);
final File configurationFile = serverEnvironment.getServerConfigurationFile().getBootFile();
XmlConfigurationPersister persister = new TransientConfigurationPersister(configurationFile, rootElement, parser, parser);
for (Namespace namespace : Namespace.domainValues()) {
if (!namespace.equals(Namespace.CURRENT)) {
persister.registerAdditionalRootElement(new QName(namespace.getUriString(), "server"), parser);
}
}
extensionRegistry.setWriterRegistry(persister);
return persister;
}
};
configuration.setConfigurationPersisterFactory(configurationPersisterFactory);
*/
configuration.setModuleLoader(moduleLoader);
Future future = bootstrap.startup(configuration, Collections.emptyList());
serviceContainer = future.get();
@SuppressWarnings("unchecked")
final Value controllerService = (Value) serviceContainer.getRequiredService(Services.JBOSS_SERVER_CONTROLLER);
final ModelController controller = controllerService.getValue();
serverDeploymentManager = new ModelControllerServerDeploymentManager(controller);
modelControllerClient = controller.createClient(Executors.newCachedThreadPool());
context = new InitialContext();
} catch (RuntimeException rte) {
throw rte;
} catch (Exception ex) {
throw EmbeddedLogger.ROOT_LOGGER.cannotStartEmbeddedServer(ex);
}
}
@Override
public void stop() {
if (context != null) {
try {
context.close();
context = null;
} catch (NamingException e) {
// TODO: use logging?
e.printStackTrace();
}
}
serverDeploymentManager = null;
if (serviceContainer != null) {
try {
serviceContainer.shutdown();
serviceContainer.awaitTermination();
} catch (RuntimeException rte) {
throw rte;
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
@Override
public void undeploy(File file) throws ExecutionException, InterruptedException {
execute(serverDeploymentManager.newDeploymentPlan()
.undeploy(file.getName()).andRemoveUndeployed()
.build());
}
@Override
public ServiceController> getService(ServiceName serviceName) {
return serviceContainer != null ? serviceContainer.getService(serviceName) : null;
}
};
return standaloneServer;
}
static void setupCleanDirectories(Properties props) {
File jbossHomeDir = new File(props.getProperty(ServerEnvironment.HOME_DIR));
setupCleanDirectories(jbossHomeDir, props);
}
static void setupCleanDirectories(File jbossHomeDir, Properties props) {
File tempRoot = getTempRoot(props);
if (tempRoot == null) {
return;
}
File originalConfigDir = getFileUnderAsRoot(jbossHomeDir, props, ServerEnvironment.SERVER_CONFIG_DIR, "configuration", true);
File originalDataDir = getFileUnderAsRoot(jbossHomeDir, props, ServerEnvironment.SERVER_DATA_DIR, "data", false);
File configDir = new File(tempRoot, "config");
configDir.mkdir();
File dataDir = new File(tempRoot, "data");
dataDir.mkdir();
// For jboss.server.deployment.scanner.default
File deploymentsDir = new File(tempRoot, "deployments");
deploymentsDir.mkdir();
copyDirectory(originalConfigDir, configDir);
if (originalDataDir.exists()) {
copyDirectory(originalDataDir, dataDir);
}
props.put(ServerEnvironment.SERVER_BASE_DIR, tempRoot.getAbsolutePath());
props.put(ServerEnvironment.SERVER_CONFIG_DIR, configDir.getAbsolutePath());
props.put(ServerEnvironment.SERVER_DATA_DIR, dataDir.getAbsolutePath());
}
private static File getFileUnderAsRoot(File jbossHomeDir, Properties props, String propName, String relativeLocation, boolean mustExist) {
String prop = props.getProperty(propName, null);
if (prop == null) {
prop = props.getProperty(ServerEnvironment.SERVER_BASE_DIR, null);
if (prop == null) {
File dir = new File(jbossHomeDir, "standalone" + File.separator + relativeLocation);
if (mustExist && (!dir.exists() || !dir.isDirectory())) {
throw ServerLogger.ROOT_LOGGER.embeddedServerDirectoryNotFound("standalone" + File.separator + relativeLocation, jbossHomeDir.getAbsolutePath());
}
return dir;
} else {
File server = new File(prop);
validateDirectory(ServerEnvironment.SERVER_BASE_DIR, server);
return new File(server, relativeLocation);
}
} else {
File dir = new File(prop);
validateDirectory(ServerEnvironment.SERVER_CONFIG_DIR, dir);
return dir;
}
}
private static File getTempRoot(Properties props) {
String tempRoot = props.getProperty(JBOSS_EMBEDDED_ROOT, null);
if (tempRoot == null) {
return null;
}
File root = new File(tempRoot);
if (!root.exists()) {
//Attempt to try to create the directory, in case something like target/embedded was specified
root.mkdirs();
}
validateDirectory("jboss.test.clean.root", root);
root = new File(root, "configs");
root.mkdir();
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmssSSS");
root = new File(root, format.format(new Date()));
root.mkdir();
return root;
}
private static void validateDirectory(String property, File file) {
if (!file.exists()) {
throw ServerLogger.ROOT_LOGGER.propertySpecifiedFileDoesNotExist(property, file.getAbsolutePath());
}
if (!file.isDirectory()) {
throw ServerLogger.ROOT_LOGGER.propertySpecifiedFileIsNotADirectory(property, file.getAbsolutePath());
}
}
private static void copyDirectory(File src, File dest) {
for (String current : src.list()) {
final File srcFile = new File(src, current);
final File destFile = new File(dest, current);
if (srcFile.isDirectory()) {
destFile.mkdir();
copyDirectory(srcFile, destFile);
} else {
try {
final InputStream in = new BufferedInputStream(new FileInputStream(srcFile));
final OutputStream out = new BufferedOutputStream(new FileOutputStream(destFile));
try {
int i;
while ((i = in.read()) != -1) {
out.write(i);
}
} catch (IOException e) {
throw ServerLogger.ROOT_LOGGER.errorCopyingFile(srcFile.getAbsolutePath(), destFile.getAbsolutePath(), e);
} finally {
StreamUtils.safeClose(in);
StreamUtils.safeClose(out);
}
} catch (FileNotFoundException e) {
throw EmbeddedLogger.ROOT_LOGGER.cannotSetupEmbeddedServer(e);
}
}
}
}
}