001/* 002 * (C) Copyright 2009 Nuxeo SA (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 */ 019 020package org.nuxeo.runtime.datasource; 021 022import java.util.HashMap; 023import java.util.Map; 024 025import javax.naming.CompositeName; 026import javax.naming.Context; 027import javax.naming.Name; 028import javax.naming.NamingException; 029 030import org.apache.commons.logging.Log; 031import org.apache.commons.logging.LogFactory; 032import org.nuxeo.runtime.jtajca.NuxeoContainer; 033import org.nuxeo.runtime.model.ComponentContext; 034import org.nuxeo.runtime.model.ComponentInstance; 035import org.nuxeo.runtime.model.DefaultComponent; 036 037/** 038 * Nuxeo component allowing the JNDI registration of datasources by extension point contributions. 039 * <p> 040 * For now only the internal Nuxeo JNDI server is supported. 041 */ 042public class DataSourceComponent extends DefaultComponent { 043 044 private final Log log = LogFactory.getLog(DataSourceComponent.class); 045 046 public static final String DATASOURCES_XP = "datasources"; 047 048 public static final String ENV_CTX_NAME = "java:comp/env/"; 049 050 protected final Map<String, DataSourceDescriptor> datasources = new HashMap<String, DataSourceDescriptor>(); 051 052 protected final Map<String, DataSourceLinkDescriptor> links = new HashMap<String, DataSourceLinkDescriptor>(); 053 054 protected final PooledDataSourceRegistry registry = new PooledDataSourceRegistry(); 055 056 protected Context namingContext; 057 058 @Override 059 public void registerContribution(Object contrib, String extensionPoint, ComponentInstance component) { 060 if (DATASOURCES_XP.equals(extensionPoint)) { 061 if (contrib instanceof DataSourceDescriptor) { 062 addDataSource((DataSourceDescriptor) contrib); 063 } else if (contrib instanceof DataSourceLinkDescriptor) { 064 addDataSourceLink((DataSourceLinkDescriptor) contrib); 065 } else { 066 log.error("Wrong datasource extension type " + contrib.getClass().getName()); 067 } 068 } else { 069 log.error("Ignoring unknown extension point: " + extensionPoint); 070 } 071 } 072 073 @Override 074 public void unregisterContribution(Object contrib, String extensionPoint, ComponentInstance component) { 075 if (DATASOURCES_XP.equals(extensionPoint)) { 076 if (contrib instanceof DataSourceDescriptor) { 077 removeDataSource((DataSourceDescriptor) contrib); 078 } else if (contrib instanceof DataSourceLinkDescriptor) { 079 removeDataSourceLink((DataSourceLinkDescriptor) contrib); 080 } 081 } 082 } 083 084 @Override 085 public int getApplicationStartedOrder() { 086 return -1000; 087 } 088 089 public boolean isStarted() { 090 return namingContext != null; 091 } 092 093 @Override 094 public void applicationStarted(ComponentContext context) { 095 if (namingContext != null) { 096 return; 097 } 098 namingContext = NuxeoContainer.getRootContext(); 099 // allocate datasource sub-contexts 100 Name comp; 101 try { 102 comp = new CompositeName(DataSourceHelper.getDataSourceJNDIPrefix()); 103 } catch (NamingException e) { 104 throw new RuntimeException(e); 105 } 106 Context ctx = namingContext; 107 for (int i = 0; i < comp.size(); i++) { 108 try { 109 ctx = (Context) ctx.lookup(comp.get(i)); 110 } catch (NamingException e) { 111 try { 112 ctx = ctx.createSubcontext(comp.get(i)); 113 } catch (NamingException e1) { 114 throw new RuntimeException(e1); 115 } 116 } 117 } 118 // bind datasources 119 for (DataSourceDescriptor datasourceDesc : datasources.values()) { 120 bindDataSource(datasourceDesc); 121 } 122 // bind links 123 for (DataSourceLinkDescriptor linkDesc : links.values()) { 124 bindDataSourceLink(linkDesc); 125 } 126 } 127 128 @Override 129 public void deactivate(ComponentContext context) { 130 super.deactivate(context); 131 for (DataSourceLinkDescriptor desc : links.values()) { 132 unbindDataSourceLink(desc); 133 } 134 links.clear(); 135 for (DataSourceDescriptor desc : datasources.values()) { 136 unbindDataSource(desc); 137 } 138 datasources.clear(); 139 namingContext = null; 140 } 141 142 protected void addDataSource(DataSourceDescriptor contrib) { 143 datasources.put(contrib.getName(), contrib); 144 bindDataSource(contrib); 145 } 146 147 protected void removeDataSource(DataSourceDescriptor contrib) { 148 unbindDataSource(contrib); 149 datasources.remove(contrib.getName()); 150 } 151 152 protected void bindDataSource(DataSourceDescriptor descr) { 153 if (namingContext == null) { 154 return; 155 } 156 log.info("Registering datasource: " + descr.getName()); 157 try { 158 descr.bindSelf(namingContext); 159 } catch (NamingException e) { 160 log.error("Cannot bind datasource '" + descr.getName() + "' in JNDI", e); 161 } 162 } 163 164 protected void unbindDataSource(DataSourceDescriptor descr) { 165 if (namingContext == null) { 166 return; 167 } 168 log.info("Unregistering datasource: " + descr.name); 169 try { 170 descr.unbindSelf(namingContext); 171 } catch (NamingException cause) { 172 log.error("Cannot unbind datasource '" + descr.name + "' in JNDI", cause); 173 } 174 } 175 176 protected void addDataSourceLink(DataSourceLinkDescriptor contrib) { 177 links.put(contrib.name, contrib); 178 bindDataSourceLink(contrib); 179 } 180 181 protected void removeDataSourceLink(DataSourceLinkDescriptor contrib) { 182 unbindDataSourceLink(contrib); 183 links.remove(contrib.name); 184 } 185 186 protected void bindDataSourceLink(DataSourceLinkDescriptor descr) { 187 if (namingContext == null) { 188 return; 189 } 190 log.info("Registering DataSourceLink: " + descr.name); 191 try { 192 descr.bindSelf(namingContext); 193 } catch (NamingException e) { 194 log.error("Cannot bind DataSourceLink '" + descr.name + "' in JNDI", e); 195 } 196 } 197 198 protected void unbindDataSourceLink(DataSourceLinkDescriptor descr) { 199 if (namingContext == null) { 200 return; 201 } 202 log.info("Unregistering DataSourceLink: " + descr.name); 203 try { 204 descr.unbindSelf(namingContext); 205 } catch (NamingException e) { 206 log.error("Cannot unbind DataSourceLink '" + descr.name + "' in JNDI", e); 207 } 208 } 209 210 @Override 211 public <T> T getAdapter(Class<T> adapter) { 212 if (adapter.isAssignableFrom(PooledDataSourceRegistry.class)) { 213 return adapter.cast(registry); 214 } 215 return super.getAdapter(adapter); 216 } 217 218}