1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.xml.internal.utils;
  22 
  23 import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
  24 import com.sun.org.apache.xml.internal.res.XMLErrorResources;
  25 import com.sun.org.apache.xml.internal.res.XMLMessages;
  26 import java.lang.reflect.InvocationTargetException;
  27 import java.util.ArrayList;
  28 import java.util.List;
  29 
  30 
  31 /**
  32  * Pool of object of a given type to pick from to help memory usage
  33  * @xsl.usage internal
  34  * @LastModified: Oct 2017
  35  */
  36 public class ObjectPool implements java.io.Serializable
  37 {
  38     static final long serialVersionUID = -8519013691660936643L;
  39 
  40   /** Type of objects in this pool.
  41    *  @serial          */
  42   private final Class<?> objectType;
  43 
  44   /** Stack of given objects this points to.
  45    *  @serial          */
  46   private final List<Object> freeStack;
  47 
  48   /**
  49    * Constructor ObjectPool
  50    *
  51    * @param type Type of objects for this pool
  52    */
  53   public ObjectPool(Class<?> type)
  54   {
  55     objectType = type;
  56     freeStack = new ArrayList<>();
  57   }
  58 
  59   /**
  60    * Constructor ObjectPool
  61    *
  62    * @param className Fully qualified name of the type of objects for this pool.
  63    */
  64   public ObjectPool(String className)
  65   {
  66     try
  67     {
  68       objectType = ObjectFactory.findProviderClass(className, true);
  69     }
  70     catch(ClassNotFoundException cnfe)
  71     {
  72       throw new WrappedRuntimeException(cnfe);
  73     }
  74     freeStack = new ArrayList<>();
  75   }
  76 
  77 
  78   /**
  79    * Constructor ObjectPool
  80    *
  81    *
  82    * @param type Type of objects for this pool
  83    * @param size Size of vector to allocate
  84    */
  85   public ObjectPool(Class<?> type, int size)
  86   {
  87     objectType = type;
  88     freeStack = new ArrayList<>(size);
  89   }
  90 
  91   /**
  92    * Constructor ObjectPool
  93    *
  94    */
  95   public ObjectPool()
  96   {
  97     objectType = null;
  98     freeStack = new ArrayList<>();
  99   }
 100 
 101   /**
 102    * Get an instance of the given object in this pool if available
 103    *
 104    *
 105    * @return an instance of the given object if available or null
 106    */
 107   public synchronized Object getInstanceIfFree()
 108   {
 109 
 110     // Check if the pool is empty.
 111     if (!freeStack.isEmpty())
 112     {
 113 
 114       // Remove object from end of free pool.
 115       Object result = freeStack.remove(freeStack.size() - 1);
 116       return result;
 117     }
 118 
 119     return null;
 120   }
 121 
 122   /**
 123    * Get an instance of the given object in this pool
 124    *
 125    *
 126    * @return An instance of the given object
 127    */
 128   public synchronized Object getInstance()
 129   {
 130 
 131     // Check if the pool is empty.
 132     if (freeStack.isEmpty())
 133     {
 134 
 135       // Create a new object if so.
 136       try
 137       {
 138         return objectType.getConstructor().newInstance();
 139       }
 140       catch (InstantiationException | IllegalAccessException | SecurityException |
 141               IllegalArgumentException | InvocationTargetException | NoSuchMethodException ex){}
 142 
 143       // Throw unchecked exception for error in pool configuration.
 144       throw new RuntimeException(XMLMessages.createXMLMessage(
 145               XMLErrorResources.ER_EXCEPTION_CREATING_POOL, null));
 146     }
 147     else
 148     {
 149 
 150       // Remove object from end of free pool.
 151       Object result = freeStack.remove(freeStack.size() - 1);
 152       return result;
 153     }
 154   }
 155 
 156   /**
 157    * Add an instance of the given object to the pool
 158    *
 159    *
 160    * @param obj Object to add.
 161    */
 162   public synchronized void freeInstance(Object obj)
 163   {
 164 
 165     // Make sure the object is of the correct type.
 166     // Remove safety.  -sb
 167     // if (objectType.isInstance(obj))
 168     // {
 169     freeStack.add(obj);
 170     // }
 171     // else
 172     // {
 173     //  throw new IllegalArgumentException("argument type invalid for pool");
 174     // }
 175   }
 176 }