001/** 002 * Copyright (C) 2006-2020 Talend Inc. - www.talend.com 003 * 004 * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0 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 */ 016package org.talend.sdk.component.server.service.security; 017 018import static java.util.Optional.ofNullable; 019 020import java.util.HashMap; 021import java.util.Map; 022 023import javax.enterprise.event.Observes; 024import javax.enterprise.inject.spi.AfterBeanDiscovery; 025import javax.enterprise.inject.spi.AfterDeploymentValidation; 026import javax.enterprise.inject.spi.BeanManager; 027import javax.enterprise.inject.spi.EventContext; 028import javax.enterprise.inject.spi.Extension; 029import javax.enterprise.inject.spi.ObserverMethod; 030import javax.enterprise.inject.spi.ProcessObserverMethod; 031import javax.enterprise.inject.spi.ProcessSyntheticObserverMethod; 032import javax.enterprise.inject.spi.configurator.ObserverMethodConfigurator; 033import javax.inject.Named; 034 035import org.talend.sdk.component.server.configuration.ComponentServerConfiguration; 036import org.talend.sdk.component.server.service.security.event.OnCommand; 037import org.talend.sdk.component.server.service.security.event.OnConnection; 038 039import lombok.extern.slf4j.Slf4j; 040 041// this extension will: 042// - capture all OnConnection/OnCommand observers 043// - bind the configured one (ComponentServerConfiguration) to handle the security 044@Slf4j 045public class SecurityExtension implements Extension { 046 047 private final Map<String, ObserverMethod<OnConnection>> onConnectionObservers = new HashMap<>(); 048 049 private final Map<String, ObserverMethod<OnCommand>> onCommandObservers = new HashMap<>(); 050 051 private ObserverMethod<OnConnection> onConnectionMtd; 052 053 private ObserverMethod<OnCommand> onCommandMtd; 054 055 void findOnConnectionMethod(@Observes final ProcessObserverMethod<OnConnection, ?> processObserverMethod) { 056 if (ProcessSyntheticObserverMethod.class.isInstance(processObserverMethod)) { 057 return; 058 } 059 onConnectionObservers.put(getName(processObserverMethod), processObserverMethod.getObserverMethod()); 060 processObserverMethod.veto(); 061 } 062 063 void findOnCommandMethod(@Observes final ProcessObserverMethod<OnCommand, ?> processObserverMethod) { 064 if (ProcessSyntheticObserverMethod.class.isInstance(processObserverMethod)) { 065 return; 066 } 067 onCommandObservers.put(getName(processObserverMethod), processObserverMethod.getObserverMethod()); 068 processObserverMethod.veto(); 069 } 070 071 void addSecurityHandlerObservers(@Observes final AfterBeanDiscovery afterBeanDiscovery) { 072 final ObserverMethodConfigurator<OnConnection> onConnection = afterBeanDiscovery.addObserverMethod(); 073 onConnection.observedType(OnConnection.class).notifyWith(this::onConnection); 074 final ObserverMethodConfigurator<OnCommand> onCommand = afterBeanDiscovery.addObserverMethod(); 075 onCommand.observedType(OnCommand.class).notifyWith(this::onCommand); 076 } 077 078 void bindSecurityHandlers(@Observes final AfterDeploymentValidation afterDeploymentValidation, 079 final BeanManager beanManager) { 080 final ComponentServerConfiguration configuration = ComponentServerConfiguration.class 081 .cast(beanManager 082 .getReference(beanManager.resolve(beanManager.getBeans(ComponentServerConfiguration.class)), 083 ComponentServerConfiguration.class, beanManager.createCreationalContext(null))); 084 085 final String connectionHandler = configuration.getSecurityConnectionHandler(); 086 onConnectionMtd = ofNullable(onConnectionObservers.get(connectionHandler)) 087 .orElseThrow(() -> new IllegalArgumentException("No handler '" + connectionHandler + "'")); 088 089 final String commandHandler = configuration.getSecurityCommandHandler(); 090 onCommandMtd = ofNullable(onCommandObservers.get(commandHandler)) 091 .orElseThrow(() -> new IllegalArgumentException("No handler '" + commandHandler + "'")); 092 093 // no more needed 094 onConnectionObservers.clear(); 095 onCommandObservers.clear(); 096 097 log 098 .info("Security configured with connection handler '{}' and command handler '{}'", connectionHandler, 099 commandHandler); 100 } 101 102 private void onConnection(final EventContext<OnConnection> onConnection) { 103 onConnectionMtd.notify(onConnection); 104 } 105 106 private void onCommand(final EventContext<OnCommand> onCommand) { 107 onCommandMtd.notify(onCommand); 108 } 109 110 private String getName(final ProcessObserverMethod<?, ?> processObserverMethod) { 111 return ofNullable(processObserverMethod.getAnnotatedMethod().getDeclaringType().getAnnotation(Named.class)) 112 .map(Named::value) 113 .orElseGet(() -> processObserverMethod.getAnnotatedMethod().getJavaMember().getName()); 114 } 115}