/* * Copyright 2013 Robert von Burg <eitch@eitchnet.ch> * * 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. */ package li.strolch.service.api; import java.text.MessageFormat; import li.strolch.agent.api.ComponentContainer; import li.strolch.agent.api.StrolchComponent; import li.strolch.exception.StrolchAccessDeniedException; import li.strolch.exception.StrolchException; import li.strolch.privilege.base.PrivilegeException; import li.strolch.privilege.model.Certificate; import li.strolch.privilege.model.PrivilegeContext; import li.strolch.runtime.configuration.ComponentConfiguration; import li.strolch.runtime.configuration.RuntimeConfiguration; import li.strolch.runtime.privilege.PrivilegeHandler; import li.strolch.utils.helper.StringHelper; /** * @author Robert von Burg <eitch@eitchnet.ch> */ public class DefaultServiceHandler extends StrolchComponent implements ServiceHandler { private static final String PARAM_THROW_ON_PRIVILEGE_FAIL = "throwOnPrivilegeFail"; private RuntimeConfiguration runtimeConfiguration; private PrivilegeHandler privilegeHandler; private boolean throwOnPrivilegeFail; /** * @param container * @param componentName */ public DefaultServiceHandler(ComponentContainer container, String componentName) { super(container, componentName); } @Override public void initialize(ComponentConfiguration configuration) throws Exception { this.privilegeHandler = getContainer().getPrivilegeHandler(); this.runtimeConfiguration = configuration.getRuntimeConfiguration(); this.throwOnPrivilegeFail = configuration.getBoolean(PARAM_THROW_ON_PRIVILEGE_FAIL, Boolean.FALSE); super.initialize(configuration); } public <T> T getComponent(Class<T> clazz) { return getContainer().getComponent(clazz); } public RuntimeConfiguration getRuntimeConfiguration() { return this.runtimeConfiguration; } @Override public <U extends ServiceResult> U doService(Certificate certificate, Service<ServiceArgument, U> service) { return doService(certificate, service, null); } @Override public <T extends ServiceArgument, U extends ServiceResult> U doService(Certificate certificate, Service<T, U> service, T argument) { long start = System.nanoTime(); // first check that the caller may perform this service PrivilegeContext privilegeContext; String username = certificate == null ? "null" : certificate.getUsername(); try { privilegeContext = this.privilegeHandler.getPrivilegeContext(certificate); privilegeContext.validateAction(service); } catch (PrivilegeException e) { long end = System.nanoTime(); String msg = "User {0}: Service {1} failed after {2} due to {3}"; //$NON-NLS-1$ msg = MessageFormat.format(msg, username, service.getClass().getName(), StringHelper.formatNanoDuration(end - start), e.getMessage()); logger.error(msg); if (!this.throwOnPrivilegeFail && service instanceof AbstractService) { logger.error(e.getMessage(), e); AbstractService<?, ?> abstractService = (AbstractService<?, ?>) service; @SuppressWarnings("unchecked") U arg = (U) abstractService.getResultInstance(); arg.setState(ServiceResultState.ACCESS_DENIED); arg.setMessage(e.getMessage()); arg.setThrowable(e); return arg; } throw new StrolchAccessDeniedException(certificate, service, e.getMessage(), e); } try { // then perform the service if (service instanceof AbstractService) { AbstractService<?, ?> abstractService = (AbstractService<?, ?>) service; abstractService.setContainer(getContainer()); abstractService.setPrivilegeContext(privilegeContext); } U serviceResult = service.doService(argument); if (serviceResult == null) { String msg = "Service {0} is not properly implemented as it returned a null result!"; //$NON-NLS-1$ msg = MessageFormat.format(msg, service.getClass().getSimpleName()); throw new StrolchException(msg); } // log the result logResult(service, start, username, serviceResult); return serviceResult; } catch (Exception e) { long end = System.nanoTime(); String msg = "User {0}: Service failed {1} after {2} due to {3}"; //$NON-NLS-1$ msg = MessageFormat.format(msg, username, service.getClass().getName(), StringHelper.formatNanoDuration(end - start), e.getMessage()); logger.error(msg); throw new StrolchException(msg, e); } } private void logResult(Service<?, ?> service, long start, String username, ServiceResult serviceResult) { long end = System.nanoTime(); String msg = "User {0}: Service {1} took {2}"; //$NON-NLS-1$ msg = MessageFormat.format(msg, username, service.getClass().getName(), StringHelper.formatNanoDuration(end - start)); if (serviceResult.getState() == ServiceResultState.SUCCESS) { logger.info(msg); } else if (serviceResult.getState() == ServiceResultState.WARNING) { msg = ServiceResultState.WARNING + " " + msg; logger.warn(msg); if (StringHelper.isNotEmpty(serviceResult.getMessage()) && serviceResult.getThrowable() != null) { logger.warn("Reason: " + serviceResult.getMessage(), serviceResult.getThrowable()); } else if (StringHelper.isNotEmpty(serviceResult.getMessage())) { logger.warn("Reason: " + serviceResult.getMessage()); } else if (serviceResult.getThrowable() != null) { logger.warn("Reason: " + serviceResult.getThrowable().getMessage(), serviceResult.getThrowable()); } } else if (serviceResult.getState() == ServiceResultState.FAILED) { msg = ServiceResultState.FAILED + " " + msg; logger.error(msg); if (StringHelper.isNotEmpty(serviceResult.getMessage()) && serviceResult.getThrowable() != null) { logger.error("Reason: " + serviceResult.getMessage(), serviceResult.getThrowable()); } else if (StringHelper.isNotEmpty(serviceResult.getMessage())) { logger.error("Reason: " + serviceResult.getMessage()); } else if (serviceResult.getThrowable() != null) { logger.error("Reason: " + serviceResult.getThrowable().getMessage(), serviceResult.getThrowable()); } } else if (serviceResult.getState() == null) { logger.warn("Service " + service.getClass().getName() + " returned a null ServiceResultState!"); logger.warn(msg); } else { logger.warn("UNHANDLED SERVICE RESULT STATE: " + serviceResult.getState()); logger.warn(msg); } } }