/*
* Copyright 2009-2012 Michael Dalton
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jtaint;
/** Klass represents a Java class that may be instrumented at runtime. We
* identify classes by their full name (for example, java.lang.String).
* We further divide Klasses into two types: exact, which are only
* instrumented if a loaded class exactly matches the name of our Klass object,
* and inexact, where we instrument any class that has a method with the
* type name and signature of a security-relevant method in our Klass.
* In the latter case, we ensure that such instrumentation performs runtime
* type checks so that any security operations occur only if the class is
* assignment compatible with Klass's name.
*
* Exact classes are used when we know the user will not subclass or override
* the class in question (for example, when instrumenting
* java.servlet.http.HttpUtils, where we instrument only static methods).
* In other cases, for safety reasons, we must instrument arbitrary classes
* that may be subclassing a security-relevant class, determining only at
* runtime if they are truly a subclass or just a false positive. We can't
* tell at load time as the JVM may not have loaded their parent class
* before the defineClass method is called in java.lang.ClassLoader.
*/
final class Klass
{
private final String name;
private final boolean isExact;
public Klass(String name, boolean isExact) {
this.name = name;
this.isExact = isExact;
}
public Klass(String name) {
this(name, false);
}
public boolean isExact() { return isExact; }
public String name() { return name; }
public String internalName() {
return name.replace('.', '/');
}
public String simpleName() {
return name.substring(name.lastIndexOf('.') + 1);
}
public String toString() { return name; }
}