org.apache.ojb.broker.metadata.ConnectionRepository.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.ojb.broker.metadata.ConnectionRepository.java

Source

package org.apache.ojb.broker.metadata;

/* Copyright 2002-2005 The Apache Software Foundation
 *
 * 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.
 */

import org.apache.commons.lang.SerializationUtils;
import org.apache.commons.lang.SystemUtils;
import org.apache.ojb.broker.PBKey;
import org.apache.ojb.broker.util.logging.Logger;
import org.apache.ojb.broker.util.logging.LoggerFactory;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

import javax.sql.DataSource;

public class ConnectionRepository implements Serializable, XmlCapable {
    private static final long serialVersionUID = -5581126412817848887L;
    private static Logger log = LoggerFactory.getLogger(ConnectionRepository.class);

    private HashMap jcdMap;
    private Hashtable jcdAliasToPBKeyMap;
    private JdbcMetadataUtils utils;

    public ConnectionRepository() {
        jcdMap = new HashMap();
        jcdAliasToPBKeyMap = new Hashtable();
        utils = new JdbcMetadataUtils();
    }

    /**
     * Returns the matching {@link JdbcConnectionDescriptor}
     * or <code>null</code> if no descriptor could be found. The user name
     * and pass word will be set to match the supplied </code>PBKey</code>
     * object. If the original user name and pass word are desired, the PBKey
     * should be obtained with {@link #getStandardPBKeyForJcdAlias(String)}.
     */
    public JdbcConnectionDescriptor getDescriptor(PBKey pbKey) {
        JdbcConnectionDescriptor result = (JdbcConnectionDescriptor) jcdMap.get(pbKey);
        if (result == null) {
            result = deepCopyOfFirstFound(pbKey.getAlias());
            if (result != null) {
                result.setUserName(pbKey.getUser());
                result.setPassWord(pbKey.getPassword());
                // this build connection descriptor could not be the default connection
                result.setDefaultConnection(false);
                log.info("Automatic create of new jdbc-connection-descriptor for PBKey " + pbKey);
                addDescriptor(result);
            } else {
                log.info("Could not find " + JdbcConnectionDescriptor.class.getName() + " for PBKey " + pbKey);
            }
        }
        return result;
    }

    /**
     * Returns a deep copy of the first found connection descriptor
     * with the given <code>jcdAlias</code> name or <code>null</code>
     * if none found.
     */
    private JdbcConnectionDescriptor deepCopyOfFirstFound(String jcdAlias) {
        Iterator it = jcdMap.values().iterator();
        JdbcConnectionDescriptor jcd;
        while (it.hasNext()) {
            jcd = (JdbcConnectionDescriptor) it.next();
            if (jcdAlias.equals(jcd.getJcdAlias())) {
                return (JdbcConnectionDescriptor) SerializationUtils.clone(jcd);
            }
        }
        return null;
    }

    /**
     * Return the matching {@link org.apache.ojb.broker.PBKey} for
     * the given jcdAlias name, or <code>null</code> if no match
     * was found.
     */
    public PBKey getStandardPBKeyForJcdAlias(String jcdAlias) {
        return (PBKey) jcdAliasToPBKeyMap.get(jcdAlias);
    }

    /**
     * Add a new {@link JdbcConnectionDescriptor}.
     */
    public void addDescriptor(JdbcConnectionDescriptor jcd) {
        synchronized (jcdMap) {
            if (jcdMap.containsKey(jcd.getPBKey())) {
                throw new MetadataException("Found duplicate connection descriptor using PBKey " + jcd.getPBKey()
                        + ", remove the old descriptor first, before add the new one. " + jcd);
            }
            jcdMap.put(jcd.getPBKey(), jcd);
            // only if the jcdAlias was not found, put the new PBKey,
            // because we don't want to replace the original PBKey with
            // automatic generated descriptors PBKey's - see method getDescriptor(PBKey key)
            if (!jcdAliasToPBKeyMap.containsKey(jcd.getJcdAlias())) {
                jcdAliasToPBKeyMap.put(jcd.getJcdAlias(), jcd.getPBKey());
            }
            if (log.isDebugEnabled())
                log.debug("New descriptor was added: " + jcd);
        }
    }

