< prev index next >

src/java.base/share/classes/java/nio/charset/Charset.java

Print this page

  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 package java.nio.charset;
 27 

 28 import jdk.internal.misc.VM;
 29 import sun.nio.cs.ThreadLocalCoders;
 30 import sun.security.action.GetPropertyAction;
 31 
 32 import java.nio.ByteBuffer;
 33 import java.nio.CharBuffer;
 34 import java.nio.charset.spi.CharsetProvider;
 35 import java.security.AccessController;
 36 import java.security.PrivilegedAction;
 37 import java.util.Arrays;
 38 import java.util.Collections;
 39 import java.util.HashSet;
 40 import java.util.Iterator;
 41 import java.util.Locale;
 42 import java.util.Map;
 43 import java.util.NoSuchElementException;
 44 import java.util.Objects;
 45 import java.util.ServiceConfigurationError;
 46 import java.util.ServiceLoader;
 47 import java.util.Set;

353 
354                 public boolean hasNext() {
355                     return getNext();
356                 }
357 
358                 public CharsetProvider next() {
359                     if (!getNext())
360                         throw new NoSuchElementException();
361                     CharsetProvider n = next;
362                     next = null;
363                     return n;
364                 }
365 
366                 public void remove() {
367                     throw new UnsupportedOperationException();
368                 }
369 
370             };
371     }
372 
373     // Thread-local gate to prevent recursive provider lookups
374     private static ThreadLocal<ThreadLocal<?>> gate =
375             new ThreadLocal<ThreadLocal<?>>();
376 
377     @SuppressWarnings("removal")
378     private static Charset lookupViaProviders(final String charsetName) {
379 
380         // The runtime startup sequence looks up standard charsets as a
381         // consequence of the VM's invocation of System.initializeSystemClass
382         // in order to, e.g., set system properties and encode filenames.  At
383         // that point the application class loader has not been initialized,
384         // however, so we can't look for providers because doing so will cause
385         // that loader to be prematurely initialized with incomplete
386         // information.
387         //
388         if (!VM.isBooted())
389             return null;
390 
391         if (gate.get() != null)
392             // Avoid recursive provider lookups
393             return null;
394         try {
395             gate.set(gate);
396 
397             return AccessController.doPrivileged(
398                 new PrivilegedAction<>() {
399                     public Charset run() {
400                         for (Iterator<CharsetProvider> i = providers();
401                              i.hasNext();) {
402                             CharsetProvider cp = i.next();
403                             Charset cs = cp.charsetForName(charsetName);
404                             if (cs != null)
405                                 return cs;
406                         }
407                         return null;
408                     }
409                 });
410 
411         } finally {
412             gate.set(null);
413         }
414     }
415 
416     /* The extended set of charsets */
417     private static class ExtendedProviderHolder {
418         static final CharsetProvider[] extendedProviders = extendedProviders();
419         // returns ExtendedProvider, if installed
420         @SuppressWarnings("removal")
421         private static CharsetProvider[] extendedProviders() {
422             return AccessController.doPrivileged(new PrivilegedAction<>() {
423                     public CharsetProvider[] run() {
424                         CharsetProvider[] cps = new CharsetProvider[1];
425                         int n = 0;
426                         ServiceLoader<CharsetProvider> sl =
427                             ServiceLoader.loadInstalled(CharsetProvider.class);
428                         for (CharsetProvider cp : sl) {
429                             if (n + 1 > cps.length) {
430                                 cps = Arrays.copyOf(cps, cps.length << 1);
431                             }
432                             cps[n++] = cp;

796      *
797      * <pre>
798      *     cs.newDecoder()
799      *       .onMalformedInput(CodingErrorAction.REPLACE)
800      *       .onUnmappableCharacter(CodingErrorAction.REPLACE)
801      *       .decode(bb); </pre>
802      *
803      * except that it is potentially more efficient because it can cache
804      * decoders between successive invocations.
805      *
806      * <p> This method always replaces malformed-input and unmappable-character
807      * sequences with this charset's default replacement byte array.  In order
808      * to detect such sequences, use the {@link
809      * CharsetDecoder#decode(java.nio.ByteBuffer)} method directly.  </p>
810      *
811      * @param  bb  The byte buffer to be decoded
812      *
813      * @return  A char buffer containing the decoded characters
814      */
815     public final CharBuffer decode(ByteBuffer bb) {






816         try {
817             return ThreadLocalCoders.decoderFor(this)
818                 .onMalformedInput(CodingErrorAction.REPLACE)
819                 .onUnmappableCharacter(CodingErrorAction.REPLACE)
820                 .decode(bb);
821         } catch (CharacterCodingException x) {
822             throw new Error(x);         // Can't happen
823         }
824     }
825 
826     /**
827      * Convenience method that encodes Unicode characters into bytes in this
828      * charset.
829      *
830      * <p> An invocation of this method upon a charset {@code cs} returns the
831      * same result as the expression
832      *
833      * <pre>
834      *     cs.newEncoder()
835      *       .onMalformedInput(CodingErrorAction.REPLACE)
836      *       .onUnmappableCharacter(CodingErrorAction.REPLACE)
837      *       .encode(bb); </pre>
838      *
839      * except that it is potentially more efficient because it can cache
840      * encoders between successive invocations.
841      *
842      * <p> This method always replaces malformed-input and unmappable-character
843      * sequences with this charset's default replacement string.  In order to
844      * detect such sequences, use the {@link
845      * CharsetEncoder#encode(java.nio.CharBuffer)} method directly.  </p>
846      *
847      * @param  cb  The char buffer to be encoded
848      *
849      * @return  A byte buffer containing the encoded characters
850      */
851     public final ByteBuffer encode(CharBuffer cb) {






852         try {
853             return ThreadLocalCoders.encoderFor(this)
854                 .onMalformedInput(CodingErrorAction.REPLACE)
855                 .onUnmappableCharacter(CodingErrorAction.REPLACE)
856                 .encode(cb);
857         } catch (CharacterCodingException x) {
858             throw new Error(x);         // Can't happen
859         }
860     }
861 
862     /**
863      * Convenience method that encodes a string into bytes in this charset.
864      *
865      * <p> An invocation of this method upon a charset {@code cs} returns the
866      * same result as the expression
867      *
868      * <pre>
869      *     cs.encode(CharBuffer.wrap(s)); </pre>
870      *
871      * @param  str  The string to be encoded
872      *
873      * @return  A byte buffer containing the encoded characters
874      */

  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 package java.nio.charset;
 27 
 28 import jdk.internal.misc.Gate;
 29 import jdk.internal.misc.VM;
 30 import sun.nio.cs.ThreadLocalCoders;
 31 import sun.security.action.GetPropertyAction;
 32 
 33 import java.nio.ByteBuffer;
 34 import java.nio.CharBuffer;
 35 import java.nio.charset.spi.CharsetProvider;
 36 import java.security.AccessController;
 37 import java.security.PrivilegedAction;
 38 import java.util.Arrays;
 39 import java.util.Collections;
 40 import java.util.HashSet;
 41 import java.util.Iterator;
 42 import java.util.Locale;
 43 import java.util.Map;
 44 import java.util.NoSuchElementException;
 45 import java.util.Objects;
 46 import java.util.ServiceConfigurationError;
 47 import java.util.ServiceLoader;
 48 import java.util.Set;

354 
355                 public boolean hasNext() {
356                     return getNext();
357                 }
358 
359                 public CharsetProvider next() {
360                     if (!getNext())
361                         throw new NoSuchElementException();
362                     CharsetProvider n = next;
363                     next = null;
364                     return n;
365                 }
366 
367                 public void remove() {
368                     throw new UnsupportedOperationException();
369                 }
370 
371             };
372     }
373 
374     // gate to prevent recursive provider lookups
375     private static final Gate LOOKUP_GATE = Gate.create();

376 
377     @SuppressWarnings("removal")
378     private static Charset lookupViaProviders(final String charsetName) {
379 
380         // The runtime startup sequence looks up standard charsets as a
381         // consequence of the VM's invocation of System.initializeSystemClass
382         // in order to, e.g., set system properties and encode filenames.  At
383         // that point the application class loader has not been initialized,
384         // however, so we can't look for providers because doing so will cause
385         // that loader to be prematurely initialized with incomplete
386         // information.
387         //
388         if (!VM.isBooted())
389             return null;
390 
391         if (!LOOKUP_GATE.tryEnter())
392             // Avoid recursive provider lookups
393             return null;
394         try {


395             return AccessController.doPrivileged(
396                 new PrivilegedAction<>() {
397                     public Charset run() {
398                         for (Iterator<CharsetProvider> i = providers();
399                              i.hasNext();) {
400                             CharsetProvider cp = i.next();
401                             Charset cs = cp.charsetForName(charsetName);
402                             if (cs != null)
403                                 return cs;
404                         }
405                         return null;
406                     }
407                 });
408 
409         } finally {
410             LOOKUP_GATE.exit();
411         }
412     }
413 
414     /* The extended set of charsets */
415     private static class ExtendedProviderHolder {
416         static final CharsetProvider[] extendedProviders = extendedProviders();
417         // returns ExtendedProvider, if installed
418         @SuppressWarnings("removal")
419         private static CharsetProvider[] extendedProviders() {
420             return AccessController.doPrivileged(new PrivilegedAction<>() {
421                     public CharsetProvider[] run() {
422                         CharsetProvider[] cps = new CharsetProvider[1];
423                         int n = 0;
424                         ServiceLoader<CharsetProvider> sl =
425                             ServiceLoader.loadInstalled(CharsetProvider.class);
426                         for (CharsetProvider cp : sl) {
427                             if (n + 1 > cps.length) {
428                                 cps = Arrays.copyOf(cps, cps.length << 1);
429                             }
430                             cps[n++] = cp;

794      *
795      * <pre>
796      *     cs.newDecoder()
797      *       .onMalformedInput(CodingErrorAction.REPLACE)
798      *       .onUnmappableCharacter(CodingErrorAction.REPLACE)
799      *       .decode(bb); </pre>
800      *
801      * except that it is potentially more efficient because it can cache
802      * decoders between successive invocations.
803      *
804      * <p> This method always replaces malformed-input and unmappable-character
805      * sequences with this charset's default replacement byte array.  In order
806      * to detect such sequences, use the {@link
807      * CharsetDecoder#decode(java.nio.ByteBuffer)} method directly.  </p>
808      *
809      * @param  bb  The byte buffer to be decoded
810      *
811      * @return  A char buffer containing the decoded characters
812      */
813     public final CharBuffer decode(ByteBuffer bb) {
814         CharsetDecoder decoder;
815         if (Thread.currentThread().isVirtual()) {
816             decoder = newDecoder();
817         } else {
818             decoder = ThreadLocalCoders.decoderFor(this);
819         }
820         try {
821             return decoder.onMalformedInput(CodingErrorAction.REPLACE)

822                 .onUnmappableCharacter(CodingErrorAction.REPLACE)
823                 .decode(bb);
824         } catch (CharacterCodingException x) {
825             throw new Error(x);         // Can't happen
826         }
827     }
828 
829     /**
830      * Convenience method that encodes Unicode characters into bytes in this
831      * charset.
832      *
833      * <p> An invocation of this method upon a charset {@code cs} returns the
834      * same result as the expression
835      *
836      * <pre>
837      *     cs.newEncoder()
838      *       .onMalformedInput(CodingErrorAction.REPLACE)
839      *       .onUnmappableCharacter(CodingErrorAction.REPLACE)
840      *       .encode(bb); </pre>
841      *
842      * except that it is potentially more efficient because it can cache
843      * encoders between successive invocations.
844      *
845      * <p> This method always replaces malformed-input and unmappable-character
846      * sequences with this charset's default replacement string.  In order to
847      * detect such sequences, use the {@link
848      * CharsetEncoder#encode(java.nio.CharBuffer)} method directly.  </p>
849      *
850      * @param  cb  The char buffer to be encoded
851      *
852      * @return  A byte buffer containing the encoded characters
853      */
854     public final ByteBuffer encode(CharBuffer cb) {
855         CharsetEncoder encoder;
856         if (Thread.currentThread().isVirtual()) {
857             encoder = newEncoder();
858         } else {
859             encoder = ThreadLocalCoders.encoderFor(this);
860         }
861         try {
862             return encoder.onMalformedInput(CodingErrorAction.REPLACE)

863                 .onUnmappableCharacter(CodingErrorAction.REPLACE)
864                 .encode(cb);
865         } catch (CharacterCodingException x) {
866             throw new Error(x);         // Can't happen
867         }
868     }
869 
870     /**
871      * Convenience method that encodes a string into bytes in this charset.
872      *
873      * <p> An invocation of this method upon a charset {@code cs} returns the
874      * same result as the expression
875      *
876      * <pre>
877      *     cs.encode(CharBuffer.wrap(s)); </pre>
878      *
879      * @param  str  The string to be encoded
880      *
881      * @return  A byte buffer containing the encoded characters
882      */
< prev index next >