Exemplo n.º 1
0
  @Test
  public void testUpdateReadonlyMultidir() throws Exception {
    MultiDirectory readonlyMultidir =
        (MultiDirectory) directoryService.getDirectory("readonlymulti");
    MultiDirectorySession readonlyDir = (MultiDirectorySession) readonlyMultidir.getSession();
    Session dir1 = memdir1.getSession();
    Session dir2 = memdir2.getSession();
    Session dir3 = memdir3.getSession();

    // multi-subdirs update
    DocumentModel e = readonlyDir.getEntry("1");
    assertEquals("foo1", e.getProperty("schema3", "thefoo"));
    assertEquals("bar1", e.getProperty("schema3", "thebar"));
    e.setProperty("schema3", "thefoo", "fffooo1");
    e.setProperty("schema3", "thebar", "babar1");

    readonlyDir.updateEntry(e);
    e = readonlyDir.getEntry("1");
    // the multidirectory entry was not updated
    assertEquals("foo1", e.getProperty("schema3", "thefoo"));
    assertEquals("bar1", e.getProperty("schema3", "thebar"));

    // neither the underlying directories
    assertEquals("foo1", dir1.getEntry("1").getProperty("schema1", "foo"));
    assertEquals("bar1", dir2.getEntry("1").getProperty("schema2", "bar"));
    assertNull(dir3.getEntry("1"));
  }
