55 * validates a member name
56 * @param name the name of the member
57 * @return the name passed if valid
58 */
59 public static String validateMemberName(String name) {
60 requireNonNull(name);
61 if (name.length() == 0)
62 throw new IllegalArgumentException("zero-length member name");
63 for (int i=0; i<name.length(); i++) {
64 char ch = name.charAt(i);
65 if (ch == '.' || ch == ';' || ch == '[' || ch == '/')
66 throw new IllegalArgumentException("Invalid member name: " + name);
67 if (ch == '<' || ch == '>') {
68 if (!pointyNames.contains(name))
69 throw new IllegalArgumentException("Invalid member name: " + name);
70 }
71 }
72 return name;
73 }
74
75 static void validateClassOrInterface(ClassDesc clazz) {
76 if (!clazz.isClassOrInterface())
77 throw new IllegalArgumentException("not a class or interface type: " + clazz);
78 }
79
80 static int arrayDepth(String descriptorString) {
81 int depth = 0;
82 while (descriptorString.charAt(depth) == '[')
83 depth++;
84 return depth;
85 }
86
87 static String binaryToInternal(String name) {
88 return name.replace('.', '/');
89 }
90
91 static String internalToBinary(String name) {
92 return name.replace('/', '.');
93 }
94
95 static String dropLastChar(String s) {
96 return s.substring(0, s.length() - 1);
97 }
98
99 static String dropFirstAndLastChar(String s) {
100 return s.substring(1, s.length() - 1);
101 }
102
103 /**
104 * Produce an {@code Optional<DynamicConstantDesc<T>>} describing the invocation
105 * of the specified bootstrap with the specified arguments. The arguments will
106 * be converted to nominal descriptors using the provided lookup. Helper
107 * method for implementing {@link Constable#describeConstable()}.
108 *
109 * @param <T> the type of the resulting constant
110 * @param bootstrap nominal descriptor for the bootstrap method
111 * @param type nominal descriptor for the type of the resulting constant
112 * @param args nominal descriptors for the bootstrap arguments
113 * @return the nominal descriptor for the dynamic constant
114 */
115 public static<T> Optional<DynamicConstantDesc<T>> symbolizeHelper(MethodHandleDesc bootstrap,
116 ClassDesc type,
117 Constable<?>... args) {
118 requireNonNull(bootstrap);
119 requireNonNull(type);
120 requireNonNull(args);
121 try {
122 ConstantDesc<?>[] quotedArgs = new ConstantDesc<?>[args.length + 1];
123 quotedArgs[0] = bootstrap;
124 for (int i=0; i<args.length; i++)
125 quotedArgs[i+1] = args[i].describeConstable().orElseThrow();
126 return Optional.of(DynamicConstantDesc.ofNamed(ConstantDescs.BSM_INVOKE,
127 ConstantDescs.DEFAULT_NAME,
128 type, quotedArgs));
129 }
130 catch (NoSuchElementException e) {
131 return Optional.empty();
132 }
133 }
134
135 /**
136 * Parse a method descriptor string, and return a list of field descriptor
137 * strings, return type first, then parameter types
138 *
139 * @param descriptor the descriptor string
140 * @return the list of types
141 * @throws IllegalArgumentException if the descriptor string is not valid
142 */
143 static List<String> parseMethodDescriptor(String descriptor) {
144 int cur = 0, end = descriptor.length();
145 ArrayList<String> ptypes = new ArrayList<>();
146
147 if (cur >= end || descriptor.charAt(cur) != '(')
148 throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
149
150 ++cur; // skip '('
151 while (cur < end && descriptor.charAt(cur) != ')') {
152 int len = matchSig(descriptor, cur, end);
153 if (len == 0 || descriptor.charAt(cur) == 'V')
154 throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
155 ptypes.add(descriptor.substring(cur, cur + len));
|
55 * validates a member name
56 * @param name the name of the member
57 * @return the name passed if valid
58 */
59 public static String validateMemberName(String name) {
60 requireNonNull(name);
61 if (name.length() == 0)
62 throw new IllegalArgumentException("zero-length member name");
63 for (int i=0; i<name.length(); i++) {
64 char ch = name.charAt(i);
65 if (ch == '.' || ch == ';' || ch == '[' || ch == '/')
66 throw new IllegalArgumentException("Invalid member name: " + name);
67 if (ch == '<' || ch == '>') {
68 if (!pointyNames.contains(name))
69 throw new IllegalArgumentException("Invalid member name: " + name);
70 }
71 }
72 return name;
73 }
74
75 /**
76 * validates a bootstrap method: must have a leading Lookup parameter, or else be a valid expression-mode BSM
77 * @param bootstrapMethod the method to validate
78 * @param constantName the name associated with the proposed {@code CONSTANT_Dynamic} constant
79 * @return the method passed if valid
80 */
81 public static DirectMethodHandleDesc validateBootstrapMethod(DirectMethodHandleDesc bootstrapMethod, String constantName) {
82 if (hasLeadingLookupParameter(bootstrapMethod)) return bootstrapMethod;
83 switch (constantName) {
84 case ConstantDescs.INVOKE_NAME:
85 case ConstantDescs.SYMBOLIC_NAME:
86 return bootstrapMethod;
87 }
88 throw new IllegalArgumentException("Invalid bootstrap method: " + bootstrapMethod + " with reserved invocation name " + constantName);
89 }
90
91 /**
92 * validates an expression-mode bootstrap method: must not have a leading Lookup parameter
93 * @param bootstrapMethod the method to validate
94 * @param constantName the name associated with the proposed {@code CONSTANT_Dynamic} constant
95 * @return the method passed if valid
96 */
97 public static DirectMethodHandleDesc validateExpressionModeBootstrapMethod(DirectMethodHandleDesc bootstrapMethod, String constantName) {
98 if (hasLeadingLookupParameter(bootstrapMethod)) {
99 throw new IllegalArgumentException("Bootstrap method has leading Lookup parameter: " + bootstrapMethod);
100 }
101 return validateBootstrapMethod(bootstrapMethod, constantName);
102 }
103
104 private static boolean hasLeadingLookupParameter(DirectMethodHandleDesc bootstrapMethod) {
105 MethodTypeDesc type = bootstrapMethod.methodType();
106 return (type.parameterCount() > 0 && type.parameterType(0).equals(ConstantDescs.CR_MethodHandles_Lookup));
107 }
108
109 static void validateClassOrInterface(ClassDesc clazz) {
110 if (!clazz.isClassOrInterface())
111 throw new IllegalArgumentException("not a class or interface type: " + clazz);
112 }
113
114 static int arrayDepth(String descriptorString) {
115 int depth = 0;
116 while (descriptorString.charAt(depth) == '[')
117 depth++;
118 return depth;
119 }
120
121 static String binaryToInternal(String name) {
122 return name.replace('.', '/');
123 }
124
125 static String internalToBinary(String name) {
126 return name.replace('/', '.');
127 }
128
129 static String dropLastChar(String s) {
130 return s.substring(0, s.length() - 1);
131 }
132
133 static String dropFirstAndLastChar(String s) {
134 return s.substring(1, s.length() - 1);
135 }
136
137 /**
138 * Parse a method descriptor string, and return a list of field descriptor
139 * strings, return type first, then parameter types
140 *
141 * @param descriptor the descriptor string
142 * @return the list of types
143 * @throws IllegalArgumentException if the descriptor string is not valid
144 */
145 static List<String> parseMethodDescriptor(String descriptor) {
146 int cur = 0, end = descriptor.length();
147 ArrayList<String> ptypes = new ArrayList<>();
148
149 if (cur >= end || descriptor.charAt(cur) != '(')
150 throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
151
152 ++cur; // skip '('
153 while (cur < end && descriptor.charAt(cur) != ')') {
154 int len = matchSig(descriptor, cur, end);
155 if (len == 0 || descriptor.charAt(cur) == 'V')
156 throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
157 ptypes.add(descriptor.substring(cur, cur + len));
|