11 February 2009

Encapsulation though access control

Encapsulation does not necessarily means getters and setters. And have more than one aspects:

  • Inside structure control.
  • Input data validation.
  • Outside access control.

Lets consider 'Outside access control'.

While we directly do not know which class calls method, it's hard to limit context of (method) call. It is possible, but amount of work is to big now time.
Any way what solutions do we have?

Control by 'key'.

public final class SetByLock {

  private SetByLock(Object acessKey) {
    this.acessKey = acessKey;
  }

  private final Object  acessKey;

  private String      data;

  public String getData() {
    return data;
  }

  public void setData(Object accessKey, String data) {
    if (acessKey != accessKey) { throw new UnauthorizedAccessException(accessKey == null ? "null" : accessKey.toString()); }
    this.data = data;
  }

}
As we can see in the example above, we have to pass the key each time we want to execute protected method. For limiting access this solution is good enough, as only creator have the powder to access danger space (method, …), and only he can lend this powder to other objects.

Control by 'delegated accessor'.

public class Container<Type> {

  public Type  element;

}

public class SetByAccessor {

  public SetByAccessor(Container<Accessor> accessorContainer, String data) {
    this.data.data = data;
    if (accessorContainer != null) {
      accessorContainer.element = new Accessor(this.data);
    }
  }

  private Local  data  = new Local();

  public String getData() {
    return data.data;
  }

  /*
   * Store local data
   */

  private static class Local {

    public Local() {
    }

    public String  data;
  }

  /*
   * Allow to more access
   */

  public static class Accessor {
    public Accessor(Local data) {
      if (data == null) { throw new NullPointerException(Local.class.getSimpleName()); }
      this.data = data;
    }

    private Local  data;

    public void setData(String data) {
      this.data.data = data;
    }
  }

}
In this solution we can lend 'limited' access just by one object, while previous one required pair: object & key .
Problem is when we have lot's of elements to control. 1000 objects force us to store 1000 Accessor-s

Mixed solution.


public class SetByMixed {

  public SetByMixed(Object accessKey, String data) {
    this.data.data = data;
    this.accessKey = accessKey;
  }

  private final Object  accessKey;

  private Accessor    accessor;

  public Accessor getAccessor(Object accessKey) {
    if (this.accessKey != accessKey) { throw new UnauthorizedAccessException(accessKey == null ? "null" : accessKey.toString()); }
    if (accessor == null) {
      accessor = new Accessor(data);
    }
    return accessor;
  }

  private Local  data  = new Local();

  public String getData() {
    return data.data;
  }

  /*
   * Store local data
   */

  private static class Local {

    public Local() {
    }

    public String  data;
  }

  /*
   * Allow to 'limited' access
   */

  public static class Accessor {
    public Accessor(Local data) {
      if (data == null) { throw new NullPointerException(Local.class.getSimpleName()); }
      this.data = data;
    }

    private Local  data;

    public void setData(String data) {
      this.data.data = data;
    }
  }

}
At final here we have 'nice' part of code. Keys can be reused and there no need to store pairs to have full access. What more we do not need to write 'secure check' on each method and worry if we have access to every method (it's possible for each method to have own key in control by 'key').
Key just need to be controlled to do not leak out.

Summary.

I just wander, if we really need all this stuff when we want limit write access?

0 comments / komentarz(y):

Post a Comment