Exemplo n.º 2
0
  @Test
  public void testReadOnlyEntryFromMultidirectory() throws Exception {
    MultiDirectory readonlyMultidir =
        (MultiDirectory) directoryService.getDirectory("readonlymulti");
    MultiDirectorySession readonlyDir = (MultiDirectorySession) readonlyMultidir.getSession();

    // all should be readonly
    assertTrue(BaseSession.isReadOnlyEntry(readonlyDir.getEntry("1")));
    assertTrue(BaseSession.isReadOnlyEntry(readonlyDir.getEntry("2")));
    assertTrue(BaseSession.isReadOnlyEntry(readonlyDir.getEntry("3")));
    assertTrue(BaseSession.isReadOnlyEntry(readonlyDir.getEntry("4")));
  }
 @Override
 public DocumentModel createEntry(Map<String, Object> fieldMap) {
   if (!isCurrentUserAllowed(SecurityConstants.WRITE)) {
     return null;
   }
   init();
   final Object rawid = fieldMap.get(schemaIdField);
   if (rawid == null) {
     throw new DirectoryException(String.format("Entry is missing id field '%s'", schemaIdField));
   }
   final String id = String.valueOf(rawid); // XXX allow longs too
   for (SourceInfo sourceInfo : sourceInfos) {
     if (!sourceInfo.source.creation) {
       continue;
     }
     for (SubDirectoryInfo dirInfo : sourceInfo.subDirectoryInfos) {
       Map<String, Object> map = new HashMap<String, Object>();
       map.put(dirInfo.idField, id);
       for (Entry<String, String> e : dirInfo.fromSource.entrySet()) {
         map.put(e.getValue(), fieldMap.get(e.getKey()));
       }
       dirInfo.getSession().createEntry(map);
     }
     return getEntry(id);
   }
   throw new DirectoryException(
       String.format("Directory '%s' has no source allowing creation", directory.getName()));
 }
 @Override
 public void close() throws DirectoryException {
   try {
     if (sourceInfos == null) {
       return;
     }
     DirectoryException exc = null;
     for (SourceInfo sourceInfo : sourceInfos) {
       for (SubDirectoryInfo subDirectoryInfo : sourceInfo.subDirectoryInfos) {
         Session session = subDirectoryInfo.session;
         subDirectoryInfo.session = null;
         if (session != null) {
           try {
             session.close();
           } catch (DirectoryException e) {
             // remember exception, we want to close all session
             // first
             if (exc == null) {
               exc = e;
             } else {
               // we can't reraise both, log this one
               log.error("Error closing directory " + subDirectoryInfo.dirName, e);
             }
           }
         }
       }
       if (exc != null) {
         throw exc;
       }
     }
   } finally {
     directory.removeSession(this);
   }
 }
 public MultiDirectorySession(MultiDirectory directory) {
   directoryService = Framework.getService(DirectoryService.class);
   schemaManager = Framework.getLocalService(SchemaManager.class);
   this.directory = directory;
   descriptor = directory.getDescriptor();
   schemaName = descriptor.schemaName;
   schemaIdField = descriptor.idField;
   schemaPasswordField = descriptor.passwordField;
   permissions = descriptor.permissions;
 }
  @Override
  @SuppressWarnings("boxing")
  public DocumentModelList query(
      Map<String, Serializable> filter,
      Set<String> fulltext,
      Map<String, String> orderBy,
      boolean fetchReferences) {
    // list of entries
    final DocumentModelList results = new DocumentModelListImpl();
    if (!isCurrentUserAllowed(SecurityConstants.READ)) {
      return results;
    }
    init();

    // entry ids already seen (mapped to the source name)
    final Map<String, String> seen = new HashMap<String, String>();
    if (fulltext == null) {
      fulltext = Collections.emptySet();
    }
    Set<String> readOnlyEntries = new HashSet<String>();

    for (SourceInfo sourceInfo : sourceInfos) {
      // accumulated map for each entry
      final Map<String, Map<String, Object>> maps = new HashMap<String, Map<String, Object>>();
      // number of dirs seen for each entry
      final Map<String, Integer> counts = new HashMap<String, Integer>();

      // list of optional dirs where filter matches default values
      List<SubDirectoryInfo> optionalDirsMatching = new ArrayList<SubDirectoryInfo>();
      for (SubDirectoryInfo dirInfo : sourceInfo.subDirectoryInfos) {
        // compute filter
        final Map<String, Serializable> dirFilter = new HashMap<String, Serializable>();
        for (Entry<String, Serializable> e : filter.entrySet()) {
          final String fieldName = dirInfo.fromSource.get(e.getKey());
          if (fieldName == null) {
            continue;
          }
          dirFilter.put(fieldName, e.getValue());
        }
        if (dirInfo.isOptional) {
          // check if filter matches directory default values
          boolean matches = true;
          for (Map.Entry<String, Serializable> dirFilterEntry : dirFilter.entrySet()) {
            Object defaultValue = dirInfo.defaultEntry.get(dirFilterEntry.getKey());
            Object filterValue = dirFilterEntry.getValue();
            if (defaultValue == null && filterValue != null) {
              matches = false;
            } else if (defaultValue != null && !defaultValue.equals(filterValue)) {
              matches = false;
            }
          }
          if (matches) {
            optionalDirsMatching.add(dirInfo);
          }
        }
        // compute fulltext
        Set<String> dirFulltext = new HashSet<String>();
        for (String sourceFieldName : fulltext) {
          final String fieldName = dirInfo.fromSource.get(sourceFieldName);
          if (fieldName != null) {
            dirFulltext.add(fieldName);
          }
        }
        // make query to subdirectory
        DocumentModelList l =
            dirInfo.getSession().query(dirFilter, dirFulltext, null, fetchReferences);
        for (DocumentModel entry : l) {
          final String id = entry.getId();
          Map<String, Object> map = maps.get(id);
          if (map == null) {
            map = new HashMap<String, Object>();
            maps.put(id, map);
            counts.put(id, 1);
          } else {
            counts.put(id, counts.get(id) + 1);
          }
          for (Entry<String, String> e : dirInfo.toSource.entrySet()) {
            map.put(e.getValue(), entry.getProperty(dirInfo.dirSchemaName, e.getKey()));
          }
          if (BaseSession.isReadOnlyEntry(entry)) {
            readOnlyEntries.add(id);
          }
        }
      }
      // add default entry values for optional dirs
      for (SubDirectoryInfo dirInfo : optionalDirsMatching) {
        // add entry for every data found in other dirs
        Set<String> existingIds =
            new HashSet<String>(
                dirInfo
                    .getSession()
                    .getProjection(Collections.<String, Serializable>emptyMap(), dirInfo.idField));
        for (Entry<String, Map<String, Object>> result : maps.entrySet()) {
          final String id = result.getKey();
          if (!existingIds.contains(id)) {
            counts.put(id, counts.get(id) + 1);
            final Map<String, Object> map = result.getValue();
            for (Entry<String, String> e : dirInfo.toSource.entrySet()) {
              String value = e.getValue();
              if (!map.containsKey(value)) {
                map.put(value, dirInfo.defaultEntry.get(e.getKey()));
              }
            }
          }
        }
      }
      // intersection, ignore entries not in all subdirectories
      final int numdirs = sourceInfo.subDirectoryInfos.size();
      for (Iterator<String> it = maps.keySet().iterator(); it.hasNext(); ) {
        final String id = it.next();
        if (counts.get(id) != numdirs) {
          it.remove();
        }
      }
      // now create entries
      ((ArrayList<?>) results).ensureCapacity(results.size() + maps.size());
      for (Entry<String, Map<String, Object>> e : maps.entrySet()) {
        final String id = e.getKey();
        if (seen.containsKey(id)) {
          log.warn(
              String.format(
                  "Entry '%s' is present in source '%s' but also in source '%s'. "
                      + "The second one will be ignored.",
                  id, seen.get(id), sourceInfo.source.name));
          continue;
        }
        final Map<String, Object> map = e.getValue();
        seen.put(id, sourceInfo.source.name);
        final DocumentModel entry =
            BaseSession.createEntryModel(null, schemaName, id, map, readOnlyEntries.contains(id));
        results.add(entry);
      }
    }
    if (orderBy != null && !orderBy.isEmpty()) {
      directory.orderEntries(results, orderBy);
    }
    return results;
  }
  /** Recomputes all the info needed for efficient access. */
  private void recomputeSourceInfos() throws DirectoryException {

    final Schema schema = schemaManager.getSchema(schemaName);
    if (schema == null) {
      throw new DirectoryException(
          String.format("Directory '%s' has unknown schema '%s'", directory.getName(), schemaName));
    }
    final Set<String> sourceFields = new HashSet<String>();
    for (Field f : schema.getFields()) {
      sourceFields.add(f.getName().getLocalName());
    }
    if (!sourceFields.contains(schemaIdField)) {
      throw new DirectoryException(
          String.format(
              "Directory '%s' schema '%s' has no id field '%s'",
              directory.getName(), schemaName, schemaIdField));
    }

    List<SourceInfo> newSourceInfos = new ArrayList<SourceInfo>(2);
    for (SourceDescriptor source : descriptor.sources) {
      int ndirs = source.subDirectories.length;
      if (ndirs == 0) {
        throw new DirectoryException(
            String.format(
                "Directory '%s' source '%s' has no subdirectories",
                directory.getName(), source.name));
      }

      final List<SubDirectoryInfo> subDirectoryInfos = new ArrayList<SubDirectoryInfo>(ndirs);

      SubDirectoryInfo authDirectoryInfo = null;
      boolean hasRequiredDir = false;
      for (SubDirectoryDescriptor subDir : source.subDirectories) {
        final String dirName = subDir.name;
        final String dirSchemaName = directoryService.getDirectorySchema(dirName);
        final String dirIdField = directoryService.getDirectoryIdField(dirName);
        final boolean dirIsAuth = directoryService.getDirectoryPasswordField(dirName) != null;
        final Map<String, String> fromSource = new HashMap<String, String>();
        final Map<String, String> toSource = new HashMap<String, String>();
        final Map<String, Serializable> defaultEntry = new HashMap<String, Serializable>();
        final boolean dirIsOptional = subDir.isOptional;

        // XXX check authenticating
        final Schema dirSchema = schemaManager.getSchema(dirSchemaName);
        if (dirSchema == null) {
          throw new DirectoryException(
              String.format(
                  "Directory '%s' source '%s' subdirectory '%s' " + "has unknown schema '%s'",
                  directory.getName(), source.name, dirName, dirSchemaName));
        }
        // record default field mappings if same name and record default
        // values
        final Set<String> dirSchemaFields = new HashSet<String>();
        for (Field f : dirSchema.getFields()) {
          final String fieldName = f.getName().getLocalName();
          dirSchemaFields.add(fieldName);
          if (sourceFields.contains(fieldName)) {
            // XXX check no duplicates!
            fromSource.put(fieldName, fieldName);
            toSource.put(fieldName, fieldName);
          }
          // XXX cast to Serializable
          defaultEntry.put(fieldName, (Serializable) f.getDefaultValue());
        }
        // treat renamings
        // XXX id field ?
        for (FieldDescriptor field : subDir.fields) {
          final String sourceFieldName = field.forField;
          final String fieldName = field.name;
          if (!sourceFields.contains(sourceFieldName)) {
            throw new DirectoryException(
                String.format(
                    "Directory '%s' source '%s' subdirectory '%s' "
                        + "has mapping for unknown field '%s'",
                    directory.getName(), source.name, dirName, sourceFieldName));
          }
          if (!dirSchemaFields.contains(fieldName)) {
            throw new DirectoryException(
                String.format(
                    "Directory '%s' source '%s' subdirectory '%s' "
                        + "has mapping of unknown field' '%s'",
                    directory.getName(), source.name, dirName, fieldName));
          }
          fromSource.put(sourceFieldName, fieldName);
          toSource.put(fieldName, sourceFieldName);
        }
        SubDirectoryInfo subDirectoryInfo =
            new SubDirectoryInfo(
                dirName,
                dirSchemaName,
                dirIdField,
                dirIsAuth,
                fromSource,
                toSource,
                defaultEntry,
                dirIsOptional);
        subDirectoryInfos.add(subDirectoryInfo);

        if (dirIsAuth) {
          if (authDirectoryInfo != null) {
            throw new DirectoryException(
                String.format(
                    "Directory '%s' source '%s' has two subdirectories "
                        + "with a password field, '%s' and '%s'",
                    directory.getName(), source.name, authDirectoryInfo.dirName, dirName));
          }
          authDirectoryInfo = subDirectoryInfo;
        }
        if (!dirIsOptional) {
          hasRequiredDir = true;
        }
      }
      if (isAuthenticating() && authDirectoryInfo == null) {
        throw new DirectoryException(
            String.format(
                "Directory '%s' source '%s' has no subdirectory " + "with a password field",
                directory.getName(), source.name));
      }
      if (!hasRequiredDir) {
        throw new DirectoryException(
            String.format(
                "Directory '%s' source '%s' only has optional subdirectories: "
                    + "no directory can be used has a reference.",
                directory.getName(), source.name));
      }
      newSourceInfos.add(new SourceInfo(source, subDirectoryInfos, authDirectoryInfo));
    }
    sourceInfos = newSourceInfos;
  }
