pax_global_header00006660000000000000000000000064121070377220014513gustar00rootroot0000000000000052 comment=ccb5d2479c7e20ee9f8a99abae164e5be49a4d08 access-modifier-access-modifier-1.4/000077500000000000000000000000001210703772200174475ustar00rootroot00000000000000access-modifier-access-modifier-1.4/.gitignore000066400000000000000000000000311210703772200214310ustar00rootroot00000000000000target *.iml *.ipr *.iws access-modifier-access-modifier-1.4/README000066400000000000000000000006051210703772200203300ustar00rootroot00000000000000Allows applications to define custom access modifiers programmatically, to be enforced at compile time in the opt-in basis. Obviously, there's no runtime check either --- this is strictly a voluntary annotations. This mechanism is useful for actually making sure that deprecated features are not used (without actually removing such declarations, which would break binary compatibility.) access-modifier-access-modifier-1.4/access-modifier-annotation/000077500000000000000000000000001210703772200246545ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-annotation/pom.xml000066400000000000000000000015271210703772200261760ustar00rootroot00000000000000 4.0.0 access-modifier org.kohsuke 1.4 access-modifier-annotation Custom Acess Modifier annotations org.jenkins-ci annotation-indexer 1.4 junit junit 3.8.1 test access-modifier-access-modifier-1.4/access-modifier-annotation/src/000077500000000000000000000000001210703772200254435ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-annotation/src/main/000077500000000000000000000000001210703772200263675ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-annotation/src/main/java/000077500000000000000000000000001210703772200273105ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-annotation/src/main/java/org/000077500000000000000000000000001210703772200300775ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-annotation/src/main/java/org/kohsuke/000077500000000000000000000000001210703772200315505ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-annotation/src/main/java/org/kohsuke/accmod/000077500000000000000000000000001210703772200327765ustar00rootroot00000000000000AccessRestriction.java000066400000000000000000000070601210703772200372140ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-annotation/src/main/java/org/kohsuke/accmod/* * The MIT License * * Copyright (c) 2010, Kohsuke Kawaguchi * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.kohsuke.accmod; import org.kohsuke.accmod.impl.ErrorListener; import org.kohsuke.accmod.impl.Location; import org.kohsuke.accmod.impl.RestrictedElement; import org.kohsuke.accmod.restrictions.None; /** * Access restriction policy — determines what access is OK and what are not. * *

* The subtype of this interface is a strategy object. Instances of * these classes are created during the access enforcement to perform constraint checks. * *

