| /** |
| * |
| * Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany) |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation |
| * |
| */ |
| package org.eclipse.osbp.xtext.functionlibrarydsl.provider; |
| |
| import java.beans.BeanInfo; |
| import java.beans.IntrospectionException; |
| import java.beans.Introspector; |
| import java.beans.MethodDescriptor; |
| import java.beans.ParameterDescriptor; |
| import java.beans.PropertyDescriptor; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.util.HashSet; |
| import java.util.Locale; |
| import java.util.Set; |
| |
| import org.eclipse.osbp.ui.api.functionlibrary.IFunctionLibraryGroup; |
| import org.eclipse.osbp.ui.api.functionlibrary.IFunctionLibraryPackage; |
| import org.eclipse.osbp.ui.api.functionlibrary.IFunctionLibraryService; |
| import org.eclipse.osbp.ui.api.statemachine.IStateMachine; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.service.component.ComponentContext; |
| import org.osgi.service.component.annotations.Activate; |
| import org.osgi.service.component.annotations.Component; |
| import org.osgi.service.component.annotations.Deactivate; |
| import org.osgi.service.component.annotations.Reference; |
| import org.osgi.service.component.annotations.ReferenceCardinality; |
| import org.osgi.service.component.annotations.ReferencePolicy; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * This service provides access to the function library. |
| */ |
| @Component(immediate = true) |
| public class FunctionLibraryService implements IFunctionLibraryService { |
| |
| private final Logger LOGGER = LoggerFactory |
| .getLogger(FunctionLibraryService.class); |
| private Set<ServiceReference<IFunctionLibraryPackage>> functionLibraryPackages = new HashSet<>(); |
| private Set<Bundle> bundles = new HashSet<>(); |
| @SuppressWarnings("unused") |
| private ComponentContext context; |
| |
| @Activate |
| protected void activate(ComponentContext context) { |
| this.context = context; |
| } |
| |
| @Deactivate |
| protected void deactivate(ComponentContext context) { |
| this.context = null; |
| functionLibraryPackages.clear(); |
| bundles.clear(); |
| } |
| |
| @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC, unbind = "removeFunctionLibraryPackage") |
| public synchronized void addFunctionLibraryPackage( |
| final ServiceReference<IFunctionLibraryPackage> ref) { |
| |
| functionLibraryPackages.add(ref); |
| |
| createBundleList(); |
| |
| LOGGER.debug("IFunctionLibraryPackage " + ref.getProperty("name") |
| + " bound"); |
| } |
| |
| public synchronized void removeFunctionLibraryPackage( |
| final ServiceReference<IFunctionLibraryPackage> ref) { |
| functionLibraryPackages.remove(ref); |
| |
| createBundleList(); |
| |
| LOGGER.debug("IFunctionLibraryPackage " + ref.getProperty("name") |
| + " unbound"); |
| } |
| |
| private void createBundleList() { |
| if (LOGGER.isDebugEnabled()) |
| LOGGER.debug("creating class loader list"); |
| bundles.clear(); |
| for (ServiceReference<IFunctionLibraryPackage> ref : functionLibraryPackages) { |
| try { |
| bundles.add(ref.getBundle()); |
| } catch (Exception e) { |
| LOGGER.error("{}", e); |
| } |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| private Class<IFunctionLibraryGroup> getFunctionLibraryClass( |
| String className) { |
| for (Bundle bundle : bundles) { |
| try { |
| return (Class<IFunctionLibraryGroup>) bundle |
| .loadClass(className); |
| } catch (ClassNotFoundException e) { |
| LOGGER.error("{}", e); |
| } |
| } |
| return null; |
| } |
| |
| private Object callFunctionLibrary( |
| Class<IFunctionLibraryGroup> functionLibGroupClass, |
| String methodName, Object fieldValue, Locale locale, |
| Object... params) { |
| if (functionLibGroupClass != null) { |
| try { |
| IFunctionLibraryGroup functionLibGroup = functionLibGroupClass |
| .newInstance(); |
| for (Method method : functionLibGroupClass.getDeclaredMethods()) { |
| if (method.getName().equals(methodName)) { |
| try { |
| // both locale and fieldValue are set |
| if (locale != null && fieldValue != null) { |
| if (params.length > 0) { |
| return method.invoke(functionLibGroup, |
| fieldValue, locale, params); |
| } |
| return method.invoke(functionLibGroup, |
| fieldValue, locale); |
| } |
| // both locale and fieldValue are UNSET |
| else if (locale == null && fieldValue == null) { |
| return method.invoke(functionLibGroup); |
| } |
| // either locale or fieldValue is set, the other is |
| // unset |
| // only fieldValue is set |
| else if (fieldValue != null) { |
| return method.invoke(functionLibGroup, |
| fieldValue); |
| } |
| // only locale is set (last possible condition) |
| else { |
| return method.invoke(functionLibGroup, locale); |
| } |
| } catch (IllegalArgumentException e) { |
| LOGGER.error("{}", e); |
| } catch (InvocationTargetException e) { |
| LOGGER.error("{}", e); |
| } |
| } |
| } |
| } catch (InstantiationException e) { |
| LOGGER.error("{}", e); |
| } catch (IllegalAccessException e) { |
| LOGGER.error("{}", e); |
| } |
| } |
| return null; |
| } |
| |
| public Object callFunctionLibrary(String className, String methodName, |
| Object fieldValue, Locale locale, Object... params) { |
| return callFunctionLibrary(getFunctionLibraryClass(className), |
| methodName, fieldValue, locale, params); |
| } |
| |
| public Object callFunctionLibrary(String className, String methodName, |
| Object fieldValue) { |
| return callFunctionLibrary(getFunctionLibraryClass(className), |
| methodName, fieldValue, null); |
| } |
| |
| public Object callFunctionLibrary(String className, String methodName, |
| Locale locale) { |
| return callFunctionLibrary(getFunctionLibraryClass(className), |
| methodName, null, locale); |
| } |
| |
| public Object callFunctionLibrary(String className, String methodName) { |
| return callFunctionLibrary(className, methodName, null); |
| } |
| |
| public boolean guard(IStateMachine statemachine, String className, |
| String methodName) { |
| Class<?> clz = getFunctionLibraryClass(className); |
| try { |
| BeanInfo info = Introspector.getBeanInfo(clz); |
| for (MethodDescriptor methodDesc : info.getMethodDescriptors()) { |
| Method method = methodDesc.getMethod(); |
| Class[] parameterTypes = method.getParameterTypes(); |
| if (methodName.equals(method.getName())) { |
| if(parameterTypes.length == 1) { |
| if(IStateMachine.class.isAssignableFrom(parameterTypes[0])) { |
| if(boolean.class.isAssignableFrom(method.getReturnType())) { |
| return (Boolean) method.invoke(clz, statemachine); |
| } else { |
| LOGGER.error("method "+methodName+" in class "+className+" must have a return type Boolean. Found "+method.getReturnType().getCanonicalName()+" instead."); |
| } |
| } else { |
| LOGGER.error("method "+methodName+" in class "+className+" must have a parameter of type IStateMachine. Found "+parameterTypes[0].getCanonicalName()+" instead."); |
| } |
| } else { |
| LOGGER.error("method "+methodName+" in class "+className+" must have exactly 1 parameter. Found "+parameterTypes.length+" parameters instead."); |
| } |
| } |
| } |
| LOGGER.error("method "+methodName+" was not found in class "+className); |
| } catch (IntrospectionException | IllegalAccessException |
| | IllegalArgumentException | InvocationTargetException e) { |
| LOGGER.error("{}", e); |
| } |
| return false; |
| } |
| |
| public boolean operation(IStateMachine statemachine, String className, |
| String methodName, Object... params) { |
| Class<?> clz = getFunctionLibraryClass(className); |
| try { |
| BeanInfo info = Introspector.getBeanInfo(clz); |
| for (MethodDescriptor methodDesc : info.getMethodDescriptors()) { |
| Method method = methodDesc.getMethod(); |
| Class[] parameterTypes = method.getParameterTypes(); |
| if (methodName.equals(method.getName())) { |
| if(parameterTypes.length >= 1) { |
| if(IStateMachine.class.isAssignableFrom(parameterTypes[0])) { |
| if(boolean.class.isAssignableFrom(method.getReturnType())) { |
| if(parameterTypes.length == 1) { |
| return (Boolean) method.invoke(clz, statemachine); |
| } else { |
| return (Boolean) method.invoke(clz, statemachine, params); |
| } |
| } else { |
| LOGGER.error("method "+methodName+" in class "+className+" must have a return type Boolean. Found "+method.getReturnType().getCanonicalName()+" instead."); |
| } |
| } else { |
| LOGGER.error("method "+methodName+" in class "+className+" must have as first parameter type IStateMachine. Found "+parameterTypes[0].getCanonicalName()+" instead."); |
| } |
| } else { |
| LOGGER.error("method "+methodName+" in class "+className+" must have at least one parameter. Found "+parameterTypes.length+" parameters instead."); |
| } |
| } |
| } |
| LOGGER.error("method "+methodName+" was not found in class "+className); |
| } catch (IntrospectionException | IllegalAccessException |
| | IllegalArgumentException | InvocationTargetException e) { |
| LOGGER.error("{}", e); |
| } |
| return false; |
| } |
| |
| @Override |
| public Object function(IStateMachine statemachine, String className, |
| String methodName, Object... params) { |
| Class<?> clz = getFunctionLibraryClass(className); |
| try { |
| BeanInfo info = Introspector.getBeanInfo(clz); |
| for (MethodDescriptor methodDesc : info.getMethodDescriptors()) { |
| Method method = methodDesc.getMethod(); |
| Class[] parameterTypes = method.getParameterTypes(); |
| if (methodName.equals(method.getName())) { |
| if(parameterTypes.length >= 1) { |
| if(IStateMachine.class.isAssignableFrom(parameterTypes[0])) { |
| if(parameterTypes.length == 1) { |
| return method.invoke(clz, statemachine); |
| } else { |
| return method.invoke(clz, statemachine, params); |
| } |
| } else { |
| LOGGER.error("method "+methodName+" in class "+className+" must have as first parameter type IStateMachine. Found "+parameterTypes[0].getCanonicalName()+" instead."); |
| } |
| } else { |
| LOGGER.error("method "+methodName+" in class "+className+" must have at least one parameter. Found "+parameterTypes.length+" parameters instead."); |
| } |
| } |
| } |
| LOGGER.error("method "+methodName+" was not found in class "+className); |
| } catch (IntrospectionException | IllegalAccessException |
| | IllegalArgumentException | InvocationTargetException e) { |
| LOGGER.error("{}", e); |
| } |
| return null; |
| } |
| } |