Package org.teiid.services

Source Code of org.teiid.services.SessionServiceImpl

/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.  Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/

package org.teiid.services;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;

import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

import org.jboss.managed.api.annotation.ManagementComponent;
import org.jboss.managed.api.annotation.ManagementObject;
import org.jboss.managed.api.annotation.ManagementProperties;
import org.jboss.managed.api.annotation.ManagementProperty;
import org.teiid.adminapi.VDB;
import org.teiid.adminapi.VDB.ConnectionType;
import org.teiid.adminapi.impl.SessionMetadata;
import org.teiid.adminapi.impl.VDBMetaData;
import org.teiid.client.security.InvalidSessionException;
import org.teiid.client.security.SessionToken;
import org.teiid.core.util.ArgCheck;
import org.teiid.deployers.VDBRepository;
import org.teiid.dqp.internal.process.DQPCore;
import org.teiid.dqp.service.SessionService;
import org.teiid.dqp.service.SessionServiceException;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.net.ServerConnection;
import org.teiid.net.TeiidURL;
import org.teiid.runtime.RuntimePlugin;
import org.teiid.security.Credentials;
import org.teiid.security.SecurityHelper;


/**
* This class serves as the primary implementation of the Session Service.
*/
@ManagementObject(name="SessionService", componentType=@ManagementComponent(type="teiid",subtype="dqp"), properties=ManagementProperties.EXPLICIT)
public class SessionServiceImpl implements SessionService {
  public static final String SECURITY_DOMAINS = "securitydomains"; //$NON-NLS-1$
 
  /*
   * Configuration state
   */
    private long sessionMaxLimit = DEFAULT_MAX_SESSIONS;
  private long sessionExpirationTimeLimit = DEFAULT_SESSION_EXPIRATION;
 
  /*
   * Injected state
   */
  private VDBRepository vdbRepository;
    private SecurityHelper securityHelper;

    private DQPCore dqp;

    private Map<String, SessionMetadata> sessionCache = new ConcurrentHashMap<String, SessionMetadata>();
    private Timer sessionMonitor = new Timer("SessionMonitor", true); //$NON-NLS-1$
    private LinkedList<String> securityDomains = new LinkedList<String>();
    private LinkedList<String> adminSecurityDomains = new LinkedList<String>();
   
   
    // -----------------------------------------------------------------------------------
    // S E R V I C E - R E L A T E D M E T H O D S
    // -----------------------------------------------------------------------------------

    private void monitorSessions() {
    long currentTime = System.currentTimeMillis();
    for (SessionMetadata info : sessionCache.values()) {
      try {
          if (!info.isEmbedded() && currentTime - info.getLastPingTime() > ServerConnection.PING_INTERVAL * 5) {
            LogManager.logInfo(LogConstants.CTX_SECURITY, RuntimePlugin.Util.getString( "SessionServiceImpl.keepaliveFailed", info.getSessionId())); //$NON-NLS-1$
            closeSession(info.getSessionId());
          } else if (sessionExpirationTimeLimit > 0 && currentTime - info.getCreatedTime() > sessionExpirationTimeLimit) {
            LogManager.logInfo(LogConstants.CTX_SECURITY, RuntimePlugin.Util.getString( "SessionServiceImpl.expireSession", info.getSessionId())); //$NON-NLS-1$
            closeSession(info.getSessionId());
          }
      } catch (Exception e) {
        LogManager.logDetail(LogConstants.CTX_SECURITY, e, "error running session monitor, unable to monitor:", info.getSessionId()); //$NON-NLS-1$
      }
    }
  }

  @Override
  public void closeSession(String sessionID) throws InvalidSessionException {
    LogManager.logDetail(LogConstants.CTX_SECURITY, new Object[] {"closeSession", sessionID}); //$NON-NLS-1$
    if (sessionID == null) {
      throw new InvalidSessionException(RuntimePlugin.Util.getString("SessionServiceImpl.invalid_session", sessionID)); //$NON-NLS-1$
    }
    SessionMetadata info = this.sessionCache.remove(sessionID);
    if (info == null) {
      throw new InvalidSessionException(RuntimePlugin.Util.getString("SessionServiceImpl.invalid_session", sessionID)); //$NON-NLS-1$
    }
    if (info.getVDBName() != null) {
            try {
          dqp.terminateSession(info.getSessionId());
            } catch (Exception e) {
                LogManager.logWarning(LogConstants.CTX_SECURITY,e,"Exception terminitating session"); //$NON-NLS-1$
            }
    }

        // try to log out of the context.
        try {
          LoginContext context = info.getLoginContext();
          if (context != null) {
            context.logout();
          }
    } catch (LoginException e) {
       LogManager.logWarning(LogConstants.CTX_SECURITY,e,"Exception terminitating session"); //$NON-NLS-1$
    }
  }
 
