org.wso2.carbon.datasource.core.DataSourceRepository.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.datasource.core.DataSourceRepository.java

Source

/**
 *  Copyright (c) 2012, WSO2 Inc. (http://www.wso2.org) 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.wso2.carbon.datasource.core;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Element;
import org.wso2.carbon.datasource.api.DataSourceConstants;
import org.wso2.carbon.datasource.api.DataSourceException;
import org.wso2.carbon.datasource.api.spi.DataSourceReader;
import org.wso2.carbon.datasource.core.utils.DataSourceUtils;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.util.HashMap;
import java.util.Map;

/**
 * This class represents the repository which is used to hold the data sources.
 */
public class DataSourceRepository {

    private static Log log = LogFactory.getLog(DataSourceRepository.class);

    private int tenantId;

    private Map<String, CarbonDataSource> dataSources;

    private Marshaller dsmMarshaller;

    private Unmarshaller dsmUnmarshaller;

    public DataSourceRepository(int tenantId) throws DataSourceException {
        this.tenantId = tenantId;
        this.dataSources = new HashMap<String, CarbonDataSource>();
        try {
            JAXBContext ctx = JAXBContext.newInstance(DataSourceMetaInfo.class);
            this.dsmMarshaller = ctx.createMarshaller();
            this.dsmUnmarshaller = ctx.createUnmarshaller();
        } catch (JAXBException e) {
            throw new DataSourceException(
                    "Error creating data source meta info marshaller/unmarshaller: " + e.getMessage(), e);
        }
    }

    public int getTenantId() {
        return tenantId;
    }

    /**
     * Initializes the data sources repository. This method must be
     * called after the registry service is available to be used.
     * @throws org.wso2.carbon.datasource.api.DataSourceException
     */
    public void initRepository() throws DataSourceException {
        //this.refreshAllUserDataSources();
    }

    private String resourceNameFromPath(String path) {
        return path.substring(path.lastIndexOf('/') + 1);
    }

    /**
     * Reloads all the data sources from the repository.
     * @throws org.wso2.carbon.datasource.api.DataSourceException
     */
    /*public void refreshAllUserDataSources() throws DataSourceException {
     this.updateAllUserDataSource(false);
     }*/

    /**
     * Unregisters all the data sources from the repository.
     * @throws org.wso2.carbon.datasource.api.DataSourceException
     */
    /*public void unregisterAllUserDataSources() throws DataSourceException {
     this.updateAllUserDataSource(true);
     }*/

    /*private void updateAllUserDataSource(boolean unregister) throws DataSourceException {
     try {
         if (this.getRegistry().resourceExists(
                 DataSourceConstants.DATASOURCES_REPOSITORY_BASE_PATH)) {
             Collection dsCollection = (Collection) this.getRegistry().get(
                     DataSourceConstants.DATASOURCES_REPOSITORY_BASE_PATH);
             String[] dsmPaths = dsCollection.getChildren();
             for (String dsmPath : dsmPaths) {
                 try {
                     this.updateDataSource(this.resourceNameFromPath(dsmPath), unregister);
                 } catch (DataSourceException e) {
                     log.error("Error in updating data source [remove:" + unregister +
                             "] at path '" + dsmPath + "': " + e.getMessage(), e);
                 }
             }
         }
     } catch (Exception e) {
         throw new DataSourceException(
                 "Error in getting all data sources from repository: " + e.getMessage(), e);
     }
     }*/

    /**
     * Reloads only a specific given data source.
     * @throws org.wso2.carbon.datasource.api.DataSourceException
     */
    /*public void refreshUserDataSource(String dsName) throws DataSourceException {
     if (log.isDebugEnabled()) {
         log.debug("Refreshing data source: " + dsName);
     }
     this.updateDataSource(dsName, false);
     }*/

