| /* |
| * 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.core.converter.BaseConverter.EXEC_EXT; |
| import static org.apache.openmeetings.util.OpenmeetingsVariables.USER_LOGIN_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 static org.springframework.web.context.support.WebApplicationContextUtils.getWebApplicationContext; |
| |
| import java.io.File; |
| import java.io.Serializable; |
| import java.net.URI; |
| import java.sql.Connection; |
| import java.sql.DriverManager; |
| import java.sql.PreparedStatement; |
| import java.time.Duration; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| |
| import org.apache.openmeetings.cli.ConnectionPropertiesPatcher; |
| import org.apache.openmeetings.core.converter.DocumentConverter; |
| import org.apache.openmeetings.core.util.StrongPasswordValidator; |
| import org.apache.openmeetings.db.dao.label.LabelDao; |
| import org.apache.openmeetings.db.entity.user.User; |
| import org.apache.openmeetings.installation.ImportInitvalues; |
| import org.apache.openmeetings.installation.InstallationConfig; |
| import org.apache.openmeetings.util.ConnectionProperties; |
| import org.apache.openmeetings.util.ConnectionProperties.DbType; |
| import org.apache.openmeetings.util.OmFileHelper; |
| import org.apache.openmeetings.util.process.ProcessHelper; |
| import org.apache.openmeetings.util.process.ProcessResult; |
| 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.openmeetings.web.util.OmTooltipBehavior; |
| import org.apache.openmeetings.web.util.ThreadHelper; |
| import org.apache.wicket.Component; |
| import org.apache.wicket.ajax.AjaxRequestTarget; |
| import org.apache.wicket.ajax.attributes.AjaxRequestAttributes; |
| import org.apache.wicket.ajax.form.AjaxFormSubmitBehavior; |
| import org.apache.wicket.ajax.form.OnChangeAjaxBehavior; |
| import org.apache.wicket.core.request.handler.IPartialPageRequestHandler; |
| import org.apache.wicket.extensions.validation.validator.RfcCompliantEmailAddressValidator; |
| import org.apache.wicket.extensions.wizard.IWizard; |
| import org.apache.wicket.extensions.wizard.WizardButton; |
| import org.apache.wicket.extensions.wizard.WizardButtonBar; |
| 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.Button; |
| import org.apache.wicket.markup.html.form.CheckBox; |
| 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.PasswordTextField; |
| import org.apache.wicket.markup.html.form.RequiredTextField; |
| import org.apache.wicket.markup.html.form.TextField; |
| 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.model.StringResourceModel; |
| import org.apache.wicket.request.cycle.RequestCycle; |
| import org.apache.wicket.spring.injection.annot.SpringBean; |
| import org.apache.wicket.util.string.Strings; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| import org.springframework.orm.jpa.LocalEntityManagerFactoryBean; |
| import org.springframework.web.context.support.XmlWebApplicationContext; |
| |
| import de.agilecoders.wicket.core.markup.html.bootstrap.button.BootstrapAjaxButton; |
| import de.agilecoders.wicket.core.markup.html.bootstrap.button.ButtonBehavior; |
| import de.agilecoders.wicket.core.markup.html.bootstrap.button.Buttons; |
| import de.agilecoders.wicket.core.markup.html.bootstrap.button.Buttons.Type; |
| import de.agilecoders.wicket.core.markup.html.bootstrap.common.NotificationPanel; |
| import de.agilecoders.wicket.core.markup.html.bootstrap.components.progress.UpdatableProgressBar; |
| import de.agilecoders.wicket.core.markup.html.bootstrap.utilities.BackgroundColorBehavior; |
| import de.agilecoders.wicket.extensions.markup.html.bootstrap.spinner.SpinnerAjaxButton; |
| import de.agilecoders.wicket.extensions.wizard.BootstrapWizard; |
| |
| public class InstallWizard extends BootstrapWizard { |
| private static final long serialVersionUID = 1L; |
| private static final Logger log = LoggerFactory.getLogger(InstallWizard.class); |
| private IDynamicWizardStep welcomeStep; |
| private IDynamicWizardStep dbStep; |
| private ParamsStep1 paramsStep1; |
| private IDynamicWizardStep paramsStep2; |
| private IDynamicWizardStep paramsStep3; |
| private IDynamicWizardStep paramsStep4; |
| private InstallStep installStep; |
| private Throwable th = null; |
| private DbType initDbType = null; |
| private DbType dbType = null; |
| private NotificationPanel feedback; |
| private final CompoundPropertyModel<InstallationConfig> model; |
| private final List<Button> buttons = new ArrayList<>(4); |
| private WizardButtonBar btnBar; |
| |
| @SpringBean |
| private ImportInitvalues initvalues; |
| |
| //onInit, applyState |
| public InstallWizard(String id, String title) { |
| super(id); |
| setOutputMarkupPlaceholderTag(true); |
| setOutputMarkupId(true); |
| model = new CompoundPropertyModel<>(new InstallationConfig()); |
| setDefaultModel(model); |
| } |
| |
| @Override |
| protected void onInitialize() { |
| welcomeStep = new WelcomeStep(); |
| dbStep = new DbStep(); |
| paramsStep1 = new ParamsStep1(); |
| paramsStep2 = new ParamsStep2(); |
| paramsStep3 = new ParamsStep3(); |
| paramsStep4 = new ParamsStep4(); |
| installStep = new InstallStep(); |
| DynamicWizardModel wmodel = new DynamicWizardModel(welcomeStep); |
| wmodel.setCancelVisible(false); |
| wmodel.setLastVisible(true); |
| init(wmodel); |
| |
| super.onInitialize(); |
| } |
| |
| public void initTzDropDown() { |
| paramsStep1.tzDropDown.setOption(); |
| } |
| |
| @Override |
| protected WebMarkupContainer newFeedbackPanel(String id) { |
| feedback = (NotificationPanel)super.newFeedbackPanel(id); |
| feedback.setEscapeModelStrings(false).setOutputMarkupId(true); |
| return feedback; |
| } |
| |
| @Override |
| protected Component newButtonBar(String id) { |
| btnBar = new WizardButtonBar(id, this) { |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| protected WizardButton newCancelButton(String id, IWizard wizard) { |
| WizardButton button = super.newCancelButton(id, wizard); |
| button.add(new ButtonBehavior(Type.Outline_Warning, Buttons.Size.Medium)); |
| return button; |
| } |
| |
| @Override |
| protected WizardButton newFinishButton(String id, IWizard wizard) { |
| WizardButton button = super.newFinishButton(id, wizard); |
| button.add(new ButtonBehavior(Type.Outline_Success, Buttons.Size.Medium)); |
| button.add(new AjaxFormSubmitBehavior("click") { |
| private static final long serialVersionUID = 1L; |
| |
| |
| @Override |
| protected void updateAjaxAttributes(AjaxRequestAttributes attributes) { |
| super.updateAjaxAttributes(attributes); |
| |
| // do not allow normal form submit to happen |
| attributes.setPreventDefault(true); |
| } |
| |
| @Override |
| protected void onSubmit(AjaxRequestTarget target) { |
| button.onSubmit(); |
| } |
| }); |
| buttons.add(button); |
| return button; |
| } |
| |
| @Override |
| protected WizardButton newLastButton(String id, IWizard wizard) { |
| WizardButton button = super.newLastButton(id, wizard); |
| button.add(new ButtonBehavior(Type.Outline_Secondary, Buttons.Size.Medium)); |
| buttons.add(button); |
| return button; |
| } |
| |
| @Override |
| protected WizardButton newNextButton(String id, IWizard wizard) { |
| WizardButton button = super.newNextButton(id, wizard); |
| button.add(new ButtonBehavior(Type.Outline_Secondary, Buttons.Size.Medium)); |
| buttons.add(button); |
| return button; |
| } |
| |
| @Override |
| protected WizardButton newPreviousButton(String id, IWizard wizard) { |
| WizardButton button = super.newPreviousButton(id, wizard); |
| button.add(new ButtonBehavior(Type.Outline_Secondary, Buttons.Size.Medium)); |
| buttons.add(button); |
| return button; |
| } |
| }; |
| btnBar.setOutputMarkupId(true); |
| return btnBar; |
| } |
| |
| private abstract class BaseStep extends DynamicWizardStep { |
| private static final long serialVersionUID = 1L; |
| |
| public BaseStep(IDynamicWizardStep prev) { |
| super(prev); |
| } |
| |
| @Override |
| protected void onInitialize() { |
| super.onInitialize(); |
| setSummaryModel(Model.of("")); |
| setTitleModel(Model.of(model.getObject().getAppName() + " - " + getString("install.wizard.installation"))); |
| } |
| } |
| |
| private final class WelcomeStep extends BaseStep { |
| private static final long serialVersionUID = 1L; |
| |
| public WelcomeStep() { |
| super(null); |
| } |
| |
| @Override |
| protected void onInitialize() { |
| super.onInitialize(); |
| add(new Label("step", getString("install.wizard.welcome.panel")).setEscapeModelStrings(false)); |
| } |
| |
| @Override |
| public boolean isLastStep() { |
| return false; |
| } |
| |
| @Override |
| public IDynamicWizardStep next() { |
| return dbStep; |
| } |
| } |
| |
| private final class DbStep extends BaseStep { |
| private static final long serialVersionUID = 1L; |
| private final RequiredTextField<String> host = new RequiredTextField<>("host", Model.of("")); |
| private final RequiredTextField<Integer> port = new RequiredTextField<>("port", Model.of(0)); |
| private final RequiredTextField<String> dbname = new RequiredTextField<>("dbname", Model.of("")); |
| private final RequiredTextField<String> user = new RequiredTextField<>("login"); |
| private final TextField<String> pass = new TextField<>("password"); |
| private final Form<ConnectionProperties> form = new Form<>("form", new CompoundPropertyModel<>(getProps(null))) { |
| private static final long serialVersionUID = 1L; |
| private final DropDownChoice<DbType> db = new DropDownChoice<>("dbType", List.of(DbType.values()), new ChoiceRenderer<DbType>() { |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| public Object getDisplayValue(DbType object) { |
| return getString(String.format("install.wizard.db.step.%s.name", object.dbName())); |
| } |
| |
| @Override |
| public String getIdValue(DbType object, int index) { |
| return object.name(); |
| } |
| }); |
| |
| @Override |
| protected void onInitialize() { |
| super.onInitialize(); |
| add(db.add(new OnChangeAjaxBehavior() { |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| protected void onUpdate(AjaxRequestTarget target) { |
| target.add(feedback); |
| initForm(true, target); |
| } |
| })); |
| add(host, port, dbname, user, pass); |
| add(new SpinnerAjaxButton("check", new ResourceModel("install.wizard.db.step.check"), Buttons.Type.Outline_Primary) { |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| protected void onSubmit(AjaxRequestTarget target) { |
| target.add(feedback); |
| } |
| |
| @Override |
| protected void onError(AjaxRequestTarget target) { |
| target.add(feedback); |
| } |
| }); |
| } |
| |
| private String getDbName(ConnectionProperties props) { |
| return getString("install.wizard.db.step.instructions." + props.getDbType().dbName()); |
| } |
| |
| @Override |
| protected void onValidateModelObjects() { |
| ConnectionProperties props = getModelObject(); |
| try { |
| Class.forName(props.getDriver()); |
| } catch (Exception e) { |
| form.error(new StringResourceModel("install.wizard.db.step.nodriver", InstallWizard.this).setParameters(getDbName(props)).getObject()); |
| return; |
| } |
| boolean valid = true; |
| ConnectionPropertiesPatcher.updateUrl(props, host.getModelObject(), "" + port.getModelObject(), dbname.getModelObject()); |
| DriverManager.setLoginTimeout(3); |
| try (Connection conn = DriverManager.getConnection(props.getURL(), props.getLogin(), props.getPassword())) { |
| valid = conn.isValid(0); //no timeout |
| String sql = null; |
| switch (props.getDbType()) { |
| case DB2: |
| sql = "select count(*) from systables"; |
| break; |
| case ORACLE: |
| sql = "SELECT 1 FROM DUAL"; |
| break; |
| default: |
| sql = "SELECT 1"; |
| break; |
| } |
| try (PreparedStatement ps = conn.prepareStatement(sql)) { |
| valid &= ps.execute(); |
| } |
| if (!valid) { |
| form.error(getString("install.wizard.db.step.notvalid") + "<br/>" + getDbName(props)); |
| } |
| } catch (Exception e) { |
| form.error(e.getMessage() + "<br/>" + getDbName(props)); |
| log.error("error while testing DB", e); |
| valid = false; |
| } |
| if (valid) { |
| form.success(getString("install.wizard.db.step.valid")); |
| } |
| } |
| |
| @Override |
| protected void onSubmit() { |
| try { |
| ConnectionPropertiesPatcher.patch(getModelObject()); |
| XmlWebApplicationContext ctx = (XmlWebApplicationContext)getWebApplicationContext(Application.get().getServletContext()); |
| if (ctx == null) { |
| form.error(new StringResourceModel("install.wizard.db.step.error.patch", InstallWizard.this).setParameters("Web context is NULL").getObject()); |
| log.error("Web context is NULL"); |
| return; |
| } |
| LocalEntityManagerFactoryBean emb = ctx.getBeanFactory().getBean(LocalEntityManagerFactoryBean.class); |
| emb.afterPropertiesSet(); |
| dbType = getModelObject().getDbType(); |
| } catch (Exception e) { |
| form.error(new StringResourceModel("install.wizard.db.step.error.patch", InstallWizard.this).setParameters(e.getMessage()).getObject()); |
| log.error("error while patching", e); |
| } |
| } |
| }; |
| |
| public DbStep() { |
| super(welcomeStep); |
| } |
| |
| private ConnectionProperties getProps(DbType type) { |
| ConnectionProperties props = new ConnectionProperties(); |
| try { |
| File conf = OmFileHelper.getPersistence(type); |
| if (!conf.exists() && type == null) { |
| return props; // initial select |
| } |
| props = ConnectionPropertiesPatcher.getConnectionProperties(conf); |
| if (DbType.H2 != props.getDbType()) { |
| // resetting default login/password |
| props.setLogin(null); |
| props.setPassword(null); |
| } |
| } catch (Exception e) { |
| form.warn(getString("install.wizard.db.step.errorprops")); |
| } |
| return props; |
| } |
| |
| private void initForm(boolean getProps, AjaxRequestTarget target) { |
| ConnectionProperties props = getProps ? getProps(form.getModelObject().getDbType()) : form.getModelObject(); |
| form.setModelObject(props); |
| host.setVisible(props.getDbType() != DbType.H2); |
| port.setVisible(props.getDbType() != DbType.H2); |
| user.setVisible(props.getDbType() != DbType.H2); |
| pass.setVisible(props.getDbType() != DbType.H2); |
| try { |
| switch (props.getDbType()) { |
| case MSSQL: |
| dbMssql(props); |
| break; |
| case ORACLE: |
| dbOracle(props); |
| break; |
| case H2: |
| dbH2(props); |
| break; |
| default: |
| URI uri = URI.create(props.getURL().substring(5)); |
| host.setModelObject(uri.getHost()); |
| port.setModelObject(uri.getPort()); |
| dbname.setModelObject(uri.getPath().substring(1)); |
| break; |
| } |
| } catch (Exception e) { |
| form.warn(getString("install.wizard.db.step.errorprops")); |
| } |
| if (target != null) { |
| target.add(form); |
| } |
| } |
| |
| private void dbMssql(ConnectionProperties props) { |
| String url = props.getURL().substring("jdbc:sqlserver://".length()); |
| String[] parts = url.split(";"); |
| String[] hp = parts[0].split(":"); |
| host.setModelObject(hp[0]); |
| port.setModelObject(Integer.parseInt(hp[1])); |
| dbname.setModelObject(parts[1].substring(parts[1].indexOf('=') + 1)); |
| } |
| |
| private void dbOracle(ConnectionProperties props) { |
| String[] parts = props.getURL().split(":"); |
| host.setModelObject(parts[3].substring(1)); |
| port.setModelObject(Integer.parseInt(parts[4])); |
| dbname.setModelObject(parts[5]); |
| } |
| |
| private void dbH2(ConnectionProperties props) { |
| host.setModelObject(""); |
| port.setModelObject(0); |
| String[] parts = props.getURL().split(";"); |
| dbname.setModelObject(parts[0].substring("jdbc:h2:".length())); |
| } |
| |
| @Override |
| protected void onInitialize() { |
| super.onInitialize(); |
| add(form.setOutputMarkupId(true)); |
| initDbType = form.getModelObject().getDbType(); |
| initForm(false, null); |
| add(new OmLabel("note", "install.wizard.db.step.note", model.getObject().getAppName(), getString("install.wizard.db.step.instructions.h2") |
| , getString("install.wizard.db.step.instructions.mysql"), getString("install.wizard.db.step.instructions.postgresql") |
| , getString("install.wizard.db.step.instructions.db2"), getString("install.wizard.db.step.instructions.mssql") |
| , getString("install.wizard.db.step.instructions.oracle")).setEscapeModelStrings(false)); |
| } |
| |
| @Override |
| public boolean isLastStep() { |
| return false; |
| } |
| |
| @Override |
| public IDynamicWizardStep next() { |
| return paramsStep1; |
| } |
| } |
| |
| private final class ParamsStep1 extends BaseStep { |
| private static final long serialVersionUID = 1L; |
| private final TzDropDown tzDropDown = new TzDropDown("timeZone"); |
| |
| public ParamsStep1() { |
| super(dbStep); |
| } |
| |
| @Override |
| protected void onInitialize() { |
| super.onInitialize(); |
| add(tzDropDown); |
| add(new RequiredTextField<String>("username").setLabel(new ResourceModel("install.wizard.params.step1.username")).add(minimumLength(USER_LOGIN_MINIMUM_LENGTH))); |
| add(new PasswordTextField("password") |
| .setResetPassword(false).setLabel(new ResourceModel("install.wizard.params.step1.password")) |
| .add(new StrongPasswordValidator(new User()))); |
| add(new RequiredTextField<String>("email").setLabel(new ResourceModel("lbl.email")).add(RfcCompliantEmailAddressValidator.getInstance())); |
| add(new RequiredTextField<String>("group").setLabel(new ResourceModel("install.wizard.params.step1.group"))); |
| } |
| |
| @Override |
| public boolean isLastStep() { |
| return false; |
| } |
| |
| @Override |
| public boolean isLastAvailable() { |
| return true; |
| } |
| |
| @Override |
| public IDynamicWizardStep next() { |
| return paramsStep2; |
| } |
| |
| @Override |
| public IDynamicWizardStep last() { |
| return installStep; |
| } |
| } |
| |
| private final class ParamsStep2 extends BaseStep { |
| private static final long serialVersionUID = 1L; |
| |
| public ParamsStep2() { |
| super(paramsStep1); |
| } |
| |
| @Override |
| protected void onInitialize() { |
| super.onInitialize(); |
| add(new CheckBox("allowFrontendRegister")); |
| add(new CheckBox("sendEmailAtRegister")); |
| add(new CheckBox("sendEmailWithVerficationCode")); |
| add(new CheckBox("createDefaultObjects")); |
| add(new TextField<String>("mailReferer")); |
| add(new TextField<String>("smtpServer")); |
| add(new TextField<Integer>("smtpPort").setRequired(true)); |
| add(new TextField<String>("mailAuthName")); |
| add(new PasswordTextField("mailAuthPass").setResetPassword(false).setRequired(false)); |
| add(new CheckBox("mailUseTls")); |
| add(new CheckBox("replyToOrganizer")); |
| add(new LangDropDown("defaultLangId")); |
| } |
| |
| @Override |
| public boolean isLastStep() { |
| return false; |
| } |
| |
| @Override |
| public IDynamicWizardStep next() { |
| return paramsStep3; |
| } |
| |
| @Override |
| public IDynamicWizardStep last() { |
| return installStep; |
| } |
| } |
| |
| private final class ParamsStep3 extends BaseStep { |
| private static final long serialVersionUID = 1L; |
| private static final String REGEX = "\\r\\n|\\r|\\n"; |
| private static final String OPT_VERSION = "-version"; |
| private final TextField<String> ffmpegPath = new TextField<>("ffmpegPath"); |
| private final TextField<String> imageMagicPath = new TextField<>("imageMagicPath"); |
| private final TextField<String> soxPath = new TextField<>("soxPath"); |
| private final TextField<String> officePath = new TextField<>("officePath"); |
| private boolean isAllChecked = false; |
| |
| public ParamsStep3() { |
| super(paramsStep2); |
| } |
| |
| @Override |
| protected void onInitialize() { |
| super.onInitialize(); |
| add(imageMagicPath.setLabel(new ResourceModel("install.wizard.params.step3.imageMagicPath"))); |
| add(ffmpegPath.setLabel(new ResourceModel("install.wizard.params.step3.ffmpegPath"))); |
| add(soxPath.setLabel(new ResourceModel("install.wizard.params.step3.soxPath"))); |
| add(officePath.setLabel(new ResourceModel("install.wizard.params.step3.officePath"))); |
| add(new TextField<Integer>("docDpi").setRequired(true).add(range(50, 600))); |
| add(new TextField<Integer>("docQuality").setRequired(true).add(range(1, 100))); |
| add(new BootstrapAjaxButton("validateImageMagic", new ResourceModel("install.wizard.db.step.check"), Buttons.Type.Outline_Primary) { |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| protected void onSubmit(AjaxRequestTarget target) { |
| checkMagicPath(); |
| target.add(feedback); |
| } |
| }); |
| add(new BootstrapAjaxButton("validateFfmpeg", new ResourceModel("install.wizard.db.step.check"), Buttons.Type.Outline_Primary) { |
| private static final long serialVersionUID = 1L; |
| @Override |
| protected void onSubmit(AjaxRequestTarget target) { |
| checkFfmpegPath(); |
| target.add(feedback); |
| } |
| }); |
| add(new BootstrapAjaxButton("validateSox", new ResourceModel("install.wizard.db.step.check"), Buttons.Type.Outline_Primary) { |
| private static final long serialVersionUID = 1L; |
| @Override |
| protected void onSubmit(AjaxRequestTarget target) { |
| checkSoxPath(); |
| target.add(feedback); |
| } |
| }); |
| add(new BootstrapAjaxButton("validateOffice", new ResourceModel("install.wizard.db.step.check"), Buttons.Type.Outline_Primary) { |
| private static final long serialVersionUID = 1L; |
| @Override |
| protected void onSubmit(AjaxRequestTarget target) { |
| checkOfficePath(); |
| target.add(feedback); |
| } |
| }); |
| add(new OmTooltipBehavior()); |
| } |
| |
| private void reportSuccess(TextField<String> path) { |
| path.success(path.getLabel().getObject() + " - " + getString("54")); |
| } |
| |
| private boolean checkToolPath(TextField<String> path, List<String> args) { |
| ProcessResult result = ProcessHelper.exec(path.getInputName() + " path:: '" + path.getValue() + "'", args); |
| if (!result.isOk()) { |
| path.error(result.getError().replaceAll(REGEX, "")); |
| } else { |
| reportSuccess(path); |
| } |
| return result.isOk(); |
| } |
| |
| private boolean checkMagicPath() { |
| return checkToolPath(imageMagicPath, List.of(getToolPath(imageMagicPath.getValue(), "convert" + EXEC_EXT), OPT_VERSION)); |
| } |
| |
| private boolean checkFfmpegPath() { |
| return checkToolPath(ffmpegPath, List.of(getToolPath(ffmpegPath.getValue(), "ffmpeg" + EXEC_EXT), OPT_VERSION)); |
| } |
| |
| private boolean checkSoxPath() { |
| return checkToolPath(soxPath, List.of(getToolPath(soxPath.getValue(), "sox" + EXEC_EXT), "--version")); |
| } |
| |
| private boolean checkOfficePath() { |
| String err = ""; |
| try { |
| DocumentConverter.createOfficeManager(officePath.getValue(), null); |
| reportSuccess(officePath); |
| } catch (Exception ex) { |
| String msg = ex.getMessage(); |
| officePath.error(err = (msg == null ? "" : msg.replaceAll(REGEX, ""))); |
| } |
| return err.isEmpty(); |
| } |
| |
| private boolean checkAllPath() { |
| boolean result = checkMagicPath(); |
| result = checkFfmpegPath() && result; |
| result = checkSoxPath() && result; |
| result = checkOfficePath() && result; |
| isAllChecked = true; |
| return result; |
| } |
| |
| @Override |
| public boolean isLastStep() { |
| return false; |
| } |
| |
| @Override |
| public IDynamicWizardStep next() { |
| if (!isAllChecked && !checkAllPath()) { |
| return this; |
| } |
| return paramsStep4; |
| } |
| |
| @Override |
| public boolean isLastAvailable() { |
| return isAllChecked; |
| } |
| |
| @Override |
| public IDynamicWizardStep last() { |
| return installStep; |
| } |
| |
| private String getToolPath(String inPath, String app) { |
| StringBuilder path = new StringBuilder(); |
| if (!Strings.isEmpty(inPath)) { |
| path.append(inPath); |
| if (!inPath.endsWith(File.separator)) { |
| path.append(File.separator); |
| } |
| } |
| path.append(app); |
| return path.toString(); |
| } |
| } |
| |
| private final class ParamsStep4 extends BaseStep { |
| private static final long serialVersionUID = 1L; |
| |
| public ParamsStep4() { |
| super(paramsStep3); |
| } |
| |
| @Override |
| protected void onInitialize() { |
| super.onInitialize(); |
| add(new RequiredTextField<String>("cryptClassName")); //Validate class |
| |
| add(new CheckBox("sipEnable")); |
| add(new TextField<String>("sipRoomPrefix")); |
| add(new TextField<String>("sipExtenContext")); |
| add(new OmTooltipBehavior()); |
| } |
| |
| @Override |
| public boolean isLastStep() { |
| return false; |
| } |
| |
| @Override |
| 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 = new CongratulationsPanel("status"); |
| private final WebMarkupContainer container = new WebMarkupContainer("container"); |
| private final UpdatableProgressBar progressBar = new UpdatableProgressBar("progress", new Model<>(0), BackgroundColorBehavior.Color.Info, true) { |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| protected IModel<Integer> newValue() { |
| return Model.of(initvalues.getProgress()); |
| } |
| |
| @Override |
| protected void onPostProcessTarget(IPartialPageRequestHandler target) { |
| if (!started) { |
| stop(target); |
| return; |
| } |
| if (th != null) { |
| stop(target); |
| progressBar.setVisible(false); |
| target.add(container.replace(new ErrorMessagePanel("status", getString("install.wizard.install.failed"), th)) |
| , desc.setVisible(false) |
| ); |
| } |
| super.onPostProcessTarget(target); |
| } |
| |
| @Override |
| protected void onComplete(IPartialPageRequestHandler target) { |
| stop(target); |
| progressBar.setVisible(false); |
| congrat.show(initDbType != dbType); |
| target.add(container, desc.setVisible(false), btnBar.setVisible(false)); |
| } |
| }; |
| private final Label desc = new Label("desc", ""); |
| private boolean started = false; |
| |
| public InstallStep() { |
| super(paramsStep4); |
| } |
| |
| @Override |
| public void applyState() { |
| started = true; |
| ThreadHelper.startRunnable(new InstallProcess(initvalues) |
| , "Openmeetings - Installation"); |
| desc.setDefaultModelObject(getString("install.wizard.install.started")); |
| RequestCycle.get().find(AjaxRequestTarget.class).ifPresent(target -> { |
| progressBar.restart(target).setModelObject(0); |
| buttons.forEach(b -> target.add(b.setEnabled(false))); |
| target.add(desc, container); |
| }); |
| } |
| |
| @Override |
| protected void onInitialize() { |
| super.onInitialize(); |
| progressBar.updateInterval(Duration.ofSeconds(1)).stop(null).striped(false).setOutputMarkupId(true); |
| container.add(progressBar, congrat); |
| congrat.setVisible(false); |
| |
| add(container.setOutputMarkupId(true)); |
| desc.setDefaultModelObject(getString("install.wizard.install.desc")); |
| add(desc.setOutputMarkupId(true)); |
| } |
| |
| @Override |
| public boolean isLastStep() { |
| return true; |
| } |
| |
| @Override |
| public IDynamicWizardStep next() { |
| return null; |
| } |
| } |
| |
| private class InstallProcess implements Runnable { |
| private ImportInitvalues installer; |
| |
| public InstallProcess(ImportInitvalues installer) { |
| this.installer = installer; |
| th = null; |
| } |
| |
| @Override |
| public void run() { |
| try { |
| installer.loadAll(model.getObject(), true); |
| } catch (Exception e) { |
| th = e; |
| } |
| } |
| } |
| |
| private static class SelectOption implements Serializable { |
| private static final long serialVersionUID = 1L; |
| private final String key; |
| @SuppressWarnings("unused") |
| private final String value; |
| |
| SelectOption(String key, String value) { |
| this.key = key; |
| this.value = value; |
| } |
| } |
| |
| private abstract class WizardDropDown<T extends Serializable> extends DropDownChoice<T> { |
| private static final long serialVersionUID = 1L; |
| T option; |
| IModel<Object> propModel; |
| |
| WizardDropDown(String id) { |
| super(id); |
| propModel = model.bind(id); |
| setModel(new PropertyModel<>(this, "option")); |
| } |
| |
| @Override |
| protected void onDetach() { |
| propModel.detach(); |
| super.onDetach(); |
| } |
| } |
| |
| private final class TzDropDown extends WizardDropDown<String> { |
| private static final long serialVersionUID = 1L; |
| |
| public TzDropDown(String id) { |
| super(id); |
| setChoices(AVAILABLE_TIMEZONES); |
| setChoiceRenderer(new ChoiceRenderer<String>() { |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| public Object getDisplayValue(String object) { |
| return object; |
| } |
| |
| @Override |
| public String getIdValue(String object, int index) { |
| return object; |
| } |
| }); |
| } |
| |
| public void setOption() { |
| String tzId = WebSession.get().getClientTZCode(); |
| option = AVAILABLE_TIMEZONE_SET.contains(tzId) ? tzId : AVAILABLE_TIMEZONES.get(0); |
| } |
| |
| @Override |
| protected void onModelChanged() { |
| if (propModel != null && option != null) { |
| propModel.setObject(option); |
| } |
| } |
| } |
| |
| private class SelectOptionDropDown extends WizardDropDown<SelectOption> { |
| private static final long serialVersionUID = 1L; |
| |
| SelectOptionDropDown(String id) { |
| super(id); |
| setChoiceRenderer(new ChoiceRenderer<>("value", "key")); |
| } |
| |
| @Override |
| protected void onModelChanged() { |
| if (propModel != null && option != null) { |
| propModel.setObject(option.key); |
| } |
| } |
| } |
| |
| private final class LangDropDown extends SelectOptionDropDown { |
| private static final long serialVersionUID = 1L; |
| |
| public LangDropDown(String id) { |
| super(id); |
| |
| List<SelectOption> list = new ArrayList<>(); |
| for (Map.Entry<Long, Locale> me : LabelDao.getLanguages()) { |
| SelectOption op = new SelectOption(me.getKey().toString(), me.getValue().getDisplayName()); |
| if (getSession().getLocale().equals(me.getValue())) { |
| option = op; |
| } |
| if (option == null && getSession().getLocale().getLanguage().equals(me.getValue().getLanguage())) { |
| option = op; |
| } |
| list.add(op); |
| if (option == null && me.getKey().intValue() == model.getObject().getDefaultLangId()) { |
| option = op; |
| } |
| } |
| setChoices(list); |
| } |
| } |
| |
| @Override |
| protected void onDetach() { |
| model.detach(); |
| super.onDetach(); |
| } |
| } |