def Open(self,
           urn,
           aff4_type=None,
           mode="r",
           token=None,
           local_cache=None,
           age=NEWEST_TIME,
           follow_symlinks=True,
           transaction=None):
    """Opens the named object.

    This instantiates the object from the AFF4 data store.
    Note that the root aff4:/ object is a container for all other
    objects. Opening it for reading will instantiate a AFF4Volume instance, even
    if the row does not exist.

    The mode parameter specifies, how the object should be opened. A read only
    mode will raise when calling Set() on it, while a write only object will
    never read from the data store. Note that its impossible to open an object
    with pure write support (since we have no idea what type it should be
    without reading the data base) - use Create() instead for purely write mode.

    Args:
      urn: The urn to open.
      aff4_type: If this parameter is set, we raise an IOError if the object is
        not an instance of this type. This check is important when a different
        object can be stored in this location. If mode is "w", this parameter
        will determine the type of the object and is mandatory.
      mode: The mode to open the file with.
      token: The Security Token to use for opening this item.
      local_cache: A dict containing a cache as returned by GetAttributes. If
        set, this bypasses the factory cache.
      age: The age policy used to build this object. Should be one of
        NEWEST_TIME, ALL_TIMES or a time range given as a tuple (start, end) in
        microseconds since Jan 1st, 1970.
      follow_symlinks: If object opened is a symlink, follow it.
      transaction: A lock in case this object is opened under lock.

    Returns:
      An AFF4Object instance.

    Raises:
      IOError: If the object is not of the required type.
      AttributeError: If the requested mode is incorrect.
    """

    if not data_store.AFF4Enabled():
      raise NotImplementedError("AFF4 data store has been disabled.")

    _ValidateAFF4Type(aff4_type)

    if mode not in ["w", "r", "rw"]:
      raise AttributeError("Invalid mode %s" % mode)

    if mode == "w":
      if aff4_type is None:
        raise AttributeError("Need a type to open in write only mode.")
      return self.Create(
          urn,
          aff4_type,
          mode=mode,
          token=token,
          age=age,
          force_new_version=False,
          transaction=transaction)

    urn = rdfvalue.RDFURN(urn)

    if token is None:
      token = data_store.default_token

    if "r" in mode and (local_cache is None or urn not in local_cache):
      local_cache = dict(self.GetAttributes([urn], age=age))

    # Read the row from the table. We know the object already exists if there is
    # some data in the local_cache already for this object.
    result = AFF4Object(
        urn,
        mode=mode,
        token=token,
        local_cache=local_cache,
        age=age,
        follow_symlinks=follow_symlinks,
        object_exists=bool(local_cache.get(urn)),
        transaction=transaction)

    result.aff4_type = aff4_type

    # Now we have a AFF4Object, turn it into the type it is currently supposed
    # to be as specified by Schema.TYPE.
    existing_type = result.Get(result.Schema.TYPE, default="AFF4Volume")

    if existing_type:
      try:
        result = result.Upgrade(AFF4Object.classes[existing_type])
      except KeyError:
        raise InstantiationError("Unable to open %s, type %s unknown." %
                                 (urn, existing_type))

    if aff4_type is not None and not isinstance(result, aff4_type):
      raise InstantiationError(
          "Object %s is of type %s, but required_type is %s" %
          (urn, result.__class__.__name__, aff4_type.__name__))

    return result