Exemplo n.º 8
0
  @Before
  public void setUp() throws Exception {
    // mem dir factory
    directoryService = Framework.getLocalService(DirectoryService.class);
    memoryDirectoryFactory = new MemoryDirectoryFactory();
    directoryService.registerDirectory("memdirs", memoryDirectoryFactory);

    // create and register mem directories
    Map<String, Object> e;

    // dir 1
    Set<String> schema1Set = new HashSet<String>(Arrays.asList("uid", "foo"));
    memdir1 = new MemoryDirectory("dir1", "schema1", schema1Set, "uid", "foo");
    memoryDirectoryFactory.registerDirectory(memdir1);

    Session dir1 = memdir1.getSession();
    e = new HashMap<String, Object>();
    e.put("uid", "1");
    e.put("foo", "foo1");
    dir1.createEntry(e);
    e = new HashMap<String, Object>();
    e.put("uid", "2");
    e.put("foo", "foo2");
    dir1.createEntry(e);

    // dir 2
    Set<String> schema2Set = new HashSet<String>(Arrays.asList("id", "bar"));
    memdir2 = new MemoryDirectory("dir2", "schema2", schema2Set, "id", null);
    memoryDirectoryFactory.registerDirectory(memdir2);

    Session dir2 = memdir2.getSession();
    e = new HashMap<String, Object>();
    e.put("id", "1");
    e.put("bar", "bar1");
    dir2.createEntry(e);
    e = new HashMap<String, Object>();
    e.put("id", "2");
    e.put("bar", "bar2");
    dir2.createEntry(e);

    // dir 3
    Set<String> schema3Set = new HashSet<String>(Arrays.asList("uid", "thefoo", "thebar"));
    memdir3 = new MemoryDirectory("dir3", "schema3", schema3Set, "uid", "thefoo");
    memoryDirectoryFactory.registerDirectory(memdir3);

    Session dir3 = memdir3.getSession();
    e = new HashMap<String, Object>();
    e.put("uid", "3");
    e.put("thefoo", "foo3");
    e.put("thebar", "bar3");
    dir3.createEntry(e);
    e = new HashMap<String, Object>();
    e.put("uid", "4");
    e.put("thefoo", "foo4");
    e.put("thebar", "bar4");
    dir3.createEntry(e);

    // the multi directory
    multiDir = (MultiDirectory) directoryService.getDirectory("multi");
    dir = (MultiDirectorySession) multiDir.getSession();
  }