src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 52220 9c260a6b6471
child 58679 9c3209ff7550
equal deleted inserted replaced
58677:13588c901957 58678:9cf78a70fa4f
     1 /*
     1 /*
     2  * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    39  *
    39  *
    40  * @author  Josh Bloch
    40  * @author  Josh Bloch
    41  * @since   1.5
    41  * @since   1.5
    42  */
    42  */
    43 class AnnotationInvocationHandler implements InvocationHandler, Serializable {
    43 class AnnotationInvocationHandler implements InvocationHandler, Serializable {
       
    44     @java.io.Serial
    44     private static final long serialVersionUID = 6182022883658399397L;
    45     private static final long serialVersionUID = 6182022883658399397L;
    45     private final Class<? extends Annotation> type;
    46     private final Class<? extends Annotation> type;
       
    47     @SuppressWarnings("serial") // Not statically typed as Serializable
    46     private final Map<String, Object> memberValues;
    48     private final Map<String, Object> memberValues;
    47 
    49 
    48     AnnotationInvocationHandler(Class<? extends Annotation> type, Map<String, Object> memberValues) {
    50     AnnotationInvocationHandler(Class<? extends Annotation> type, Map<String, Object> memberValues) {
    49         Class<?>[] superInterfaces = type.getInterfaces();
    51         Class<?>[] superInterfaces = type.getInterfaces();
    50         if (!type.isAnnotation() ||
    52         if (!type.isAnnotation() ||
   143         StringBuilder result = new StringBuilder(128);
   145         StringBuilder result = new StringBuilder(128);
   144         result.append('@');
   146         result.append('@');
   145         result.append(type.getName());
   147         result.append(type.getName());
   146         result.append('(');
   148         result.append('(');
   147         boolean firstMember = true;
   149         boolean firstMember = true;
   148         for (Map.Entry<String, Object> e : memberValues.entrySet()) {
   150         Set<Map.Entry<String, Object>> entries = memberValues.entrySet();
       
   151         boolean loneValue = entries.size() == 1;
       
   152         for (Map.Entry<String, Object> e : entries) {
   149             if (firstMember)
   153             if (firstMember)
   150                 firstMember = false;
   154                 firstMember = false;
   151             else
   155             else
   152                 result.append(", ");
   156                 result.append(", ");
   153 
   157 
   154             result.append(e.getKey());
   158             String key = e.getKey();
   155             result.append('=');
   159             if (!loneValue || !"value".equals(key)) {
       
   160                 result.append(key);
       
   161                 result.append('=');
       
   162             }
       
   163             loneValue = false;
   156             result.append(memberValueToString(e.getValue()));
   164             result.append(memberValueToString(e.getValue()));
   157         }
   165         }
   158         result.append(')');
   166         result.append(')');
   159         return result.toString();
   167         return result.toString();
   160     }
   168     }
   176                 return  toSourceString((double) value);
   184                 return  toSourceString((double) value);
   177             else if (type == Float.class)
   185             else if (type == Float.class)
   178                 return  toSourceString((float) value);
   186                 return  toSourceString((float) value);
   179             else if (type == Long.class)
   187             else if (type == Long.class)
   180                 return  toSourceString((long) value);
   188                 return  toSourceString((long) value);
       
   189             else if (type == Byte.class)
       
   190                 return  toSourceString((byte) value);
   181             else
   191             else
   182                 return value.toString();
   192                 return value.toString();
   183         } else {
   193         } else {
   184             Stream<String> stringStream;
   194             Stream<String> stringStream;
   185             if (type == byte[].class)
   195             if (type == byte[].class)
   219      * Translates a Class value to a form suitable for use in the
   229      * Translates a Class value to a form suitable for use in the
   220      * string representation of an annotation.
   230      * string representation of an annotation.
   221      */
   231      */
   222     private static String toSourceString(Class<?> clazz) {
   232     private static String toSourceString(Class<?> clazz) {
   223         Class<?> finalComponent = clazz;
   233         Class<?> finalComponent = clazz;
   224         StringBuilder arrayBackets = new StringBuilder();
   234         StringBuilder arrayBrackets = new StringBuilder();
   225 
   235 
   226         while(finalComponent.isArray()) {
   236         while(finalComponent.isArray()) {
   227             finalComponent = finalComponent.getComponentType();
   237             finalComponent = finalComponent.getComponentType();
   228             arrayBackets.append("[]");
   238             arrayBrackets.append("[]");
   229         }
   239         }
   230 
   240 
   231         return finalComponent.getName() + arrayBackets.toString() + ".class" ;
   241         return finalComponent.getName() + arrayBrackets.toString() + ".class";
   232     }
   242     }
   233 
   243 
   234     private static String toSourceString(float f) {
   244     private static String toSourceString(float f) {
   235         if (Float.isFinite(f))
   245         if (Float.isFinite(f))
   236             return Float.toString(f) + "f" ;
   246             return Float.toString(f) + "f" ;
   254     }
   264     }
   255 
   265 
   256     private static String toSourceString(char c) {
   266     private static String toSourceString(char c) {
   257         StringBuilder sb = new StringBuilder(4);
   267         StringBuilder sb = new StringBuilder(4);
   258         sb.append('\'');
   268         sb.append('\'');
   259         if (c == '\'')
   269         sb.append(quote(c));
   260             sb.append("\\'");
   270         return sb.append('\'') .toString();
   261         else
   271     }
   262             sb.append(c);
   272 
   263         return sb.append('\'')
   273     /**
   264                 .toString();
   274      * Escapes a character if it has an escape sequence or is
       
   275      * non-printable ASCII.  Leaves non-ASCII characters alone.
       
   276      */
       
   277     private static String quote(char ch) {
       
   278         switch (ch) {
       
   279         case '\b':  return "\\b";
       
   280         case '\f':  return "\\f";
       
   281         case '\n':  return "\\n";
       
   282         case '\r':  return "\\r";
       
   283         case '\t':  return "\\t";
       
   284         case '\'':  return "\\'";
       
   285         case '\"':  return "\\\"";
       
   286         case '\\':  return "\\\\";
       
   287         default:
       
   288             return (isPrintableAscii(ch))
       
   289                 ? String.valueOf(ch)
       
   290                 : String.format("\\u%04x", (int) ch);
       
   291         }
       
   292     }
       
   293 
       
   294     /**
       
   295      * Is a character printable ASCII?
       
   296      */
       
   297     private static boolean isPrintableAscii(char ch) {
       
   298         return ch >= ' ' && ch <= '~';
       
   299     }
       
   300 
       
   301     private static String toSourceString(byte b) {
       
   302         return String.format("(byte)0x%02x", b);
   265     }
   303     }
   266 
   304 
   267     private static String toSourceString(long ell) {
   305     private static String toSourceString(long ell) {
   268         String str = String.valueOf(ell);
   306         return String.valueOf(ell) + "L";
   269         return (ell < Integer.MIN_VALUE || ell > Integer.MAX_VALUE)
       
   270                 ? (str + 'L') : str;
       
   271     }
   307     }
   272 
   308 
   273     /**
   309     /**
   274      * Return a string suitable for use in the string representation
   310      * Return a string suitable for use in the string representation
   275      * of an annotation.
   311      * of an annotation.
   276      */
   312      */
   277     private static String toSourceString(String s) {
   313     private static String toSourceString(String s) {
   278         StringBuilder sb = new StringBuilder();
   314         StringBuilder sb = new StringBuilder();
   279         sb.append('"');
   315         sb.append('"');
   280         // Escape embedded quote characters, if present, but don't do
   316         for (int i = 0; i < s.length(); i++) {
   281         // anything more heroic.
   317             sb.append(quote(s.charAt(i)));
   282         sb.append(s.replace("\"", "\\\""));
   318         }
   283         sb.append('"');
   319         sb.append('"');
   284         return sb.toString();
   320         return sb.toString();
   285     }
   321     }
   286 
   322 
   287     private static Stream<String> convert(byte[] values) {
   323     private static Stream<String> convert(byte[] values) {
   288         List<String> list = new ArrayList<>(values.length);
   324         List<String> list = new ArrayList<>(values.length);
   289         for (byte b : values)
   325         for (byte b : values)
   290             list.add(Byte.toString(b));
   326             list.add(toSourceString(b));
   291         return list.stream();
   327         return list.stream();
   292     }
   328     }
   293 
   329 
   294     private static Stream<String> convert(char[] values) {
   330     private static Stream<String> convert(char[] values) {
   295         List<String> list = new ArrayList<>(values.length);
   331         List<String> list = new ArrayList<>(values.length);
   567         if (type == boolean[].class)
   603         if (type == boolean[].class)
   568             return Arrays.hashCode((boolean[]) value);
   604             return Arrays.hashCode((boolean[]) value);
   569         return Arrays.hashCode((Object[]) value);
   605         return Arrays.hashCode((Object[]) value);
   570     }
   606     }
   571 
   607 
       
   608     @java.io.Serial
   572     private void readObject(java.io.ObjectInputStream s)
   609     private void readObject(java.io.ObjectInputStream s)
   573         throws java.io.IOException, ClassNotFoundException {
   610         throws java.io.IOException, ClassNotFoundException {
   574         ObjectInputStream.GetField fields = s.readFields();
   611         ObjectInputStream.GetField fields = s.readFields();
   575 
   612 
   576         @SuppressWarnings("unchecked")
   613         @SuppressWarnings("unchecked")