001    /*
002      GRANITE DATA SERVICES
003      Copyright (C) 2011 GRANITE DATA SERVICES S.A.S.
004    
005      This file is part of Granite Data Services.
006    
007      Granite Data Services is free software; you can redistribute it and/or modify
008      it under the terms of the GNU Library General Public License as published by
009      the Free Software Foundation; either version 2 of the License, or (at your
010      option) any later version.
011    
012      Granite Data Services is distributed in the hope that it will be useful, but
013      WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014      FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015      for more details.
016    
017      You should have received a copy of the GNU Library General Public License
018      along with this library; if not, see <http://www.gnu.org/licenses/>.
019    */
020    
021    package org.granite.tide.spring;
022    
023    import org.springframework.beans.factory.config.BeanDefinition;
024    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
025    import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
026    import org.springframework.beans.factory.xml.ParserContext;
027    import org.springframework.core.Conventions;
028    import org.springframework.util.StringUtils;
029    import org.w3c.dom.Element;
030    
031    /**
032     * @author William Drai
033     */
034    public class TideIdentityBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
035    
036        @Override
037        protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
038            
039            element.setAttribute(ID_ATTRIBUTE, "identity");
040            
041            builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
042            
043            String aclService = element.getAttribute("acl-service");
044            if (aclService != null && aclService.trim().length() > 0)
045                    builder.addPropertyReference("aclService", aclService);
046            
047            String sidRetrievalStrategy = element.getAttribute("sid-retrieval-strategy");
048            if (sidRetrievalStrategy != null && sidRetrievalStrategy.trim().length() > 0)
049                    builder.addPropertyReference("sidRetrievalStrategy", sidRetrievalStrategy);
050            
051            String objectIdentityRetrievalStrategy = element.getAttribute("object-identity-retrieval-strategy");
052            if (objectIdentityRetrievalStrategy != null && objectIdentityRetrievalStrategy.trim().length() > 0)
053                    builder.addPropertyReference("objectIdentityRetrievalStrategy", objectIdentityRetrievalStrategy);
054        }
055    
056        @Override
057        protected String getBeanClassName(Element element) {
058            // Determine Spring Security version
059            boolean spring3 = false;
060            try {
061                    getClass().getClassLoader().loadClass("org.springframework.security.access.AccessDeniedException");
062                    spring3 = true;
063            }
064            catch (ClassNotFoundException e) {
065                    // Assume Spring 2
066            }
067            
068            String aclService = element.getAttribute("acl-service");
069            return "org.granite.tide.spring.security." 
070                    + (aclService != null && aclService.trim().length() > 0 ? "AclIdentity" : "Identity") 
071                    + (spring3 ? "3" : "");
072        }
073    
074        static void mapOptionalAttributes(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, String... attrs) {
075            for (String attr : attrs) {
076                String value = element.getAttribute(attr);
077                if (StringUtils.hasText(value)) {
078                    String propertyName = Conventions.attributeNameToPropertyName(attr);
079                    if (validateProperty(element, parserContext, propertyName, attr)) {
080                        builder.addPropertyValue(propertyName, value);
081                    }
082                }
083            }
084        }
085    
086        private static boolean validateProperty(Element element, ParserContext parserContext, String propertyName, String attr) {
087            if (!StringUtils.hasText(propertyName)) {
088                parserContext.getReaderContext().error(
089                    "Illegal property name trying to convert from attribute '" + attr + "' : cannot be null or empty.",
090                    parserContext.extractSource(element));
091                return false;
092            }
093            return true;
094        }
095    }