/* * JBoss, a division of Red Hat * Copyright 2011, Red Hat Middleware, LLC, and individual * contributors as indicated by the @authors tag. See the * copyright.txt in the distribution for a full listing of * individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.gatein.wsrp.admin.ui; import org.gatein.registration.policies.DefaultRegistrationPolicy; import org.gatein.registration.policies.RegistrationPolicyWrapper; import org.gatein.wsrp.WSRPConstants; import org.gatein.wsrp.producer.config.ProducerConfiguration; import org.gatein.wsrp.producer.config.ProducerConfigurationService; import org.gatein.wsrp.producer.config.ProducerRegistrationRequirements; import org.gatein.wsrp.registration.LocalizedString; import org.gatein.wsrp.registration.RegistrationPropertyDescription; import javax.annotation.PostConstruct; import javax.faces.application.FacesMessage; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.event.ValueChangeEvent; import javax.faces.model.SelectItem; import javax.faces.validator.ValidatorException; import javax.xml.namespace.QName; import java.io.Serializable; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; /** * @author <a href="mailto:chris.laprun@jboss.com">Chris Laprun</a> * @version $Revision: 12854 $ * @since 2.6.3 */ public class ProducerBean extends WSRPManagedBean implements Serializable { private static final String REGISTRATION_PROPERTY_TYPE = "REGISTRATION_PROPERTY_TYPE"; private static final String SELECTED_PROP = "selectedProp"; private static final String PROPERTY = "property"; private static final String CURRENT_CONFIG = "currentConfig"; private transient ProducerConfigurationService configurationService; private transient LocalProducerConfiguration localProducerConfiguration; @PostConstruct public void init() { if (localProducerConfiguration == null) { // try to get the local configuration from session to restore it after a property deletion for example localProducerConfiguration = beanContext.getFromSession(CURRENT_CONFIG, LocalProducerConfiguration.class); // if it's still null, load it from persistence if (localProducerConfiguration == null) { localProducerConfiguration = new LocalProducerConfiguration(this); localProducerConfiguration.initFrom(getConfiguration()); return; } else { beanContext.removeFromSession(CURRENT_CONFIG); } } // update configuration if needed localProducerConfiguration.updateIfNeededFrom(); } public ProducerConfigurationService getConfigurationService() { if (configurationService == null) { configurationService = beanContext.findBean("ProducerConfigurationService", ProducerConfigurationService.class); } return configurationService; } public void setConfigurationService(ProducerConfigurationService configurationService) { this.configurationService = configurationService; } public ProducerConfiguration getConfiguration() { return getConfigurationService().getConfiguration(); } public boolean isRegistrationRequiredForFullDescription() { return getLocalConfiguration().isRegistrationRequiredForFullDescription(); } public void setRegistrationRequiredForFullDescription(boolean requireRegForFullDescription) { getLocalConfiguration().setRegistrationRequiredForFullDescription(requireRegForFullDescription); } public boolean isRegistrationRequired() { return getLocalConfiguration().isRegistrationRequired(); } public void setRegistrationRequired(boolean requireRegistration) { getLocalConfiguration().setRegistrationRequired(requireRegistration); } public boolean isStrictMode() { return getLocalConfiguration().isUsingStrictMode(); } public void setStrictMode(boolean strictMode) { getLocalConfiguration().setUsingStrictMode(strictMode); } public List<RegistrationPropertyDescription> getRegistrationProperties() { return getLocalConfiguration().getRegistrationProperties(); } public boolean isRegistrationPropertiesEmpty() { return getLocalConfiguration().getRegistrationProperties().isEmpty(); } public List<SelectItem> getSupportedPropertyTypes() { return Collections.singletonList(new SelectItem("xsd:string")); } public String save() { try { // replicate local state to producer state ProducerConfiguration currentlyPersistedConfiguration = getConfiguration(); LocalProducerConfiguration localConfiguration = getLocalConfiguration(); ProducerRegistrationRequirements registrationRequirements = currentlyPersistedConfiguration.getRegistrationRequirements(); registrationRequirements.setRegistrationRequiredForFullDescription(localConfiguration.isRegistrationRequiredForFullDescription()); registrationRequirements.setRegistrationRequired(localConfiguration.isRegistrationRequired()); registrationRequirements.reloadPolicyFrom(localConfiguration.getRegistrationPolicyClassName(), localConfiguration.getValidatorClassName()); registrationRequirements.setRegistrationProperties(localConfiguration.getRegistrationProperties()); currentlyPersistedConfiguration.setUsingStrictMode(localConfiguration.isUsingStrictMode()); getConfigurationService().saveConfiguration(); // force a reload local state localProducerConfiguration = null; beanContext.createInfoMessage("bean_producer_save_success"); } catch (Exception e) { log.debug("Couldn't save producer", e); beanContext.createErrorMessage("bean_producer_cannot_save", e.getLocalizedMessage()); } return null; } public String reloadConfiguration() { try { getConfigurationService().reloadConfiguration(); // force a reload local state localProducerConfiguration = null; beanContext.createInfoMessage("bean_producer_cancel_success"); } catch (Exception e) { log.debug("Couldn't reload producer configuration", e); beanContext.createErrorMessage("bean_producer_cannot_reload", e.getLocalizedMessage()); } return null; } public String addRegistrationProperty() { getLocalConfiguration().addEmptyRegistrationProperty(PROPERTY + System.currentTimeMillis()); return null; } public String confirmPropDeletion(String selectedProp) { beanContext.replaceInSession(SELECTED_PROP, selectedProp); beanContext.replaceInSession(CURRENT_CONFIG, getLocalConfiguration()); return "confirmPropDeletion"; } public String deleteRegistrationProperty() { final String propertyName = beanContext.getFromSession(SELECTED_PROP, String.class); if (propertyName != null) { getLocalConfiguration().removeRegistrationProperty(propertyName); beanContext.replaceInSession(CURRENT_CONFIG, getLocalConfiguration()); } beanContext.removeFromSession(SELECTED_PROP); return "producer"; } public void requireRegistrationListener(ValueChangeEvent event) { setRegistrationRequired((Boolean)event.getNewValue()); bypassAndRedisplay(); } public void strictModeListener(ValueChangeEvent event) { setStrictMode((Boolean)event.getNewValue()); bypassAndRedisplay(); } public void requireRegistrationForFullDescListener(ValueChangeEvent event) { setRegistrationRequiredForFullDescription((Boolean)event.getNewValue()); bypassAndRedisplay(); } protected String getObjectTypeName() { return REGISTRATION_PROPERTY_TYPE; } public boolean isAlreadyExisting(String objectName) { // allow for edit of properties since they will be replaced anyway return false; } private LocalProducerConfiguration getLocalConfiguration() { init(); return localProducerConfiguration; } public String getV1WSDL() { return beanContext.getServerAddress() + "/wsrp-producer/v1/MarkupService?wsdl"; } public String getV2WSDL() { return beanContext.getServerAddress() + "/wsrp-producer/v2/MarkupService?wsdl"; } public void validate(FacesContext facesContext, UIComponent uiComponent, Object o) { validate(facesContext, uiComponent, o, getValidator()); } private void validate(FacesContext facesContext, UIComponent uiComponent, Object o, PropertyValidator validator) { String toValidate = null; if (o instanceof String) { toValidate = (String)o; } else if (o instanceof LocalizedString) { toValidate = LocalizedStringConverter.getAsString(o); } final String validated = this.checkAndReturnValueIfValid(toValidate, uiComponent.getClientId(facesContext), validator); if (validated == null) { throw new ValidatorException(new FacesMessage()); // need a non-null FacesMessage to avoid NPE } } public void validateLabelOrHint(FacesContext facesContext, UIComponent uiComponent, Object o) { validate(facesContext, uiComponent, o, new LabelOrHintValidator()); } public List<SelectItem> getAvailableRegistrationPolicies() { return getSelectItemsFrom(getConfiguration().getRegistrationRequirements().getAvailableRegistrationPolicies()); } public void policyChangeListener(ValueChangeEvent event) { getLocalConfiguration().setRegistrationPolicyClassName((String)event.getNewValue()); bypassAndRedisplay(); } public String getRegistrationPolicyClassName() { return getLocalConfiguration().getRegistrationPolicyClassName(); } public void setRegistrationPolicyClassName(String policyClassName) { getLocalConfiguration().setRegistrationPolicyClassName(policyClassName); } public boolean isDefaultRegistrationPolicy() { return getLocalConfiguration().isDefaultRegistrationPolicy(); } public String getValidatorClassName() { return getLocalConfiguration().getValidatorClassName(); } public void setValidatorClassName(String validatorClassName) { getLocalConfiguration().setValidatorClassName(validatorClassName); } public List<SelectItem> getAvailableValidators() { return getSelectItemsFrom(getConfiguration().getRegistrationRequirements().getAvailableRegistrationPropertyValidators()); } private static class LocalProducerConfiguration implements Serializable { private List<RegistrationPropertyDescription> registrationProperties; private boolean strictMode; private String policyClassName; private String validatorClassName; private boolean registrationRequiredForFullDescription; private boolean registrationRequired; private long originalLastModified; private final ProducerBean producerBean; private long lastUpdateCheckTime; public LocalProducerConfiguration(ProducerBean producerBean) { this.producerBean = producerBean; } public void initFrom(ProducerConfiguration configuration) { ProducerRegistrationRequirements registrationRequirements = configuration.getRegistrationRequirements(); Map<QName, RegistrationPropertyDescription> descriptions = registrationRequirements.getRegistrationProperties(); registrationProperties = new LinkedList<RegistrationPropertyDescription>(descriptions.values()); Collections.sort(registrationProperties); policyClassName = registrationRequirements.getPolicyClassName(); if (isDefaultRegistrationPolicy()) { DefaultRegistrationPolicy policy = (DefaultRegistrationPolicy)RegistrationPolicyWrapper.unwrap(registrationRequirements.getPolicy()); validatorClassName = policy.getValidator().getClass().getName(); } else { validatorClassName = null; } registrationRequiredForFullDescription = registrationRequirements.isRegistrationRequiredForFullDescription(); registrationRequired = registrationRequirements.isRegistrationRequired(); this.strictMode = configuration.isUsingStrictMode(); originalLastModified = configuration.getLastModified(); } public boolean isRegistrationRequiredForFullDescription() { return registrationRequiredForFullDescription; } public void setRegistrationRequiredForFullDescription(boolean registrationRequiredForFullDescription) { this.registrationRequiredForFullDescription = registrationRequiredForFullDescription; } public List<RegistrationPropertyDescription> getRegistrationProperties() { return registrationProperties; } public void addEmptyRegistrationProperty(String propertyName) { RegistrationPropertyDescription prop = new RegistrationPropertyDescription(propertyName, WSRPConstants.XSD_STRING); // Search for the non-existent item int index = Collections.binarySearch(registrationProperties, prop); // Add the non-existent item to the list if (index < 0) { registrationProperties.add(-index - 1, prop); } } public void removeRegistrationProperty(String propertyName) { int toRemove = -1; int index = 0; for (RegistrationPropertyDescription property : registrationProperties) { if (property.getName().equals(QName.valueOf(propertyName))) { toRemove = index; break; } index++; } if (toRemove != -1) { registrationProperties.remove(toRemove); } } public boolean isUsingStrictMode() { return strictMode; } public void setUsingStrictMode(boolean usingStrictMode) { this.strictMode = usingStrictMode; } public String getRegistrationPolicyClassName() { return policyClassName; } public void setRegistrationPolicyClassName(String className) { policyClassName = className; } public boolean isDefaultRegistrationPolicy() { return ProducerRegistrationRequirements.DEFAULT_POLICY_CLASS_NAME.equals(getRegistrationPolicyClassName()); } public String getValidatorClassName() { return validatorClassName; } public void setValidatorClassName(String className) { validatorClassName = className; } public boolean isRegistrationRequired() { return registrationRequired; } public void setRegistrationRequired(boolean registrationRequired) { this.registrationRequired = registrationRequired; } public void updateIfNeededFrom() { // cool down period to avoid hammering the DB with constant checks if (System.currentTimeMillis() - lastUpdateCheckTime < 100) { return; } // if the configuration we got from the configuration service has been modified after the one we initialized from, we need to update ourselves if (producerBean.getConfigurationService().getPersistedLastModifiedForConfiguration() > originalLastModified) { initFrom(producerBean.getConfiguration()); } lastUpdateCheckTime = System.currentTimeMillis(); } } private class LabelOrHintValidator extends DefaultPropertyValidator { public static final String INVALID_HINT_OR_LABEL_ERROR = "INVALID_HINT_OR_LABEL_ERROR"; @Override public boolean checkForDuplicates() { // no need to check for duplicates return false; } /** * Only checks if the specified value contains a '/' * * @param value the value which format we want to check * @return */ @Override public String checkForInvalidCharacters(String value) { // allow . in value return (value.indexOf('/') != -1) ? null : value; } @Override public String getErrorKey() { return INVALID_HINT_OR_LABEL_ERROR; } } }