/* * RHQ Management Platform * Copyright (C) 2005-2012 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 2 of the License. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.rhq.enterprise.server.auth.prefs; import java.util.HashMap; import java.util.Map; import javax.ejb.ConcurrencyManagement; import javax.ejb.ConcurrencyManagementType; import javax.ejb.EJB; import javax.ejb.Lock; import javax.ejb.LockType; import javax.ejb.Singleton; import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.Property; import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.enterprise.server.auth.SubjectManagerLocal; import org.rhq.enterprise.server.common.EntityManagerFacadeLocal; import org.rhq.enterprise.server.configuration.ConfigurationManagerLocal; @ConcurrencyManagement(ConcurrencyManagementType.CONTAINER) @Singleton @TransactionAttribute(TransactionAttributeType.SUPPORTS) public class SubjectPreferencesCacheBean implements SubjectPreferencesCacheLocal { protected final Log log = LogFactory.getLog(SubjectPreferencesCacheBean.class); private Map<Integer, Configuration> subjectPreferences; @EJB private SubjectManagerLocal subjectManager; @EJB private EntityManagerFacadeLocal entityManagerFacade; @EJB private ConfigurationManagerLocal configurationManager; public SubjectPreferencesCacheBean() { subjectPreferences = new HashMap<Integer, Configuration>(); } private void load(int subjectId) { // if subject ID is 0, it probably means this is a new LDAP user that needs to be registered if (subjectId != 0 && !subjectPreferences.containsKey(subjectId)) { try { Subject subject = subjectManager.loadUserConfiguration(subjectId); Configuration configuration = subject.getUserConfiguration(); subjectPreferences.put(subjectId, configuration); } catch (Throwable t) { log.warn("Can not get preferences for subject[id=" + subjectId + "], subject does not exist yet"); } } } @Override @Lock(LockType.READ) public PropertySimple getUserProperty(int subjectId, String propertyName) { load(subjectId); Configuration config = subjectPreferences.get(subjectId); if (config == null) { return null; } PropertySimple prop = config.getSimple(propertyName); if (prop == null) { return null; } return new PropertySimple(propertyName, prop.getStringValue()); } @Override @Lock(LockType.WRITE) public void setUserProperty(int subjectId, String propertyName, String value) { load(subjectId); Configuration config = subjectPreferences.get(subjectId); if (config == null) { return; } PropertySimple prop = config.getSimple(propertyName); if (prop == null) { prop = new PropertySimple(propertyName, value); config.put(prop); // add new to collection mergeProperty(prop); } else if (prop.getStringValue() == null || !prop.getStringValue().equals(value)) { prop.setStringValue(value); mergeProperty(prop); } } private void mergeProperty(PropertySimple prop) { // merge will persist if property doesn't exist (i.e., id = 0) PropertySimple mergedProperty = entityManagerFacade.merge(prop); // only merge changes if (prop.getId() == 0) { // so subsequent merges do not continue re-persisting property as new prop.setId(mergedProperty.getId()); } } @Override @Lock(LockType.WRITE) public void unsetUserProperty(int subjectId, String propertyName) { load(subjectId); Configuration config = subjectPreferences.get(subjectId); if (config == null) { return; } Property property = config.remove(propertyName); // it's possible property was already removed, and thus this operation becomes a no-op to the backing store if (property != null && property.getId() != 0) { try { configurationManager.deleteProperties(new int[] { property.getId() }); } catch (Throwable t) { log.error("Could not remove " + property, t); } } } /** * @param subjectId the subject to get preferences of * @return the <b>COPY</b> of the configuration object - changes done to that instance will not be reflected in the persisted * preferences */ @Override @Lock(LockType.READ) public Configuration getPreferences(int subjectId) { load(subjectId); Configuration config = subjectPreferences.get(subjectId); if (config == null) { return new Configuration(); } else { return config.deepCopy(); } } @Override @Lock(LockType.WRITE) public void clearConfiguration(int subjectId) { if (log.isTraceEnabled()) { log.trace("Removing PreferencesCache For " + subjectId); } subjectPreferences.remove(subjectId); } }