    /*private synchronized void updateDataSource(String dsName,
         boolean unregister) throws DataSourceException {
     String dsmPath = DataSourceConstants.DATASOURCES_REPOSITORY_BASE_PATH + "/" + dsName;
     try {
         DataSourceMetaInfo dsmInfo = this.getDataSourceMetaInfoFromRegistryPath(dsmPath);
         CarbonDataSource currentCDS = this.getDataSource(dsName);
         DataSourceMetaInfo currentDsmInfo = null;
         if (currentCDS != null) {
             currentDsmInfo = currentCDS.getDSMInfo();
         }
         if (unregister) {
             this.unregisterDataSource(dsName);
         } else {
             if (DataSourceUtils.nullAllowEquals(dsmInfo, currentDsmInfo)) {
                 if (log.isDebugEnabled()) {
                     log.debug("No update change for data source: " + dsName);
                 }
                 return;
             }
             if (dsmInfo != null) {
                 this.registerDataSource(dsmInfo);
             } else {
                 this.unregisterDataSource(dsName);
             }
         }
     } catch (Exception e) {
         throw new DataSourceException("Error in updating data source '" + dsName +
                 "' from registry [remove:" + unregister +"]: " + e.getMessage(), e);
     }
     }*/

    private Object createDataSourceObject(DataSourceMetaInfo dsmInfo, boolean isUseDataSourceFactory)
            throws DataSourceException {
        DataSourceReader dsReader = DataSourceManager.getInstance()
                .getDataSourceReader(dsmInfo.getDefinition().getType());
        if (dsReader == null) {
            throw new DataSourceException("A data source reader cannot be found for the type '"
                    + dsmInfo.getDefinition().getType() + "'");
        }
        /* sets the current data source's (tenantId + ":" + name) as a thread local value
           * so it can be read by data source readers */
        DataSourceUtils.setCurrentDataSourceId(this.getTenantId() + ":" + dsmInfo.getName());
        return dsReader.createDataSource(
                DataSourceUtils.elementToString((Element) dsmInfo.getDefinition().getDsXMLConfiguration()),
                isUseDataSourceFactory);
    }

    private Context lookupJNDISubContext(Context context, String jndiName) throws DataSourceException {
        try {
            Object obj = context.lookup(jndiName);
            if (!(obj instanceof Context)) {
                throw new DataSourceException("Non JNDI context already exists at '" + context + "/" + jndiName);
            }
            return (Context) obj;
        } catch (NamingException e) {
            return null;
        }
    }

    private void checkAndCreateJNDISubContexts(Context context, String jndiName) throws DataSourceException {
        String[] tokens = jndiName.split("/");
        Context tmpCtx;
        String token;
        for (int i = 0; i < tokens.length - 1; i++) {
            token = tokens[i];
            tmpCtx = (Context) this.lookupJNDISubContext(context, token);
            if (tmpCtx == null) {
                try {
                    tmpCtx = context.createSubcontext(token);
                } catch (NamingException e) {
                    throw new DataSourceException(
                            "Error in creating JNDI subcontext '" + context + "/" + token + ": " + e.getMessage(),
                            e);
                }
            }
            context = tmpCtx;
        }
    }

    private void registerJNDI(DataSourceMetaInfo dsmInfo, Object dsObject) throws DataSourceException {
        try {
            /*PrivilegedCarbonContext.startTenantFlow();
               PrivilegedCarbonContext.getCurrentContext().setTenantId(this.getTenantId());*/
            JNDIConfig jndiConfig = dsmInfo.getJndiConfig();
            if (jndiConfig == null) {
                return;
            }
            InitialContext context;
            try {
                context = new InitialContext(jndiConfig.extractHashtableEnv());
            } catch (NamingException e) {
                throw new DataSourceException("Error creating JNDI initial context: " + e.getMessage(), e);
            }
            this.checkAndCreateJNDISubContexts(context, jndiConfig.getName());

            try {
                context.rebind(jndiConfig.getName(), dsObject);
            } catch (NamingException e) {
                throw new DataSourceException(
                        "Error in binding to JNDI with name '" + jndiConfig.getName() + "' - " + e.getMessage(), e);
            }
        } finally {
            /*PrivilegedCarbonContext.endTenantFlow();*/
        }
    }

    private void unregisterJNDI(DataSourceMetaInfo dsmInfo) {
        try {
            /*PrivilegedCarbonContext.startTenantFlow();
               PrivilegedCarbonContext.getCurrentContext().setTenantId(this.getTenantId());*/
            JNDIConfig jndiConfig = dsmInfo.getJndiConfig();
            if (jndiConfig == null) {
                return;
            }
            try {
                InitialContext context = new InitialContext(jndiConfig.extractHashtableEnv());
                context.unbind(jndiConfig.getName());
            } catch (NamingException e) {
                log.error("Error in unregistering JNDI name: " + jndiConfig.getName() + " - " + e.getMessage(), e);
            }
        } finally {
            /*PrivilegedCarbonContext.endTenantFlow();*/
        }
    }

