001/* 002 * (C) Copyright 2009-2017 Nuxeo (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Florent Guillaume 018 */ 019package org.nuxeo.runtime.datasource; 020 021import java.util.HashMap; 022import java.util.Map; 023 024import javax.naming.NamingException; 025import javax.sql.DataSource; 026 027import org.apache.commons.logging.Log; 028import org.apache.commons.logging.LogFactory; 029import org.nuxeo.runtime.RuntimeServiceException; 030import org.nuxeo.runtime.model.ComponentContext; 031import org.nuxeo.runtime.model.ComponentInstance; 032import org.nuxeo.runtime.model.DefaultComponent; 033 034/** 035 * Nuxeo component allowing the JNDI registration of datasources by extension 036 * point contributions. 037 * <p> 038 * For now only the internal Nuxeo JNDI server is supported. 039 */ 040public class DataSourceComponent extends DefaultComponent { 041 042 private final Log log = LogFactory.getLog(DataSourceComponent.class); 043 044 public static final String DATASOURCES_XP = "datasources"; 045 046 public static final String ENV_CTX_NAME = "java:comp/env/"; 047 048 protected Map<String, DataSourceDescriptor> datasources = new HashMap<>(); 049 050 protected Map<String, DataSourceLinkDescriptor> links = new HashMap<>(); 051 052 protected final PooledDataSourceRegistry poolRegistry = new PooledDataSourceRegistry(); 053 054 protected boolean started; 055 056 @Override 057 public void activate(ComponentContext context) { 058 datasources = new HashMap<>(); 059 links = new HashMap<>(); 060 } 061 062 @Override 063 public void deactivate(ComponentContext context) { 064 super.deactivate(context); 065 links = null; 066 datasources = null; 067 //TODO should poolRegistry and sorterRegistry be removed? 068 } 069 070 @Override 071 public void registerContribution(Object contrib, String extensionPoint, ComponentInstance component) { 072 if (contrib instanceof DataSourceDescriptor) { 073 addDataSource((DataSourceDescriptor) contrib); 074 } else if (contrib instanceof DataSourceLinkDescriptor) { 075 addDataSourceLink((DataSourceLinkDescriptor) contrib); 076 } else { 077 log.error("Wrong datasource extension type " + contrib.getClass().getName()); 078 } 079 } 080 081 @Override 082 public void unregisterContribution(Object contrib, String extensionPoint, ComponentInstance component) { 083 if (contrib instanceof DataSourceDescriptor) { 084 removeDataSource((DataSourceDescriptor) contrib); 085 } else if (contrib instanceof DataSourceLinkDescriptor) { 086 removeDataSourceLink((DataSourceLinkDescriptor) contrib); 087 } 088 } 089 090 @Override 091 public int getApplicationStartedOrder() { 092 return -1000; 093 } 094 095 public boolean isStarted() { 096 return started; 097 } 098 099 @Override 100 public void start(ComponentContext context) { 101 if (started) { 102 return; 103 } 104 started = true; 105 // bind datasources 106 for (DataSourceDescriptor datasourceDesc : datasources.values()) { 107 bindDataSource(datasourceDesc); 108 } 109 // bind links 110 for (DataSourceLinkDescriptor linkDesc : links.values()) { 111 bindDataSourceLink(linkDesc); 112 } 113 } 114 115 @Override 116 public void stop(ComponentContext context) { 117 try { 118 for (DataSourceLinkDescriptor desc : links.values()) { 119 unbindDataSourceLink(desc); 120 } 121 for (DataSourceDescriptor desc : datasources.values()) { 122 unbindDataSource(desc); 123 } 124 } finally { 125 started = false; 126 } 127 } 128 129 protected void addDataSource(DataSourceDescriptor contrib) { 130 datasources.put(contrib.getName(), contrib); 131 bindDataSource(contrib); 132 } 133 134 protected void removeDataSource(DataSourceDescriptor contrib) { 135 unbindDataSource(contrib); 136 datasources.remove(contrib.getName()); 137 } 138 139 protected void bindDataSource(DataSourceDescriptor descr) { 140 log.info("Registering datasource: " + descr.getName()); 141 poolRegistry.registerPooledDataSource(descr.getName(), descr.getAllProperties()); 142 } 143 144 protected void unbindDataSource(DataSourceDescriptor descr) { 145 log.info("Unregistering datasource: " + descr.getName()); 146 poolRegistry.unregisterPooledDataSource(descr.getName()); 147 } 148 149 protected void addDataSourceLink(DataSourceLinkDescriptor contrib) { 150 links.put(contrib.name, contrib); 151 bindDataSourceLink(contrib); 152 } 153 154 protected void removeDataSourceLink(DataSourceLinkDescriptor contrib) { 155 unbindDataSourceLink(contrib); 156 links.remove(contrib.name); 157 } 158 159 protected void bindDataSourceLink(DataSourceLinkDescriptor descr) { 160 log.info("Registering DataSourceLink: " + descr.name); 161 DataSource ds; 162 try { 163 ds = DataSourceHelper.getDataSource(descr.global, DataSource.class); 164 } catch (NamingException e) { 165 throw new RuntimeServiceException("Cannot find DataSourceLink '" + descr.name + "' in JNDI", e); 166 } 167 poolRegistry.createAlias(DataSourceHelper.relativize(descr.name), ds); 168 } 169 170 protected void unbindDataSourceLink(DataSourceLinkDescriptor descr) { 171 log.info("Unregistering DataSourceLink: " + descr.name); 172 poolRegistry.removeAlias(descr.name); 173 } 174 175 @Override 176 public <T> T getAdapter(Class<T> adapter) { 177 if (adapter.isAssignableFrom(PooledDataSourceRegistry.class)) { 178 return adapter.cast(poolRegistry); 179 } 180 return super.getAdapter(adapter); 181 } 182 183}