EMMA Coverage Report (generated Tue Jan 14 02:29:45 CET 2014)
[all classes][org.jdtaus.core.nio.util]

COVERAGE SUMMARY FOR SOURCE FILE [Charsets.java]

nameclass, %method, %block, %line, %
Charsets.java100% (1/1)67%  (4/6)45%  (210/465)45%  (50.5/113)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Charsets100% (1/1)67%  (4/6)45%  (210/465)45%  (50.5/113)
Charsets (): void 0%   (0/1)0%   (0/3)0%   (0/2)
decode (byte [], int, int, String): String 0%   (0/1)0%   (0/103)0%   (0/26)
decode (byte [], String): String 100% (1/1)36%  (27/75)36%  (8/22)
encode (String, String): byte [] 100% (1/1)48%  (41/86)46%  (11/24)
getCharset (String): Charset 100% (1/1)70%  (121/174)80%  (28.7/36)
<static initializer> 100% (1/1)88%  (21/24)96%  (2.9/3)

1/*
2 *  jDTAUS Core Utilities
3 *  Copyright (C) 2005 Christian Schulte
4 *  <cs@schulte.it>
5 *
6 *  This library is free software; you can redistribute it and/or
7 *  modify it under the terms of the GNU Lesser General Public
8 *  License as published by the Free Software Foundation; either
9 *  version 2.1 of the License, or any later version.
10 *
11 *  This library is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 *  Lesser General Public License for more details.
15 *
16 *  You should have received a copy of the GNU Lesser General Public
17 *  License along with this library; if not, write to the Free Software
18 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19 *
20 */
21package org.jdtaus.core.nio.util;
22 
23import java.io.BufferedReader;
24import java.io.IOException;
25import java.io.InputStream;
26import java.io.InputStreamReader;
27import java.net.URL;
28import java.nio.ByteBuffer;
29import java.nio.CharBuffer;
30import java.nio.charset.Charset;
31import java.nio.charset.spi.CharsetProvider;
32import java.util.Enumeration;
33import java.util.HashMap;
34import java.util.Iterator;
35import java.util.LinkedList;
36import java.util.List;
37import java.util.Map;
38 
39/**
40 * Charset coder and decoder utility.
41 * <p>This class extends the former charset provider implementations which
42 * cannot be used in every environment (e.g. WebStart, Maven) without
43 * installation in the JRE extensions directory where they are available to the
44 * system classloader. It uses the same service provider files as the
45 * platform implementation ({@code java.nio.charset.spi.CharsetProvider}) but
46 * is capable of using the current thread's classloader before falling back
47 * to the system classloader for loading {@code CharsetProvider} classes.</p>
48 *
49 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
50 * @version $JDTAUS: Charsets.java 8743 2012-10-07 03:06:20Z schulte $
51 */
52public class Charsets
53{
54    //--Charsets----------------------------------------------------------------
55 
56    /** Cached {@code CharsetProvider} instances. */
57    private static final List providers = new LinkedList();
58 
59    /** Cached {@code Charset} instances by name. */
60    private static final Map charsets = new HashMap( 100 );
61 
62    /** Private constructor. */
63    private Charsets()
64    {
65        super();
66    }
67 
68    /**
69     * Gets a charset for the given name.
70     *
71     * @param name the name of the charset to return.
72     *
73     * @return a {@code Charset} corresponding to {@code name} or {@code null}
74     * if no such {@code Charset} is available.
75     *
76     * @throws IOException if reading the service provider files fails.
77     * @throws ClassNotFoundException if a service provider file defines
78     * a class which cannot be loaded.
79     * @throws InstantiationException if creating an instance of a
80     * {@code CharsetProvider} fails.
81     * @throws IllegalAccessException if a {@code CharsetProvider} class
82     * does not define a public no-arg constructor.
83     * @throws java.nio.charset.IllegalCharsetNameException if {@code name} is
84     * no valid charset name.
85     * @throws java.nio.charset.UnsupportedCharsetException if {@code name} is
86     * not supported.
87     */
88    private static Charset getCharset( final String name )
89        throws IOException, ClassNotFoundException, InstantiationException,
90               IllegalAccessException
91    {
92        // Populate the provider list with available providers if it is empty.
93        if ( providers.size() == 0 )
94        {
95            synchronized ( Charsets.class )
96            {
97                // Use the current thread's context classloader if available or
98                // fall back to the system classloader.
99                ClassLoader classLoader = Thread.currentThread().
100                    getContextClassLoader();
101 
102                if ( classLoader == null )
103                {
104                    classLoader = ClassLoader.getSystemClassLoader();
105                }
106 
107                assert classLoader != null :
108                    "Expected system classloader to always be available.";
109 
110                // Read all service provider files and load all defined
111                // provider classes.
112                final Enumeration providerFiles = classLoader.getResources(
113                    "META-INF/services/java.nio.charset.spi.CharsetProvider" );
114 
115                if ( providerFiles != null )
116                {
117                    while ( providerFiles.hasMoreElements() )
118                    {
119                        final URL url = ( URL ) providerFiles.nextElement();
120                        BufferedReader reader = null;
121 
122                        try
123                        {
124                            String line;
125                            reader = new BufferedReader(
126                                new InputStreamReader( url.openStream(),
127                                                       "UTF-8" ) );
128 
129                            while ( ( line = reader.readLine() ) != null )
130                            {
131                                // Check that the line denotes a valid Java
132                                // classname and load that class using
133                                // reflection.
134                                if ( line.indexOf( '#' ) < 0 )
135                                {
136                                    providers.add(
137                                        classLoader.loadClass( line ).
138                                        newInstance() );
139 
140                                }
141                            }
142 
143                            reader.close();
144                            reader = null;
145                        }
146                        finally
147                        {
148                            if ( reader != null )
149                            {
150                                reader.close();
151                            }
152                        }
153                    }
154                }
155            }
156        }
157 
158        // Search cached charsets.
159        Charset charset = ( Charset ) charsets.get( name );
160        if ( charset == null )
161        {
162            synchronized ( Charsets.class )
163            {
164                // Search all available providers for a charset matching "name".
165                for ( final Iterator it = providers.iterator(); it.hasNext();)
166                {
167                    charset =
168                        ( ( CharsetProvider ) it.next() ).charsetForName( name );
169 
170                    if ( charset != null )
171                    {
172                        charsets.put( name, charset );
173                        break;
174                    }
175                }
176            }
177        }
178 
179        // Fall back to platform charsets if nothing is found so far.
180        if ( charset == null )
181        {
182            synchronized ( Charsets.class )
183            {
184                charset = Charset.forName( name );
185                charsets.put( name, charset );
186            }
187        }
188 
189        return charset;
190    }
191 
192    /**
193     * Encodes a given string to an array of bytes representing the characters
194     * of the string in a given charset.
195     *
196     * @param str the string to encode.
197     * @param charset the name of the charset to use.
198     *
199     * @throws NullPointerException if {@code str} or {@code charset} is
200     * {@code null}.
201     * @throws java.nio.charset.IllegalCharsetNameException if {@code charset}
202     * is no valid charset name.
203     * @throws java.nio.charset.UnsupportedCharsetException if {@code charset}
204     * is not supported.
205     */
206    public static byte[] encode( final String str, final String charset )
207    {
208        if ( str == null )
209        {
210            throw new NullPointerException( "str" );
211        }
212        if ( charset == null )
213        {
214            throw new NullPointerException( "charset" );
215        }
216 
217        final byte[] ret;
218        try
219        {
220            final Charset cset = Charsets.getCharset( charset );
221            final ByteBuffer buf = cset.encode( str );
222 
223            if ( buf.hasArray() )
224            {
225                if ( buf.array().length == buf.limit() )
226                {
227                    ret = buf.array();
228                }
229                else
230                {
231                    ret = new byte[ buf.limit() ];
232                    System.arraycopy( buf.array(), buf.arrayOffset(),
233                                      ret, 0, ret.length );
234 
235                }
236            }
237            else
238            {
239                ret = new byte[ buf.limit() ];
240                buf.rewind();
241                buf.get( ret );
242            }
243        }
244        catch ( final ClassNotFoundException e )
245        {
246            throw new AssertionError( e );
247        }
248        catch ( final InstantiationException e )
249        {
250            throw new AssertionError( e );
251        }
252        catch ( final IllegalAccessException e )
253        {
254            throw new AssertionError( e );
255        }
256        catch ( final IOException e )
257        {
258            throw new AssertionError( e );
259        }
260 
261        return ret;
262    }
263 
264    /**
265     * Decodes the bytes of a given array to a string.
266     *
267     * @param bytes the bytes to decode.
268     * @param charset the name of the charset to use.
269     *
270     * @throws NullPointerException if {@code bytes} or {@code charset} is
271     * {@code null}.
272     * @throws java.nio.charset.IllegalCharsetNameException if {@code charset}
273     * is no valid charset name.
274     * @throws java.nio.charset.UnsupportedCharsetException if {@code charset}
275     * is not supported.
276     */
277    public static String decode( final byte[] bytes, final String charset )
278    {
279        if ( bytes == null )
280        {
281            throw new NullPointerException( "bytes" );
282        }
283        if ( charset == null )
284        {
285            throw new NullPointerException( "charset" );
286        }
287 
288        final String ret;
289        try
290        {
291            final Charset cset = Charsets.getCharset( charset );
292            final CharBuffer buf = cset.decode( ByteBuffer.wrap( bytes ) );
293 
294            if ( buf.hasArray() )
295            {
296                ret = String.valueOf( buf.array(), buf.arrayOffset(),
297                                      buf.length() );
298 
299            }
300            else
301            {
302                final char[] c = new char[ buf.length() ];
303                buf.rewind();
304                buf.get( c );
305                ret = String.valueOf( c );
306            }
307        }
308        catch ( final ClassNotFoundException e )
309        {
310            throw new AssertionError( e );
311        }
312        catch ( final InstantiationException e )
313        {
314            throw new AssertionError( e );
315        }
316        catch ( final IllegalAccessException e )
317        {
318            throw new AssertionError( e );
319        }
320        catch ( final IOException e )
321        {
322            throw new AssertionError( e );
323        }
324 
325        return ret;
326    }
327 
328    /**
329     * Decodes the bytes of a given array to a string.
330     *
331     * @param bytes the bytes to decode.
332     * @param off the offset from where to start decoding.
333     * @param count the number of bytes to decode starting at {@code offset}.
334     * @param charset the name of the charset to use.
335     *
336     * @throws NullPointerException if {@code bytes} or {@code charset} is
337     * {@code null}.
338     * @throws IndexOutOfBoundsException if {@code off} is negative or greater
339     * than the length of {@code bytes} or {@code off + count} is negative or
340     * greater than the length of {@code bytes}.
341     * @throws java.nio.charset.IllegalCharsetNameException if {@code charset}
342     * is no valid charset name.
343     * @throws java.nio.charset.UnsupportedCharsetException if {@code charset}
344     * is not supported.
345     */
346    public static String decode( final byte[] bytes, final int off,
347                                   final int count, final String charset )
348    {
349        if ( bytes == null )
350        {
351            throw new NullPointerException( "bytes" );
352        }
353        if ( charset == null )
354        {
355            throw new NullPointerException( "charset" );
356        }
357        if ( off < 0 || off >= bytes.length )
358        {
359            throw new ArrayIndexOutOfBoundsException( off );
360        }
361        if ( count < 0 || off + count >= bytes.length )
362        {
363            throw new ArrayIndexOutOfBoundsException( count + off );
364        }
365 
366        final String ret;
367        try
368        {
369            final Charset cset = Charsets.getCharset( charset );
370            final CharBuffer buf = cset.decode(
371                ByteBuffer.wrap( bytes, off, count ) );
372 
373            if ( buf.hasArray() )
374            {
375                ret = String.valueOf( buf.array(), buf.arrayOffset(),
376                                      buf.length() );
377 
378            }
379            else
380            {
381                final char[] c = new char[ buf.length() ];
382                buf.rewind();
383                buf.get( c );
384                ret = String.valueOf( c );
385            }
386        }
387        catch ( final ClassNotFoundException e )
388        {
389            throw new AssertionError( e );
390        }
391        catch ( final InstantiationException e )
392        {
393            throw new AssertionError( e );
394        }
395        catch ( final IllegalAccessException e )
396        {
397            throw new AssertionError( e );
398        }
399        catch ( final IOException e )
400        {
401            throw new AssertionError( e );
402        }
403 
404        return ret;
405    }
406 
407    //----------------------------------------------------------------Charsets--
408}

[all classes][org.jdtaus.core.nio.util]
EMMA 2.1.5320 (stable) (C) Vladimir Roubtsov