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
27package sun.nio.cs;
28
29import java.nio.*;
30import java.nio.charset.*;
31
32
33/**
34 * Utility class for caching per-thread decoders and encoders.
35 */
36
37public 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