001    /*
002     * Copyright 2007-2008 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.kim.util;
017    
018    import java.security.GeneralSecurityException;
019    import java.util.ArrayList;
020    import java.util.HashMap;
021    import java.util.List;
022    import java.util.Map;
023    import java.util.Set;
024    
025    import javax.xml.namespace.QName;
026    
027    import org.apache.commons.beanutils.PropertyUtils;
028    import org.apache.commons.lang.StringUtils;
029    import org.kuali.rice.kew.doctype.bo.DocumentType;
030    import org.kuali.rice.kim.bo.Group;
031    import org.kuali.rice.kim.bo.KimType;
032    import org.kuali.rice.kim.bo.entity.KimEntityPrivacyPreferences;
033    import org.kuali.rice.kim.bo.entity.dto.KimEntityDefaultInfo;
034    import org.kuali.rice.kim.bo.group.impl.GroupAttributeDataImpl;
035    import org.kuali.rice.kim.bo.impl.GroupImpl;
036    import org.kuali.rice.kim.bo.impl.KimAttributes;
037    import org.kuali.rice.kim.bo.reference.ExternalIdentifierType;
038    import org.kuali.rice.kim.bo.reference.impl.ExternalIdentifierTypeImpl;
039    import org.kuali.rice.kim.bo.types.dto.AttributeSet;
040    import org.kuali.rice.kim.bo.types.dto.KimTypeAttributeInfo;
041    import org.kuali.rice.kim.service.IdentityManagementService;
042    import org.kuali.rice.kim.service.KIMServiceLocator;
043    import org.kuali.rice.kim.service.support.KimTypeService;
044    import org.kuali.rice.kns.UserSession;
045    import org.kuali.rice.kns.service.KNSServiceLocator;
046    import org.kuali.rice.kns.service.KualiModuleService;
047    import org.kuali.rice.kns.service.ModuleService;
048    import org.kuali.rice.kns.util.GlobalVariables;
049    
050    /**
051     * This is a description of what this class does - bhargavp don't forget to fill
052     * this in.
053     *
054     * @author Kuali Rice Team (rice.collab@kuali.org)
055     *
056     */
057    public class KimCommonUtils {
058        private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KimCommonUtils.class);
059    
060        private static KualiModuleService kualiModuleService;
061        private static Map<String,KimTypeService> kimTypeServiceCache = new HashMap<String,KimTypeService>();
062        private static IdentityManagementService identityManagementService;
063    
064            private KimCommonUtils() {
065        }
066    
067            private static KualiModuleService getKualiModuleService() {
068                    if (kualiModuleService == null) {
069                            kualiModuleService = KNSServiceLocator.getKualiModuleService();
070                    }
071                    return kualiModuleService;
072            }
073    
074            public static String getClosestParentDocumentTypeName(
075                            DocumentType documentType,
076                            Set<String> potentialParentDocumentTypeNames) {
077                    if ( potentialParentDocumentTypeNames == null || documentType == null ) {
078                            return null;
079                    }
080                    if (potentialParentDocumentTypeNames.contains(documentType.getName())) {
081                            return documentType.getName();
082                    } else {
083                            if ((documentType.getDocTypeParentId() == null)
084                                            || documentType.getDocTypeParentId().equals(
085                                                            documentType.getDocumentTypeId())) {
086                                    return null;
087                            } else {
088                                    return getClosestParentDocumentTypeName(documentType
089                                                    .getParentDocType(), potentialParentDocumentTypeNames);
090                            }
091                    }
092            }
093    
094            public static boolean storedValueNotSpecifiedOrInputValueMatches(AttributeSet storedValues, AttributeSet inputValues, String attributeName) {
095                    return ((storedValues == null) || (inputValues == null)) || !storedValues.containsKey(attributeName) || storedValues.get(attributeName).equals(inputValues.get(attributeName));
096            }
097    
098            public static boolean doesPropertyNameMatch(
099                            String requestedDetailsPropertyName,
100                            String permissionDetailsPropertyName) {
101                    if (StringUtils.isBlank(permissionDetailsPropertyName)) {
102                            return true;
103                    }
104                    if ( requestedDetailsPropertyName == null ) {
105                        requestedDetailsPropertyName = ""; // prevent NPE
106                    }
107                    return StringUtils.equals(requestedDetailsPropertyName, permissionDetailsPropertyName)
108                                    || (requestedDetailsPropertyName.startsWith(permissionDetailsPropertyName+"."));
109            }
110    
111            public static AttributeSet getNamespaceAndComponentSimpleName( Class<? extends Object> clazz) {
112                    AttributeSet attributeSet = new AttributeSet();
113                    attributeSet.put(KimAttributes.NAMESPACE_CODE, getNamespaceCode(clazz));
114                    attributeSet.put(KimAttributes.COMPONENT_NAME, getComponentSimpleName(clazz));
115                    return attributeSet;
116            }
117    
118            public static AttributeSet getNamespaceAndComponentFullName( Class<? extends Object> clazz) {
119                    AttributeSet attributeSet = new AttributeSet();
120                    attributeSet.put(KimAttributes.NAMESPACE_CODE, getNamespaceCode(clazz));
121                    attributeSet.put(KimAttributes.COMPONENT_NAME, getComponentFullName(clazz));
122                    return attributeSet;
123            }
124    
125            public static AttributeSet getNamespaceAndActionClass( Class<? extends Object> clazz) {
126                    AttributeSet attributeSet = new AttributeSet();
127                    attributeSet.put(KimAttributes.NAMESPACE_CODE, getNamespaceCode(clazz));
128                    attributeSet.put(KimAttributes.ACTION_CLASS, clazz.getName());
129                    return attributeSet;
130            }
131    
132            public static String getNamespaceCode(Class<? extends Object> clazz) {
133                    ModuleService moduleService = getKualiModuleService().getResponsibleModuleService(clazz);
134                    if (moduleService == null) {
135                            return KimConstants.KIM_TYPE_DEFAULT_NAMESPACE;
136                    }
137                    return moduleService.getModuleConfiguration().getNamespaceCode();
138            }
139    
140            public static String getComponentSimpleName(Class<? extends Object> clazz) {
141                    return clazz.getSimpleName();
142            }
143    
144            public static String getComponentFullName(Class<? extends Object> clazz) {
145                    return clazz.getName();
146            }
147    
148            public static boolean isAttributeSetEntryEquals( AttributeSet map1, AttributeSet map2, String key ) {
149                    return StringUtils.equals( map1.get( key ), map2.get( key ) );
150            }
151    
152            /**
153             * Resolves the given kim type service name represented as a String to the appropriate QName.
154             * If the value given is empty or null, then it will resolve to the default KimTypeService name.
155             */
156            public static QName resolveKimTypeServiceName(String kimTypeServiceName) {
157                    if (StringUtils.isBlank(kimTypeServiceName)) {
158                            return resolveKimTypeServiceName(KimConstants.DEFAULT_KIM_TYPE_SERVICE);
159                    }
160                    return QName.valueOf(kimTypeServiceName);
161            }
162    
163            /**
164             * @deprecated Please use KIMServiceLocator.getKimTypeService(KimType) instead
165             */
166            @Deprecated
167            public static KimTypeService getKimTypeService(KimType kimType){
168                    return KIMServiceLocator.getKimTypeService(kimType);
169            }
170    
171            /**
172             * @deprecated Please use KIMServiceLocator.getKimTypeService(QName) instead
173             */
174            @Deprecated
175            public static KimTypeService getKimTypeService( String serviceName ) {
176                    return KIMServiceLocator.getKimTypeService(resolveKimTypeServiceName(serviceName));
177        }
178    
179            public static void copyProperties(Object targetToCopyTo, Object sourceToCopyFrom){
180                    if(targetToCopyTo!=null && sourceToCopyFrom!=null)
181                    try{
182                            PropertyUtils.copyProperties(targetToCopyTo, sourceToCopyFrom);
183                    } catch(Exception ex){
184                            throw new RuntimeException("Failed to copy from source object: "+sourceToCopyFrom.getClass()+" to target object: "+targetToCopyTo,ex);
185                    }
186            }
187    
188            public static String getKimBasePath(){
189                    String kimBaseUrl = KNSServiceLocator.getKualiConfigurationService().getPropertyString(KimConstants.KimUIConstants.KIM_URL_KEY);
190                    if (!kimBaseUrl.endsWith(KimConstants.KimUIConstants.URL_SEPARATOR)) {
191                            kimBaseUrl = kimBaseUrl + KimConstants.KimUIConstants.URL_SEPARATOR;
192                    }
193                    return kimBaseUrl;
194            }
195    
196            public static String getPathWithKimContext(String path, String kimActionName){
197                    String kimContext = KimConstants.KimUIConstants.KIM_APPLICATION+KimConstants.KimUIConstants.URL_SEPARATOR;
198                    String kimContextParameterized = KimConstants.KimUIConstants.KIM_APPLICATION+KimConstants.KimUIConstants.PARAMETERIZED_URL_SEPARATOR;
199            if(path.contains(kimActionName) && !path.contains(kimContext + kimActionName)
200                            && !path.contains(kimContextParameterized + kimActionName))
201                    path = path.replace(kimActionName, kimContext+kimActionName);
202            return path;
203            }
204    
205            public static String stripEnd(String toStripFrom, String toStrip){
206                    String stripped;
207                    if(toStripFrom==null) return null;
208                    if(toStrip==null) return toStripFrom;
209            if(toStrip.length() > toStripFrom.length()) return toStripFrom;
210                    if(toStripFrom.endsWith(toStrip)){
211                            StringBuffer buffer = new StringBuffer(toStripFrom);
212                            buffer.delete(buffer.length()-toStrip.length(), buffer.length());
213                            stripped = buffer.toString();
214                    } else stripped = toStripFrom;
215                    return stripped;
216            }
217    
218            protected static boolean canOverrideEntityPrivacyPreferences( String principalId ){
219                    return getIdentityManagementService().isAuthorized(
220                                    GlobalVariables.getUserSession().getPrincipalId(),
221                                    KimConstants.NAMESPACE_CODE,
222                                    KimConstants.PermissionNames.OVERRIDE_ENTITY_PRIVACY_PREFERENCES,
223                                    null,
224                                    new AttributeSet(KimAttributes.PRINCIPAL_ID, principalId) );
225            }
226    
227            public static boolean isSuppressName(String entityId) {
228                KimEntityPrivacyPreferences privacy = null;
229            KimEntityDefaultInfo entityInfo = getIdentityManagementService().getEntityDefaultInfo(entityId);
230            if (entityInfo != null) {
231                privacy = entityInfo.getPrivacyPreferences();
232            }
233                UserSession userSession = GlobalVariables.getUserSession();
234    
235            boolean suppressName = false;
236            if (privacy != null) {
237                suppressName = privacy.isSuppressName();
238            }
239            return suppressName
240                    && userSession != null
241                    && !StringUtils.equals(userSession.getPerson().getEntityId(), entityId)
242                    && !canOverrideEntityPrivacyPreferences(entityInfo.getPrincipals().get(0).getPrincipalId());
243        }
244    
245        public static boolean isSuppressEmail(String entityId) {
246            KimEntityPrivacyPreferences privacy = null;
247            KimEntityDefaultInfo entityInfo = getIdentityManagementService().getEntityDefaultInfo(entityId);
248            if (entityInfo != null) {
249                privacy = entityInfo.getPrivacyPreferences();
250            }
251            UserSession userSession = GlobalVariables.getUserSession();
252    
253            boolean suppressEmail = false;
254            if (privacy != null) {
255                suppressEmail = privacy.isSuppressEmail();
256            }
257            return suppressEmail
258                    && userSession != null
259                    && !StringUtils.equals(userSession.getPerson().getEntityId(), entityId)
260                    && !canOverrideEntityPrivacyPreferences(entityInfo.getPrincipals().get(0).getPrincipalId());
261        }
262    
263        public static boolean isSuppressAddress(String entityId) {
264            KimEntityPrivacyPreferences privacy = null;
265            KimEntityDefaultInfo entityInfo = getIdentityManagementService().getEntityDefaultInfo(entityId);
266            if (entityInfo != null) {
267                privacy = entityInfo.getPrivacyPreferences();
268            }
269            UserSession userSession = GlobalVariables.getUserSession();
270    
271            boolean suppressAddress = false;
272            if (privacy != null) {
273                suppressAddress = privacy.isSuppressAddress();
274            }
275            return suppressAddress
276                    && userSession != null
277                    && !StringUtils.equals(userSession.getPerson().getEntityId(), entityId)
278                    && !canOverrideEntityPrivacyPreferences(entityInfo.getPrincipals().get(0).getPrincipalId());
279        }
280    
281        public static boolean isSuppressPhone(String entityId) {
282            KimEntityPrivacyPreferences privacy = null;
283            KimEntityDefaultInfo entityInfo = getIdentityManagementService().getEntityDefaultInfo(entityId);
284            if (entityInfo != null) {
285                privacy = entityInfo.getPrivacyPreferences();
286            }
287            UserSession userSession = GlobalVariables.getUserSession();
288    
289            boolean suppressPhone = false;
290            if (privacy != null) {
291                suppressPhone = privacy.isSuppressPhone();
292            }
293            return suppressPhone
294                    && userSession != null
295                    && !StringUtils.equals(userSession.getPerson().getEntityId(), entityId)
296                    && !canOverrideEntityPrivacyPreferences(entityInfo.getPrincipals().get(0).getPrincipalId());
297        }
298    
299        public static boolean isSuppressPersonal(String entityId) {
300            KimEntityPrivacyPreferences privacy = null;
301            KimEntityDefaultInfo entityInfo = getIdentityManagementService().getEntityDefaultInfo(entityId);
302            if (entityInfo != null) {
303                privacy = entityInfo.getPrivacyPreferences();
304            }
305            UserSession userSession = GlobalVariables.getUserSession();
306    
307            boolean suppressPersonal = false;
308            if (privacy != null) {
309                suppressPersonal = privacy.isSuppressPersonal();
310            }
311            return suppressPersonal
312                    && userSession != null
313                    && !StringUtils.equals(userSession.getPerson().getEntityId(), entityId)
314                    && !canOverrideEntityPrivacyPreferences(entityInfo.getPrincipals().get(0).getPrincipalId());
315        }
316    
317            public static String encryptExternalIdentifier(String externalIdentifier, String externalIdentifierType){
318                    Map<String, String> criteria = new HashMap<String, String>();
319                criteria.put(KimConstants.PrimaryKeyConstants.KIM_TYPE_CODE, externalIdentifierType);
320                ExternalIdentifierType externalIdentifierTypeObject = (ExternalIdentifierType) KNSServiceLocator.getBusinessObjectService().findByPrimaryKey(ExternalIdentifierTypeImpl.class, criteria);
321                    if( externalIdentifierTypeObject!= null && externalIdentifierTypeObject.isEncryptionRequired()){
322                            if(StringUtils.isNotEmpty(externalIdentifier)){
323                                    try{
324                                            return KNSServiceLocator.getEncryptionService().encrypt(externalIdentifier);
325                                    }catch (GeneralSecurityException e) {
326                                LOG.info("Unable to encrypt value : " + e.getMessage() + " or it is already encrypted");
327                            }
328                            }
329                    }
330                    return externalIdentifier;
331        }
332    
333        public static String decryptExternalIdentifier(String externalIdentifier, String externalIdentifierType){
334            Map<String, String> criteria = new HashMap<String, String>();
335                criteria.put(KimConstants.PrimaryKeyConstants.KIM_TYPE_CODE, externalIdentifierType);
336                ExternalIdentifierType externalIdentifierTypeObject = (ExternalIdentifierType) KNSServiceLocator.getBusinessObjectService().findByPrimaryKey(ExternalIdentifierTypeImpl.class, criteria);
337                    if( externalIdentifierTypeObject!= null && externalIdentifierTypeObject.isEncryptionRequired()){
338                            if(StringUtils.isNotEmpty(externalIdentifier)){
339                                    try{
340                                            return KNSServiceLocator.getEncryptionService().decrypt(externalIdentifier);
341                                    }catch (GeneralSecurityException e) {
342                                LOG.info("Unable to decrypt value : " + e.getMessage() + " or it is already decrypted");
343                            }
344                            }
345                    }
346                    return externalIdentifier;
347        }
348    
349            public static IdentityManagementService getIdentityManagementService() {
350                    if ( identityManagementService == null ) {
351                            identityManagementService = KIMServiceLocator.getIdentityManagementService();
352                    }
353                    return identityManagementService;
354            }
355    
356    
357        public static GroupImpl copyInfoToGroup(Group info, GroupImpl group) {
358            group.setActive(info.isActive());
359            group.setGroupDescription(info.getGroupDescription());
360            group.setGroupId(info.getGroupId());
361            group.setGroupName(info.getGroupName());
362            group.setKimTypeId(info.getKimTypeId());
363            group.setNamespaceCode(info.getNamespaceCode());
364    
365            return group;
366        }
367    
368        /**
369         *
370         * @param infoMap Containing the Info Attribute objects.
371         * @param groupId for the group of attributes
372         * @param kimTypeId for the group of attributes
373         * @return a list of group attributes
374         */
375    
376        public static List<GroupAttributeDataImpl> copyInfoAttributesToGroupAttributes(Map<String, String> infoMap, String groupId, String kimTypeId) {
377            List<GroupAttributeDataImpl> attrList = new ArrayList<GroupAttributeDataImpl>(infoMap.size());
378            List<KimTypeAttributeInfo> attributeInfoList = KIMServiceLocator.getTypeInfoService().getKimType(kimTypeId).getAttributeDefinitions();
379    
380            for (String key : infoMap.keySet()) {
381                KimTypeAttributeInfo typeAttributeInfo = getAttributeInfo(attributeInfoList, key);
382    
383                if (typeAttributeInfo != null) {
384                    GroupAttributeDataImpl groupAttribute = new GroupAttributeDataImpl();
385                    groupAttribute.setKimAttributeId(typeAttributeInfo.getKimAttributeId());
386                    groupAttribute.setAttributeValue(infoMap.get(typeAttributeInfo.getAttributeName()));
387                    groupAttribute.setGroupId(groupId);
388                    groupAttribute.setKimTypeId(kimTypeId);
389                    attrList.add(groupAttribute);
390                } else {
391                    throw new IllegalArgumentException("KimAttribute not found: " + key);
392                }
393            }
394            return attrList;
395        }
396    
397        private static KimTypeAttributeInfo getAttributeInfo(List<KimTypeAttributeInfo> attributeInfoList, String attributeName) {
398            KimTypeAttributeInfo kRet = null;
399            for (KimTypeAttributeInfo attributeInfo : attributeInfoList) {
400                if (attributeInfo.getAttributeName().equals(attributeName)) {
401                    kRet = attributeInfo;
402                    break;
403                }
404            }
405            return kRet;
406        }
407    
408    }