org.hyperic.hq.plugin.appha.VSphereConnection.java Source code

Java tutorial

Introduction

Here is the source code for org.hyperic.hq.plugin.appha.VSphereConnection.java

Source

/*
 * NOTE: This copyright does *not* cover user programs that use HQ
 * program services by normal system calls through the application
 * program interfaces provided as part of the Hyperic Plug-in Development
 * Kit or the Hyperic Client Development Kit - this is merely considered
 * normal use of the program, and does *not* fall under the heading of
 * "derived work".
 * 
 * Copyright (C) [2004-2010], VMWare, Inc.
 * This file is part of HQ.
 * 
 * HQ is free software; you can redistribute it and/or modify
 * it under the terms version 2 of the GNU General Public License as
 * published by the Free Software Foundation. This program 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 General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA.
 */

package org.hyperic.hq.plugin.appha;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.hq.product.PluginException;

public class VSphereConnection {
    private static final Log _log = LogFactory.getLog(VSphereConnection.class);
    private static final Map<String, List<VSphereConnection>> _conns = new HashMap<String, List<VSphereConnection>>();
    private static final int POOL_SIZE = Integer.valueOf(System.getProperty("vsphere.pool.size", "2"));

    final Object LOCK = new Object();
    VSphereUtil vim;
    private String _user = "", _pass = "";
    private String url;

    public VSphereConnection(String url) {
        this.url = url;
    }

    private static String address(Object obj) {
        if (obj == null) {
            return "@NULL";
        }
        return "@" + Integer.toHexString(obj.hashCode());
    }

    private static String mask(String val) {
        return val.replaceAll(".", "*");
    }

    private static String diff(String old, String cur) {
        return "'" + old + "'->'" + cur + "'";
    }

    /**
     * @return {@link VSphereConnection} from the connection pool.  Once a connection is grabbed
     * it must be returned to the pool via the release() method
     */
    public static VSphereConnection getPooledInstance(Properties props) throws PluginException {
        synchronized (_conns) {
            VSphereConnection rtn;
            String url = VSphereUtil.getURL(props);
            List<VSphereConnection> tmp;
            if (null == (tmp = _conns.get(url))) {
                tmp = new ArrayList<VSphereConnection>();
                for (int ii = 0; ii < POOL_SIZE; ii++) {
                    tmp.add(new VSphereConnection(url));
                }
                _conns.put(url, tmp);
            } else {
                while (tmp.size() == 0) {
                    try {
                        _conns.wait();
                    } catch (InterruptedException e) {
                        _log.warn(e, e);
                    }
                }
            }
            rtn = tmp.remove(0);
            rtn.validate(props);
            return rtn;
        }
    }

    public static void evict(String url) throws PluginException {
        synchronized (_conns) {
            try {
                List<VSphereConnection> instances = _conns.get(url);
                if (instances != null) {
                    for (VSphereConnection v : instances) {
                        v.dispose();
                    }
                    _conns.remove(url);
                }
            } catch (Exception e) {
                throw new PluginException(e);
            }
        }
    }

    public void release() {
        synchronized (_conns) {
            List<VSphereConnection> tmp;
            if (null != (tmp = _conns.get(getUrl()))) {
                tmp.add(this);
                _conns.notifyAll();
            }
        }
    }

    public void dispose() {
        if (vim != null) {
            VSphereUtil.dispose(vim);
            if (_log.isDebugEnabled()) {
                _log.debug("Closed previous connection (" + address(vim) + ") for: " + url);
            }
            vim = null;
        }
    }

    private String getUrl() {
        return url;
    }

    private void validate(Properties props) throws PluginException {
        String url = VSphereUtil.getURL(props);
        String username = props.getProperty(VSphereUtil.PROP_USERNAME, "");
        String password = props.getProperty(VSphereUtil.PROP_PASSWORD, "");
        boolean requiresReconnect = false;
        boolean usernameChanged = !username.equals(_user);
        boolean passwordChanged = !password.equals(_pass);
        if (usernameChanged || passwordChanged) {
            requiresReconnect = true;
            if (_log.isDebugEnabled()) {
                String diff = "";
                if (usernameChanged) {
                    diff += "user:" + diff(_user, username);
                }
                if (passwordChanged) {
                    if (diff.length() != 0) {
                        diff += ",";
                    }
                    diff += "pass:" + diff(mask(_pass), mask(password));
                }
                _log.debug("Credentials changed (" + diff + ") reconnecting cached connection for: " + url);
            }
        } else {
            if (vim != null) {
                requiresReconnect = !vim.isSessionValid();
            }
            // Else, some previous error must have happened -- expect it to be already logged.
        }
        if (requiresReconnect) {
            dispose();
        }
        if (vim == null) {
            try {
                vim = VSphereUtil.getInstance(props);
            } catch (Exception e) {
                throw new PluginException(e);
            }
            if (_log.isDebugEnabled()) {
                _log.debug("Opened new connection (" + address(vim) + "/" + address(LOCK) + ") for: " + url);
            }
            _user = username;
            _pass = password;
        }
    }
}