    /**
     * Creates and adds a new connection descriptor for the given JDBC connection url.
     * This method tries to guess the platform to be used, but it should be checked
     * afterwards nonetheless using the {@link JdbcConnectionDescriptor#getDbms()} method.
     * For properties that are not part of the url, the following standard values are
     * explicitly set:
     * <ul>
     * <li>jdbc level = 2.0</li>
     * </ul>
     * 
     * @param jcdAlias          The connection alias for the created connection; if 'default' is used,
     *                          then the new descriptor will become the default connection descriptor
     * @param jdbcDriver        The fully qualified jdbc driver name 
     * @param jdbcConnectionUrl The connection url of the form '[protocol]:[sub protocol]:{database-specific path]'
     *                          where protocol is usually 'jdbc'
     * @param username          The user name (can be <code>null</code>) 
     * @param password          The password (can be <code>null</code>) 
     * @return The created connection descriptor
     * @see JdbcConnectionDescriptor#getDbms()
     */
    public JdbcConnectionDescriptor addDescriptor(String jcdAlias, String jdbcDriver, String jdbcConnectionUrl,
            String username, String password) {
        JdbcConnectionDescriptor jcd = new JdbcConnectionDescriptor();
        HashMap props = utils.parseConnectionUrl(jdbcConnectionUrl);

        jcd.setJcdAlias(jcdAlias);
        jcd.setProtocol((String) props.get(JdbcMetadataUtils.PROPERTY_PROTOCOL));
        jcd.setSubProtocol((String) props.get(JdbcMetadataUtils.PROPERTY_SUBPROTOCOL));
        jcd.setDbAlias((String) props.get(JdbcMetadataUtils.PROPERTY_DBALIAS));

        String platform = utils.findPlatformFor(jcd.getSubProtocol(), jdbcDriver);

        jcd.setDbms(platform);
        jcd.setJdbcLevel(2.0);
        jcd.setDriver(jdbcDriver);
        if (username != null) {
            jcd.setUserName(username);
            jcd.setPassWord(password);
        }
        if ("default".equals(jcdAlias)) {
            jcd.setDefaultConnection(true);
            // arminw: MM will search for the default key
            // MetadataManager.getInstance().setDefaultPBKey(jcd.getPBKey());
        }

        addDescriptor(jcd);
        return jcd;
    }

    /**
     * Creates and adds a new connection descriptor for the given JDBC data source.
     * This method tries to guess the platform to be used, but it should be checked
     * afterwards nonetheless using the {@link JdbcConnectionDescriptor#getDbms()} method.
     * Note that the descriptor won't have a value for the driver because it is not possible
     * to retrieve the driver classname from the data source. 
     * 
     * @param jcdAlias   The connection alias for the created connection; if 'default' is used,
     *                   then the new descriptor will become the default connection descriptor
     * @param dataSource The data source
     * @param username   The user name (can be <code>null</code>) 
     * @param password   The password (can be <code>null</code>) 
     * @return The created connection descriptor
     * @see JdbcConnectionDescriptor#getDbms()
     */
    public JdbcConnectionDescriptor addDescriptor(String jcdAlias, DataSource dataSource, String username,
            String password) {
        JdbcConnectionDescriptor jcd = new JdbcConnectionDescriptor();

        jcd.setJcdAlias(jcdAlias);
        jcd.setDataSource(dataSource);
        if (username != null) {
            jcd.setUserName(username);
            jcd.setPassWord(password);
        }
        utils.fillJCDFromDataSource(jcd, dataSource, username, password);
        if ("default".equals(jcdAlias)) {
            jcd.setDefaultConnection(true);
            // arminw: MM will search for the default key
            // MetadataManager.getInstance().setDefaultPBKey(jcd.getPBKey());
        }
        addDescriptor(jcd);
        return jcd;
    }

    /**
     * Remove a descriptor.
     * @param validKey  This could be the {@link JdbcConnectionDescriptor}
     * itself, or the associated {@link JdbcConnectionDescriptor#getPBKey PBKey}.
     */
    public void removeDescriptor(Object validKey) {
        PBKey pbKey;
        if (validKey instanceof PBKey) {
            pbKey = (PBKey) validKey;
        } else if (validKey instanceof JdbcConnectionDescriptor) {
            pbKey = ((JdbcConnectionDescriptor) validKey).getPBKey();
        } else {
            throw new MetadataException("Could not remove descriptor, given object was no vaild key: " + validKey);
        }
        Object removed = null;
        synchronized (jcdMap) {
            removed = jcdMap.remove(pbKey);
            jcdAliasToPBKeyMap.remove(pbKey.getAlias());
        }
        log.info("Remove descriptor: " + removed);
    }

    /**
     * Return a deep copy of all managed {@link JdbcConnectionDescriptor}.
     */
    public List getAllDescriptor() {
        return (List) SerializationUtils.clone(new ArrayList(jcdMap.values()));
    }

    public String toXML() {
        String eol = SystemUtils.LINE_SEPARATOR;
        // use copy to avoid sync problems
        HashMap map = (HashMap) jcdMap.clone();
        StringBuffer buf = new StringBuffer();
        Iterator it = map.values().iterator();
        while (it.hasNext()) {
            JdbcConnectionDescriptor jcd = (JdbcConnectionDescriptor) it.next();
            buf.append(jcd.toXML());
            buf.append(eol);
        }
        return buf.toString();
    }
}