public void unlock(String id, boolean force, UserInformation user) throws MorseException {

    if (log.t4()) log.info("UNLOCK: " + id + ' ' + user);

    ObjectUtil.assetId(id);
    if (!force && user == null) throw new MorseException(MorseException.UNKNOWN_USER);

    // create lock file
    ObjectFileStore ofs = driver.getFileStore().get(IType.TYPE_OBJECT)[0];

    try {
      if (log.t4()) log.debug("xLOCK: " + id + ' ' + user);
      if (!ofs.lock(id)) throw new MorseException(MorseException.ERROR);
    } catch (IOException e) {
      throw new MorseException(MorseException.ERROR, e);
    }

    try {

      IQueryResult res = fetch(id, user, false);
      if (!res.next()) {
        res.close();
        throw new MorseException(MorseException.ACCESS_DENIED, id);
      }
      String lock = res.getString(IAttribute.M_LOCK);
      res.close();

      if (!force && ObjectUtil.validateId(lock) && !lock.equals(user.getUserId())) {
        throw new MorseException(MorseException.NOT_OWNER, id);
      }

      Properties p = new Properties();
      Reader reader = ofs.getReader(id);
      p.load(reader);
      reader.close();
      p.setProperty(IAttribute.M_LOCK, "");
      Writer writer = ofs.getWriter(id);
      p.store(writer);
      writer.close();

    } catch (Exception e) {
      log.error(e);
    } finally {
      if (log.t4()) log.debug("xUNLOCK: " + id + ' ' + user);
      ofs.unlock(id);
    }
  }
  private IQueryResult querySave(ICompiledQuery code, UserInformation user) throws MorseException {

    String parentId = code.getString(4);
    String format = code.getString(6);
    String typeName = code.getString(2);
    IType type = typeProvider.get(typeName);
    if (type == null) throw new MorseException(MorseException.TYPE_NOT_FOUND, typeName);
    ObjectFileStore[] fs = fileStore.get(typeName);
    if (fs == null) throw new MorseException(MorseException.TABLE_NOT_FOUND, typeName);

    if (!aclManager.hasCreate(user, type.getAccessAcl()))
      throw new MorseException(
          MorseException.ACCESS_DENIED_CREATE,
          new String[] {"type", type.getName(), type.getAccessAcl()});

    IQueryResult parent = getConnection().fetch(parentId, user, false);
    if (!parent.next()) {
      parent.close();
      throw new MorseException(MorseException.OBJECT_NOT_FOUND, parentId);
    }
    String parentType = parent.getString(IAttribute.M_TYPE);
    parent.close();

    String newId = objectManager.newObjectId(typeProvider.get(IType.TYPE_MC_CONTENT), driver);

    Btc obj = ServerTypesUtil.createBtc(getConnection(), type);
    obj.initObject(type, connection, null, typeProvider, user, aclManager);
    obj.setString(IAttribute.MC_FORMAT, format);
    obj.setString(IAttribute.M_ACL, aclManager.getNewContentAcl(user, type));
    obj.doInsertCheck();

    try {

      driver.storeObject(type, obj, newId);
      // TODO create files in m_object etc.
      return new FileAbstractSaveResult(this, newId, obj, fs, parentId, parentType);

    } catch (Exception e) {
      log.error(e);
      // TODO rollback !!!!
    }
    return null;
  }