Home | History | Annotate | Download | only in cs
      1 /*
      2  * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25 
     26 
     27 package sun.nio.cs;
     28 
     29 import java.nio.*;
     30 import java.nio.charset.*;
     31 
     32 
     33 /**
     34  * Utility class for caching per-thread decoders and encoders.
     35  */
     36 
     37 public class ThreadLocalCoders {
     38 
     39     private static final int CACHE_SIZE = 3;
     40 
     41     private static abstract class Cache {
     42 
     43         // Thread-local reference to array of cached objects, in LRU order
     44         private ThreadLocal cache = new ThreadLocal();
     45         private final int size;
     46 
     47         Cache(int size) {
     48             this.size = size;
     49         }
     50 
     51         abstract Object create(Object name);
     52 
     53         private void moveToFront(Object[] oa, int i) {
     54             Object ob = oa[i];
     55             for (int j = i; j > 0; j--)
     56                 oa[j] = oa[j - 1];
     57             oa[0] = ob;
     58         }
     59 
     60         abstract boolean hasName(Object ob, Object name);
     61 
     62         Object forName(Object name) {
     63             Object[] oa = (Object[])cache.get();
     64             if (oa == null) {
     65                 oa = new Object[size];
     66                 cache.set(oa);
     67             } else {
     68                 for (int i = 0; i < oa.length; i++) {
     69                     Object ob = oa[i];
     70                     if (ob == null)
     71                         continue;
     72                     if (hasName(ob, name)) {
     73                         if (i > 0)
     74                             moveToFront(oa, i);
     75                         return ob;
     76                     }
     77                 }
     78             }
     79 
     80             // Create a new object
     81             Object ob = create(name);
     82             oa[oa.length - 1] = ob;
     83             moveToFront(oa, oa.length - 1);
     84             return ob;
     85         }
     86 
     87     }
     88 
     89     private static Cache decoderCache = new Cache(CACHE_SIZE) {
     90             boolean hasName(Object ob, Object name) {
     91                 if (name instanceof String)
     92                     return (((CharsetDecoder)ob).charset().name().equals(name));
     93                 if (name instanceof Charset)
     94                     return ((CharsetDecoder)ob).charset().equals(name);
     95                 return false;
     96             }
     97             Object create(Object name) {
     98                 if (name instanceof String)
     99                     return Charset.forName((String)name).newDecoder();
    100                 if (name instanceof Charset)
    101                     return ((Charset)name).newDecoder();
    102                 assert false;
    103                 return null;
    104             }
    105         };
    106 
    107     public static CharsetDecoder decoderFor(Object name) {
    108         CharsetDecoder cd = (CharsetDecoder)decoderCache.forName(name);
    109         cd.reset();
    110         return cd;
    111     }
    112 
    113     private static Cache encoderCache = new Cache(CACHE_SIZE) {
    114             boolean hasName(Object ob, Object name) {
    115                 if (name instanceof String)
    116                     return (((CharsetEncoder)ob).charset().name().equals(name));
    117                 if (name instanceof Charset)
    118                     return ((CharsetEncoder)ob).charset().equals(name);
    119                 return false;
    120             }
    121             Object create(Object name) {
    122                 if (name instanceof String)
    123                     return Charset.forName((String)name).newEncoder();
    124                 if (name instanceof Charset)
    125                     return ((Charset)name).newEncoder();
    126                 assert false;
    127                 return null;
    128             }
    129         };
    130 
    131     public static CharsetEncoder encoderFor(Object name) {
    132         CharsetEncoder ce = (CharsetEncoder)encoderCache.forName(name);
    133         ce.reset();
    134         return ce;
    135     }
    136 
    137 }
    138