* Single execution of the enforcement check would create at most one instance * of a given {@link AccessRestriction} type, so instance fields can be used to store * heavy-weight objects or other indicies that you might need for implementing * access control checks. * * @author Kohsuke Kawaguchi */ public abstract class AccessRestriction { /** * The type on which this restriction is placed is used as a supertype by another class. * The location points to the subtype. * * @param loc * Points to the subtype. * @param errorListener * Report any error here. */ public abstract void usedAsSuperType(Location loc, RestrictedElement target, ErrorListener errorListener); /** * The type on which this restriction is placed is used as an interface that another class/interface implements. * * @param loc * Points to the subtype. * @param errorListener * Report any error here. */ public abstract void usedAsInterface(Location loc, RestrictedElement target, ErrorListener errorListener); /** * The type on which this restriction is placed is instantiated elsewhere. */ public abstract void instantiated(Location loc, RestrictedElement target, ErrorListener errorListener); /** * The method on which this restriction is placed is invoked elsewhere. */ public abstract void invoked(Location loc, RestrictedElement target, ErrorListener errorListener); /** * The field on which this restriction is placed is read. */ public abstract void read(Location loc, RestrictedElement target, ErrorListener errorListener); /** * The field on which this restriction is placed is updated. */ public abstract void written(Location loc, RestrictedElement target, ErrorListener errorListener); /** * {@link AccessRestriction} that imposes no restriction. */ public static final AccessRestriction NONE = new None(); } Restricted.java000066400000000000000000000037311210703772200356760ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-annotation/src/main/java/org/kohsuke/accmod/* * The MIT License * * Copyright (c) 2010, Kohsuke Kawaguchi * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.kohsuke.accmod; import org.jvnet.hudson.annotation_indexer.Indexed; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.CLASS; /** * Indicates that a particular element is really deprecated and that the access to it * is subject to the additional restrictions. * *

* These annotations and restrictions introduced by them are enforced by the * "access-modifier-checker" mojo. * * @author Kohsuke Kawaguchi */ @Retention(CLASS) @Documented @Indexed public @interface Restricted { /** * Kind of access that are restricted. * If multiple values are specified, those restrictions are OR-ed — thus if an use * violates any of the restrictions, it'll be considered as an error. */ Class[] value(); } 000077500000000000000000000000001210703772200336605ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-annotation/src/main/java/org/kohsuke/accmod/implErrorListener.java000066400000000000000000000031261210703772200373240ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-annotation/src/main/java/org/kohsuke/accmod/impl/* * The MIT License * * Copyright (c) 2010, Kohsuke Kawaguchi * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.kohsuke.accmod.impl; /** * @author Kohsuke Kawaguchi */ public interface ErrorListener { void onError(Throwable t, Location loc, String msg); void onWarning(Throwable t, Location loc, String msg); /** * No-op listener. */ ErrorListener NULL = new ErrorListener() { public void onError(Throwable t, Location loc, String msg) { } public void onWarning(Throwable t, Location loc, String msg) { } }; } Location.java000066400000000000000000000051031210703772200362720ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-annotation/src/main/java/org/kohsuke/accmod/impl/* * The MIT License * * Copyright (c) 2010, Kohsuke Kawaguchi * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.kohsuke.accmod.impl; import org.kohsuke.accmod.AccessRestriction; /** * Indicates the location that the use occurred. * * @author Kohsuke Kawaguchi */ public interface Location { /** * The fully-qualified class name in which the use happened, * for example "abc.def.Ghi" */ String getClassName(); /** * If the use happened in the byte code instruction, * method name that the use occurred in. *

* For example "getAbc" */ String getMethodName(); /** * This is the encoded method signature like "(II)Z" * in which the use happened. Used in conjunction with * {@link #getMethodName()} to disambiguate overload. */ String getMethodDescriptor(); /** * The line number in the source file where the use happened. */ int getLineNumber(); /** * Obtains a human readable description of the location. * Useful for an error message. */ String toString(); /** * {@link AccessRestriction} implementations can use this classloader * to access the classes referenced by classes being inspected. * *

* Loading a class has a side effect, so it's generally not recommended * to do so, but the caller can use {@link ClassLoader#getResource(String)} * and parse the class files via libraries like ASM to define more elaborate * access restrictions. */ ClassLoader getDependencyClassLoader(); } RestrictedElement.java000066400000000000000000000031461210703772200401510ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-annotation/src/main/java/org/kohsuke/accmod/impl/* * The MIT License * * Copyright (c) 2010, Kohsuke Kawaguchi * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.kohsuke.accmod.impl; import org.kohsuke.accmod.Restricted; /** * Represents the element annotated by {@link Restricted} * * @author Kohsuke Kawaguchi */ public interface RestrictedElement { /** * True if the restricted element is a part of the code that's being inspected. * Often you want to relax restrictions for those that are in the same module, * and this can be used for that. */ boolean isInTheInspectedModule(); String toString(); } 000077500000000000000000000000001210703772200354475ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-annotation/src/main/java/org/kohsuke/accmod/restrictionsDoNotUse.java000066400000000000000000000050301210703772200400100ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-annotation/src/main/java/org/kohsuke/accmod/restrictions/* * The MIT License * * Copyright (c) 2010, Kohsuke Kawaguchi * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.kohsuke.accmod.restrictions; import org.kohsuke.accmod.AccessRestriction; import org.kohsuke.accmod.impl.ErrorListener; import org.kohsuke.accmod.impl.Location; import org.kohsuke.accmod.impl.RestrictedElement; /** * This type, field, or method shall never be referenced from anywhere at all. * * @author Kohsuke Kawaguchi */ public class DoNotUse extends AccessRestriction { public void written(Location loc, RestrictedElement target, ErrorListener errorListener) { error(loc,target,errorListener); } public void usedAsSuperType(Location loc, RestrictedElement target, ErrorListener errorListener) { error(loc,target,errorListener); } public void usedAsInterface(Location loc, RestrictedElement target, ErrorListener errorListener) { error(loc,target,errorListener); } public void instantiated(Location loc, RestrictedElement target, ErrorListener errorListener) { error(loc,target,errorListener); } public void invoked(Location loc, RestrictedElement target, ErrorListener errorListener) { error(loc,target,errorListener); } public void read(Location loc, RestrictedElement target, ErrorListener errorListener) { error(loc,target,errorListener); } public void error(Location loc, RestrictedElement target, ErrorListener errorListener) { errorListener.onError(null,loc,target+" must not be used"); } } NoExternalUse.java000066400000000000000000000013551210703772200410520ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-annotation/src/main/java/org/kohsuke/accmod/restrictionspackage org.kohsuke.accmod.restrictions; import org.kohsuke.accmod.impl.ErrorListener; import org.kohsuke.accmod.impl.Location; import org.kohsuke.accmod.impl.RestrictedElement; /** * References are allowed only when they are within the same module * (that is, if the reference is compiled at the same time as the restricted element.) * *

* Otherwise the access is rejected. * * @author Kohsuke Kawaguchi */ public class NoExternalUse extends DoNotUse { @Override public void error(Location loc, RestrictedElement target, ErrorListener errorListener) { if (target.isInTheInspectedModule()) return; // OK as long as the use happens in the same module super.error(loc, target, errorListener); } } None.java000066400000000000000000000017231210703772200372140ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-annotation/src/main/java/org/kohsuke/accmod/restrictionspackage org.kohsuke.accmod.restrictions; import org.kohsuke.accmod.AccessRestriction; import org.kohsuke.accmod.impl.ErrorListener; import org.kohsuke.accmod.impl.Location; import org.kohsuke.accmod.impl.RestrictedElement; /** * No access restriction whatsoever. * * @author Kohsuke Kawaguchi */ public class None extends AccessRestriction { public void usedAsSuperType(Location loc, RestrictedElement target, ErrorListener errorListener) { } public void usedAsInterface(Location loc, RestrictedElement target, ErrorListener errorListener) { } public void instantiated(Location loc, RestrictedElement target, ErrorListener errorListener) { } public void invoked(Location loc, RestrictedElement target, ErrorListener errorListener) { } public void read(Location loc, RestrictedElement target, ErrorListener errorListener) { } public void written(Location loc, RestrictedElement target, ErrorListener errorListener) { } } access-modifier-access-modifier-1.4/access-modifier-checker/000077500000000000000000000000001210703772200241065ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-checker/pom.xml000066400000000000000000000030261210703772200254240ustar00rootroot00000000000000 4.0.0 access-modifier org.kohsuke 1.4 access-modifier-checker maven-plugin Custom Access Modifier Checker junit junit 3.8.1 test ${project.groupId} access-modifier-annotation ${project.version} asm asm-debug-all 3.2 org.apache.maven maven-plugin-api 2.0.1 org.apache.maven maven-project 2.0.1 org.kohsuke.metainf-services metainf-services 1.1 true access-modifier-access-modifier-1.4/access-modifier-checker/src/000077500000000000000000000000001210703772200246755ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-checker/src/main/000077500000000000000000000000001210703772200256215ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-checker/src/main/java/000077500000000000000000000000001210703772200265425ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-checker/src/main/java/org/000077500000000000000000000000001210703772200273315ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-checker/src/main/java/org/kohsuke/000077500000000000000000000000001210703772200310025ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-checker/src/main/java/org/kohsuke/accmod/000077500000000000000000000000001210703772200322305ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-checker/src/main/java/org/kohsuke/accmod/impl/000077500000000000000000000000001210703772200331715ustar00rootroot00000000000000AccessRestrictionFactory.java000066400000000000000000000043331210703772200407370ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-checker/src/main/java/org/kohsuke/accmod/impl/* * The MIT License * * Copyright (c) 2010, Kohsuke Kawaguchi * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.kohsuke.accmod.impl; import org.kohsuke.accmod.AccessRestriction; import org.objectweb.asm.Type; import java.util.HashMap; import java.util.Map; /** * Pool of {@link AccessRestriction} instances. * * @author Kohsuke Kawaguchi */ public class AccessRestrictionFactory { private final Map instances = new HashMap(); private final ClassLoader cl; public AccessRestrictionFactory(ClassLoader cl) { this.cl = cl; } public AccessRestriction get(Type type) throws ClassNotFoundException, IllegalAccessException, InstantiationException { String className = type.getClassName(); AccessRestriction a = instances.get(className); if (a!=null) return a; // in this way, even if the restriction fails to load, we'll just report an error once a = AccessRestriction.NONE; try { Class c = cl.loadClass(className); a = (AccessRestriction)c.newInstance(); return a; } finally { instances.put(className,a); } } } Checker.java000066400000000000000000000311761210703772200353310ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-checker/src/main/java/org/kohsuke/accmod/impl/* * The MIT License * * Copyright (c) 2010, Kohsuke Kawaguchi * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.kohsuke.accmod.impl; import org.kohsuke.accmod.AccessRestriction; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.impl.Restrictions.Parser; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.ClassReader; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.commons.EmptyVisitor; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import static org.objectweb.asm.ClassReader.SKIP_FRAMES; /** * Performs check. * * @author Kohsuke Kawaguchi */ public class Checker { /** * Where dependencies are loaded. We don't actually load classes, * but this is used to search for class files and indexed restrictions. */ public final ClassLoader dependencies; /** * Where errors and warnings are sent. */ private final ErrorListener errorListener; /** * Restrictions found from dependencies. *

* The string is either: *

*/ private final Map restrictions = new HashMap(); private final AccessRestrictionFactory factory; public Checker(ClassLoader dependencies, ErrorListener errorListener) throws IOException { this.dependencies = dependencies; this.errorListener = errorListener; this.factory = new AccessRestrictionFactory(dependencies); // load access restrictions loadAccessRestrictions(); } public ErrorListener getErrorListener() { return errorListener; } /** * Checks a single class file or a directory full of class files (recursively.) */ public void check(File f) throws IOException { if (f.isDirectory()) { for (File c : f.listFiles()) check(c); return; } if (f.getPath().endsWith(".class")) checkClass(f); } /** * Loads all the access restrictions defined in our dependencies. */ private void loadAccessRestrictions() throws IOException { final Enumeration res = dependencies.getResources("META-INF/annotations/"+Restricted.class.getName()); while (res.hasMoreElements()) { URL url = res.nextElement(); loadRestrictions(url.openStream(),false); } } /** * Loads an additional restriction from the specified "META-INF/annotations/org.kohsuke.accmod.Restricted" file. * * @param isInTheInspectedModule * This value shows up in {@link RestrictedElement#isInTheInspectedModule()}. * @param stream */ public void loadRestrictions(InputStream stream, final boolean isInTheInspectedModule) throws IOException { if (stream==null) return; BufferedReader r = new BufferedReader(new InputStreamReader(stream, "UTF-8")); String className; while ((className=r.readLine())!=null) { InputStream is = dependencies.getResourceAsStream(className.replace('.','/') + ".class"); if (is==null) { errorListener.onWarning(null,null,"Failed to find class file for "+ className); continue; } try { new ClassReader(is).accept(new EmptyVisitor() { private String className; @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { this.className = name; } @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { return onAnnotationFor(className,desc); } @Override public FieldVisitor visitField(int access, final String name, String desc, String signature, Object value) { return new EmptyVisitor() { @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { return onAnnotationFor(className+'.'+name,desc); } }; } @Override public MethodVisitor visitMethod(int access, final String methodName, final String methodDesc, String signature, String[] exceptions) { return new EmptyVisitor() { @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { return onAnnotationFor(className+'.'+methodName+methodDesc,desc); } }; } /** * Parse {@link Restricted} annotation on some annotated element. */ private AnnotationVisitor onAnnotationFor(final String keyName, String desc) { if (RESTRICTED_DESCRIPTOR.equals(desc)) { RestrictedElement target = new RestrictedElement() { public boolean isInTheInspectedModule() { return isInTheInspectedModule; } public String toString() { return keyName; } }; return new Parser(target) { @Override public void visitEnd() { try { restrictions.put(keyName,build(factory)); } catch (ClassNotFoundException e) { failure(e); } catch (InstantiationException e) { failure(e); } catch (IllegalAccessException e) { failure(e); } } /** * Fails to load a {@link AccessRestriction} instance. */ private void failure(Exception e) { errorListener.onError(e,null,"Failed to load restrictions"); } }; } return null; } }, ClassReader.SKIP_CODE); } finally { is.close(); } } } /** * Inspects a class for the restriction violations. */ public void checkClass(File clazz) throws IOException { FileInputStream in = new FileInputStream(clazz); try { ClassReader cr = new ClassReader(in); cr.accept(new EmptyVisitor() { private String className; private String methodName,methodDesc; private int line; @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { this.className = name; if (superName!=null) getRestrictions(superName).usedAsSuperType(currentLocation,errorListener); if (interfaces!=null) { for (String intf : interfaces) getRestrictions(intf).usedAsInterface(currentLocation,errorListener); } } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { this.methodName = name; this.methodDesc = desc; return new EmptyVisitor() { @Override public void visitLineNumber(int _line, Label start) { line = _line; } public void visitTypeInsn(int opcode, String type) { switch (opcode) { case Opcodes.NEW: getRestrictions(type).instantiated(currentLocation,errorListener); } } @Override public void visitMethodInsn(int opcode, String owner, String name, String desc) { getRestrictions(owner+'.'+name+desc).invoked(currentLocation,errorListener); } @Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { Restrictions r = getRestrictions(owner + '.' + name); switch (opcode) { case Opcodes.GETSTATIC: case Opcodes.GETFIELD: r.read(currentLocation,errorListener); break; case Opcodes.PUTSTATIC: case Opcodes.PUTFIELD: r.written(currentLocation,errorListener); break; } super.visitFieldInsn(opcode, owner, name, desc); } }; } /** * Constant that represents the current location. */ private final Location currentLocation = new Location() { public String getClassName() { return className.replace('/','.'); } public String getMethodName() { return methodName; } public String getMethodDescriptor() { return methodDesc; } public int getLineNumber() { return line; } public String toString() { return className+':'+line; } public ClassLoader getDependencyClassLoader() { return dependencies; } public boolean isInTheSameModuleAs(RestrictedElement e) { // TODO throw new UnsupportedOperationException(); } }; }, SKIP_FRAMES); } finally { in.close(); } } private Restrictions getRestrictions(String keyName) { Restrictions r = restrictions.get(keyName); if (r==null) return Restrictions.NONE; return r; } private static final String RESTRICTED_DESCRIPTOR = Type.getDescriptor(Restricted.class); } EnforcerMojo.java000066400000000000000000000054011210703772200363450ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-checker/src/main/java/org/kohsuke/accmod/implpackage org.kohsuke.accmod.impl; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProject; import org.kohsuke.accmod.Restricted; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * Enforces the {@link Restricted} access modifier annotations. * * @author Kohsuke Kawaguchi * @goal enforce * @phase process-classes * @requiresDependencyResolution compile * @author Kohsuke Kawaguchi */ public class EnforcerMojo extends AbstractMojo { /** * The maven project. * * @parameter expression="${project}" * @required * @readonly */ protected MavenProject project; public void execute() throws MojoExecutionException, MojoFailureException { try { File outputDir = new File(project.getBuild().getOutputDirectory()); List dependencies = new ArrayList(); for (Artifact a : (Collection)project.getArtifacts()) dependencies.add(a.getFile().toURI().toURL()); URL outputURL = outputDir.toURI().toURL(); dependencies.add(outputURL); final boolean[] failed = new boolean[1]; Checker checker = new Checker(new URLClassLoader(dependencies.toArray(new URL[dependencies.size()]), getClass().getClassLoader()), new ErrorListener() { public void onError(Throwable t, Location loc, String msg) { getLog().error(loc+" "+msg,t); failed[0] = true; } public void onWarning(Throwable t, Location loc, String msg) { getLog().warn(loc+" "+msg,t); } }); {// if there's restriction list in the inspected module itself, load it as well InputStream self = null; try { self = new URL(outputURL, "META-INF/annotations/" + Restricted.class.getName()).openStream(); } catch (IOException e) { } if (self!=null) checker.loadRestrictions(self, true); } // perform checks checker.check(outputDir); if (failed[0]) throw new MojoFailureException("Access modifier checks failed. See the details above"); } catch (IOException e) { throw new MojoExecutionException("Failed to enforce @Restricted constraints",e); } } } Restrictions.java000066400000000000000000000100051210703772200364410ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-checker/src/main/java/org/kohsuke/accmod/impl/* * The MIT License * * Copyright (c) 2010, Kohsuke Kawaguchi * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.kohsuke.accmod.impl; import org.kohsuke.accmod.AccessRestriction; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Type; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * @author Kohsuke Kawaguchi */ public class Restrictions extends ArrayList { private final RestrictedElement target; public Restrictions(RestrictedElement target, Collection c) { super(c); this.target = target; } public Restrictions(RestrictedElement target) { this.target = target; } public void usedAsSuperType(Location loc, ErrorListener errorListener) { for (AccessRestriction ar : this) ar.usedAsSuperType(loc,target,errorListener); } public void usedAsInterface(Location loc, ErrorListener errorListener) { for (AccessRestriction ar : this) ar.usedAsInterface(loc,target,errorListener); } public void instantiated(Location loc, ErrorListener errorListener) { for (AccessRestriction ar : this) ar.instantiated(loc,target,errorListener); } public void invoked(Location location, ErrorListener errorListener) { for (AccessRestriction ar : this) ar.invoked(location,target,errorListener); } public void read(Location location, ErrorListener errorListener) { for (AccessRestriction ar : this) ar.read(location,target,errorListener); } public void written(Location location, ErrorListener errorListener) { for (AccessRestriction ar : this) ar.written(location,target,errorListener); } public static final Restrictions NONE = new Restrictions(new RestrictedElement() { public boolean isInTheInspectedModule() { return false; } public String toString() { return "NONE"; } }); abstract static class Parser implements AnnotationVisitor { private List restrictions = new ArrayList(); private final RestrictedElement target; protected Parser(RestrictedElement target) { this.target = target; } public void visit(String name, Object value) { restrictions.add((Type)value); } public void visitEnum(String name, String desc, String value) { } public AnnotationVisitor visitAnnotation(String name, String desc) { return this; } public AnnotationVisitor visitArray(String name) { return this; } public abstract void visitEnd(); public Restrictions build(AccessRestrictionFactory f) throws ClassNotFoundException, InstantiationException, IllegalAccessException { Restrictions r = new Restrictions(target); for (Type t : restrictions) { r.add(f.get(t)); } return r; } } } access-modifier-access-modifier-1.4/access-modifier-checker/src/main/resources/000077500000000000000000000000001210703772200276335ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-checker/src/main/resources/META-INF/000077500000000000000000000000001210703772200307735ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-checker/src/main/resources/META-INF/m2e/000077500000000000000000000000001210703772200314565ustar00rootroot00000000000000lifecycle-mapping-metadata.xml000066400000000000000000000004751210703772200372750ustar00rootroot00000000000000access-modifier-access-modifier-1.4/access-modifier-checker/src/main/resources/META-INF/m2e enforce access-modifier-access-modifier-1.4/pom.xml000066400000000000000000000053021210703772200207640ustar00rootroot00000000000000 4.0.0 org.kohsuke pom 3 access-modifier 1.4 Custom access modifier for Java pom Extensible application-specific access modifiers for Java access-modifier-annotation access-modifier-checker kohsuke.org scp://kohsuke.org/home/kohsuke/kohsuke.org/access-modifier/ maven-compiler-plugin 1.5 1.5 org.apache.maven.plugins maven-release-plugin 2.0 org.apache.maven.scm maven-scm-provider-gitexe 1.2 org.apache.maven.plugins maven-scm-plugin 1.3 org.jvnet.wagon-svn wagon-svn 1.9 scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ kohsuke Kohsuke Kawaguchi org.apache.maven.plugins maven-javadoc-plugin MIT License repository http://www.opensource.org/licenses/mit-license.php access-modifier-access-modifier-1.4/src/000077500000000000000000000000001210703772200202365ustar00rootroot00000000000000access-modifier-access-modifier-1.4/src/site/000077500000000000000000000000001210703772200212025ustar00rootroot00000000000000access-modifier-access-modifier-1.4/src/site/apt/000077500000000000000000000000001210703772200217665ustar00rootroot00000000000000access-modifier-access-modifier-1.4/src/site/apt/index.apt000066400000000000000000000040431210703772200236040ustar00rootroot00000000000000 What is this? This library defines an annotation and extensible mechanism to let you define your own access modifiers. Those additional custom access modifiers can be enforced when you compile other source files that refer them. For example, consider a deprecated feature in your library that you plan to remove in a near future. If you just put <<<@Deprecated>>>, code can be still written to use them quite casually (I still often use <<>>, for example.) But if you remove it, it'll break existing applications out there. Custom access modifier can fix this. With the following annotation on your method, you can flag an error whenever someone tries to call this method. ----------------- public class Library { @Deprecated @Restricted(DoNotUse.class) public void foo() { ... } } ----------------- These checks are not enforced during the runtime, so in this way, you can keep the old application working, and at the same time prevent the new code from using this feature. (I should point out that technically speaking the enforcement is optional, even during the compile time --- after all, it's just a semantics imposed by a library external to Javac.) Extensible Access Modifiers The library comes with a few built-in access modifiers, but your application can define your own by extending the <<>> type. For example, maybe you want to allow read but prevent write to a field. Maybe you want to only allow certain methods to be called from within the constructor (or the other way around.) There's a lot of freedom. Enforcing Access Modifiers Currently we provide a Maven mojo to enforce access modifiers. Use it like the following: ----------------- org.kohsuke access-modifier-checker 1.0 enforce ----------------- access-modifier-access-modifier-1.4/src/site/site.xml000066400000000000000000000015271210703772200226750ustar00rootroot00000000000000 Custom Access Modifier http://kohsuke.org/access-modifier org.kohsuke maven-skin 1.1