
de.fraunhofer.iese.ind2uce.reactive.AbstractRxPEP Maven / Gradle / Ivy
/*-
* =================================LICENSE_START=================================
* IND2UCE
* %%
* Copyright (C) 2017 Fraunhofer IESE (www.iese.fraunhofer.de)
* %%
* Licensed 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.
* =================================LICENSE_END=================================
*/
package de.fraunhofer.iese.ind2uce.reactive;
import de.fraunhofer.iese.ind2uce.api.component.interfaces.IPolicyEnforcementPoint;
import de.fraunhofer.iese.ind2uce.api.policy.Event;
import de.fraunhofer.iese.ind2uce.api.policy.identifier.ActionId;
import de.fraunhofer.iese.ind2uce.api.policy.parameter.ParameterList;
import de.fraunhofer.iese.ind2uce.logger.LoggerFactory;
import de.fraunhofer.iese.ind2uce.pep.PolicyEnforcementPoint;
import de.fraunhofer.iese.ind2uce.reactive.common.EventParameter;
import de.fraunhofer.iese.ind2uce.reactive.common.EventSpecification;
import de.fraunhofer.iese.ind2uce.reactive.common.EventUUID;
import de.fraunhofer.iese.ind2uce.reactive.common.IncorrectPEPDescriptionError;
import de.fraunhofer.iese.ind2uce.reactive.common.RxPEP;
import de.fraunhofer.iese.ind2uce.reactive.common.RxPEPState;
import org.slf4j.Logger;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Proxy;
import java.util.concurrent.atomic.AtomicReference;
import rx.Observable;
import rx.schedulers.Schedulers;
/**
* Base Implementation of a RxPEP.
*/
public abstract class AbstractRxPEP implements RxPEP {
protected static Logger LOG = LoggerFactory.getLogger(PolicyEnforcementPoint.class);
/**
* The pep state.
*/
protected final AtomicReference pepState = new AtomicReference<>(RxPEPState.REGISTRATION_NOT_STARTED);
/**
* The policy enforcement point.
*/
protected final IPolicyEnforcementPoint policyEnforcementPoint;
/**
* The documentation API.
*/
protected final Class pepInterfaceDescription;
/**
* Instantiates a new Rx PEP.
*
* @param pepInterfaceDescription the documentation API
* @param policyEnforcementPoint the policy enforcement point
*/
public AbstractRxPEP(IPolicyEnforcementPoint policyEnforcementPoint, Class pepInterfaceDescription) {
this.policyEnforcementPoint = policyEnforcementPoint;
this.pepInterfaceDescription = pepInterfaceDescription;
}
/*
* (non-Javadoc)
* @see de.fraunhofer.iese.ind2uce.reactive.common.RxPEP#createInstanceAPI()
*/
@Override
@SuppressWarnings("unchecked")
public T createInstanceAPI() {
if (this.pepState.get() == RxPEPState.REGISTRATION_DONE_SUCCESSFULLY) {
return (T)Proxy.newProxyInstance(this.pepInterfaceDescription.getClassLoader(), new Class>[] {
this.pepInterfaceDescription
}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// pass to object class if method belongs to Object class
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
return AbstractRxPEP.this.enforceDecision(method, args);
}
});
}
throw new IllegalStateException("RxPEP is not registered yet, please perform successful registration before using documentation API");
}
/*
* (non-Javadoc)
* @see de.fraunhofer.iese.ind2uce.reactive.common.RxPEP#doRegisterAtPMP()
*/
@Override
public Observable doRegisterAtPMP() {
return Observable.fromCallable(() -> {
switch (this.pepState.get()) {
case REGISTRATION_DONE_SUCCESSFULLY:
return false;
case REGISTRATION_FAILED:
return false;
case REGISTRATION_NOT_STARTED:
this.pepState.set(RxPEPState.REGISTRATION_UNDER_PROCESS);
return this.policyEnforcementPoint.initialize();
case REGISTRATION_UNDER_PROCESS:
throw new IllegalStateException("PEP under registration, don't try to register when it's already under the process");
default:
throw new IllegalStateException("WTF state");
}
}).doOnError((e) -> {
if (e instanceof IOException) {
LOG.error("Registration of PEP at PMP failed!");
this.pepState.set(RxPEPState.REGISTRATION_FAILED);
}
}).doOnNext(aBoolean -> {
if (this.pepState.get() != RxPEPState.REGISTRATION_DONE_SUCCESSFULLY) {
if (aBoolean) {
this.pepState.set(RxPEPState.REGISTRATION_DONE_SUCCESSFULLY);
this.postSuccessfulRegistration();
} else {
this.pepState.set(RxPEPState.REGISTRATION_FAILED);
}
}
}).subscribeOn(Schedulers.immediate());
}
protected abstract Object enforceDecision(Method method, Object[] args);
/**
* Returns the parameter of type PEPParamKey.
*
* @param annotations the annotations
* @return the parameter annotation
*/
EventParameter getParameterAnnotation(Annotation[] annotations) {
for (final Annotation annotation : annotations) {
if (annotation instanceof EventParameter) {
return (EventParameter)annotation;
}
}
return null;
}
/*
* (non-Javadoc)
* @see
* de.fraunhofer.iese.ind2uce.reactive.common.RxPEP#getPolicyEnforcementPoint(
* )
*/
@Override
public IPolicyEnforcementPoint getPolicyEnforcementPoint() {
return this.policyEnforcementPoint;
}
/*
* (non-Javadoc)
* @see de.fraunhofer.iese.ind2uce.reactive.common.RxPEP#isReady()
*/
@Override
public RxPEPState isReady() {
return this.pepState.get();
}
protected abstract void postSuccessfulRegistration();
/**
* Gets the action id from the given method and creates a new event with
* specific UUID and parameters set.
*
* @param method the method
* @param methodArguments the method arguments
* @return the event
* @throws IncorrectPEPDescriptionError the incorrect PEP description error
*/
protected Event readAndCreateEvent(Method method, Object[] methodArguments) throws IncorrectPEPDescriptionError {
Event event;
final ActionId actionId = this.readEventDescription(method);
event = new Event(actionId);
event.setTag(this.readUUID(method, methodArguments));
event.setParameters(this.readParameterList(method.getParameterTypes(), method.getParameterAnnotations(), methodArguments));
return event;
}
/**
* Gets the platform, context and action values from the event specification
* of the given method and creates the action id and returns it.
*
* @param method the method
* @return the action id
*/
protected ActionId readEventDescription(Method method) {
final Annotation[] methodAnnotation = method.getDeclaredAnnotationsByType(EventSpecification.class);
if (methodAnnotation.length > 0) {
ActionId eventId = null;
final EventSpecification ed = ((EventSpecification)methodAnnotation[0]);
eventId = new ActionId(ed.scope(), ed.action());
return eventId;
}
LOG.error("API declaration error: ActionId can't be null for event.");
throw new IncorrectPEPDescriptionError("ActionId can't be null for event. API declaration error");
}
/**
* Returns the annotations of type PEPParamKey with their corresponding method
* argument.
*
* @param parametersType parameter type
* @param parametersAnnotations the parameters annotations
* @param methodArguments the method arguments
* @return the parameter list
*/
protected ParameterList readParameterList(Class>[] parametersType, Annotation[][] parametersAnnotations, Object[] methodArguments) {
final ParameterList parameters = new ParameterList();
for (int i = 0; i < parametersAnnotations.length; i++) {
final EventParameter PEPParamKey = this.getParameterAnnotation(parametersAnnotations[i]);
if (PEPParamKey != null) {
parameters.addParameter(PEPParamKey.name(), methodArguments[i], parametersType[i]);
}
}
return parameters;
}
/**
* Returns the corresponding argument to the UUID of the given method.
*
* @param method the method
* @param methodArguments the method arguments
* @return the UUID
*/
private Object readUUID(final Method method, final Object[] methodArguments) {
final Parameter parameters[] = method.getParameters();
for (int i = 0; i < parameters.length; i++) {
if (parameters[i].getAnnotationsByType(EventUUID.class).length != 0) {
return methodArguments[i];
}
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy