1

This demo, I want to understand AccessController.doPrivileged() better.In jetty-xml module, the main() methods has the following code:

AccessController.doPrivileged(new PrivilegedAction<Object>() {
    @Override
    public Object run() {
        try {

            Properties properties = null;
        }

        ...
    }
}

I think this is to ensure jetty-start module can invoke jetty-xml module successed.So I write a simple demo.But I have a new problem,now this problem has no relations with Jetty. I had use google to search related issues,but most about rmi.Following diagram is the project structure, has two module, jetty-start and jetty-xml (I just simulate jetty module names):

enter image description here

The jetty-start module Main class, first invoke XmlConfiguration#readFile(), then invoke XmlConfiguration#readFileWithPrivilegedAction() by constructor a new classloader and reflect.In addition, run the Main class, use the -Djava.security.policy=jetty-testXmlModulePrivileged.policy vm args.

public class Main {
    public static void main(String[] args) throws IOException, ReflectiveOperationException {
        ClassLoader loader = getLoader();
        Thread.currentThread().setContextClassLoader(loader);
        Class<?> clazz = loader.loadClass("org.jetty.xml.XmlConfiguration");

        System.setSecurityManager(new SecurityManager());

        try {
            System.out.println("invoke readFile().");
            Method method = clazz.getMethod("readFile");
            String lines = (String) method.invoke(null);
            System.out.println("File Content: \n" + lines);
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("/////////////////////////////////////////////////////////");
        System.out.println();

        try {
            System.out.println("invoke readFileWithPrivilegedAction().");
            Method method = clazz.getMethod("readFileWithPrivilegedAction");
            String lines = (String) method.invoke(null);
            System.out.println("File Content: \n" + lines);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private static ClassLoader getLoader() throws IOException {
        ClassLoader parent = Thread.currentThread().getContextClassLoader();
        final String CLASSPATH_PATH = "E:\\Java\\workspace\\Test\\jetty-xml\\bin\\";
        File bin = new File(CLASSPATH_PATH);
        URL binUrl = bin.getCanonicalFile().toURI().toURL();
        System.out.println("add classpath : " + binUrl);

        URL[] urls = {binUrl};

        ClassLoader loader = new StartClassLoader(urls, parent);
        return loader;
    }


    private static class StartClassLoader extends URLClassLoader {
        public StartClassLoader(URL[] urls, ClassLoader parent) {
            super(urls, parent);
        }
    }
}

The jetty-xml module XmlConfiguration class,one method is normal method invoke, the other method use AccessController.doPrivileged:

public class XmlConfiguration {
    private final static String FOLDER_PATH = "E:\\Java\\workspace\\Test\\jetty-xml\\config\\";
    private final static String FILENAME = "server.xml";

    public static String readFile() throws IOException {
        File fs = new File(FOLDER_PATH + FILENAME);
        StringBuilder lines = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(
                new FileInputStream(fs)))) {
            String line = null;
            while ((line = reader.readLine()) != null) {
                lines.append(line);
            }
        }

        return lines.toString();
    }

    /**
     */
    public static String readFileWithPrivilegedAction() throws IOException {
        String lines = AccessController.doPrivileged(new PrivilegedAction<String>() {
                    @Override
                    public String run() {
                        File fs = new File(FOLDER_PATH + FILENAME);
                        StringBuilder lines = new StringBuilder();
                        try (BufferedReader reader = new BufferedReader(
                                new InputStreamReader(new FileInputStream(fs)))) {
                            String line = null;
                            while ((line = reader.readLine()) != null) {
                                lines.append(line);
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                        return lines.toString();
                    }

                });

        return lines;
    }
}

The jetty-testXmlModulePrivileged.policy is, give the jetty-xml permission to read the server.xml file.

grant codebase "file:/E:/Java/workspace/Test/jetty-xml/bin"
{ 
    permission java.io.FilePermission "E:\\Java\\workspace\\Test\\jetty-xml\\config\\server.xml", "read,write";
};

Finally I run the Main, the first exception I can understand, It has no permission(eg, invoke readFile() method), and not run in AccessController.doPrivileged, but the second exception, I was a little puzzled(eg. invoke readFileWithPrivilegedAction() method):

invoke readFile().
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.jetty.start.Main.main(Main.java:23)
Caused by: java.security.AccessControlException: access denied ("java.io.FilePermission" "E:\Java\workspace\Test\jetty-xml\config\server.xml" "read")
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:372)
    at java.security.AccessController.checkPermission(AccessController.java:559)
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
    at java.lang.SecurityManager.checkRead(SecurityManager.java:888)
    at java.io.FileInputStream.<init>(FileInputStream.java:135)
    at org.jetty.xml.XmlConfiguration.readFile(XmlConfiguration.java:19)
    ... 5 more
/////////////////////////////////////////////////////////

invoke readFileWithPrivilegedAction().
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.jetty.start.Main.main(Main.java:35)
Caused by: java.lang.NoClassDefFoundError: org/jetty/xml/XmlConfiguration$1
    at org.jetty.xml.XmlConfiguration.readFileWithPrivilegedAction(XmlConfiguration.java:34)
    ... 5 more
Caused by: java.lang.ClassNotFoundException: org.jetty.xml.XmlConfiguration$1
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 6 more

I had constructor a new classloader, add the jetty-xml bin classpath,then set the current thread classloader to this new classloader, I think this classloader can load org.jetty.xml.XmlConfiguration$1.If I modify the Main class,It's OK:

Class<?> clazz = loader.loadClass("org.jetty.xml.XmlConfiguration");
loader.loadClass("org.jetty.xml.XmlConfiguration$1");

This is similar to Tomcat's SecurityClassLoad class.Preload some class.But here, why not throws AccessControlException?

ykgarfield
  • 33
  • 5

0 Answers0