    /*private void removePersistedDataSource(String dsName) throws DataSourceException {
     try {
         this.getRegistry().beginTransaction();
         String path = DataSourceConstants.DATASOURCES_REPOSITORY_BASE_PATH + "/" + dsName;
         if (this.getRegistry().resourceExists(path)) {
             this.getRegistry().delete(path);
         }
         this.getRegistry().commitTransaction();
     } catch (Exception e) {
         try {
             this.getRegistry().rollbackTransaction();
         } catch (RegistryException e1) {
             log.error("Error in rollback transaction in removing data source:" +
                     e1.getMessage(), e1);
         }
         throw new DataSourceException("Error in removing data source: " + dsName +
                 " - " + e.getMessage(), e);
     }
     }*/

    /*private void persistDataSource(DataSourceMetaInfo dsmInfo) throws DataSourceException {
     try {
         Element element = DataSourceUtils.
                 convertDataSourceMetaInfoToElement(dsmInfo, this.getDSMMarshaller());
         DataSourceUtils.secureSaveElement(element);
        
         Resource resource = this.getRegistry().newResource();
         resource.setContentStream(DataSourceUtils.elementToInputStream(element));
         this.getRegistry().put(DataSourceConstants.DATASOURCES_REPOSITORY_BASE_PATH + "/" +
                 dsmInfo.getName(), resource);
     } catch (Exception e) {
         throw new DataSourceException("Error in persisting data source: " +
                 dsmInfo.getName() + " - " + e.getMessage(), e);
     }
     }*/

    private void unregisterDataSource(String dsName) {
        CarbonDataSource cds = this.getDataSource(dsName);
        if (cds == null) {
            return;
        }
        if (log.isDebugEnabled()) {
            log.debug("Unregistering data source: " + dsName);
        }
        this.unregisterJNDI(cds.getDSMInfo());
        this.dataSources.remove(dsName);
    }

    private synchronized void registerDataSource(DataSourceMetaInfo dsmInfo) throws DataSourceException {
        /* if a data source is already registered with the given name, unregister it first */
        CarbonDataSource currentCDS = this.getDataSource(dsmInfo.getName());
        if (currentCDS != null) {
            /* if the data source is a system data source, throw exception */
            if (dsmInfo.isSystem()) {
                throw new DataSourceException("System datasource " + dsmInfo.getName() + "can not be updated.");
            }
            this.unregisterDataSource(currentCDS.getDSMInfo().getName());
        }
        if (log.isDebugEnabled()) {
            log.debug("Registering data source: " + dsmInfo.getName());
        }
        Object dsObject = null;
        boolean isDataSourceFactoryReference = false;
        DataSourceStatus dsStatus;
        try {
            JNDIConfig jndiConfig = dsmInfo.getJndiConfig();
            if (jndiConfig != null) {
                isDataSourceFactoryReference = jndiConfig.isUseDataSourceFactory();
            }
            dsObject = this.createDataSourceObject(dsmInfo, isDataSourceFactoryReference);
            this.registerJNDI(dsmInfo, dsObject);
            dsStatus = new DataSourceStatus(DataSourceConstants.DataSourceStatusModes.ACTIVE, null);
        } catch (Exception e) {
            String msg = "Error in registering data source: " + dsmInfo.getName() + " - " + e.getMessage();
            log.error(msg, e);
            dsStatus = new DataSourceStatus(DataSourceConstants.DataSourceStatusModes.ERROR, msg);
        }
        /* Creating DataSource object , if dsObject is a Reference */
        if (isDataSourceFactoryReference) {
            dsObject = this.createDataSourceObject(dsmInfo, false);
        }
        CarbonDataSource cds = new CarbonDataSource(dsmInfo, dsStatus, dsObject);
        this.dataSources.put(cds.getDSMInfo().getName(), cds);
    }

