Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6502392

Invalid relative names for Filer.createResource and Filer.getResource





        javax.annotation.processing.Filer has two methods: createResource() and
        The spec for getResource() and createResource() states that
        IllegalArgumentException is thrown if relativeName is not relative,
        IOException is thrown if the file cannot be created/opened.

        On the top of Filer interface description there is a spec excerpt:
        A relative name is a non-null, non-empty sequence of path segments
        separated by '/'; '.' and '..' are invalid path segments. A valid
        relative name must match the "path-rootless" rule of RFC 3986, section 3.3.

        So the following relative names are invalid: "/boo", "goo/../hoo",
        "./ioo", "".
        And the filer should throw IllegalArgumentException if it uses the
        relative names above when
        creating or getting resources. As a variant the filer may throw
        IOException when getResource is trying to open nonexistent file.

        However, getting or creating resource with invalid relative names causes
        to throwing neither
        IllegalArgumentException nor IOException.

        # javac -cp . -processor tmp.InvalidRelativeNameProcessor java.lang.Object

        You may reproduce the behavior using following processor class (you need
        to uncomment either writer,
        or reader, or output stream, or inputstream block of code marked as 1,
        2, 3, and 4). Also you may substitute StandardLocation.SOURCE_OUTPUT to
        StandardLocation.CLASS_OUTPUT and run it once more.

        package tmp;

        import java.io.InputStream;
        import java.io.Reader;
        import java.io.Writer;
        import javax.annotation.processing.AbstractProcessor;
        import javax.annotation.processing.RoundEnvironment;
        import javax.annotation.processing.Filer;
        import javax.lang.model.element.TypeElement;
        import javax.lang.model.element.Element;
        import javax.lang.model.SourceVersion;
        import java.util.Set;
        import java.util.HashSet;
        import java.io.IOException;
        import java.io.OutputStream;
        import javax.tools.JavaFileManager;
        import javax.tools.StandardLocation;

        public class InvalidRelativeNameProcessor extends AbstractProcessor {
            String[] invalidRelativeNames = {
                    "/boo", "goo/../hoo", "./ioo", ""

            public Set<String> getSupportedAnnotationTypes() {
                return new HashSet<String>() {{add("*");}};

            public SourceVersion getSupportedSourceVersion() {
                return SourceVersion.RELEASE_6;

            public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
                boolean passed = true;
                if(roundEnv.processingOver()) {
                    Filer filer = processingEnv.getFiler();
                    for (String relative: invalidRelativeNames) {
                        try {
        // Writer writer = filer.createResource( // 1
        // StandardLocation.SOURCE_OUTPUT, "", relative).openWriter(); // 1
        // writer.close(); // 1

        // Reader reader = filer.createResource( // 2
        // StandardLocation.SOURCE_OUTPUT, "", relative).openReader(true); // 2
        // reader.close(); // 2

        // OutputStream out = filer.createResource( // 3
        // StandardLocation.SOURCE_OUTPUT, "", relative).openOutputStream(); // 3
        // out.close(); // 3

        // InputStream in = filer.createResource( // 4
        // StandardLocation.SOURCE_OUTPUT, "", relative).openInputStream(); // 4
        // in.close(); // 4
                            System.out.println("relative path: " + relative);
                        } catch (IllegalArgumentException expected) {
                        } catch (IOException expected) {
                        } catch (Exception e) {
                            passed = false;
                            System.out.println("relative path: " + relative + ", thrown: " + e);
                return true;

        As a result of running these tests relative names "goo/../hoo" and
        "./ioo" doesn't cause to throwing either IllegalArgumentException, or
        IOException. When we are trying to write a resource there are no
        exception thrown at all. When we are trying to get resource then
        unexpected java.lang.IllegalStateException is thrown.

        I suppose it is unexpected behavior.


            Issue Links



                jjg Jonathan Gibbons
                ydanilev Yury Danilevich (Inactive)
                0 Vote for this issue
                1 Start watching this issue