/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.vertical.adminweb.wizard; import java.io.IOException; import java.io.Serializable; import java.io.StringReader; import java.io.StringWriter; import java.util.HashMap; import java.util.Iterator; import java.util.Map; 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.dom.DOMSource; import javax.xml.transform.stream.StreamSource; import org.springframework.context.ApplicationContext; import org.w3c.dom.Document; import org.w3c.dom.Element; import com.google.common.collect.Maps; import com.enonic.esl.containers.ExtendedMap; import com.enonic.esl.xml.XMLTool; import com.enonic.vertical.adminweb.AdminHandlerBaseServlet; import com.enonic.vertical.adminweb.AdminStore; import com.enonic.vertical.adminweb.VerticalAdminException; import com.enonic.vertical.engine.VerticalEngineException; import com.enonic.cms.core.security.user.User; import com.enonic.cms.core.service.AdminService; import com.enonic.cms.core.xslt.admin.AdminXsltProcessorHelper; public abstract class Wizard implements Serializable { /** * XSL used for creating the wizard xsl */ private final static String BUILD_XSL = "__build_wizard_form_xsl.xsl"; public final static int BUTTON_NONE = -1; public final static int BUTTON_PREVIOUS = 0; public final static int BUTTON_NEXT = 1; public final static int BUTTON_CANCEL = 2; public final static int BUTTON_PROCESS = 3; public final static int BUTTON_RELOAD = 4; public final static int BUTTON_CLOSE = 5; private final static class NextButton implements Serializable { private String name; private String[] testConditions; private Step[] nextSteps; private Step defaultNextStep; private NextButton( Map<String, Step> stepMap, Element buttonElem ) throws WizardException { this.name = buttonElem.getAttribute( "name" ); Element[] conditionElems = XMLTool.getElements( buttonElem, "condition" ); testConditions = new String[conditionElems.length]; nextSteps = new Step[conditionElems.length]; for ( int i = 0; i < conditionElems.length; i++ ) { testConditions[i] = conditionElems[i].getAttribute( "test" ); if ( testConditions[i] == null || testConditions[i].length() == 0 ) { String message = "Missing test condition attribute."; WizardLogger.errorWizard( message, null ); } String stepName = conditionElems[i].getAttribute( "goto" ); Step nextStep = stepMap.get( stepName ); if ( nextStep != null ) { conditionElems[i].setAttribute( "gotoid", String.valueOf( nextStep.id ) ); nextSteps[i] = nextStep; } else { String message = "Unknown step name in next step condition: {0}"; WizardLogger.errorWizard( message, stepName ); } } Element defaultElem = XMLTool.getElement( buttonElem, "default" ); if ( defaultElem != null ) { String stepName = defaultElem.getAttribute( "goto" ); this.defaultNextStep = stepMap.get( stepName ); if ( this.defaultNextStep != null ) { defaultElem.setAttribute( "gotoid", String.valueOf( this.defaultNextStep.id ) ); } else { String message = "Unknown step name in default next step condition: {0}"; WizardLogger.errorWizard( message, stepName ); } } else { String message = "Missing default next step condition."; WizardLogger.errorWizard( message, null ); } } } protected abstract static class Step implements Serializable { public static final int NORMAL = 0; public static final int FINISH = 1; protected int id; protected String name; protected int type; protected Step( int id, String name, int type ) { this.id = id; this.name = name; this.type = type; } public int getId() { return id; } public String getName() { return name; } public int getType() { return type; } } protected final static class NormalStep extends Step { private boolean stateDependent; private Document dataconfigDoc; // buttons private String previousButtonName; private Map<String, NextButton> nextButtons = new HashMap<String, NextButton>(); private String cancelButtonName; private String closeButtonName; private Map<String, String> processButtonSrcs = new HashMap<String, String>(); protected NormalStep( int id, Element stepElem ) throws WizardException { super( id, stepElem.getAttribute( "name" ), NORMAL ); Element dataconfigElem = XMLTool.getElement( stepElem, "dataconfig" ); if ( dataconfigElem == null ) { String message = "Step \"{0}\" does not have a data configuration."; WizardLogger.errorWizard( message, name ); } this.dataconfigDoc = XMLTool.createDocument(); this.dataconfigDoc.appendChild( this.dataconfigDoc.importNode( dataconfigElem, true ) ); } } protected final static class FinishStep extends Step { private String styleSheetSrc; protected FinishStep( int id, Element stepElem ) throws WizardException { super( id, stepElem.getAttribute( "name" ), FINISH ); Element stylesheetElem = XMLTool.getElement( stepElem, "stylesheet" ); if ( stylesheetElem != null ) { this.styleSheetSrc = stylesheetElem.getAttribute( "src" ); if ( this.styleSheetSrc == null ) { String message = "Missing XSL source definition for stylesheet in finish step \"{0}\"."; WizardLogger.errorWizard( message, name ); } } } } protected final static class StepState implements Serializable { private NormalStep step; private StepState previousStepState, nextStepState; private Document stateDoc; private String buttonPressed; private boolean errorState; private StepState( NormalStep step ) { this.step = step; this.stateDoc = XMLTool.createDocument( "stepstate" ); Element stepstateElem = this.stateDoc.getDocumentElement(); stepstateElem.setAttribute( "stepid", String.valueOf( step.id ) ); } private void clearState() { Element rootElem = this.stateDoc.getDocumentElement(); rootElem.removeAttribute( "buttonpressed" ); XMLTool.removeChildNodes( rootElem, true ); } private void saveCustomState( ExtendedMap formItems ) { Element rootElem = this.stateDoc.getDocumentElement(); XMLTool.removeChildNodes( rootElem, true ); XMLTool.buildSubTree( stateDoc, rootElem, "stepstate", formItems ); } private void saveCommonState( ExtendedMap formItems ) { this.buttonPressed = formItems.getString( "__wizard_button" ); Element rootElem = this.stateDoc.getDocumentElement(); rootElem.setAttribute( "buttonpressed", this.buttonPressed ); } public StepState getNextStepState() { return nextStepState; } public StepState getPreviousStepState() { return previousStepState; } public Document getStateDoc() { return stateDoc; } public NormalStep getStep() { return step; } public String getButtonPressed() { return buttonPressed; } public void setButtonPressed( String string ) { buttonPressed = string; } public boolean isErrorState() { return errorState; } public void setErrorState( boolean errorState ) { this.errorState = errorState; Element rootElem = stateDoc.getDocumentElement(); if ( errorState ) { rootElem.setAttribute( "errorstate", "true" ); } else { rootElem.removeAttribute( "errorstate" ); } } } protected final static class WizardState implements Serializable { private String redirectURL; private Map<String, StepState> stepStateMap = Maps.newHashMap(); private StepState firstStepState, currentStepState; private Step currentStep; private Map<String, String> errorCodes = Maps.newHashMap(); private Map<String, String[]> errorParts = Maps.newHashMap(); private WizardState() { } private void saveCommonState( ExtendedMap formItems ) { errorCodes.clear(); errorParts.clear(); if ( currentStepState == null ) { throw new IllegalStateException( "The wizard has completed it's work and is no longer accessible. This error message is normally caused by pressing" + " the finish button too many times, or the back or refresh button in the browser after the last step of the wizard." ); } currentStepState.clearState(); currentStepState.saveCommonState( formItems ); } private void saveCustomState( ExtendedMap formItems ) { currentStepState.saveCustomState( formItems ); } public int getPressedButtonType() { // when the wizard are in its first state, no button is pressed if ( currentStepState == null || currentStepState.buttonPressed == null ) { return BUTTON_NONE; } String buttonName = currentStepState.buttonPressed; NormalStep currentStep = currentStepState.step; if ( buttonName.equals( currentStep.previousButtonName ) ) { return BUTTON_PREVIOUS; } else if ( buttonName.equals( currentStep.cancelButtonName ) ) { return BUTTON_CANCEL; } else if ( buttonName.equals( currentStep.closeButtonName ) ) { return BUTTON_CLOSE; } else if ( currentStep.nextButtons.containsKey( buttonName ) ) { return BUTTON_NEXT; } else if ( currentStep.processButtonSrcs.containsKey( buttonName ) ) { return BUTTON_PROCESS; } else { return BUTTON_RELOAD; } } /** * Returns an xml document representation of the wizard state. */ public Document toDocument() { Document wizardstateDoc = XMLTool.createDocument( "wizardstate" ); Element wizardstateElem = wizardstateDoc.getDocumentElement(); // set current step and step state id wizardstateElem.setAttribute( "currentstepid", String.valueOf( currentStep.id ) ); // add state documents int nextId = 0; StepState stepState = firstStepState; while ( stepState != null ) { Element stepstateElem = stepState.stateDoc.getDocumentElement(); stepstateElem = (Element) wizardstateDoc.importNode( stepstateElem, true ); int currentStepStateId = nextId++; stepstateElem.setAttribute( "id", String.valueOf( currentStepStateId ) ); wizardstateElem.appendChild( stepstateElem ); if ( stepState == currentStepState ) { wizardstateElem.setAttribute( "currentstepstateid", String.valueOf( currentStepStateId ) ); } stepState = stepState.nextStepState; } Element errorsElem = XMLTool.createElement( wizardstateDoc, wizardstateElem, "errors" ); for ( Iterator<String> iter = errorCodes.keySet().iterator(); iter.hasNext(); ) { String errorCode = iter.next(); String fieldName = errorCodes.get( errorCode ); Element errorElem = XMLTool.createElement( wizardstateDoc, errorsElem, "error" ); errorElem.setAttribute( "code", errorCode ); errorElem.setAttribute( "name", fieldName ); if ( errorParts.containsKey( errorCode ) ) { String[] parts = errorParts.get( errorCode ); for ( int i = 0; i < parts.length; i++ ) { XMLTool.createElement( wizardstateDoc, errorElem, "part", parts[i] ); } } } return wizardstateDoc; } /** * @see java.lang.Object#toString() */ public String toString() { return XMLTool.documentToString( toDocument(), 2 ); } public void addError( String errorCode, String fieldName ) { addError( errorCode, fieldName, (String[]) null ); } public void addError( String errorCode, String fieldName, String part ) { addError( errorCode, fieldName, new String[]{part} ); } public void addError( String errorCode, String fieldName, String[] parts ) { if ( !errorCodes.containsKey( errorCode ) ) { errorCodes.put( errorCode, fieldName ); } if ( parts != null ) { errorParts.put( errorCode, parts ); } } public boolean hasErrors() { return errorCodes.size() > 0; } public boolean hasError( String errorCode ) { return errorCodes.containsKey( errorCode ); } public Step getCurrentStep() { return currentStep; } public StepState getCurrentStepState() { return currentStepState; } public StepState getStepState( String stepName ) { return stepStateMap.get( stepName ); } public String getRedirectURL() { return redirectURL; } public void setRedirectURL( String string ) { redirectURL = string; } public StepState getFirstStepState() { return firstStepState; } } private static int nextWizardId; private int wizardId = nextWizardId++; private String wizardConfigFilename; private Document wizardconfigDoc; protected transient AdminHandlerBaseServlet servlet; private NormalStep firstStep; private static Wizard createWizard( AdminService admin, ApplicationContext applicationContext, AdminHandlerBaseServlet servlet, HttpSession session, String wizardConfigFilename ) throws WizardException { Document wizardconfigDoc = AdminStore.getXml( session, wizardConfigFilename ).getAsDOMDocument(); Element rootElem = wizardconfigDoc.getDocumentElement(); String className = rootElem.getAttribute( "class" ); // create new wizard Wizard wizard; Class wizardClass = null; try { wizardClass = Class.forName( className ); } catch ( ClassNotFoundException cnfe ) { String message = "Wizard class not found: %t"; WizardLogger.errorWizard( message, cnfe ); } catch ( ClassCastException cce ) { String message = "Wizard class does not extend Wizard: %t"; WizardLogger.errorWizard( message, cce ); } wizard = (Wizard) applicationContext.getBean( className, wizardClass ); wizard.wizardConfigFilename = wizardConfigFilename; wizard.servlet = servlet; // initialize wizard wizard.initializeInternal( admin, wizardconfigDoc ); return wizard; } public static Wizard getInstance( AdminService admin, ApplicationContext applicationContext, AdminHandlerBaseServlet servlet, HttpSession session, ExtendedMap formItems, String wizardConfigFilename ) throws WizardException { String buttonName = formItems.getString( "__wizard_button", null ); // // Her genereres Wizarden og legges på sesjonen. // Hvis den er en inner class av en Servlet, blir hele servletten lagret. :( // if ( buttonName == null ) { Wizard wizard = createWizard( admin, applicationContext, servlet, session, wizardConfigFilename ); session.setAttribute( "__" + wizardConfigFilename, wizard ); return wizard; } else { return (Wizard) session.getAttribute( "__" + wizardConfigFilename ); } } protected Wizard() { } private void initializeInternal( AdminService admin, Document wizardconfigDoc ) throws WizardException { Element rootElem = wizardconfigDoc.getDocumentElement(); // set wizard config document this.wizardconfigDoc = wizardconfigDoc; // steps config Element stepsElem = XMLTool.getElement( rootElem, "steps" ); if ( stepsElem == null ) { String message = "No steps defined."; WizardLogger.errorWizard( message, null ); } Element[] stepElems = XMLTool.getElements( stepsElem ); Element[] buttonsElems = new Element[stepElems.length]; Step[] steps = new Step[stepElems.length]; if ( stepElems.length == 0 ) { String message = "No steps defined."; WizardLogger.errorWizard( message, null ); } // create steps Map<String, Step> stepMap = new HashMap<String, Step>(); for ( int i = 0; i < stepElems.length; i++ ) { // set id stepElems[i].setAttribute( "id", String.valueOf( i ) ); // get type and create step String type = stepElems[i].getAttribute( "type" ); if ( "normal".equals( type ) ) { steps[i] = new NormalStep( i, stepElems[i] ); } else if ( "finish".equals( type ) ) { steps[i] = new FinishStep( i, stepElems[i] ); if ( i == 0 ) { String message = "First step cannot be a finish step"; WizardLogger.errorWizard( message, null ); } } else { String message = "Unknown step type: {0}"; WizardLogger.errorWizard( message, type ); } // save step for later String name = stepElems[i].getAttribute( "name" ); stepMap.put( name, steps[i] ); // save button definitions for later processing Element buttonsElem = XMLTool.getElement( stepElems[i], "buttons" ); if ( buttonsElem == null && "normal".equals( type ) ) { String message = "Normal steps must include buttons."; WizardLogger.errorWizard( message, null ); } else if ( "normal".equals( type ) ) { buttonsElems[i] = buttonsElem; } } firstStep = (NormalStep) steps[0]; // configure buttons for ( int i = 0; i < buttonsElems.length; i++ ) { // finish steps does not have buttons if ( buttonsElems[i] == null ) { continue; } Element[] buttonElems = XMLTool.getElements( buttonsElems[i] ); if ( buttonElems.length > 0 ) { NormalStep normalStep = (NormalStep) steps[i]; for ( int j = 0; j < buttonElems.length; j++ ) { String name = buttonElems[j].getAttribute( "name" ); int type = getButtonType( buttonElems[j].getAttribute( "type" ) ); if ( type == BUTTON_PREVIOUS ) { if ( normalStep.previousButtonName != null ) { String message = "Only one previous button allowed"; WizardLogger.errorWizard( message, null ); } normalStep.previousButtonName = name; } else if ( type == BUTTON_NEXT ) { normalStep.nextButtons.put( name, new NextButton( stepMap, buttonElems[j] ) ); } else if ( type == BUTTON_CANCEL ) { if ( normalStep.cancelButtonName != null ) { String message = "Only one cancel button allowed for each step."; WizardLogger.errorWizard( message, null ); } else if ( normalStep.closeButtonName != null ) { String message = "Only one cancel or close button allowed for each step."; WizardLogger.errorWizard( message, null ); } normalStep.cancelButtonName = name; } else if ( type == BUTTON_CLOSE ) { if ( normalStep.closeButtonName != null ) { String message = "Only one close button allowed for each step."; WizardLogger.errorWizard( message, null ); } else if ( normalStep.cancelButtonName != null ) { String message = "Only one cancel or close button allowed for each step."; WizardLogger.errorWizard( message, null ); } normalStep.closeButtonName = name; } else if ( type == BUTTON_PROCESS ) { Element elem = XMLTool.getElement( buttonElems[j], "stylesheet" ); if ( elem != null ) { String styleSheetSrc = elem.getAttribute( "src" ); normalStep.processButtonSrcs.put( name, styleSheetSrc ); } else { normalStep.processButtonSrcs.put( name, null ); } } } if ( normalStep.nextButtons.size() == 0 ) { String message = "Each step must contain at least one next button."; WizardLogger.errorWizard( message, null ); } if ( normalStep.cancelButtonName == null && normalStep.closeButtonName == null ) { normalStep.cancelButtonName = "cancel"; } } else { String message = "Each step must contain at least one next button."; WizardLogger.errorWizard( message, null ); } } initialize( admin, wizardconfigDoc ); } /** * Custom init. */ protected abstract void initialize( AdminService admin, Document wizardconfigDoc ) throws WizardException; private WizardState firstStep() { WizardState wizardState = new WizardState(); wizardState.currentStep = firstStep; wizardState.firstStepState = new StepState( firstStep ); wizardState.currentStepState = wizardState.firstStepState; wizardState.stepStateMap.put( firstStep.name, wizardState.firstStepState ); return wizardState; } private void nextStep( WizardState wizardState, HttpSession session, AdminService admin, ExtendedMap formItems ) throws WizardException { // validate state boolean validated = validateState( wizardState, session, admin, formItems ); StepState currentStepState = wizardState.currentStepState; if ( validated ) { currentStepState.setErrorState( false ); NormalStep currentStep = currentStepState.step; // select next step String nextButtonName = currentStepState.buttonPressed; NextButton nextButton = currentStep.nextButtons.get( nextButtonName ); if ( nextButton != null ) { Step nextStep = null; for ( int i = 0; i < nextButton.testConditions.length; i++ ) { String testCondition = nextButton.testConditions[i]; if ( evaluate( wizardState, session, admin, formItems, testCondition ) ) { nextStep = nextButton.nextSteps[i]; break; } } if ( nextStep == null ) { nextStep = nextButton.defaultNextStep; } if ( nextStep.type == Step.NORMAL ) { StepState stepState = new StepState( (NormalStep) nextStep ); currentStepState.nextStepState = stepState; stepState.previousStepState = currentStepState; wizardState.currentStepState = stepState; wizardState.stepStateMap.put( nextStep.name, stepState ); } else { wizardState.currentStepState = null; } wizardState.currentStep = nextStep; } else { String message = "Unknown next button pressed: {0}"; WizardLogger.errorWizard( message, nextButtonName ); } } else { currentStepState.setErrorState( true ); } } private void previousStep( WizardState wizardState, HttpSession session, AdminService admin, ExtendedMap formItems ) throws WizardException { StepState currentStepState = wizardState.currentStepState; // set new current state wizardState.currentStepState = currentStepState.previousStepState; currentStepState.nextStepState = null; wizardState.currentStep = wizardState.currentStepState.step; // save current step state for later if not state dependent //NormalStep currentStep = currentStepState.step; //if ( !currentStep.stateDependent ) { // wizardState.stepStateMap.put( currentStep.name, currentStepState ); // currentStepState.previousStepState = null; // currentStepState.nextStepState = null; //} } protected abstract boolean evaluate( WizardState wizardState, HttpSession session, AdminService admin, ExtendedMap formItems, String testCondition ) throws WizardException; protected abstract void appendCustomData( WizardState wizardState, HttpSession session, AdminService admin, ExtendedMap formItems, ExtendedMap parameters, User user, Document dataconfigDoc, Document wizarddataDoc ) throws WizardException; protected abstract boolean validateState( WizardState wizardState, HttpSession session, AdminService admin, ExtendedMap formItems ); protected abstract void processWizardData( WizardState wizardState, HttpSession session, AdminService admin, ExtendedMap formItems, User user, Document dataDoc ) throws VerticalAdminException, VerticalEngineException, IOException, MessagingException; public final void processRequest( HttpServletRequest request, HttpServletResponse response, HttpSession session, AdminService admin, ExtendedMap formItems, ExtendedMap parameters, User user ) throws VerticalAdminException, VerticalEngineException, IOException, MessagingException { // get wizard state WizardState wizardState = (WizardState) session.getAttribute( "wizardstate_" + wizardId ); String buttonName = formItems.getString( "__wizard_button", null ); // first step if ( wizardState == null || buttonName == null ) { // initialize wizard state wizardState = firstStep(); session.setAttribute( "wizardstate_" + wizardId, wizardState ); // set redirect url wizardState.redirectURL = formItems.getString( "redirect", null ); if ( wizardState.redirectURL == null ) { String referer = request.getHeader( "referer" ); if ( referer == null ) { String message = "No support for referer, please add redirect parameter."; WizardLogger.errorWizard( message, null ); } wizardState.redirectURL = referer; } processCurrentStep( wizardState, request, response, session, admin, formItems, parameters, user ); } // previous, next, cancel, reload or process else { // save common state wizardState.saveCommonState( formItems ); // button type pressed int pressedButtonType = wizardState.getPressedButtonType(); if ( pressedButtonType == BUTTON_CANCEL || pressedButtonType == BUTTON_CLOSE ) { // fire events if ( pressedButtonType == BUTTON_CANCEL ) { cancelClicked( wizardState ); } else { closeClicked( wizardState ); } try { response.sendRedirect( response.encodeRedirectURL( wizardState.redirectURL ) ); } catch ( IOException ioe ) { String message = "Failed to redirect client: %t"; WizardLogger.errorWizard( message, ioe ); } } else { // save custom state saveState( wizardState, request, response, admin, user, formItems ); if ( pressedButtonType == BUTTON_PREVIOUS ) { previousStep( wizardState, session, admin, formItems ); processCurrentStep( wizardState, request, response, session, admin, formItems, parameters, user ); } else if ( pressedButtonType == BUTTON_NEXT ) { nextStep( wizardState, session, admin, formItems ); processCurrentStep( wizardState, request, response, session, admin, formItems, parameters, user ); } else { // reload or process processCurrentStep( wizardState, request, response, session, admin, formItems, parameters, user ); } } } } protected void cancelClicked( WizardState wizardState ) { // default: do nothing } /** * Event fired when close button is clicked. */ protected void closeClicked( WizardState wizardState ) { // default: do nothing } private void processCurrentStep( WizardState wizardState, HttpServletRequest request, HttpServletResponse response, HttpSession session, AdminService admin, ExtendedMap formItems, ExtendedMap parameters, User user ) throws VerticalAdminException, VerticalEngineException, IOException, MessagingException { Step currentStep = wizardState.currentStep; // finish step if ( currentStep.type == Step.FINISH ) { FinishStep finishStep = (FinishStep) currentStep; // process wizard data processWizardDataInternal( wizardState, finishStep.styleSheetSrc, session, admin, formItems, user ); // redirect try { response.sendRedirect( response.encodeRedirectURL( wizardState.redirectURL ) ); } catch ( IOException ioe ) { String message = "Failed to redirect client: %t"; WizardLogger.errorWizard( message, ioe ); } } // normal step, display wizard step else { NormalStep normalStep = (NormalStep) currentStep; // if button type is "process", process wizard data int pressedButtonType = wizardState.getPressedButtonType(); if ( pressedButtonType == BUTTON_PROCESS ) { // validate state boolean validated = validateState( wizardState, session, admin, formItems ); if ( validated ) { String buttonName = wizardState.currentStepState.buttonPressed; String styleSheetSrc = normalStep.processButtonSrcs.get( buttonName ); processWizardDataInternal( wizardState, styleSheetSrc, session, admin, formItems, user ); } } Document wizarddataDoc = XMLTool.createDocument( "wizarddata" ); Element rootElem = wizarddataDoc.getDocumentElement(); // wizard data: add wizard config rootElem.appendChild( wizarddataDoc.importNode( wizardconfigDoc.getDocumentElement(), true ) ); // wizard data: add custom data appendCustomData( wizardState, session, admin, formItems, parameters, user, normalStep.dataconfigDoc, wizarddataDoc ); int unitKey = formItems.getInt( "selectedunitkey", -1 ); int menuKey = formItems.getInt( "menukey", -1 ); servlet.addCommonParameters( admin, user, request, parameters, unitKey, menuKey ); // wizard data: add wizard state Document wizardstateDoc = wizardState.toDocument(); rootElem.appendChild( wizarddataDoc.importNode( wizardstateDoc.getDocumentElement(), true ) ); // transform Source xslSource = buildWizardXSL( session, wizardState ); Source xmlSource = new DOMSource( wizarddataDoc ); try { ExtendedMap transformParams = new ExtendedMap( formItems ); transformParams.putAll( parameters ); String languageCode = (String) session.getAttribute( "languageCode" ); new AdminXsltProcessorHelper( this.servlet.getXsltProcessorFactory() ).stylesheet( xslSource, AdminStore.getURIResolver( languageCode ) ).input( xmlSource ).params( transformParams ).process( response.getWriter() ); } catch ( IOException ioe ) { String message = "Failed to get response writer: %t"; WizardLogger.errorWizard( message, ioe ); } } } private void processWizardDataInternal( WizardState wizardState, String styleSheetSrc, HttpSession session, AdminService admin, ExtendedMap formItems, User user ) throws WizardException, VerticalAdminException, VerticalEngineException, IOException, MessagingException { // transform wizard state (optional) Document dataDoc; if ( styleSheetSrc != null ) { Source xslSource = AdminStore.getStylesheet( session, styleSheetSrc ); Source xmlSource = new DOMSource( wizardState.toDocument() ); String languageCode = (String) session.getAttribute( "languageCode" ); dataDoc = new AdminXsltProcessorHelper( this.servlet.getXsltProcessorFactory() ).stylesheet( xslSource, AdminStore.getURIResolver( languageCode ) ).params( formItems ).input( xmlSource ).processDom(); } else { dataDoc = null; } // process data processWizardData( wizardState, session, admin, formItems, user, dataDoc ); } private Source buildWizardXSL( HttpSession session, WizardState wizardState ) throws WizardException { Source source = null; Source xmlSource = new DOMSource( wizardconfigDoc ); Source xslSource = AdminStore.getStylesheet( session, BUILD_XSL ); Map<String, String> xslParams = new HashMap<String, String>(); xslParams.put( "xsl_prefix", "" ); xslParams.put( "wizard_stepid", String.valueOf( wizardState.currentStep.id ) ); String languageCode = (String) session.getAttribute( "languageCode" ); StringWriter sw = new StringWriter( 4 * 1024 ); new AdminXsltProcessorHelper( this.servlet.getXsltProcessorFactory() ).stylesheet( xslSource, AdminStore.getURIResolver( languageCode ) ).input( xmlSource ).params( xslParams ).process( sw ); source = new StreamSource( new StringReader( sw.toString() ) ); source.setSystemId( xslSource.getSystemId() ); return source; } protected void saveState( WizardState wizardState, HttpServletRequest request, HttpServletResponse response, AdminService admin, User user, ExtendedMap formItems ) throws WizardException { wizardState.saveCustomState( formItems ); } private int getButtonType( String buttonTypeName ) { if ( "previous".equals( buttonTypeName ) ) { return BUTTON_PREVIOUS; } else if ( "next".equals( buttonTypeName ) ) { return BUTTON_NEXT; } else if ( "cancel".equals( buttonTypeName ) ) { return BUTTON_CANCEL; } else if ( "close".equals( buttonTypeName ) ) { return BUTTON_CLOSE; } else if ( "process".equals( buttonTypeName ) ) { return BUTTON_PROCESS; } else if ( "reload".equals( buttonTypeName ) ) { return BUTTON_RELOAD; } else { return BUTTON_NONE; } } }