  @Override
  public SessionMetadata createSession(String userName, Credentials credentials, String applicationName, Properties properties, boolean adminConnection, boolean authenticate)
    throws LoginException, SessionServiceException {
    ArgCheck.isNotNull(applicationName);
        ArgCheck.isNotNull(properties);
       
        LoginContext loginContext = null;
        String securityDomain = "none"; //$NON-NLS-1$
        Object securityContext = null;
        List<String> domains = this.securityDomains;
        if (adminConnection) {
          domains = this.adminSecurityDomains;
        }
       
        // Validate VDB and version if logging on to server product...
        VDBMetaData vdb = null;
        String vdbName = properties.getProperty(TeiidURL.JDBC.VDB_NAME);
        if (vdbName != null) {
          String vdbVersion = properties.getProperty(TeiidURL.JDBC.VDB_VERSION);
          vdb = getActiveVDB(vdbName, vdbVersion);
        }

        if (sessionMaxLimit > 0 && getActiveSessionsCount() >= sessionMaxLimit) {
            throw new SessionServiceException(RuntimePlugin.Util.getString("SessionServiceImpl.reached_max_sessions", new Object[] {new Long(sessionMaxLimit)})); //$NON-NLS-1$
        }
       
        if (!domains.isEmpty() && authenticate) {
          // Authenticate user...
          // if not authenticated, this method throws exception
          boolean onlyAllowPassthrough = Boolean.valueOf(properties.getProperty(TeiidURL.CONNECTION.PASSTHROUGH_AUTHENTICATION, "false")); //$NON-NLS-1$
          TeiidLoginContext membership = authenticate(userName, credentials, applicationName, domains, this.securityHelper, onlyAllowPassthrough);
          loginContext = membership.getLoginContext();
          userName = membership.getUserName();
          securityDomain = membership.getSecurityDomain();
          securityContext = membership.getSecurityContext();
        }       
       
        long creationTime = System.currentTimeMillis();

        // Return a new session info object
        SessionMetadata newSession = new SessionMetadata();
        newSession.setSessionToken(new SessionToken(userName));
        newSession.setSessionId(newSession.getSessionToken().getSessionID());
        newSession.setUserName(userName);
        newSession.setCreatedTime(creationTime);
        newSession.setApplicationName(applicationName);
        newSession.setClientHostName(properties.getProperty(TeiidURL.CONNECTION.CLIENT_HOSTNAME));
        newSession.setIPAddress(properties.getProperty(TeiidURL.CONNECTION.CLIENT_IP_ADDRESS));
        newSession.setSecurityDomain(securityDomain);
        if (vdb != null) {
          newSession.setVDBName(vdb.getName());
          newSession.setVDBVersion(vdb.getVersion());
        }
       
        // these are local no need for monitoring.
        newSession.setLoginContext(loginContext);
        newSession.setSecurityContext(securityContext);
        newSession.setVdb(vdb);
        LogManager.logDetail(LogConstants.CTX_SECURITY, new Object[] {"Logon successful for \"", userName, "\" - created SessionID \"", newSession.getSessionToken().getSessionID(), "\"" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        this.sessionCache.put(newSession.getSessionId(), newSession);
        return newSession;
  }

  VDBMetaData getActiveVDB(String vdbName, String vdbVersion) throws SessionServiceException {
    VDBMetaData vdb = null;
   
    // handle the situation when the version is part of the vdb name.
   
    int firstIndex = vdbName.indexOf('.');
    int lastIndex = vdbName.lastIndexOf('.');
    if (firstIndex != -1) {
      if (firstIndex != lastIndex || vdbVersion != null) {
        throw new SessionServiceException(RuntimePlugin.Util.getString("ambigious_name", vdbName, vdbVersion)); //$NON-NLS-1$
      }
      vdbVersion = vdbName.substring(firstIndex+1);
      vdbName = vdbName.substring(0, firstIndex);
    }
   
    try {
      if (vdbVersion == null) {
        vdbVersion = "latest"; //$NON-NLS-1$
        vdb = this.vdbRepository.getVDB(vdbName);
      }
      else {
        vdb = this.vdbRepository.getVDB(vdbName, Integer.parseInt(vdbVersion));
      }        
    } catch (NumberFormatException e) {
      throw new SessionServiceException(e, RuntimePlugin.Util.getString("VDBService.VDB_does_not_exist._3", vdbVersion)); //$NON-NLS-1$
    }
   
    if (vdb == null) {
      throw new SessionServiceException(RuntimePlugin.Util.getString("VDBService.VDB_does_not_exist._1", vdbName, vdbVersion)); //$NON-NLS-1$
    }
   
    if (vdb.getStatus() != VDB.Status.ACTIVE) {
      throw new SessionServiceException(RuntimePlugin.Util.getString("VDBService.VDB_does_not_exist._2", vdbName, vdbVersion)); //$NON-NLS-1$
    }
    if (vdb.getConnectionType() == ConnectionType.NONE) {
      throw new SessionServiceException(RuntimePlugin.Util.getString("VDBService.VDB_does_not_exist._4", vdbName, vdbVersion)); //$NON-NLS-1$
    }
    return vdb;
  }

  protected TeiidLoginContext authenticate(String userName, Credentials credentials, String applicationName, List<String> domains, SecurityHelper helper, boolean onlyallowPassthrough)
      throws LoginException {
    TeiidLoginContext membership = new TeiidLoginContext(helper);
        membership.authenticateUser(userName, credentials, applicationName, domains, onlyallowPassthrough);                       
    return membership;
  }
 
  @Override
  public Collection<SessionMetadata> getActiveSessions() throws SessionServiceException {
    return new ArrayList<SessionMetadata>(this.sessionCache.values());
  }
 
  @Override
  public SessionMetadata getActiveSession(String sessionID) {
    return this.sessionCache.get(sessionID);
 

  @Override
  public int getActiveSessionsCount() throws SessionServiceException{
    return this.sessionCache.size();
  }

  @Override
  public Collection<SessionMetadata> getSessionsLoggedInToVDB(String VDBName, int vdbVersion)
      throws SessionServiceException {
    if (VDBName == null || vdbVersion <= 0) {
      return Collections.emptyList();
    }
    ArrayList<SessionMetadata> results = new ArrayList<SessionMetadata>();
    for (SessionMetadata info : this.sessionCache.values()) {
      if (VDBName.equalsIgnoreCase(info.getVDBName()) && vdbVersion == info.getVDBVersion()) {
        results.add(info);
      }
    }
    return results;
  }

  @Override
  public void pingServer(String sessionID) throws InvalidSessionException {
    SessionMetadata info = getSessionInfo(sessionID);
    info.setLastPingTime(System.currentTimeMillis());
    this.sessionCache.put(sessionID, info);
    LogManager.logDetail(LogConstants.CTX_SECURITY, "Keep-alive ping received for session:", sessionID); //$NON-NLS-1$
  }

  @Override
  public boolean terminateSession(String terminatedSessionID, String adminSessionID) {
    Object[] params = {adminSessionID, terminatedSessionID};
    LogManager.logInfo(LogConstants.CTX_SECURITY, RuntimePlugin.Util.getString( "SessionServiceImpl.terminateSession", params)); //$NON-NLS-1$
    try {
      closeSession(terminatedSessionID);
      return true;
    } catch (InvalidSessionException e) {
      LogManager.logWarning(LogConstants.CTX_SECURITY,e,RuntimePlugin.Util.getString("SessionServiceImpl.invalid_session", new Object[] {e.getMessage()})); //$NON-NLS-1$
      return false;
    }
  }

  @Override
  public SessionMetadata validateSession(String sessionID) throws InvalidSessionException, SessionServiceException {
    SessionMetadata info = getSessionInfo(sessionID);
    return info;
  }

  private SessionMetadata getSessionInfo(String sessionID)
      throws InvalidSessionException {
    if (sessionID == null) {
      throw new InvalidSessionException(RuntimePlugin.Util.getString("SessionServiceImpl.invalid_session", sessionID)); //$NON-NLS-1$
    }
    SessionMetadata info = this.sessionCache.get(sessionID);
    if (info == null) {
      throw new InvalidSessionException(RuntimePlugin.Util.getString("SessionServiceImpl.invalid_session", sessionID)); //$NON-NLS-1$
    }
    return info;
  }
 
  @ManagementProperty (description="Maximum number of sessions allowed by the system (default 5000)")
  public long getSessionMaxLimit() {
    return this.sessionMaxLimit;
  }
 
  public void setSessionMaxLimit(long limit) {
    this.sessionMaxLimit = limit;
  }
 
  @ManagementProperty(description="Max allowed time before the session is terminated by the system, 0 indicates unlimited (default 0)")
  public long getSessionExpirationTimeLimit() {
    return this.sessionExpirationTimeLimit;
  }
 
  public void setSessionExpirationTimeLimit(long limit) {
    this.sessionExpirationTimeLimit = limit;
 
 
  public void setSecurityDomains(String domainNameOrder) {
        if (domainNameOrder != null && domainNameOrder.trim().length()>0) {
          LogManager.logInfo(LogConstants.CTX_SECURITY, "Security Enabled: true"); //$NON-NLS-1$

          String[] domainNames = domainNameOrder.split(","); //$NON-NLS-1$
          for (String domainName : domainNames) {
              this.securityDomains.addLast(domainName);
          }
        }   
  }
 
  public void setAdminSecurityDomain(String domain) {
    this.adminSecurityDomains.add(domain);
    LogManager.logInfo(LogConstants.CTX_SECURITY, "Admin Security Enabled: true"); //$NON-NLS-1$
  }

  public void start() {
        this.sessionMonitor.schedule(new TimerTask() {
          @Override
          public void run() {
            monitorSessions();
          }
        }, 0, ServerConnection.PING_INTERVAL * 5);
  }

  public void stop(){
    this.sessionMonitor.cancel();
    this.sessionCache.clear();
  }

  public void setVDBRepository(VDBRepository repo) {
    this.vdbRepository = repo;
  }
 
  public void setSecurityHelper(SecurityHelper securityHelper) {
    this.securityHelper = securityHelper;
  }
 
  public void setDqp(DQPCore dqp) {
    this.dqp = dqp;
  }
}
TOP

Related Classes of org.teiid.services.SessionServiceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.