/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.cms.web.main; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import com.enonic.cms.upgrade.UpgradeService; import com.enonic.cms.upgrade.log.UpgradeLog; import com.enonic.cms.upgrade.log.UpgradeLogEntry; /** * This class manages the upgrade. */ @Controller public final class UpgradeController implements InitializingBean { private static final String AUTHENTICATED_SESSION_KEY = "authenticatedUpgrade"; private static final String AUTHENTICATION_FAILED_KEY = "authenticationFailed"; private String entrerpriseAdminPassword; /** * Upgrade service. */ private UpgradeService upgradeService; /** * Upgrade process task. */ private UpgradeProcessTask upgradeProcessTask; /** * After properties set. */ public void afterPropertiesSet() { this.upgradeProcessTask = new UpgradeProcessTask( this.upgradeService ); } /** * Set the upgrade service. */ @Autowired public void setUpgradeService( UpgradeService upgradeService ) { this.upgradeService = upgradeService; } /** * Handle upgrade page view. */ @RequestMapping(value = "/upgrade", method = RequestMethod.GET) public ModelAndView handleView( HttpServletRequest req, HttpServletResponse res ) throws Exception { boolean authenticated = doAuthenticate( req ); Map<String, Object> model = populateViewModel( req, false, authenticated ); return new ModelAndView( "upgradePage", model ); } /** * Handle upgrade page mechanism. */ @RequestMapping(value = "/upgrade_db", method = RequestMethod.POST) public ModelAndView handleUpgrade( HttpServletRequest req, HttpServletResponse res ) throws Exception { boolean authenticated = doAuthenticate( req ); if ( authenticated ) { if ( Boolean.valueOf( req.getParameter( "upgrade_all" ) ) ) { this.upgradeProcessTask.startUpgrade( true ); redirectToSelf( req, res ); return null; } else { this.upgradeProcessTask.startUpgrade( false ); redirectToSelf( req, res ); return null; } } Map<String, Object> model = populateViewModel( req, true, authenticated ); return new ModelAndView( "upgradePage", model ); } private Map<String, Object> populateViewModel( HttpServletRequest req, boolean isAuthenticationFailed, boolean authenticated ) { Map<String, Object> model = new HashMap<String, Object>(); model.put( AUTHENTICATION_FAILED_KEY, isAuthenticationFailed ); model.put( "upgradeNeeded", this.upgradeService.needsUpgrade() ); model.put( "upgradeInProgress", this.upgradeProcessTask.isInProgress() ); model.put( "upgradeError", this.upgradeProcessTask.getError() ); model.put( "upgradeLog", getFormattedLog( this.upgradeProcessTask.getLog() ) ); model.put( "upgradeFrom", this.upgradeService.getCurrentModelNumber() ); model.put( "upgradeTo", this.upgradeService.getTargetModelNumber() ); model.put( "baseUrl", createBaseUrl( req ) ); model.put( "authenticated", authenticated ); if ( !this.upgradeProcessTask.isInProgress() && !this.upgradeService.needsUpgrade() ) { this.upgradeProcessTask.getLog().clear(); } return model; } private boolean isAuthenticatedSession( HttpServletRequest req ) { return req.getSession().getAttribute( AUTHENTICATED_SESSION_KEY ) != null; } private boolean doAuthenticate( HttpServletRequest req ) throws Exception { if ( isAuthenticatedSession( req ) ) { return true; } String adminPassword = req.getParameter( "adminPassword" ); if ( StringUtils.equals( adminPassword, entrerpriseAdminPassword ) ) { req.getSession().setAttribute( AUTHENTICATED_SESSION_KEY, "true" ); return true; } return false; } /** * Return the formatted log. */ private List<String> getFormattedLog( UpgradeLog log ) { ArrayList<String> list = new ArrayList<String>(); for ( UpgradeLogEntry entry : log.getEntries() ) { list.add( getFormattedLogEntry( entry ) ); } return list; } /** * Return the formatted log entry. */ private String getFormattedLogEntry( UpgradeLogEntry entry ) { StringBuffer str = new StringBuffer(); str.append( "<div class='logentry'>" ); str.append( "<div class='" ).append( "level-" ).append( entry.getLevel().name().toLowerCase() ).append( "'>" ); str.append( entry.getMessage() ); str.append( "</div>" ); if ( entry.getCause() != null ) { str.append( getFormattedCause( entry.getCause() ) ); } str.append( "</div>" ); return str.toString(); } /** * Return the formatted cause. */ private String getFormattedCause( Throwable cause ) { StringBuffer str = new StringBuffer(); str.append( "<div class='stacktrace'>" ); for ( StackTraceElement elem : cause.getStackTrace() ) { str.append( "<div class='traceelem'>" ); str.append( elem.getClassName() ).append( "." ).append( elem.getMethodName() ).append( " (line " ); str.append( elem.getLineNumber() ).append( ")" ); str.append( "</div>" ); } str.append( "</div>" ); return str.toString(); } /** * Return the base path. */ private String createBaseUrl( HttpServletRequest req ) { StringBuffer str = new StringBuffer(); str.append( req.getScheme() ).append( "://" ).append( req.getServerName() ); if ( req.getServerPort() != 80 ) { str.append( ":" ).append( req.getServerPort() ); } str.append( req.getContextPath() ); return str.toString(); } /** * Redirect to self. */ private void redirectToSelf( HttpServletRequest req, HttpServletResponse res ) throws Exception { String url = req.getRequestURL().toString(); int index = url.indexOf( "?" ); if ( index > -1 ) { url = url.substring( 0, index ); } // change '/upgrade_db [GET]' to '/upgrade [POST]' index = url.lastIndexOf( "/" ); if ( index > -1 ) { url = url.substring( 0, index ); } res.sendRedirect( url + "/upgrade" ); } @Value("${cms.admin.password}") public void setEntrerpriseAdminPassword( String password ) { this.entrerpriseAdminPassword = password; } }