Search code examples
javapackageprivacyfactories

Managing privacy within a large program


I'm working on a program for robotics with this structure (I'll include what the layers do just for laughs):

  • Layer A - GUI simple interface to handle buttons, joysticks, etc. Translates these values into commands to send to the control interface.

  • Layer B - Control evaluates device-read/write-entries from the database and command requests from gui, in order to calculate new device-write-entries for the database

  • Layer C - Database logical representation of devices, creating a history of values written and read from the devices

  • Layer D - Hardware talks to physical hardware. Translates device-write-entries into commands and sends them to the devices. Updates the database device-read-entries with values from the devices.

I want to create a java application where no layer is able to call functions which are more than one layer above or below it.

Is it possible to create a project structure using package privacy, or patterns like factories which makes it impossible for code in, lets say Layer A, to import anything from Layers D or C?


Solution

  • This is not something that you can achieve using access modifiers alone.

    You also can't do it by (somehow) controlling import ... because the Java language doesn't place any (extra) restrictions on imports. (The import directive is really just syntactic sugar so that you don't need to use fully-qualified names everywhere.)

    So what else could you do?

    • You could try to implement runtime restrictions to prevent the wrong layer getting access to factory objects. But such restrictions are easily subverted, deliberately or by accident.

    • You could use some kind of internal "capability" or "credential" mechanism, but it is hard to see how you would prevent credential leakage. (If the credentials were managed by a security manager (see below) that might work, but that's making the problem more complicated.)

    The only way I think you could do it would be to implement a custom SecurityManager, and implement security checks each time there is a potentially layer-crossing call. For example, it is possible (though expensive) for a security manager to check the call stack to find what method / class / package called it. You would also need to turn off certain reflective operations that can be used to (trivially) subvert the security manager. Essentially, all but the inner ring needs to be treated as "untrusted" code.

    Frankly, implementing this kind of thing with a JVM with "hacker-proof" security is probably beyond the capability of a mortal human. (Sun / Oracle haven't succeeded yet ....)


    The other alternatives are:

    • Rely on programmer discipline.

    • Rely on static analysis of the codebase; e.g. aided by annotations that document the access rules. You would need to write your own code analyser to do this.

    • Use address-space separation, and small footprint, security-minded APIs between the layers. (We are no longer talking about a single conventional JVM here ...)