    /*private void notifyClusterDSChange(String dsName) throws DataSourceException {
     if (log.isDebugEnabled()) {
         log.debug("Notifying cluster DS change: " + dsName);
     }
     ConfigurationContextService configCtxService = DataSourceServiceComponent.
             getConfigContextService();
     if (configCtxService == null) {
         throw new DataSourceException("ConfigurationContextService not available " +
                 "for notifying the cluster");
     }
     ConfigurationContext configCtx = configCtxService.getServerConfigContext();
     ClusteringAgent agent = configCtx.getAxisConfiguration().getClusteringAgent();
     if (log.isDebugEnabled()) {
         log.debug("Clustering Agent: " + agent);
     }
     if (agent != null) {
         DataSourceStatMessage msg = new DataSourceStatMessage();
         msg.setTenantId(this.getTenantId());
         msg.setDsName(dsName);
         try {
             agent.sendMessage(msg, true);
         } catch (ClusteringFault e) {
             throw new DataSourceException("Error in sending out cluster message: " +
                     e.getMessage(), e);
         }
     }
     }*/

    /*private DataSourceMetaInfo getDataSourceMetaInfoFromRegistryPath(String path)
         throws DataSourceException, Exception {
     InputStream in = null;
     try {
         this.getRegistry().beginTransaction();
         if (this.getRegistry().resourceExists(path)) {
             Resource resource;
             try {
                 resource = this.getRegistry().get(path);
             } catch (ResourceNotFoundException e) {
                 *//* this step is as a precaution, because sometimes even though the
                    * resource is deleted, "resourceExists" returns true *//*
                                                                            return null;
                                                                            }
                                                                            in = resource.getContentStream();
                                                                            Document doc = DataSourceUtils.convertToDocument(in);
                                                                            *//* only super tenant will lookup secure vault information for system data sources,
                                                                               * others are not allowed to *//*
                                                                                                              DataSourceUtils.secureResolveDocument(doc, false);
                                                                                                              this.getRegistry().commitTransaction();
                                                                                                              return (DataSourceMetaInfo) this.getDSMUnmarshaller().unmarshal(doc);
                                                                                                              } else {
                                                                                                              return null;
                                                                                                              }
                                                                                                              } catch (Exception e) {
                                                                                                              this.getRegistry().rollbackTransaction();
                                                                                                              throw e;
                                                                                                              } finally {
                                                                                                              if (in != null) {
                                                                                                              in.close();
                                                                                                              }
                                                                                                              }
                                                                                                              }*/

    private Unmarshaller getDSMUnmarshaller() {
        return dsmUnmarshaller;
    }

    private Marshaller getDSMMarshaller() {
        return dsmMarshaller;
    }

    /**
     * Gets information about all the data sources.
     * @return A list of all data sources
     */
    public java.util.Collection<CarbonDataSource> getAllDataSources() {
        return dataSources.values();
    }

    /**
     * Gets information about a specific given data source.
     * @param dsName The name of the data source.
     * @return The data source information
     */
    public CarbonDataSource getDataSource(String dsName) {
        return this.dataSources.get(dsName);
    }

    /**
     * Adds a new data source to the repository.
     * @param dsmInfo The meta information of the data source to be added.
     */
    public void addDataSource(DataSourceMetaInfo dsmInfo) throws DataSourceException {
        if (log.isDebugEnabled()) {
            log.debug("Adding data source: " + dsmInfo.getName());
        }
        this.registerDataSource(dsmInfo);

    }

    /**
     * Unregisters and deletes the data source from the repository.
     * @param dsName The data source name
     */
    public void deleteDataSource(String dsName) throws DataSourceException {
        if (log.isDebugEnabled()) {
            log.debug("Deleting data source: " + dsName);
        }
        CarbonDataSource cds = this.getDataSource(dsName);
        if (cds == null) {
            throw new DataSourceException("Data source does not exist: " + dsName);
        }
        if (cds.getDSMInfo().isSystem()) {
            throw new DataSourceException("System data sources cannot be deleted: " + dsName);
        }
        this.unregisterDataSource(dsName);
    }

    /**
     * Tests Connection of the data source
     * @param dsmInfo The meta information of the data source to be tested.
     */
    public boolean testDataSourceConnection(DataSourceMetaInfo dsmInfo) throws DataSourceException {
        if (log.isDebugEnabled()) {
            log.debug("Testing connection of data source: " + dsmInfo.getName());
        }
        DataSourceReader dsReader = DataSourceManager.getInstance()
                .getDataSourceReader(dsmInfo.getDefinition().getType());
        try {
            return dsReader.testDataSourceConnection(
                    DataSourceUtils.elementToString((Element) dsmInfo.getDefinition().getDsXMLConfiguration()));
        } catch (DataSourceException e) {
            log.error(e.getMessage(), e);
            throw e;
        }

    }

}