1/* 2 * Copyright (c) 2015, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24package compiler.compilercontrol.share.method; 25 26import java.lang.reflect.Executable; 27import java.util.Arrays; 28import java.util.stream.Collectors; 29 30/** 31 * Element represents class in method descriptor 32 * that consist from class package and class itself 33 */ 34public class ClassType extends MethodElementType { 35 private final String[] packageDirs; 36 private final Class<?> aClass; 37 private boolean setPackage; 38 39 public ClassType(Executable method) { 40 // Use pack/subpack/Class::method separators style 41 super(MethodDescriptor.Separator.SLASH); 42 // Get package 43 aClass = method.getDeclaringClass(); 44 Package aPackage = method.getDeclaringClass().getPackage(); 45 if (aPackage != null) { 46 // split into directories 47 packageDirs = aPackage.getName().split("\\."); 48 } else { 49 packageDirs = null; 50 } 51 setPackage = true; 52 buildElement(setPackage); 53 } 54 55 @Override 56 public boolean isValid() { 57 if (element.isEmpty()) { 58 return false; 59 } 60 boolean separatorMet = false; 61 char separatorChar = 0; 62 char[] charArray = element.toCharArray(); 63 for (int i = 0; i < charArray.length; i++) { 64 char ch = charArray[i]; 65 switch (ch) { 66 case '/': 67 case '.': 68 if (separatorMet) { 69 if (ch != separatorChar) { 70 // there are two different separators 71 return false; 72 } 73 } else { 74 separatorChar = ch; 75 separatorMet = true; 76 } 77 break; 78 case ':': 79 if (++i != charArray.length) { 80 if (charArray[i] == ':') { 81 // :: is invalid separator 82 separator = MethodDescriptor.Separator.DOUBLECOLON; 83 return false; 84 } 85 } 86 break; 87 // Invalid separators 88 case ',': 89 case ' ': 90 return false; 91 } 92 } 93 // set correct separator 94 switch (separatorChar) { 95 case '.': 96 separator = MethodDescriptor.Separator.DOT; 97 break; 98 case '/': 99 separator = MethodDescriptor.Separator.SLASH; 100 break; 101 default: 102 separator = MethodDescriptor.Separator.NONE; 103 break; 104 } 105 return super.isValid(); 106 } 107 108 @Override 109 public void setSeparator(MethodDescriptor.Separator separator) { 110 this.separator = separator; 111 buildElement(setPackage); 112 } 113 114 @Override 115 public void setPattern(MethodDescriptor.PatternType patternType) { 116 switch (patternType) { 117 case EXACT: 118 break; 119 case PREFIX: 120 // For prefix pattern use only class name without package 121 buildElement(false); 122 regexp = ".*" + regexp; 123 element = "*" + element; 124 break; 125 case ANY: 126 regexp = ".*"; 127 element = "*"; 128 break; 129 case SUFFIX: 130 regexp = regexp + ".*"; 131 element = element + "*"; 132 break; 133 case SUBSTRING: 134 setPattern(MethodDescriptor.PatternType.PREFIX); 135 setPattern(MethodDescriptor.PatternType.SUFFIX); 136 break; 137 default: 138 throw new IllegalArgumentException("ERROR: wrong pattern type " 139 + patternType); 140 } 141 } 142 143 /** 144 * Builds element string and regexp. 145 * 146 * @param setPackage shows that element should have a package name 147 */ 148 private void buildElement(boolean setPackage) { 149 this.setPackage = setPackage; 150 StringBuilder elementBuilder = new StringBuilder(); 151 if (packageDirs != null && setPackage) { 152 elementBuilder.append(Arrays.stream(packageDirs) 153 .collect(Collectors.joining(separator.symbol))); 154 elementBuilder.append(separator.symbol); 155 } 156 String className = aClass.getSimpleName(); 157 if (setPackage) { 158 // Add outer classes if any 159 Class<?> enclosingClass = aClass.getEnclosingClass(); 160 while (enclosingClass != null) { 161 className = enclosingClass.getSimpleName() + "$" + className; 162 enclosingClass = enclosingClass.getEnclosingClass(); 163 } 164 } 165 elementBuilder.append(className); 166 element = elementBuilder.toString(); 167 if (separator == MethodDescriptor.Separator.DOT) { 168 // Replace . with / to make regexp look like CommandSignature 169 regexp = element.replace(".", "/"); 170 } else { 171 regexp = element; 172 } 173 regexp = regexp.replace("$", "\\$"); 174 } 175} 176