001: /*
002: * FindBugs - Find Bugs in Java programs
003: * Copyright (C) 2006, University of Maryland
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019:
020: package edu.umd.cs.findbugs.util;
021:
022: import edu.umd.cs.findbugs.annotations.CheckForNull;
023: import edu.umd.cs.findbugs.classfile.DescriptorFactory;
024: import edu.umd.cs.findbugs.internalAnnotations.DottedClassName;
025: import edu.umd.cs.findbugs.internalAnnotations.SlashedClassName;
026:
027: /**
028: * Utility methods for working with class names.
029: *
030: * @author David Hovemeyer
031: */
032: public abstract class ClassName {
033:
034: public static String toSignature(@SlashedClassName
035: String className) {
036: if (className.charAt(0) == '[' || className.endsWith(";"))
037: return className;
038: return "L" + className + ";";
039: }
040:
041: public static @CheckForNull
042: String fromFieldSignature(String signature) {
043: if (signature.charAt(0) != 'L')
044: return null;
045: return signature.substring(1, signature.length() - 1);
046: }
047:
048: /**
049: *
050: * @param signature bytecode notated type name
051: * @return for reference types: class name without bytecode characters, otherwise
052: * unchanged signature
053: */
054: public static String fromSignature(String signature) {
055: if (signature.charAt(0) == '[') {
056: if (signature.charAt(signature.length() - 1) == ';') {
057: // [Ljava.lang.String; or [[Ljava.lang.String;
058: int start = 1;
059: while (signature.charAt(start) == '[') {
060: start++;
061: }
062: return signature.substring(start + 1, signature
063: .length() - 1);
064: } else {
065: // [Z
066: return signature; //signature.substring(start, signature.length());
067: }
068: }
069: return signature;
070: }
071:
072: /**
073: * Convert class name to slashed format.
074: * If the class name is already in slashed format,
075: * it is returned unmodified.
076: *
077: * @param className a class name
078: * @return the same class name in slashed format
079: */
080: public static @SlashedClassName
081: String toSlashedClassName(String className) {
082: if (className.indexOf('.') >= 0) {
083: return DescriptorFactory.canonicalizeString(className
084: .replace('.', '/'));
085: }
086: return className;
087: }
088:
089: /**
090: * Convert class name to dotted format.
091: * If the class name is already in dotted format,
092: * it is returned unmodified.
093: *
094: * @param className a class name
095: * @return the same class name in dotted format
096: */
097: public static String toDottedClassName(String className) {
098: if (className.indexOf('/') >= 0) {
099: className = DescriptorFactory.canonicalizeString(className
100: .replace('/', '.'));
101: }
102: return className;
103: }
104:
105: /**
106: * extract the package name from a dotted class name.
107: * Package names are always in dotted format.
108: *
109: * @param className a dotted class name
110: * @return the name of the package containing the class
111: */
112: public static @DottedClassName
113: String extractPackageName(@DottedClassName
114: String className) {
115: int i = className.lastIndexOf('.');
116: if (i < 0)
117: return "";
118: return className.substring(0, i);
119: }
120:
121: public static @DottedClassName
122: String extractSimpleName(@DottedClassName
123: String className) {
124: int i = className.lastIndexOf('.');
125: if (i < 0)
126: return className;
127: return className.substring(i + 1);
128: }
129:
130: /**
131: * Return whether or not the given class name is valid.
132: *
133: * @param className a possible class name
134: * @return true if it's a valid class name, false otherwise
135: */
136: public static boolean isValidClassName(String className) {
137: // FIXME: should use a regex
138:
139: if (className.indexOf('(') >= 0) {
140: return false;
141: }
142: return true;
143: }
144:
145: /**
146: * Does a class name appear to designate an anonymous class?
147: * Only the name is analyzed. No classes are loaded or looked up.
148: *
149: * @param className class name, slashed or dotted, fully qualified or unqualified
150: * @return true if className is the name of an anonymous class
151: */
152: public static boolean isAnonymous(String className) {
153: int i = className.lastIndexOf('$');
154: if (i >= 0 && i + 1 < className.length()) {
155: return Character.isDigit(className.charAt(i + 1));
156: }
157: return false;
158: }
159:
160: }
|