/*
* Embedded Jopr Project
* Copyright (C) 2006-2009 Red Hat, Inc.
* All rights reserved.
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.jboss.on.embedded.ui;
import java.io.File;
import java.io.FileInputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jetbrains.annotations.Nullable;
import org.rhq.core.pc.PluginContainer;
import org.rhq.core.pc.PluginContainerConfiguration;
import org.rhq.core.pc.ServerServices;
import org.rhq.core.pc.plugin.PluginEnvironment;
import org.rhq.core.pc.plugin.SimplePluginFinder;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Observer;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.Startup;
import org.jboss.seam.contexts.ServletLifecycle;
import org.jboss.seam.security.Identity;
import org.jboss.on.embedded.EmbeddedInventoryEventListener;
import org.jboss.on.embedded.LoggingInventoryEventListener;
import org.jboss.on.embedded.bean.history.content.ContentHistoryManagerBean;
import org.jboss.on.embedded.bean.history.content.ContentServerServiceImpl;
import org.jboss.on.embedded.bean.history.operation.OperationServerServiceImpl;
import org.jboss.on.embedded.manager.ResourceManagerFactory;
import org.jboss.on.embedded.manager.history.operation.OperationHistoryManager;
/**
* A Seam component that is in charge of initializing and shutting down the Admin Console.
*
* @author Ian Springer
*/
@Name("bootstrapAction")
@Scope(ScopeType.APPLICATION)
@Startup
public class BootstrapAction
{
private static final Log LOG = LogFactory.getLog(BootstrapAction.class);
private static final String FACES_API_LOGGER_NAME = "javax.faces";
private static final String FACES_RI_LOGGER_NAME = "javax.enterprise.resource.webcontainer.jsf";
private static final String FACELETS_LOGGER_NAME = "facelets";
@In(value = "historyManager", create = true)
private OperationHistoryManager historyManager;
@In(value = "contentHistoryManager", create = true)
private ContentHistoryManagerBean contentHistoryManager;
@In(value = "inventoryEventListener", create = true)
private EmbeddedInventoryEventListener inventoryEventListener;
private boolean initialized;
private File tempDir;
/**
* Initializes the Admin Console after the first user logs in.
*/
@Observer(Identity.EVENT_LOGIN_SUCCESSFUL)
public void init()
{
if (!this.initialized)
{
try
{
String version = getVersion();
LOG.info("Initializing Administration Console" + ((version != null) ? (" v" + version) : "") + "...");
long startTime = System.currentTimeMillis();
reconfigureJdkLogging();
initPluginContainer();
ResourceManagerFactory.resourceManager().discoverResources();
long elapsedTime = System.currentTimeMillis() - startTime;
LOG.debug("Done initializing Administration Console (" + elapsedTime + " ms elapsed).");
this.initialized = true;
}
catch (Exception e)
{
LOG.error("*** Failed to initialize Administration Console. ***", e);
}
}
}
/**
* Shuts down the Admin Console when the webapp is stopped.
*/
@Destroy
public void shutdown()
{
if (this.initialized)
{
try
{
LOG.info("Shutting down Administration Console...");
PluginContainer.getInstance().shutdown();
}
catch (RuntimeException e)
{
LOG.error("*** Failed to shutdown Administration Console. ***", e);
}
}
}
public boolean isInitialized()
{
return this.initialized;
}
public File getTempDir()
{
return this.tempDir;
}
private void initPluginContainer()
throws MalformedURLException
{
PluginContainerConfiguration pluginContainerConfig = createPluginContainerConfiguration();
PluginContainer pluginContainer = PluginContainer.getInstance();
pluginContainer.setConfiguration(pluginContainerConfig);
configureMockScenarioLoader();
pluginContainer.initialize();
logLoadedPlugins(pluginContainer);
pluginContainer.getInventoryManager().addInventoryEventListener(this.inventoryEventListener);
pluginContainer.getInventoryManager().addInventoryEventListener(new LoggingInventoryEventListener());
}
@Nullable
private String getVersion()
{
String version = null;
try
{
version = this.getClass().getPackage().getImplementationVersion();
if (version == null)
{
ServletContext servletContext = ServletLifecycle.getServletContext();
String manifestPath = servletContext.getRealPath("/META-INF/MANIFEST.MF");
Manifest manifest = new Manifest(new FileInputStream(manifestPath));
version = (String)manifest.getMainAttributes().get(Attributes.Name.IMPLEMENTATION_VERSION);
if (version == null)
{
throw new IllegalStateException(Attributes.Name.IMPLEMENTATION_VERSION + " attribute is not set in WAR's manifest.");
}
}
}
catch (Exception e)
{
LOG.error("Could not determine Administration Console version.", e);
}
return version;
}
private static void reconfigureJdkLogging()
{
try
{
LOG.trace("Reconfiguring JDK logging...");
setJdkLoggerLevel(FACES_API_LOGGER_NAME, Level.WARNING);
setJdkLoggerLevel(FACES_RI_LOGGER_NAME, Level.WARNING);
setJdkLoggerLevel(FACELETS_LOGGER_NAME, Level.WARNING);
}
catch (Exception e)
{
LOG.warn("Failed to reconfigure JDK logging.", e);
}
}
private PluginContainerConfiguration createPluginContainerConfiguration() throws MalformedURLException
{
PluginContainerConfiguration config = new PluginContainerConfiguration();
config.setPluginFinder(createPluginFinder());
setPluginContainerDataDirectory(config);
config.setTemporaryDirectory(initTempDir());
config.setContentDiscoveryPeriod(0);
ServerServices services = new ServerServices();
// Create operation listener
OperationServerServiceImpl callbackListener = new OperationServerServiceImpl();
callbackListener.setHistoryBean(this.historyManager);
// Create content listener
ContentServerServiceImpl contentListener = new ContentServerServiceImpl();
contentListener.setHistoryBean(this.contentHistoryManager);
// Add listeners to ServerServices
services.setOperationServerService(callbackListener);
services.setContentServerService(contentListener);
config.setServerServices(services);
return config;
}
private static SimplePluginFinder createPluginFinder() throws MalformedURLException
{
ServletContext servletContext = ServletLifecycle.getServletContext();
SimplePluginFinder pluginFinder = new SimplePluginFinder();
Set<String> pluginStringSet = servletContext.getResourcePaths("/plugins/");
for (String pluginString : pluginStringSet)
{
if (pluginString.endsWith(".jar"))
{
URL pluginUrl = servletContext.getResource(pluginString);
pluginFinder.addUrl(pluginUrl);
}
}
return pluginFinder;
}
private static void configureMockScenarioLoader()
{
LOG.trace("Configuring Mock Scenario Loader...");
System.setProperty("on.mock.jboss.scenario", "scenario2.xml");
}
private static void logLoadedPlugins(PluginContainer pluginContainer)
{
Collection<PluginEnvironment> pluginEnvironments = pluginContainer.getPluginManager().getPlugins();
for (PluginEnvironment pluginEnvironment : pluginEnvironments)
LOG.debug("Loaded RHQ plugin [" + pluginEnvironment.getPluginName() + "].");
}
private static void setJdkLoggerLevel(String name, Level level)
{
Logger facesApiLogger = Logger.getLogger(name);
facesApiLogger.setLevel(level);
}
private static void setPluginContainerDataDirectory(PluginContainerConfiguration config)
{
File dataDirectory = getDirectory("jboss.server.data.dir");
if (dataDirectory != null)
{
config.setDataDirectory(dataDirectory);
}
}
private File initTempDir()
{
String jbasTempDir = System.getProperty("jboss.server.temp.dir");
String javaTempDir = System.getProperty("java.io.tmpdir");
String baseTempDir = (jbasTempDir != null) ? jbasTempDir : javaTempDir;
if (baseTempDir == null)
baseTempDir = File.separatorChar == '/' ? "/tmp" : "C:/tmp";
this.tempDir = new File(baseTempDir, "embjopr");
//noinspection ResultOfMethodCallIgnored
this.tempDir.mkdirs();
if (!this.tempDir.exists())
throw new IllegalStateException("Failed to initialize temporary directory: " + this.tempDir);
return this.tempDir;
}
@Nullable
private static File getDirectory(String systemProperty)
{
File directory = null;
String directoryPath = System.getProperty(systemProperty);
if (directoryPath != null)
directory = new File(directoryPath);
return directory;
}
}