Java tutorial
/* * Copyright (c) 2008-2011, Martijn Brinkers, Djigzo. * * This file is part of Djigzo email encryption. * * Djigzo is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License * version 3, 19 November 2007 as published by the Free Software * Foundation. * * Djigzo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with Djigzo. If not, see <http://www.gnu.org/licenses/> * * Additional permission under GNU AGPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or * combining it with saaj-api-1.3.jar, saaj-impl-1.3.jar, * wsdl4j-1.6.1.jar (or modified versions of these libraries), * containing parts covered by the terms of Common Development and * Distribution License (CDDL), Common Public License (CPL) the * licensors of this Program grant you additional permission to * convey the resulting work. */ package mitm.djigzo.web.pages.admin.mta; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.Set; import mitm.application.djigzo.admin.FactoryRoles; import mitm.application.djigzo.ws.PostfixConfigManagerWS; import mitm.common.postfix.PostfixMainConfigBuilder; import mitm.common.util.AddressUtils; import mitm.common.util.DomainUtils; import mitm.common.util.DomainUtils.DomainType; import mitm.common.ws.WebServiceCheckedException; import mitm.djigzo.web.common.GenericSelectionModel; import mitm.djigzo.web.common.MTAConfigSubmitButton; import mitm.djigzo.web.pages.Admins; import org.apache.commons.lang.StringUtils; import org.apache.tapestry5.Asset; import org.apache.tapestry5.Block; import org.apache.tapestry5.ComponentResources; import org.apache.tapestry5.Link; import org.apache.tapestry5.PersistenceConstants; import org.apache.tapestry5.SelectModel; import org.apache.tapestry5.annotations.Component; import org.apache.tapestry5.annotations.IncludeStylesheet; import org.apache.tapestry5.annotations.Path; import org.apache.tapestry5.annotations.Persist; import org.apache.tapestry5.annotations.Property; import org.apache.tapestry5.annotations.SetupRender; import org.apache.tapestry5.corelib.components.Checkbox; import org.apache.tapestry5.corelib.components.Form; import org.apache.tapestry5.corelib.components.Select; import org.apache.tapestry5.corelib.components.TextField; import org.apache.tapestry5.ioc.annotations.Inject; import org.apache.tapestry5.ioc.annotations.Value; import org.apache.tapestry5.services.Request; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.annotation.Secured; @IncludeStylesheet("context:styles/pages/admin/mta/mtaConfig.css") @Secured({ FactoryRoles.ROLE_ADMIN }) public class MTAConfig { private final static Logger logger = LoggerFactory.getLogger(MTAConfig.class); @Inject private Request request; @Inject private ComponentResources resources; @Inject private PostfixConfigManagerWS postfixConfigManagerWS; @SuppressWarnings("unused") @Component(id = "myHostname", parameters = { "value = mainConfig.myHostname", "validate = required" }) private TextField myHostnameField; @SuppressWarnings("unused") @Component(id = "relayHost", parameters = { "value = mainConfig.relayHost" }) private TextField relayHostField; @SuppressWarnings("unused") @Component(id = "relayHostMxLookup", parameters = { "value = mainConfig.relayHostMxLookup" }) private Checkbox relayHostMxLookupField; @SuppressWarnings("unused") @Component(id = "relayHostPort", parameters = { "value = mainConfig.relayHostPort", "validate = min=1, max=65535" }) private TextField relayHostPortField; @SuppressWarnings("unused") @Component(id = "relayTransportHost", parameters = { "value = mainConfig.relayTransportHost" }) private TextField relayTransportHostField; @SuppressWarnings("unused") @Component(id = "relayTransportHostMxLookup", parameters = { "value = mainConfig.relayTransportHostMxLookup" }) private Checkbox relayTransportHostMxLookupField; @SuppressWarnings("unused") @Component(id = "relayTransportHostPort", parameters = { "value = mainConfig.relayTransportHostPort", "validate = min=1, max=65535" }) private TextField relayTransportHostPortField; @SuppressWarnings("unused") @Component(id = "myDestination", parameters = { "model = myDestinationModel", "value = prop:selectedDestination", "blankOption = NEVER" }) private Select myDestinationField; @SuppressWarnings("unused") @Component(id = "relayDomains", parameters = { "model = relayDomainsModel", "value = prop:selectedRelayDomain", "blankOption = NEVER" }) private Select relayDomainField; @SuppressWarnings("unused") @Component(id = "matchSubdomains", parameters = { "value = mainConfig.matchSubdomains" }) private Checkbox matchSubdomainsField; @SuppressWarnings("unused") @Component(id = "myNetworks", parameters = { "model = myNetworksModel", "value = prop:selectedNetwork", "blankOption = NEVER" }) private Select myNetworksField; @Component(id = "newDestination", parameters = { "value = newDestination" }) private TextField newDestinationField; @Component(id = "newRelayDomain", parameters = { "value = newRelayDomain" }) private TextField newRelayDomainField; @Component(id = "newNetwork", parameters = { "value = newNetwork" }) private TextField newNetworkField; @Component(id = "myDestinationForm") private Form myDestinationForm; @Component(id = "relayDomainsForm") private Form relayDomainsForm; @Component(id = "myNetworksForm") private Form myNetworksForm; @Component(id = "otherForm") private Form otherForm; @SuppressWarnings("unused") @Component(id = "smtpHeloName", parameters = { "value = mainConfig.smtpHeloName" }) private TextField smtpHeloNameField; @SuppressWarnings("unused") @Component(id = "rejectUnverifiedRecipient", parameters = { "value = mainConfig.rejectUnverifiedRecipient" }) private Checkbox rejectUnverifiedRecipientField; @SuppressWarnings("unused") @Component(id = "unverifiedRecipientRejectCode", parameters = { "model = unverifiedRecipientRejectCodeModel", "value = mainConfig.unverifiedRecipientRejectCode", "blankOption = NEVER" }) private Select unverifiedRecipientRejectCodeField; @Inject @Property private Block myDestinationBlock; @Inject @Property private Block relayDomainsBlock; @Inject @Property private Block myNetworksBlock; @Inject @Path("context:icons/cross.png") @Property @SuppressWarnings("unused") private Asset removeAsset; @Persist private PostfixMainConfigBuilder mainConfigBuilder; @Persist private boolean advancedSettings; @Persist(PersistenceConstants.FLASH) private boolean applied; @Persist(PersistenceConstants.FLASH) private boolean applyError; private String selectedDestination; private String selectedRelayDomain; private String selectedNetwork; private String newDestination; private String newRelayDomain; private String newNetwork; private MTAConfigSubmitButton submitButton; /* * If true the user can edit "my destinations" */ @Inject @Value("${mta.enableMyDestination}") private boolean enableMyDestination; /* * True when a reload need to keep the main config. We need this when Javascript is disabled because * then a full page reload is done when adding/removing entries. */ private boolean keepConfig; @Secured({ FactoryRoles.ROLE_ADMIN }) protected void onActivate(boolean keepConfig) { this.keepConfig = keepConfig; } @SetupRender @Secured({ FactoryRoles.ROLE_ADMIN }) protected void setupRender() { if (!keepConfig) { mainConfigBuilder = null; } } public PostfixMainConfigBuilder getMainConfig() throws WebServiceCheckedException { if (mainConfigBuilder == null) { StringReader reader = new StringReader(postfixConfigManagerWS.getMainConfig()); mainConfigBuilder = new PostfixMainConfigBuilder(reader); } return mainConfigBuilder; } public SelectModel getMyDestinationModel() throws WebServiceCheckedException { return new GenericSelectionModel<String>(new ArrayList<String>(getMainConfig().getMyDestinations()), null, null); } public SelectModel getRelayDomainsModel() throws WebServiceCheckedException { return new GenericSelectionModel<String>(new ArrayList<String>(getMainConfig().getRelayDomains()), null, null); } public SelectModel getMyNetworksModel() throws WebServiceCheckedException { return new GenericSelectionModel<String>(new ArrayList<String>(getMainConfig().getMyNetworks()), null, null); } public SelectModel getUnverifiedRecipientRejectCodeModel() throws WebServiceCheckedException { return new GenericSelectionModel<String>(Arrays.asList("450", "550"), null, null); } /* * Returns a link which will be used to reload the page without clearing the config. This is used when the * user disabled Javascript. */ private Link getKeepConfigReloadLink() { return resources.createPageLink(MTAConfig.class, false, true); } private Object validateAddDestination() throws WebServiceCheckedException { if (StringUtils.isEmpty(newDestination)) { myDestinationForm.recordError(newDestinationField, "Destination must be specified."); return request.isXHR() ? myDestinationBlock : getKeepConfigReloadLink(); } else if (DomainUtils.validate(newDestination, DomainType.FULLY_QUALIFIED) == null) { myDestinationForm.recordError(newDestinationField, "Destination is not a valid domain."); return request.isXHR() ? myDestinationBlock : getKeepConfigReloadLink(); } else if (getMainConfig().getMyDestinations().contains(newDestination.trim())) { myDestinationForm.recordError(newDestinationField, "Destination is already added to the list."); return request.isXHR() ? myDestinationBlock : getKeepConfigReloadLink(); } return null; } private Object validateAddRelayDomain() throws WebServiceCheckedException { if (StringUtils.isEmpty(newRelayDomain)) { relayDomainsForm.recordError(newRelayDomainField, "Relay domain must be specified."); return request.isXHR() ? relayDomainsBlock : getKeepConfigReloadLink(); } else if (DomainUtils.validate(newRelayDomain, DomainType.FULLY_QUALIFIED) == null) { relayDomainsForm.recordError(newRelayDomainField, "Relay domain is not a valid domain."); return request.isXHR() ? relayDomainsBlock : getKeepConfigReloadLink(); } else if (getMainConfig().getRelayDomains().contains(newRelayDomain.trim())) { relayDomainsForm.recordError(newRelayDomainField, "Relay domain is already added to the list."); return request.isXHR() ? relayDomainsBlock : getKeepConfigReloadLink(); } return null; } private Object validateAddNetwork() throws WebServiceCheckedException { if (StringUtils.isEmpty(newNetwork)) { myNetworksForm.recordError(newNetworkField, "Network must be specified."); return request.isXHR() ? myNetworksBlock : getKeepConfigReloadLink(); } else if (!AddressUtils.isValidNetwork(newNetwork)) { myNetworksForm.recordError(newNetworkField, "Network is not valid."); return request.isXHR() ? myNetworksBlock : getKeepConfigReloadLink(); } else if (getMainConfig().getMyNetworks().contains(newNetwork.trim())) { myNetworksForm.recordError(newNetworkField, "Network is already added to the list."); return request.isXHR() ? myNetworksBlock : getKeepConfigReloadLink(); } return null; } private void validateApply() throws WebServiceCheckedException { } public Object onValidateForm() throws WebServiceCheckedException { if (submitButton == null) { return null; } switch (submitButton) { case ADD_DESTINATION: return validateAddDestination(); case ADD_RELAY_DOMAIN: return validateAddRelayDomain(); case ADD_NETWORK: return validateAddNetwork(); case APPLY: validateApply(); break; } return null; } private Object addDestination() throws WebServiceCheckedException { Set<String> destinations = new LinkedHashSet<String>(getMainConfig().getMyDestinations()); destinations.add(newDestination); getMainConfig().setMyDestination(destinations); return request.isXHR() ? myDestinationBlock : getKeepConfigReloadLink(); } private Object removeDestination() throws WebServiceCheckedException { if (selectedDestination != null) { Set<String> destinations = new LinkedHashSet<String>(getMainConfig().getMyDestinations()); destinations.remove(selectedDestination); getMainConfig().setMyDestination(destinations); } return request.isXHR() ? myDestinationBlock : getKeepConfigReloadLink(); } private Object addRelayDomain() throws WebServiceCheckedException { Set<String> domains = new LinkedHashSet<String>(getMainConfig().getRelayDomains()); domains.add(newRelayDomain); getMainConfig().setRelayDomains(domains); return request.isXHR() ? relayDomainsBlock : getKeepConfigReloadLink(); } private Object removeRelayDomain() throws WebServiceCheckedException { if (selectedRelayDomain != null) { Set<String> domains = new LinkedHashSet<String>(getMainConfig().getRelayDomains()); domains.remove(selectedRelayDomain); getMainConfig().setRelayDomains(domains); } return request.isXHR() ? relayDomainsBlock : getKeepConfigReloadLink(); } private Object addNetwork() throws WebServiceCheckedException { Set<String> networks = new LinkedHashSet<String>(getMainConfig().getMyNetworks()); networks.add(newNetwork); getMainConfig().setMyNetworks(networks); return request.isXHR() ? myNetworksBlock : getKeepConfigReloadLink(); } private Object removeNetwork() throws WebServiceCheckedException { if (selectedNetwork != null) { Set<String> networks = new LinkedHashSet<String>(getMainConfig().getMyNetworks()); networks.remove(selectedNetwork); getMainConfig().setMyNetworks(networks); } return request.isXHR() ? myNetworksBlock : getKeepConfigReloadLink(); } private void apply() { Writer writer = new StringWriter(); try { getMainConfig().writeConfig(writer); postfixConfigManagerWS.setMainConfig(writer.toString()); postfixConfigManagerWS.reload(); applied = true; } catch (IOException e) { logger.error("Error while applying.", e); applyError = true; } catch (WebServiceCheckedException e) { logger.error("Error while applying.", e); applyError = true; } } public Object onSuccess() throws IOException, WebServiceCheckedException { if (submitButton == null) { return null; } switch (submitButton) { case ADD_DESTINATION: return addDestination(); case REMOVE_DESTINATION: return removeDestination(); case ADD_RELAY_DOMAIN: return addRelayDomain(); case REMOVE_RELAY_DOMAIN: return removeRelayDomain(); case ADD_NETWORK: return addNetwork(); case REMOVE_NETWORK: return removeNetwork(); case APPLY: apply(); break; } return null; } public Block onFailure() throws IOException, WebServiceCheckedException { if (submitButton == null) { return null; } switch (submitButton) { case ADD_DESTINATION: return myDestinationBlock; case ADD_RELAY_DOMAIN: return relayDomainsBlock; case ADD_NETWORK: return myNetworksBlock; } return null; } public void onSelectedFromApply() { submitButton = MTAConfigSubmitButton.APPLY; } public void onSelectedFromAddDestination() { submitButton = MTAConfigSubmitButton.ADD_DESTINATION; } public void onSelectedFromRemoveDestination() { submitButton = MTAConfigSubmitButton.REMOVE_DESTINATION; } public void onSelectedFromAddRelayDomain() { submitButton = MTAConfigSubmitButton.ADD_RELAY_DOMAIN; } public void onSelectedFromRemoveRelayDomain() { submitButton = MTAConfigSubmitButton.REMOVE_RELAY_DOMAIN; } public void onSelectedFromAddNetwork() { submitButton = MTAConfigSubmitButton.ADD_NETWORK; } public void onSelectedFromRemoveNetwork() { submitButton = MTAConfigSubmitButton.REMOVE_NETWORK; } public String getNewDestination() { return newDestination; } public void setNewDestination(String newDestination) { this.newDestination = newDestination; } public String getNewRelayDomain() { return newRelayDomain; } public void setNewRelayDomain(String newRelayDomain) { this.newRelayDomain = newRelayDomain; } public String getNewNetwork() { return newNetwork; } public void setNewNetwork(String newNetwork) { this.newNetwork = newNetwork; } public String getSelectedDestination() { return selectedDestination; } public void setSelectedDestination(String selectedDestination) { this.selectedDestination = selectedDestination; } public String getSelectedRelayDomain() { return selectedRelayDomain; } public void setSelectedRelayDomain(String selectedRelayDomain) { this.selectedRelayDomain = selectedRelayDomain; } public String getSelectedNetwork() { return selectedNetwork; } public void setSelectedNetwork(String selectedNetwork) { this.selectedNetwork = selectedNetwork; } public boolean isAdvancedSettings() { return advancedSettings; } public void setAdvancedSettings(boolean advancedSettings) { this.advancedSettings = advancedSettings; } public boolean isEnableMyDestination() { return enableMyDestination; } /* * Event handler called when the cancel button is pressed. */ public Object onCancel() { return Admins.class; } public boolean isApplied() { return applied; } public boolean isApplyError() { return applyError; } }