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 
Cache(int size)47         Cache(int size) {
48             this.size = size;
49         }
50 
create(Object name)51         abstract Object create(Object name);
52 
moveToFront(Object[] oa, int i)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 
hasName(Object ob, Object name)60         abstract boolean hasName(Object ob, Object name);
61 
forName(Object name)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 
decoderFor(Object name)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 
encoderFor(Object name)131     public static CharsetEncoder encoderFor(Object name) {
132         CharsetEncoder ce = (CharsetEncoder)encoderCache.forName(name);
133         ce.reset();
134         return ce;
135     }
136 
137 }
138