Shahzad Bhatti

May 28, 2006

Implementing Const in Java

Filed under: Computing — admin @ 12:33 pm

Implementing Const in Java
For those who migrate to Java from C++ (as I did back in ’95), they miss
const keyword, which provides you a nice way to prevent called functions
from mutating objects.

In C++, const keyword like static keyword is a bit overloaded (Note that
static in C++ could mean locally global variable, local variable in method,
shared field/method in class). Similarly, const in C++ can be used for

  • defining Constants, e.g. const int MAX = 100;
  • Protecting pointee in pointer, e.g. int const * ptr
  • Protecting pointer, e.g. int * const ptr
  • Protecting both pointee and pointer, e.g. int const * const ptr
  • Protecting methods from modifying any internal data, e.g.
    int get() const {return x;}
  • Protecting reference, e.g. const AClass& instance

When working on a complicated software with dozens of layers, you need to
define security policies as to what layers can change what information.
Though, C++’s security policies are not adequate, but const gives you some
basic capability.

Though, const is a keyword in Java, but it is not implemented and available
to Java programmers. The closest thing it provides is final, but it is used for :

Here are a couple of ways to add this capability to Java
Suppose you have a Widget class, and accessor and setter methos for
following four attributes:

 1  package widget;
 2
 3  public class Widget {
 4    public Widget() {
 5    }
 6    public Widget(String name, String description, int quantity, double price) {
 7      setName(name);
 8      setDescription(description);
 9      setQuantity(quantity);
10      setPrice(price);
11    }
12    public String getName() {
13      return this.name;
14    }
15
16    public void setName(String name) {
17      this.name = name;
18    }
19
20    public String getDescription() {
21      return this.description;
22    }
23
24    public void setDescription(String description) {
25      this.description = description;
26    }
27
28    public int getQuantity() {
29      return this.quantity;
30    }
31
32    public void setQuantity(int quantity) {
33      this.quantity = quantity;
34    }
35
36    public double getPrice() {
37      return this.price;
38    }
39
40    public void setPrice(double price) {
41      this.price = price;
42    }
43
44    private String name;
45    private String description;
46    private int quantity;
47    private double price;
48  }

and following are major components in the application:

  • web presentation
  • shopping cart application
  • supply chain
  • cms (content management system)
  • persistence

However, the widget name and description can only be changed by CMS component
and price and quantity can only be changed by supply chain system.

1. Adapter Pattern

If the class implements an interface then you can define another class
like WidgetAdapter, e.g.

1         public class WidgetAdapter implements IWidget {
2            public WidgetAdapter(Widget delegate) {
3              this.delegate = delegate;
4            }
5            public void setName(String aName) {
6             throw new IllegalAccessException("name cannot be changed");
7            }
8

If the class does not an interface then you can derive your class from the
Widget class.
Note that both of above approaches require that application layer be aware
of security policies and know how to instantiate these objects. Though, you
can use Factory pattern, but it is still somewhat limited solution.

2. Value pattern

This is similar to above approach except, you define a completely new class
with only the information that you need to pass to another layer. All of the
attributes in value class are final, e.g.

1     public class WidgetValue {
2       public WidgetValue(String name, String description, int quantity, double price) {
3       ...
4       public final String name;
5     }
6 

This approach clearly defines contract between layers. Often objects passed to other layers have very tight data coupling and unnecessary information is passed. With this approach, services clearly identifies what information is needed. The disadvantage of this approach are a number of additional types that look very similar.

3. AOP

This is probably most flexible way to implement security policies as it
allows you to define security policies in one place and does not require
changes to domain object classes. For example,

 1  public aspect WidgetAccessAspect {
 2      declare error
 3          : (call(* widget.Widget.set*(..)))
 4          && !within(CMSManager)
 5          : "Changes to widget name/description are restricted to the CMSManager class";
 6      declare error
 7          : (call(* widget.Widget.set*(..)))
 8          && !within(SupplyChainManager)
 9          : "Changes to widget quantity/price are restricted to the SupplyChainManager class";
10  }

Above aspect will throw compile time errors when any code other than CMSManager tries to modify name and description of the Widget or any code other than SupplyChainManager that tries to modify quantity and price of the widget.Also, above approach can also be used to another nice feature of C++, which is friend keyword. It allows private access to another class. This can be quite handy because often I have to leak encapsulation to unit tests and it would be nice to do this easily.

On the downside, most people are not familiar with AOP and since AOP works like
a magic, it could be intimidating to most people.

4. AccessController/Permission

Another way is to use Java’s security policy to enforce access policies.
However, this requires that each layer be defined in a separate jar file, .e.g

  • application.jar — defines domain classes and core application logic
  • web.jar – presentation logic
  • supply.jar — supply chain
  • cms.jar — CMS

WidgetPermission looks like this:

 1  package widget;
 2 
 3  import java.security.*;
 4 
 5  public class WidgetPermission extends BasicPermission {
 6      public WidgetPermission(String name) {
 7          super(name);
 8      }
 9 
10      public WidgetPermission(String name, String actions) {
11          super(name, actions);
12      }
13  }

Then you can define a java policy file as:

 // or grant signedBy "party" codebase codebase "file://opt/application/lib/cms.jar" {
 grant codebase "file://opt/application/lib/cms.jar" {
     permission widget.WidgetPermission "setName";
     permission widget.WidgetPermission "setDescription";
 };

 grant codebase "file://opt/application/lib/supply.jar" {
     permission widget.WidgetPermission "setQuantity";
     permission widget.WidgetPermission "setPrice";
 };

Then inside Widget class, change setName, setDescription, setQuantity, setPrice as follows:

 1  import java.security.AccessController;
 2 
 3  public class Widget {
 4      private String name;
 5      private String description;
 6      private int quantity;
 7      private double price;
 8 
 9      public void setName(String aName) {
10          AccessController.checkPermission(
11                            new WidgetPermission("setName"));
12          this.name = aName;
13      }
14 
15      public void setDescription(String aDesc) {
16          AccessController.checkPermission(
17                            new WidgetPermission("setName"));
18          this.desc = aDesc;
19      }
20 

5. Combination of AOP and AccessController/Permission

As you can see above code of adding checkPermission can also be done with AOP, e.g.

1  public aspect WidgetAccessAspect {
2      public pointcut setOperations()
3          : execution(* widget.Widget.set*(..));
4 
5      before() : setOperations() {
6          AccessController.checkPermission(
7                           getPermission(thisJoinPointStaticPart));
8      }
9 

No Comments

No comments yet.

RSS feed for comments on this post. TrackBack URL

Sorry, the comment form is closed at this time.

Powered by WordPress