/** * Licensed to the Austrian Association for Software Tool Integration (AASTI) * under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright * ownership. The AASTI licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.openengsb.core.services.internal.security; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import org.apache.commons.lang.ClassUtils; import org.openengsb.core.api.OsgiUtilsService; import org.openengsb.core.api.security.model.Permission; import org.openengsb.core.services.internal.security.model.BeanData; import org.openengsb.core.services.internal.security.model.EntryElement; import org.openengsb.core.services.internal.security.model.EntryValue; import org.openengsb.core.util.BeanUtilsExtended; import org.openengsb.core.util.FilterUtils; import org.openengsb.labs.delegation.service.ClassProvider; import org.openengsb.labs.delegation.service.Constants; import org.osgi.framework.Filter; import org.springframework.util.ReflectionUtils; import com.google.common.base.Function; import com.google.common.collect.Collections2; import com.google.common.collect.ComputationException; import com.google.common.collect.Lists; import com.google.common.collect.Maps; /** * Provides util-functions for handling multi-valued attributes, used to save {@link BeanData}. * * For more details on the conversion from a bean to {@link BeanData} and vice versa, see {@link BeanData}. */ public final class EntryUtils { private static OsgiUtilsService utilsService; /** * converts a list of {@link EntryElement} back to a list containing the original java objects. */ public static List<Object> convertAllEntryElementsToObject(List<EntryElement> value) { return Lists.transform(value, new EntryElementParserFunction()); } private static class EntryElementParserFunction implements Function<EntryElement, Object> { @Override public Object apply(EntryElement input) { Class<?> elementType; try { elementType = Class.forName(input.getType()); } catch (ClassNotFoundException e) { throw new ComputationException(e); } try { Constructor<?> constructor = elementType.getConstructor(String.class); return constructor.newInstance(input.getValue()); } catch (Exception e) { ReflectionUtils.handleReflectionException(e); throw new ComputationException(e); } } } /** * converts all Objects to {@link EntryElement}s to their Bean-data can be saved to the DB */ public static List<EntryElement> makeEntryElementList(Object... value) { List<EntryElement> valueElements = new ArrayList<EntryElement>(); for (Object o : value) { Class<?> type = ClassUtils.primitiveToWrapper(o.getClass()); EntryElement entryElement = new EntryElement(type.getName(), o.toString()); valueElements.add(entryElement); } return valueElements; } /** * converts an Object to an {@link EntryElement} so its Bean-data can be saved to the DB */ public static EntryElement makeEntryElement(Object value) { Class<?> type = ClassUtils.primitiveToWrapper(value.getClass()); return new EntryElement(type.getName(), value.toString()); } /** * Takes any bean Object and converts it to a Map of {@link EntryValue} so the beandata can be saved to the DB. */ public static Map<String, EntryValue> convertBeanToEntryMap(Object bean) { Map<String, Object> buildAttributeValueMap = BeanUtilsExtended.buildObjectAttributeMap(bean); return Maps.transformEntries(buildAttributeValueMap, new ObjectToEntryValueTransformer()); } private static final class ObjectToEntryValueTransformer implements Maps.EntryTransformer<String, Object, EntryValue> { @SuppressWarnings("unchecked") @Override public EntryValue transformEntry(String key, Object value) { if (value == null) { return null; } if (value instanceof Collection) { return new EntryValue(key, convertAllObjectsToEntryElements((Collection<Object>) value)); } if (value.getClass().isArray()) { return new EntryValue(key, convertAllObjectsToEntryElements((Object[]) value)); } return new EntryValue(key, Arrays.asList(transformObjectToEntryElement(value))); } } /** * works similar to {@link EntryUtils#makeEntryElementList(Object...)}, but takes a list as argument */ private static List<EntryElement> convertAllObjectsToEntryElements(Collection<? extends Object> collection) { List<EntryElement> result = new ArrayList<EntryElement>(); for (Object o : collection) { result.add(transformObjectToEntryElement(o)); } return result; } private static List<EntryElement> convertAllObjectsToEntryElements(Object[] array) { List<EntryElement> result = new ArrayList<EntryElement>(); for (Object o : array) { result.add(transformObjectToEntryElement(o)); } return result; } private static EntryElement transformObjectToEntryElement(Object o) { return new EntryElement(o.getClass().getName(), o.toString()); } /** * converts a Collection of {@link BeanData} to their original {@link Object} form. */ public static <T> Collection<T> convertAllBeanDataToObjects(Collection<? extends BeanData> data) { return Collections2.transform(data, new BeanDataToObjectFunction<T>()); } private static final class BeanDataToObjectFunction<T> implements Function<BeanData, T> { @Override public T apply(BeanData input) { return convertBeanDataToObject(input); } } @SuppressWarnings("unchecked") private static <T> T convertBeanDataToObject(BeanData input) { Class<?> permType; try { permType = findPermissionClass(input.getType()); } catch (ClassNotFoundException e) { throw new IllegalArgumentException("permission-type could not be found " + input.getType(), e); } Map<String, Object> attributeValues = convertEntryMapToAttributeMap(input.getAttributes()); return (T) BeanUtilsExtended.createBeanFromAttributeMap(permType, attributeValues); } @SuppressWarnings("unchecked") private static Class<? extends Permission> findPermissionClass(String name) throws ClassNotFoundException { Filter filter = FilterUtils.makeFilter(ClassProvider.class, String.format("(%s=%s)", Constants.PROVIDED_CLASSES_KEY, name)); ClassProvider provider = utilsService.getOsgiServiceProxy(filter, ClassProvider.class); return (Class<? extends Permission>) provider.loadClass(name); } private static Map<String, Object> convertEntryMapToAttributeMap(Map<String, EntryValue> entryMap) { return Maps.transformEntries(entryMap, new EntryValueToObjectTransformer()); } private static final class EntryValueToObjectTransformer implements Maps.EntryTransformer<String, EntryValue, Object> { @Override public Object transformEntry(String key, EntryValue value) { List<Object> objects = Lists.transform(value.getValue(), new EntryElementParserFunction()); if (objects.isEmpty()) { return null; } if (objects.size() == 1) { return objects.get(0); } return objects; } } public static void setUtilsService(OsgiUtilsService utilsService) { EntryUtils.utilsService = utilsService; } private EntryUtils() { } }