/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 com.frameworkset.commons.dbcp2.datasources; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import javax.naming.Context; import javax.naming.Name; import javax.naming.RefAddr; import javax.naming.Reference; import javax.naming.spi.ObjectFactory; /** * A JNDI ObjectFactory which creates <code>SharedPoolDataSource</code>s * or <code>PerUserPoolDataSource</code>s * * @version $Id: InstanceKeyDataSourceFactory.java 1649430 2015-01-04 21:29:32Z tn $ * @since 2.0 */ abstract class InstanceKeyDataSourceFactory implements ObjectFactory { private static final Map<String, InstanceKeyDataSource> instanceMap = new ConcurrentHashMap<String, InstanceKeyDataSource>(); static synchronized String registerNewInstance(InstanceKeyDataSource ds) { int max = 0; Iterator<String> i = instanceMap.keySet().iterator(); while (i.hasNext()) { String s = i.next(); if (s != null) { try { max = Math.max(max, Integer.parseInt(s)); } catch (NumberFormatException e) { // no sweat, ignore those keys } } } String instanceKey = String.valueOf(max + 1); // put a placeholder here for now, so other instances will not // take our key. we will replace with a pool when ready. instanceMap.put(instanceKey, ds); return instanceKey; } static void removeInstance(String key) { if (key != null) { instanceMap.remove(key); } } /** * Close all pools associated with this class. */ public static void closeAll() throws Exception { //Get iterator to loop over all instances of this datasource. Iterator<Entry<String,InstanceKeyDataSource>> instanceIterator = instanceMap.entrySet().iterator(); while (instanceIterator.hasNext()) { instanceIterator.next().getValue().close(); } instanceMap.clear(); } /** * implements ObjectFactory to create an instance of SharedPoolDataSource * or PerUserPoolDataSource */ @Override public Object getObjectInstance(Object refObj, Name name, Context context, Hashtable<?,?> env) throws IOException, ClassNotFoundException { // The spec says to return null if we can't create an instance // of the reference Object obj = null; if (refObj instanceof Reference) { Reference ref = (Reference) refObj; if (isCorrectClass(ref.getClassName())) { RefAddr ra = ref.get("instanceKey"); if (ra != null && ra.getContent() != null) { // object was bound to jndi via Referenceable api. obj = instanceMap.get(ra.getContent()); } else { // tomcat jndi creates a Reference out of server.xml // <ResourceParam> configuration and passes it to an // instance of the factory given in server.xml. String key = null; if (name != null) { key = name.toString(); obj = instanceMap.get(key); } if (obj == null) { InstanceKeyDataSource ds = getNewInstance(ref); setCommonProperties(ref, ds); obj = ds; if (key != null) { instanceMap.put(key, ds); } } } } } return obj; } private void setCommonProperties(Reference ref, InstanceKeyDataSource ikds) throws IOException, ClassNotFoundException { RefAddr ra = ref.get("dataSourceName"); if (ra != null && ra.getContent() != null) { ikds.setDataSourceName(ra.getContent().toString()); } ra = ref.get("description"); if (ra != null && ra.getContent() != null) { ikds.setDescription(ra.getContent().toString()); } ra = ref.get("jndiEnvironment"); if (ra != null && ra.getContent() != null) { byte[] serialized = (byte[]) ra.getContent(); ikds.setJndiEnvironment((Properties) deserialize(serialized)); } ra = ref.get("loginTimeout"); if (ra != null && ra.getContent() != null) { ikds.setLoginTimeout( Integer.parseInt(ra.getContent().toString())); } // Pool properties ra = ref.get("blockWhenExhausted"); if (ra != null && ra.getContent() != null) { ikds.setDefaultBlockWhenExhausted(Boolean.valueOf( ra.getContent().toString()).booleanValue()); } ra = ref.get("evictionPolicyClassName"); if (ra != null && ra.getContent() != null) { ikds.setDefaultEvictionPolicyClassName(ra.getContent().toString()); } // Pool properties ra = ref.get("lifo"); if (ra != null && ra.getContent() != null) { ikds.setDefaultLifo(Boolean.valueOf( ra.getContent().toString()).booleanValue()); } ra = ref.get("maxIdlePerKey"); if (ra != null && ra.getContent() != null) { ikds.setDefaultMaxIdle( Integer.parseInt(ra.getContent().toString())); } ra = ref.get("maxTotalPerKey"); if (ra != null && ra.getContent() != null) { ikds.setDefaultMaxTotal( Integer.parseInt(ra.getContent().toString())); } ra = ref.get("maxWaitMillis"); if (ra != null && ra.getContent() != null) { ikds.setDefaultMaxWaitMillis( Long.parseLong(ra.getContent().toString())); } ra = ref.get("minEvictableIdleTimeMillis"); if (ra != null && ra.getContent() != null) { ikds.setDefaultMinEvictableIdleTimeMillis( Long.parseLong(ra.getContent().toString())); } ra = ref.get("minIdlePerKey"); if (ra != null && ra.getContent() != null) { ikds.setDefaultMinIdle( Integer.parseInt(ra.getContent().toString())); } ra = ref.get("numTestsPerEvictionRun"); if (ra != null && ra.getContent() != null) { ikds.setDefaultNumTestsPerEvictionRun( Integer.parseInt(ra.getContent().toString())); } ra = ref.get("softMinEvictableIdleTimeMillis"); if (ra != null && ra.getContent() != null) { ikds.setDefaultSoftMinEvictableIdleTimeMillis( Long.parseLong(ra.getContent().toString())); } ra = ref.get("testOnCreate"); if (ra != null && ra.getContent() != null) { ikds.setDefaultTestOnCreate(Boolean.valueOf( ra.getContent().toString()).booleanValue()); } ra = ref.get("testOnBorrow"); if (ra != null && ra.getContent() != null) { ikds.setDefaultTestOnBorrow(Boolean.valueOf( ra.getContent().toString()).booleanValue()); } ra = ref.get("testOnReturn"); if (ra != null && ra.getContent() != null) { ikds.setDefaultTestOnReturn(Boolean.valueOf( ra.getContent().toString()).booleanValue()); } ra = ref.get("testWhileIdle"); if (ra != null && ra.getContent() != null) { ikds.setDefaultTestWhileIdle(Boolean.valueOf( ra.getContent().toString()).booleanValue()); } ra = ref.get("timeBetweenEvictionRunsMillis"); if (ra != null && ra.getContent() != null) { ikds.setDefaultTimeBetweenEvictionRunsMillis( Long.parseLong(ra.getContent().toString())); } // Connection factory properties ra = ref.get("validationQuery"); if (ra != null && ra.getContent() != null) { ikds.setValidationQuery(ra.getContent().toString()); } ra = ref.get("validationQueryTimeout"); if (ra != null && ra.getContent() != null) { ikds.setValidationQueryTimeout(Integer.parseInt( ra.getContent().toString())); } ra = ref.get("rollbackAfterValidation"); if (ra != null && ra.getContent() != null) { ikds.setRollbackAfterValidation(Boolean.valueOf( ra.getContent().toString()).booleanValue()); } ra = ref.get("maxConnLifetimeMillis"); if (ra != null && ra.getContent() != null) { ikds.setMaxConnLifetimeMillis( Long.parseLong(ra.getContent().toString())); } // Connection properties ra = ref.get("defaultAutoCommit"); if (ra != null && ra.getContent() != null) { ikds.setDefaultAutoCommit(Boolean.valueOf(ra.getContent().toString())); } ra = ref.get("defaultTransactionIsolation"); if (ra != null && ra.getContent() != null) { ikds.setDefaultTransactionIsolation( Integer.parseInt(ra.getContent().toString())); } ra = ref.get("defaultReadOnly"); if (ra != null && ra.getContent() != null) { ikds.setDefaultReadOnly(Boolean.valueOf(ra.getContent().toString())); } } /** * @return true if and only if className is the value returned * from getClass().getName().toString() */ protected abstract boolean isCorrectClass(String className); /** * Creates an instance of the subclass and sets any properties * contained in the Reference. */ protected abstract InstanceKeyDataSource getNewInstance(Reference ref) throws IOException, ClassNotFoundException; /** * used to set some properties saved within a Reference */ protected static final Object deserialize(byte[] data) throws IOException, ClassNotFoundException { ObjectInputStream in = null; try { in = new ObjectInputStream(new ByteArrayInputStream(data)); return in.readObject(); } finally { if (in != null) { try { in.close(); } catch (IOException ex) { } } } } }