/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.vertical.adminweb;
import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryUsage;
import java.util.ArrayList;
import java.util.Properties;
import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMSource;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.jdom.JDOMException;
import org.joda.time.format.PeriodFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.enonic.esl.containers.ExtendedMap;
import com.enonic.esl.net.URL;
import com.enonic.esl.xml.XMLTool;
import com.enonic.vertical.engine.VerticalEngineException;
import com.enonic.cms.framework.cache.CacheFacade;
import com.enonic.cms.framework.cache.CacheManager;
import com.enonic.cms.framework.util.JDOMUtil;
import com.enonic.cms.core.config.ConfigProperties;
import com.enonic.cms.core.portal.cache.PageCacheService;
import com.enonic.cms.core.product.ProductVersion;
import com.enonic.cms.core.search.query.ContentIndexService;
import com.enonic.cms.core.security.user.User;
import com.enonic.cms.core.service.AdminService;
import com.enonic.cms.core.time.DateTimeFormatters;
import com.enonic.cms.core.time.TimeService;
import com.enonic.cms.core.tools.DataSourceInfoResolver;
import com.enonic.cms.core.vacuum.ProgressInfo;
import com.enonic.cms.core.vacuum.VacuumService;
import com.enonic.cms.core.vhost.VirtualHost;
/**
*
*/
public class SystemHandlerServlet
extends AdminHandlerBaseServlet
{
@Autowired
private DataSourceInfoResolver datasourceInfoResolver;
@Autowired
private ContentIndexService contentIndexService;
@Autowired
private ConfigProperties configurationProperties;
@Autowired
private TimeService timeService;
@Autowired
private VacuumService vacuumService;
@Autowired
private CacheManager cacheManager;
@Value("${cms.home}/config/vhost.properties")
private String vhostFileName;
private ObjectMapper jacksonObjectMapper;
public SystemHandlerServlet()
{
jacksonObjectMapper = new ObjectMapper().configure( SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false );
}
public void handlerCustom( HttpServletRequest request, HttpServletResponse response, HttpSession session, AdminService admin,
ExtendedMap formItems, String operation )
throws VerticalEngineException, VerticalAdminException, MessagingException, IOException
{
if ( "page".equals( operation ) )
{
handlerPage( request, response, session, admin, formItems, operation );
}
else if ( "cleanReadLogs".equals( operation ) )
{
handlerCleanReadLogs( admin, request, response );
}
else if ( "cleanUnusedContent".equals( operation ) )
{
handlerCleanUnusedContent( admin, request, response );
}
else if ( "clearcache".equals( operation ) )
{
clearCache( request, response, formItems );
}
else if ( "optimizeIndex".equals( operation ) )
{
optimizeIndex( request, response, formItems );
}
else
{
super.handlerCustom( request, response, session, admin, formItems, operation );
}
}
public void handlerPage( HttpServletRequest request, HttpServletResponse response, HttpSession session, AdminService admin,
ExtendedMap formItems, String operation )
throws VerticalEngineException, VerticalAdminException
{
User user = securityService.getLoggedInAdminConsoleUser();
Source xslSource = AdminStore.getStylesheet( session, "system_page.xsl" );
String mode = formItems.getString( "mode" );
Document doc = XMLTool.createDocument( "vertical" );
Element root = doc.getDocumentElement();
try
{
if ( mode.equals( "system" ) )
{
root.appendChild( buildJavaInfo( doc ) );
root.setAttribute( "bootTime", DateTimeFormatters.DATE_TIME.print( timeService.bootTime() ) );
root.setAttribute( "upTime", PeriodFormat.wordBased().print( timeService.upTime() ) );
root.setAttribute( "version", ProductVersion.getVersion() );
root.setAttribute( "modelVersion", String.valueOf( this.upgradeService.getCurrentModelNumber() ) );
root.setAttribute( "isCleanInProgress", String.valueOf( vacuumService.getProgressInfo().isInProgress() ) );
root.appendChild( buildComponentsInfo( doc ) );
}
else if ( mode.equals( "java_properties" ) )
{
XMLTool.mergeDocuments( doc, createPropertiesInfoDocument(), true );
}
Source xmlSource = new DOMSource( doc );
// parameters
ExtendedMap xslParams = new ExtendedMap();
xslParams.put( "page", request.getParameter( "page" ) );
xslParams.put( "selectedtabpage", request.getParameter( "selectedtabpage" ) );
xslParams.put( "mode", mode );
xslParams.put( "selectedoperation", request.getParameter( "selectedoperation" ) );
xslParams.put( "selectedcachename", request.getParameter( "selectedcachename" ) );
addAccessLevelParameters( user, xslParams );
transformXML( session, response.getWriter(), xmlSource, xslSource, xslParams );
}
catch ( TransformerException e )
{
VerticalAdminLogger.errorAdmin( "XSLT error: %t", e );
}
catch ( IOException e )
{
VerticalAdminLogger.errorAdmin( "I/O error: %t", e );
}
}
private Document createPropertiesInfoDocument()
{
Properties properties = new Properties();
final File file = new File( this.vhostFileName );
if ( file.exists() )
{
try
{
properties = PropertiesLoaderUtils.loadProperties( new FileSystemResource( file ) );
}
catch ( Exception e )
{
// nothing - empty
}
}
PropertiesInfoModelFactory propertiesInfoModelFactory =
new PropertiesInfoModelFactory( datasourceInfoResolver, configurationProperties, properties );
PropertiesInfoModel infoModel = propertiesInfoModelFactory.createSystemPropertiesModel();
final Document doc;
try
{
doc = JDOMUtil.toW3CDocument( infoModel.toXML() );
}
catch ( JDOMException e )
{
throw new VerticalAdminException( "Failed to create system-properties document" );
}
return doc;
}
/**
* Clean read logs.
*/
private void handlerCleanReadLogs( AdminService admin, HttpServletRequest request, HttpServletResponse response )
{
if ( "getprogress".equals( request.getParameter( "subop" ) ) )
{
renderGetProgress( response );
}
else
{
vacuumService.cleanReadLogs();
}
}
/**
* Clean unused content.
*/
private void handlerCleanUnusedContent( AdminService admin, HttpServletRequest request, HttpServletResponse response )
{
if ( "getprogress".equals( request.getParameter( "subop" ) ) )
{
renderGetProgress( response );
}
else
{
vacuumService.cleanUnusedContent( );
}
}
private void renderGetProgress( final HttpServletResponse response )
{
final ProgressInfo cleanUnusedContentProgressInfo = vacuumService.getProgressInfo();
try
{
response.setHeader( "Content-Type", "application/json; charset=UTF-8" );
final String json = jacksonObjectMapper.writeValueAsString( cleanUnusedContentProgressInfo );
response.getWriter().println( json );
}
catch ( IOException e )
{
throw new RuntimeException( "Failed to transform objects to JSON: " + e.getMessage(), e );
}
}
private Element buildJavaInfo( Document doc )
{
Element javaEl = doc.createElement( "java" );
javaEl.setAttribute( "version", findJavaVersion() );
Element memoryEl = XMLTool.createElement( javaEl, "memory" );
Element heapEl = XMLTool.createElement( memoryEl, "heap" );
MemoryUsage heap = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
heapEl.setAttribute( "max", String.valueOf( heap.getMax() ) );
heapEl.setAttribute( "committed", String.valueOf( heap.getCommitted() ) );
heapEl.setAttribute( "used", String.valueOf( heap.getUsed() ) );
MemoryUsage nonheap = ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage();
Element nonheapEl = XMLTool.createElement( memoryEl, "nonheap" );
nonheapEl.setAttribute( "max", String.valueOf( nonheap.getMax() ) );
nonheapEl.setAttribute( "committed", String.valueOf( nonheap.getCommitted() ) );
nonheapEl.setAttribute( "used", String.valueOf( nonheap.getUsed() ) );
return javaEl;
}
/**
* Append component version informations.
*/
private Element buildComponentsInfo( Document doc )
{
Element root = doc.createElement( "components" );
root.appendChild( buildComponentInfo( doc, "Saxon", findSaxonVersion() ) );
return root;
}
/**
* Append component version information.
*/
private Element buildComponentInfo( Document doc, String name, String version )
{
Element root = doc.createElement( "component" );
root.setAttribute( "name", name );
root.setAttribute( "version", version );
return root;
}
/**
* Find java version.
*/
private String findJavaVersion()
{
return System.getProperty( "java.vm.version" );
}
/**
* Find saxon version.
*/
private String findSaxonVersion()
{
return net.sf.saxon.Version.getProductVersion();
}
private void clearCache( HttpServletRequest request, HttpServletResponse response, ExtendedMap formItems )
throws VerticalAdminException
{
final String cacheName = formItems.getString( "cacheName" );
final CacheFacade cache = cacheManager.getCache( cacheName );
if ( cache != null )
{
cache.removeAll();
}
URL referer = new URL( request.getHeader( "referer" ) );
referer.setParameter( "selectedtabpage", formItems.getString( "selectedtabpage", "" ) );
referer.setParameter( "selectedoperation", formItems.getString( "selectedoperation", formItems.getString( "op", "" ) ) );
referer.setParameter( "selectedcachename", formItems.getString( "selectedcachename", formItems.getString( "cacheName", "" ) ) );
referer.setParameter( "selectedtabpage", formItems.getString( "selectedtabpage", "" ) );
redirectClientToURL( referer, response );
}
private void optimizeIndex( HttpServletRequest request, HttpServletResponse response, ExtendedMap formItems )
throws VerticalAdminException
{
contentIndexService.optimize();
URL referrer = new URL( request.getHeader( "referer" ) );
referrer.setParameter( "selectedoperation", "optimizeindex" );
redirectClientToURL( referrer, response );
}
public void setPageCacheService( PageCacheService value )
{
this.pageCacheService = value;
}
public void setDatasourceInfoResolver( DataSourceInfoResolver datasourceInfoResolver )
{
this.datasourceInfoResolver = datasourceInfoResolver;
}
}