blob: 5c947d973235610f774bf369642915ca4ad2a9c7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License") + you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openmeetings.web.pages.install;
import static org.apache.openmeetings.util.OpenmeetingsVariables.USER_LOGIN_MINIMUM_LENGTH;
import static org.apache.openmeetings.util.OpenmeetingsVariables.USER_PASSWORD_MINIMUM_LENGTH;
import static org.apache.openmeetings.web.app.WebSession.AVAILABLE_TIMEZONES;
import static org.apache.openmeetings.web.app.WebSession.AVAILABLE_TIMEZONE_SET;
import static org.apache.wicket.validation.validator.RangeValidator.range;
import static org.apache.wicket.validation.validator.StringValidator.minimumLength;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.openmeetings.installation.ImportInitvalues;
import org.apache.openmeetings.installation.InstallationConfig;
import org.apache.openmeetings.web.app.Application;
import org.apache.openmeetings.web.app.WebSession;
import org.apache.openmeetings.web.common.ErrorMessagePanel;
import org.apache.openmeetings.web.common.OmLabel;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AbstractAjaxTimerBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.extensions.validation.validator.RfcCompliantEmailAddressValidator;
import org.apache.wicket.extensions.wizard.IWizardStep;
import org.apache.wicket.extensions.wizard.Wizard;
import org.apache.wicket.extensions.wizard.dynamic.DynamicWizardModel;
import org.apache.wicket.extensions.wizard.dynamic.DynamicWizardStep;
import org.apache.wicket.extensions.wizard.dynamic.IDynamicWizardStep;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.ChoiceRenderer;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.markup.html.form.RequiredTextField;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.util.time.Duration;
import com.googlecode.wicket.jquery.ui.widget.progressbar.ProgressBar;
//TODO maybe JQ wizard should be used
public class InstallWizard extends Wizard {
private static final long serialVersionUID = 1L;
private InstallationConfig cfg;
private CompoundPropertyModel<InstallWizard> model;
private final static List<SelectOption> yesNoList = Arrays.asList(SelectOption.NO, SelectOption.YES);
private final static List<SelectOption> yesNoTextList = Arrays.asList(SelectOption.NO_TEXT, SelectOption.YES_TEXT);
private final static List<String> allFonts = Arrays.asList("TimesNewRoman", "Verdana", "Arial");
private final IDynamicWizardStep welcomeStep;
private final ParamsStep1 paramsStep1;
private final IDynamicWizardStep paramsStep2;
private final IDynamicWizardStep paramsStep3;
private final IDynamicWizardStep paramsStep4;
private final InstallStep installStep;
private Throwable th = null;
public void initTzDropDown() {
paramsStep1.tzDropDown.init();
}
//onInit, applyState
public InstallWizard(String id) throws Exception {
super(id);
//TODO enable install after first params
cfg = new InstallationConfig();
setDefaultModel(model = new CompoundPropertyModel<InstallWizard>(this));
welcomeStep = new WelcomeStep();
paramsStep1 = new ParamsStep1();
paramsStep2 = new ParamsStep2();
paramsStep3 = new ParamsStep3();
paramsStep4 = new ParamsStep4();
//TODO add install/progress step
installStep = new InstallStep();
DynamicWizardModel wmodel = new DynamicWizardModel(welcomeStep);
wmodel.setCancelVisible(false);
wmodel.setLastVisible(true);
init(wmodel);
}
@Override
protected Component newButtonBar(String id) {
final Panel bBar = (Panel)super.newButtonBar(id);
AjaxButton finish = new AjaxButton("finish", new ResourceModel("org.apache.wicket.extensions.wizard.finish")) {
private static final long serialVersionUID = 1L;
public boolean isEnabled() {
IWizardStep activeStep = getWizardModel().getActiveStep();
return ((activeStep != null) && getWizardModel().isLastStep(activeStep));
}
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
installStep.startInstallation(target);
target.add(bBar.setEnabled(false));
}
};
return bBar.replace(finish).setOutputMarkupId(true);
}
private abstract class BaseStep extends DynamicWizardStep {
private static final long serialVersionUID = 1L;
public BaseStep(IDynamicWizardStep prev) {
super(prev);
//TODO localize
setTitleModel(Model.of(cfg.appName + " - Installation"));
setSummaryModel(Model.of(""));
}
}
private final class WelcomeStep extends BaseStep {
private static final long serialVersionUID = 1L;
public WelcomeStep() {
super(null);
//TODO localize
//TODO add check for DB connection
add(new OmLabel("step", "install.wizard.welcome.panel", cfg.appName).setEscapeModelStrings(false));
}
public boolean isLastStep() {
return false;
}
public IDynamicWizardStep next() {
return paramsStep1;
}
}
private final class ParamsStep1 extends BaseStep {
private static final long serialVersionUID = 1L;
private final TzDropDown tzDropDown;
public ParamsStep1() throws Exception {
super(welcomeStep);
//TODO localize
add(new RequiredTextField<String>("cfg.username").add(minimumLength(USER_LOGIN_MINIMUM_LENGTH)));
add(new PasswordTextField("cfg.password").add(minimumLength(USER_PASSWORD_MINIMUM_LENGTH)));
add(new RequiredTextField<String>("cfg.email").add(RfcCompliantEmailAddressValidator.getInstance()));
add(tzDropDown = new TzDropDown("ical_timeZone"));
add(new RequiredTextField<String>("cfg.group"));
}
public boolean isLastStep() {
return false;
}
public IDynamicWizardStep next() {
return paramsStep2;
}
@Override
public boolean isLastAvailable() {
return true;
}
@Override
public IDynamicWizardStep last() {
return installStep;
}
}
private final class ParamsStep2 extends BaseStep {
private static final long serialVersionUID = 1L;
public ParamsStep2() throws Exception {
super(paramsStep1);
//TODO localize
//TODO validation
add(new YesNoDropDown("allowFrontendRegister"));
add(new YesNoDropDown("sendEmailAtRegister"));
add(new YesNoDropDown("sendEmailWithVerficationCode"));
add(new YesNoDropDown("createDefaultRooms"));
add(new TextField<String>("cfg.mailReferer"));
add(new TextField<String>("cfg.smtpServer"));
add(new TextField<Integer>("cfg.smtpPort").setRequired(true));
add(new TextField<String>("cfg.mailAuthName"));
add(new PasswordTextField("cfg.mailAuthPass").setRequired(false));
add(new YesNoDropDown("mailUseTls"));
//TODO check mail server
add(new YesNoDropDown("replyToOrganizer"));
add(new LangDropDown("defaultLangId"));
add(new DropDownChoice<String>("cfg.defaultExportFont", allFonts));
}
public boolean isLastStep() {
return false;
}
public IDynamicWizardStep next() {
return paramsStep3;
}
@Override
public boolean isLastAvailable() {
return true;
}
@Override
public IDynamicWizardStep last() {
return installStep;
}
}
private final class ParamsStep3 extends BaseStep {
private static final long serialVersionUID = 1L;
public ParamsStep3() {
super(paramsStep2);
add(new TextField<Integer>("cfg.swfZoom").setRequired(true).add(range(50, 600)));
add(new TextField<Integer>("cfg.swfJpegQuality").setRequired(true).add(range(1, 100)));
add(new TextField<String>("cfg.swfPath"));
add(new TextField<String>("cfg.imageMagicPath"));
add(new TextField<String>("cfg.ffmpegPath"));
add(new TextField<String>("cfg.soxPath"));
add(new TextField<String>("cfg.jodPath"));
add(new TextField<String>("cfg.officePath"));
}
public boolean isLastStep() {
return false;
}
public IDynamicWizardStep next() {
return paramsStep4;
}
@Override
public boolean isLastAvailable() {
return true;
}
@Override
public IDynamicWizardStep last() {
return installStep;
}
}
private final class ParamsStep4 extends BaseStep {
private static final long serialVersionUID = 1L;
public ParamsStep4() {
super(paramsStep3);
add(new RequiredTextField<String>("cfg.cryptClassName")); //Validate class
//TODO add check for red5sip connection
add(new YesNoTextDropDown("red5SipEnable"));
add(new TextField<String>("cfg.red5SipRoomPrefix"));
add(new TextField<String>("cfg.red5SipExtenContext"));
}
public boolean isLastStep() {
return false;
}
public IDynamicWizardStep next() {
return installStep;
}
@Override
public boolean isLastAvailable() {
return true;
}
@Override
public IDynamicWizardStep last() {
return installStep;
}
}
private final class InstallStep extends BaseStep {
private static final long serialVersionUID = 1L;
private final CongratulationsPanel congrat;
private WebMarkupContainer container = new WebMarkupContainer("container");
private AbstractAjaxTimerBehavior timer;
private ProgressBar progressBar;
private Label desc = new Label("desc", getString("install.wizard.install.desc"));
private boolean started = false;
public void startInstallation(AjaxRequestTarget target) {
started = true;
timer.restart(target);
new Thread(new InstallProcess(Application.get()._getBean(ImportInitvalues.class))
, "Openmeetings - Installation").start();
//progressBar.setVisible(true);
desc.setDefaultModelObject(getString("install.wizard.install.started"));
target.add(desc, container);
}
public InstallStep() {
super(paramsStep4);
add(desc.setOutputMarkupId(true));
// Timer //
container.add(timer = new AbstractAjaxTimerBehavior(Duration.ONE_SECOND) {
private static final long serialVersionUID = 1L;
@Override
protected void onTimer(AjaxRequestTarget target) {
if (!started) {
timer.stop(target);
return;
}
if (th != null) {
timer.stop(target);
//TODO change text, localize
progressBar.setVisible(false);
target.add(container.replace(new ErrorMessagePanel("status", getString("install.wizard.install.failed"), th))
, desc.setVisible(false)
);
} else {
progressBar.setModelObject(Application.get()._getBean(ImportInitvalues.class).getProgress());
progressBar.respond(target);
//TODO uncomment later target.add(value);
//TODO add current step result as info
}
}
});
container.add(progressBar = new ProgressBar("progress", new Model<Integer>(0)) {
private static final long serialVersionUID = 1L;
@Override
protected void onComplete(AjaxRequestTarget target) {
timer.stop(target);
progressBar.setVisible(false);
congrat.setVisible(true);
target.add(container, desc.setVisible(false));
}
});
//TODO uncomment later progressBar.add(value = new Label("value", progressBar.getModel()));
//TODO uncomment later value.setOutputMarkupId(true);
//progressBar.setVisible(false);
container.add(congrat = new CongratulationsPanel("status"));
congrat.setVisible(false);
add(container.setOutputMarkupId(true));
}
public boolean isLastStep() {
return true;
}
public IDynamicWizardStep next() {
return null;
}
}
private class InstallProcess implements Runnable {
private ImportInitvalues installer;
public InstallProcess(ImportInitvalues installer) {
this.installer = installer;
th = null;
}
public void run() {
try {
installer.loadAll(cfg, true);
} catch (Exception e) {
th = e;
}
}
}
private static class SelectOption implements Serializable {
private static final long serialVersionUID = 2559982745410615390L;
private static SelectOption NO = new SelectOption("0", "No");
private static SelectOption NO_TEXT = new SelectOption("no", "No");
private static SelectOption YES = new SelectOption("1", "Yes");
private static SelectOption YES_TEXT = new SelectOption("yes", "Yes");
public String key;
@SuppressWarnings("unused")
public String value;
SelectOption(String key, String value) {
this.key = key;
this.value = value;
}
}
private abstract class WizardDropDown<T> extends DropDownChoice<T> {
private static final long serialVersionUID = 8870736740532631296L;
T option;
IModel<Object> propModel;
WizardDropDown(String id) {
super(id);
propModel = InstallWizard.this.model.bind("cfg." + id);
setModel(new PropertyModel<T>(this, "option"));
}
}
private final class TzDropDown extends WizardDropDown<String> {
private static final long serialVersionUID = 1L;
public void init() {
List<String> tzList = AVAILABLE_TIMEZONES;
String tzId = WebSession.get().getClientTimeZone();
option = AVAILABLE_TIMEZONE_SET.contains(tzId) ? tzId : tzList.get(0);
}
public TzDropDown(String id) throws Exception {
super(id);
setChoices(AVAILABLE_TIMEZONES);
setChoiceRenderer(new IChoiceRenderer<String>() {
private static final long serialVersionUID = 1L;
public Object getDisplayValue(String object) {
return object.toString();
}
public String getIdValue(String object, int index) {
return object.toString();
}
});
}
@Override
protected void onModelChanged() {
if (propModel != null && option != null) {
propModel.setObject(option);
}
}
}
private class SelectOptionDropDown extends WizardDropDown<SelectOption> {
private static final long serialVersionUID = -1433015274371279328L;
SelectOptionDropDown(String id) {
super(id);
setChoiceRenderer(new ChoiceRenderer<SelectOption>("value", "key"));
}
@Override
protected void onModelChanged() {
if (propModel != null && option != null) {
propModel.setObject(option.key);
}
}
}
private final class YesNoDropDown extends SelectOptionDropDown {
private static final long serialVersionUID = 578375825530725477L;
YesNoDropDown(String id) {
super(id);
setChoices(yesNoList);
this.option = SelectOption.NO.key.equals(propModel.getObject()) ?
SelectOption.NO : SelectOption.YES;
}
}
private final class YesNoTextDropDown extends SelectOptionDropDown {
private static final long serialVersionUID = 578375825530725477L;
YesNoTextDropDown(String id) {
super(id);
setChoices(yesNoTextList);
this.option = SelectOption.NO_TEXT.key.equals(propModel.getObject()) ?
SelectOption.NO_TEXT : SelectOption.YES_TEXT;
}
}
private final class LangDropDown extends SelectOptionDropDown {
private static final long serialVersionUID = -2826765890538795285L;
public LangDropDown(String id) throws Exception {
super(id);
Map<Integer, Map<String, Object>> allLanguagesAll = ImportInitvalues.getLanguageFiles();
List<SelectOption> list = new ArrayList<SelectOption>();
for (Integer key : allLanguagesAll.keySet()) {
String langName = (String) allLanguagesAll.get(key).get("name");
String langCode = (String) allLanguagesAll.get(key).get("code");
SelectOption op = new SelectOption(key.toString(), langName);
if (langCode != null) {
if (getSession().getLocale().toString().startsWith(langCode)) {
option = op;
}
list.add(op);
}
if (option == null && key.toString().equals(cfg.defaultLangId)) {
option = op;
}
}
setChoices(list);
}
}
}