/* * Demoiselle Framework * Copyright (C) 2010 SERPRO * Copyright (c) 2012 - Reinaldo de Carvalho <reinaldoc@gmail.com> * ---------------------------------------------------------------------------- * This file is part of Demoiselle Framework. * * Demoiselle Framework is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License version 3 * as published by the Free Software Foundation. * * 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 Lesser General Public License version 3 * along with this program; if not, see <http://www.gnu.org/licenses/> * or write to the Free Software Foundation, Inc., 51 Franklin Street, * Fifth Floor, Boston, MA 02110-1301, USA. * ---------------------------------------------------------------------------- * Este arquivo é parte do Framework Demoiselle. * * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação * do Software Livre (FSF). * * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português * para maiores detalhes. * * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título * "LICENCA.txt", junto com esse programa. Se não, acesse <http://www.gnu.org/licenses/> * ou escreva para a Fundação do Software Livre (FSF) Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. */ package br.gov.frameworkdemoiselle.ldap.template; import java.util.List; import java.util.Map; import javax.enterprise.inject.Instance; import javax.inject.Inject; import br.gov.frameworkdemoiselle.enumeration.contrib.Comparison; import br.gov.frameworkdemoiselle.enumeration.contrib.Logic; import br.gov.frameworkdemoiselle.ldap.core.EntryManager; import br.gov.frameworkdemoiselle.ldap.core.EntryQuery; import br.gov.frameworkdemoiselle.ldap.exception.EntryException; import br.gov.frameworkdemoiselle.query.contrib.QueryConfig; import br.gov.frameworkdemoiselle.query.contrib.QueryContext; import br.gov.frameworkdemoiselle.template.Crud; import br.gov.frameworkdemoiselle.util.Reflections; /** * LDAP specific implementation for Crud interface. * * @param <T> * bean object type * @param <I> * bean id type * @author SERPRO * @see Crud */ public class LDAPCrud<T, I> implements Crud<T, I> { private static final long serialVersionUID = 1L; @Inject private EntryManager entryManager; @Inject private Instance<QueryContext> queryContext; private QueryConfig<T> queryConfig; private Class<T> beanClass; protected Class<T> getBeanClass() { if (this.beanClass == null) { this.beanClass = Reflections.getGenericTypeArgument(this.getClass(), 0); } return this.beanClass; } protected EntryManager getEntryManager() { return this.entryManager; } protected EntryQuery createQuery(final String ql) { return getEntryManager().createQuery(ql); } protected QueryConfig<T> getQueryConfig() { if (queryConfig == null) { QueryContext context = queryContext.get(); queryConfig = context.getQueryConfig(getBeanClass()); } return queryConfig; } /** * Persist a @LDAPEntry annotated object. Use LDAP Add Operation * * @param entry * a entry annotated with LDAPEntry * @throws EntryException */ public void insert(final T entry) { getEntryManager().persist(entry); } /** * Remove a @LDAPEntry annotated object. Use LDAP Del Operation * * @param entry * a entry annotated with LDAPEntry * @throws EntryException */ public void delete(final I id) { T entry = getEntryManager().find(getBeanClass(), id); getEntryManager().remove(entry); } /** * Remove a LDAP Entry. Use LDAP Del Operation * * @param dn * String Representation of Distinguished Name (RFC 1485) * @throws EntryException */ public void remove(final String dn) { getEntryManager().remove(dn); } /** * Merge LDAP Entry from not null attributes only. Null attributes will * remain in DSA. Not null attributes will be replaced. Use LDAP Modify * Operation. * * @param entry * a entry annotated with LDAPEntry * @throws EntryException */ public void update(final T entry) { getEntryManager().merge(entry); } /** * Update LDAP Entry to not null attributes only. Null attributes will be * removed from DSA. Not null attributes will be replaced. You must declare * all required attributes. Use LDAP Modify Operation * * @param entry * entry annotated with LDAPEntry with values to update * @throws EntryException */ public void merge(final T entry) { getEntryManager().merge(getReference(((Entry) entry).getDn()), entry); } /** * Find a entry with objectClass equals entry class name and @id attribute * equals to id value, like &(objectClass=entryClass)(idattr=idvalue) * * @param id * find a entry with @id attribute equals to id value * @return a entry object */ public T load(final I id) { return getEntryManager().find(getBeanClass(), id); } /** * Find a Entry by DN * * @param entryClass * a entry class * @param id * find a entry with @id attribute equals to id value * @return String Representation of Distinguished Name (RFC 1485) */ public T getReference(String dn) { return getEntryManager().getReference(getBeanClass(), dn); } @SuppressWarnings("unchecked") public List<T> findAll() { String filter = "objectClass=" + getBeanClass().getSimpleName(); final QueryConfig<T> queryConfig = this.getQueryConfig(); if (queryConfig != null) if (queryConfig.getFilter() != null && !queryConfig.getFilter().isEmpty()) filter = getFilter(getBeanClass(), queryConfig.getFilter(), queryConfig.getFilterLogic(), queryConfig.getFilterComparison()); EntryQuery query = getEntryManager().createQuery(filter); if (queryConfig != null) { // TODO: implement pagination with LDAP Asynchronous Query // queryConfig.setTotalResults(countAll(queryConfig)); if (queryConfig.getMaxResults() > 0) { // query.setFirstResult(queryConfig.getFirstResult()); query.setMaxResults(queryConfig.getMaxResults()); } query.setBaseDN((String) queryConfig.getGeneric()); } return query.getResultList(); } /** * Create a filter like * "(&(objectClass=className)(attribute1=value1)(attribute2=value2))" or * "(&(objectClass=className)(|(attribute1=value1)(attribute2=value2)))" * * @param clazz * a class with objectClass as name * @param map * a map with attributes as key and attributes values as Object. * Object can be null for "(attribute=*)", or a .toString capable * object like Integer or Long for "(attribute=value)", or can be * a array, for "(attribute=value1)(attribute=value2)" * @param logic * if AND or OR result "(attribute=value)", otherwise is NAND or * NOR that means "(!(attribute=value))" * @param notation * if INFIX result "(attribute=*value*)", else if PREFIX * "(attribute=value*)", else if POSTFIX "(attribute=value*)", * otherwise is EXACT "(attribute=value)" * @return a filter like * "(&(objectClass=className)(attribute1=value1)(attribute2=value2))" * or * "(&(objectClass=className)(|(attribute1=value1)(attribute2=value2)))" */ public static String getFilter(Class<?> clazz, Map<String, Object> map, Logic logic, Comparison notation) { if (logic == Logic.AND || logic == Logic.NAND) return "(&(objectClass=" + clazz.getSimpleName() + ")" + getPartialFilter(map, logic, notation) + ")"; else return "(&(objectClass=" + clazz.getSimpleName() + ")(|" + getPartialFilter(map, logic, notation) + "))"; } /** * Create a partial filter like "(attribute1=value1)(attribute2=value2)" or * "(!(attribute1=value1))(!(attribute2=value2))". * * @param map * a map with attributes as key and attributes values as Object. * Object can be null for "(attribute=*)", or a .toString capable * object like Integer or Long for "(attribute=value)", or can be * a array, for "(attribute=value1)(attribute=value2)" * @param logic * if AND or OR result "(attribute=value)", otherwise is NAND or * NOR that means "(!(attribute=value))" * @param notation * if INFIX result "(attribute=*value*)", else if PREFIX * "(attribute=value*)", else if POSTFIX "(attribute=value*)", * otherwise is EXACT "(attribute=value)" * @return a partial filter like "(attribute1=value1)(attribute2=value2)" or * "(!(attribute1=value1))(!(attribute2=value2))". */ public static String getPartialFilter(Map<String, Object> map, Logic logic, Comparison notation) { String partialFilter = ""; for (Map.Entry<String, Object> mapEntry : map.entrySet()) if (mapEntry.getValue() == null || !mapEntry.getValue().getClass().isArray()) partialFilter = partialFilter + getPartialFilterElement(mapEntry.getKey(), mapEntry.getValue(), logic, notation); else for (Object value : (Object[]) mapEntry.getValue()) partialFilter = partialFilter + getPartialFilterElement(mapEntry.getKey(), value, logic, notation); return partialFilter; } /** * Create a partial filter element like "(attribute=value)" or * "(!(attribute=value))" * * @param attr * attribute name * @param value * attribute value * @param logic * if AND or OR result "(attribute=value)", otherwise is NAND or * NOR that means "(!(attribute=value))" * @param notation * if INFIX result "(attribute=*value*)", else if PREFIX * "(attribute=value*)", else if POSTFIX "(attribute=value*)", * otherwise is EXACT "(attribute=value)" * @return a partial filter element like "(attribute=*value*)" or * "(!(attribute=value))" */ public static String getPartialFilterElement(String attr, Object value, Logic logic, Comparison notation) { String partialFilter; if (value == null) partialFilter = "(" + attr + "=*)"; else if (notation == Comparison.EQUALS) partialFilter = "(" + attr + "=" + value + ")"; else if (notation == Comparison.CONTAINS) partialFilter = "(" + attr + "=*" + value + "*)"; else if (notation == Comparison.STARTSWITH) partialFilter = "(" + attr + "=" + value + "*)"; else partialFilter = "(" + attr + "=*" + value + ")"; if (logic == Logic.NAND || logic == Logic.NOR) partialFilter = "(!" + partialFilter + ")"; return partialFilter; } }