Java tutorial
/*! * Copyright 2010 - 2017 Pentaho Corporation. All rights reserved. * * 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 org.pentaho.di.repository.pur; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import javax.xml.ws.WebServiceException; import org.apache.commons.lang.BooleanUtils; import org.pentaho.di.core.encryption.Encr; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.core.exception.KettleSecurityException; import org.pentaho.di.core.logging.LogChannel; import org.pentaho.di.core.logging.LogChannelInterface; import org.pentaho.di.core.util.ExecutorUtil; import org.pentaho.di.i18n.BaseMessages; import org.pentaho.di.repository.IUser; import org.pentaho.di.repository.RepositorySecurityManager; import org.pentaho.di.repository.RepositorySecurityProvider; import org.pentaho.di.repository.pur.model.EEUserInfo; import org.pentaho.di.ui.repository.pur.services.IAbsSecurityManager; import org.pentaho.di.ui.repository.pur.services.IAbsSecurityProvider; import org.pentaho.di.ui.repository.pur.services.IAclService; import org.pentaho.di.ui.repository.pur.services.IConnectionAclService; import org.pentaho.di.ui.repository.pur.services.ILockService; import org.pentaho.di.ui.repository.pur.services.IRevisionService; import org.pentaho.di.ui.repository.pur.services.IRoleSupportSecurityManager; import org.pentaho.di.ui.repository.pur.services.ITrashService; import org.pentaho.platform.api.repository2.unified.IUnifiedRepository; import org.pentaho.platform.engine.core.system.PentahoSessionHolder; import org.pentaho.platform.engine.core.system.PentahoSystem; import org.pentaho.platform.repository2.unified.webservices.jaxws.IUnifiedRepositoryJaxwsWebService; import org.pentaho.platform.repository2.unified.webservices.jaxws.UnifiedRepositoryToWebServiceAdapter; import com.pentaho.pdi.ws.IRepositorySyncWebService; import com.pentaho.pdi.ws.RepositorySyncException; import com.sun.xml.ws.client.ClientTransportException; public class PurRepositoryConnector implements IRepositoryConnector { private static final String SINGLE_DI_SERVER_INSTANCE = "singleDiServerInstance"; private static final String REMOTE_DI_SERVER_INSTANCE = "remoteDiServerInstance"; private static Class<?> PKG = PurRepository.class; private final LogChannelInterface log; private final PurRepository purRepository; private final PurRepositoryMeta repositoryMeta; private final RootRef rootRef; private ServiceManager serviceManager; public PurRepositoryConnector(PurRepository purRepository, PurRepositoryMeta repositoryMeta, RootRef rootRef) { log = new LogChannel(this.getClass().getSimpleName()); if (purRepository != null & purRepository.getLog() != null) { log.setLogLevel(purRepository.getLog().getLogLevel()); } this.purRepository = purRepository; this.repositoryMeta = repositoryMeta; this.rootRef = rootRef; } private boolean allowedActionsContains(AbsSecurityProvider provider, String action) throws KettleException { List<String> allowedActions = provider.getAllowedActions(IAbsSecurityProvider.NAMESPACE); for (String actionName : allowedActions) { if (action != null && action.equals(actionName)) { return true; } } return false; } public synchronized RepositoryConnectResult connect(final String username, final String password) throws KettleException, KettleSecurityException { if (serviceManager != null) { disconnect(); } serviceManager = new WebServiceManager(repositoryMeta.getRepositoryLocation().getUrl(), username); RepositoryServiceRegistry purRepositoryServiceRegistry = new RepositoryServiceRegistry(); IUser user1 = new EEUserInfo(); final String decryptedPassword = Encr.decryptPasswordOptionallyEncrypted(password); final RepositoryConnectResult result = new RepositoryConnectResult(purRepositoryServiceRegistry); try { /* * Three scenarios: 1. Connect in process: username fetched using PentahoSessionHolder; no authentication occurs * 2. Connect externally with trust: username specified is assumed authenticated if IP of calling code is trusted * 3. Connect externally: authentication occurs normally (i.e. password is checked) */ user1.setLogin(username); user1.setPassword(decryptedPassword); user1.setName(username); result.setUser(user1); // We need to have the application context and the session available in order for us to skip authentication if (PentahoSystem.getApplicationContext() != null && PentahoSessionHolder.getSession() != null && PentahoSessionHolder.getSession().isAuthenticated()) { if (inProcess()) { // connect to the IUnifiedRepository through PentahoSystem // this assumes we're running in a BI Platform result.setUnifiedRepository(PentahoSystem.get(IUnifiedRepository.class)); if (result.getUnifiedRepository() != null) { if (log.isDebug()) { log.logDebug("begin connectInProcess()"); } String name = PentahoSessionHolder.getSession().getName(); user1 = new EEUserInfo(); user1.setLogin(name); user1.setName(name); user1.setPassword(decryptedPassword); result.setUser(user1); result.setSuccess(true); if (log.isDebug()) { log.logDebug("connected in process as '" + name + "' pur repository = " + result.getUnifiedRepository()); } // for now, there is no need to support the security manager // what about security provider? return result; } } } ExecutorService executor = ExecutorUtil.getExecutor(); Future<Boolean> authorizationWebserviceFuture = executor.submit(new Callable<Boolean>() { @Override public Boolean call() throws Exception { // We need to add the service class in the list in the order of dependencies // IRoleSupportSecurityManager depends RepositorySecurityManager to be present if (log.isBasic()) { log.logBasic( BaseMessages.getString(PKG, "PurRepositoryConnector.CreateServiceProvider.Start")); } result.setSecurityProvider(new AbsSecurityProvider(purRepository, repositoryMeta, result.getUser(), serviceManager)); if (log.isBasic()) { log.logBasic( BaseMessages.getString(PKG, "PurRepositoryConnector.CreateServiceProvider.End")); //$NON-NLS-1$ } // If the user does not have access to administer security we do not // need to added them to the service list if (allowedActionsContains((AbsSecurityProvider) result.getSecurityProvider(), IAbsSecurityProvider.ADMINISTER_SECURITY_ACTION)) { result.setSecurityManager(new AbsSecurityManager(purRepository, repositoryMeta, result.getUser(), serviceManager)); // Set the reference of the security manager to security provider for user role list change event ((PurRepositorySecurityProvider) result.getSecurityProvider()).setUserRoleDelegate( ((PurRepositorySecurityManager) result.getSecurityManager()).getUserRoleDelegate()); return true; } return false; } }); Future<WebServiceException> repoWebServiceFuture = executor.submit(new Callable<WebServiceException>() { @Override public WebServiceException call() throws Exception { try { IUnifiedRepositoryJaxwsWebService repoWebService = null; if (log.isBasic()) { log.logBasic(BaseMessages.getString(PKG, "PurRepositoryConnector.CreateRepositoryWebService.Start")); //$NON-NLS-1$ } repoWebService = serviceManager.createService(username, decryptedPassword, IUnifiedRepositoryJaxwsWebService.class); //$NON-NLS-1$ if (log.isBasic()) { log.logBasic(BaseMessages.getString(PKG, "PurRepositoryConnector.CreateRepositoryWebService.End")); //$NON-NLS-1$ } if (log.isBasic()) { log.logBasic(BaseMessages.getString(PKG, "PurRepositoryConnector.CreateUnifiedRepositoryToWebServiceAdapter.Start")); //$NON-NLS-1$ } result.setUnifiedRepository(new UnifiedRepositoryToWebServiceAdapter(repoWebService)); } catch (WebServiceException wse) { return wse; } return null; } }); Future<Exception> syncWebserviceFuture = executor.submit(new Callable<Exception>() { @Override public Exception call() throws Exception { try { if (log.isBasic()) { log.logBasic(BaseMessages.getString(PKG, "PurRepositoryConnector.CreateRepositorySyncWebService.Start")); } IRepositorySyncWebService syncWebService = serviceManager.createService(username, decryptedPassword, IRepositorySyncWebService.class); //$NON-NLS-1$ if (log.isBasic()) { log.logBasic(BaseMessages.getString(PKG, "PurRepositoryConnector.CreateRepositorySyncWebService.Sync")); //$NON-NLS-1$ } syncWebService.sync(repositoryMeta.getName(), repositoryMeta.getRepositoryLocation().getUrl()); } catch (RepositorySyncException e) { log.logError(e.getMessage(), e); // this message will be presented to the user in spoon result.setConnectMessage(e.getMessage()); return null; } catch (ClientTransportException e) { // caused by authentication errors, etc return e; } catch (WebServiceException e) { // if we can speak to the repository okay but not the sync service, assume we're talking to a BA Server log.logError(e.getMessage(), e); return new Exception(BaseMessages.getString(PKG, "PurRepository.BAServerLogin.Message"), e); } return null; } }); WebServiceException repoException = repoWebServiceFuture.get(); if (repoException != null) { log.logError(repoException.getMessage()); throw new Exception(BaseMessages.getString(PKG, "PurRepository.FailedLogin.Message"), repoException); } Exception syncException = syncWebserviceFuture.get(); if (syncException != null) { throw syncException; } Boolean isAdmin = authorizationWebserviceFuture.get(); if (log.isBasic()) { log.logBasic(BaseMessages.getString(PKG, "PurRepositoryConnector.RegisterSecurityProvider.Start")); } purRepositoryServiceRegistry.registerService(RepositorySecurityProvider.class, result.getSecurityProvider()); purRepositoryServiceRegistry.registerService(IAbsSecurityProvider.class, result.getSecurityProvider()); if (isAdmin) { purRepositoryServiceRegistry.registerService(RepositorySecurityManager.class, result.getSecurityManager()); purRepositoryServiceRegistry.registerService(IRoleSupportSecurityManager.class, result.getSecurityManager()); purRepositoryServiceRegistry.registerService(IAbsSecurityManager.class, result.getSecurityManager()); } purRepositoryServiceRegistry.registerService( PurRepositoryRestService.PurRepositoryPluginApiRevision.class, serviceManager.createService(username, decryptedPassword, PurRepositoryRestService.PurRepositoryPluginApiRevision.class)); purRepositoryServiceRegistry.registerService(IRevisionService.class, new UnifiedRepositoryRevisionService(result.getUnifiedRepository(), rootRef)); purRepositoryServiceRegistry.registerService(IAclService.class, new UnifiedRepositoryConnectionAclService(result.getUnifiedRepository())); purRepositoryServiceRegistry.registerService(IConnectionAclService.class, new UnifiedRepositoryConnectionAclService(result.getUnifiedRepository())); purRepositoryServiceRegistry.registerService(ITrashService.class, new UnifiedRepositoryTrashService(result.getUnifiedRepository(), rootRef)); purRepositoryServiceRegistry.registerService(ILockService.class, new UnifiedRepositoryLockService(result.getUnifiedRepository())); if (log.isBasic()) { log.logBasic( BaseMessages.getString(PKG, "PurRepositoryConnector.RepositoryServicesRegistered.End")); } result.setSuccess(true); } catch (NullPointerException npe) { result.setSuccess(false); throw new KettleException(BaseMessages.getString(PKG, "PurRepository.LoginException.Message")); } catch (Throwable e) { result.setSuccess(false); serviceManager.close(); throw new KettleException(e); } return result; } @Override public synchronized void disconnect() { if (serviceManager != null) { serviceManager.close(); } serviceManager = null; } public LogChannelInterface getLog() { return log; } @Override public ServiceManager getServiceManager() { return serviceManager; } public static boolean inProcess() { boolean inProcess = false; boolean remoteDiServer = BooleanUtils .toBoolean(PentahoSystem.getSystemSetting(REMOTE_DI_SERVER_INSTANCE, "false")); //$NON-NLS-1$ if ("true".equals(PentahoSystem.getSystemSetting(SINGLE_DI_SERVER_INSTANCE, "true"))) { //$NON-NLS-1$ //$NON-NLS-2$ inProcess = true; } else if (!remoteDiServer && PentahoSystem.getApplicationContext().getFullyQualifiedServerURL() != null) { inProcess = true; } return inProcess; } }