View Javadoc
1   package emissary.directory;
2   
3   import emissary.util.xml.SaferJDOMUtil;
4   
5   import jakarta.annotation.Nullable;
6   import org.jdom2.Document;
7   import org.jdom2.Element;
8   import org.jdom2.JDOMException;
9   import org.slf4j.Logger;
10  import org.slf4j.LoggerFactory;
11  
12  import java.util.List;
13  import java.util.Map;
14  
15  /**
16   * This class acts as a container and producer for turning a directory entry list into a full xml document
17   */
18  public class DirectoryXmlContainer {
19  
20      private static final Logger logger = LoggerFactory.getLogger(DirectoryXmlContainer.class);
21  
22      public static final String DIRECTORY = "directory";
23      public static final String LOC_ATTR = "location";
24      public static final String DATAID_ATTR = "dataid";
25  
26      /**
27       * Build an xml document from the contents of a directory place
28       */
29      public static Document buildDocument(final IDirectoryPlace dir) {
30          final Element root = new Element(DIRECTORY);
31          root.setAttribute(LOC_ATTR, dir.getKey());
32  
33          // Each directory entry
34          for (final String dataId : dir.getEntryKeys()) {
35              final DirectoryEntryList list = dir.getEntryList(dataId);
36              if (list != null) {
37                  final Element listEl = list.getXml();
38                  listEl.setAttribute(DATAID_ATTR, dataId);
39                  root.addContent(listEl);
40              }
41          }
42  
43          return new Document(root);
44      }
45  
46      /**
47       * Build an xml document from the map.
48       * 
49       * @param map the map of entries
50       * @param loc directory location key
51       */
52      public static Document buildDocument(final DirectoryEntryMap map, final String loc) {
53          final Element root = new Element(DIRECTORY);
54          root.setAttribute(LOC_ATTR, loc);
55  
56          // Each directory entry
57          for (final Map.Entry<String, DirectoryEntryList> entry : map.entrySet()) {
58              final String dataId = entry.getKey();
59              final DirectoryEntryList list = entry.getValue();
60              if (list != null) {
61                  final Element listEl = list.getXml();
62                  listEl.setAttribute(DATAID_ATTR, dataId);
63                  root.addContent(listEl);
64              }
65          }
66  
67          return new Document(root);
68      }
69  
70      /**
71       * Build an xml document from the contents of the directory as if proxied through the place itself. Except when the
72       * entries actually belong to the requester.
73       * 
74       * @param dir the directory that will act as a proxy
75       * @param requester the directory doing the requesting
76       */
77      public static Document buildProxyDocument(final IRemoteDirectory dir, final String requester) {
78          final String proxyKey = dir.getKey();
79          final Element root = new Element(DIRECTORY);
80          root.setAttribute(LOC_ATTR, proxyKey);
81  
82          logger.debug("Building proxy view of dir contents for {}", requester);
83  
84          // Each directory entry
85          for (final String dataId : dir.getEntryKeys()) {
86              final DirectoryEntryList list = dir.getEntryList(dataId);
87              logger.debug("List of {} for {} has {} entries", dataId, requester, list.size());
88              // set up proxy for each entry
89              for (final DirectoryEntry e : list) {
90                  e.proxyFor(proxyKey);
91              }
92  
93              // Add them to the xml
94              if (!list.isEmpty()) {
95                  final Element listEl = list.getXml();
96                  listEl.setAttribute(DATAID_ATTR, dataId);
97                  root.addContent(listEl);
98              }
99          }
100         return new Document(root);
101     }
102 
103     /**
104      * Build an xml string from the contents of a directory place This method pulls the main entryMap of the directory.
105      * 
106      * @param dir the directory to pull the entryMap contents from
107      * @return xml string representing the keys
108      */
109     public static String toXmlString(final IDirectoryPlace dir) {
110         final Document jdom = buildDocument(dir);
111         return SaferJDOMUtil.toString(jdom);
112     }
113 
114     /**
115      * Build an xml string from the contents of a directory place making it appear that the place represented by proxyKey
116      * acts as a proxy for all or the keys in the directory map
117      * 
118      * @param dir the directory to pull the entryMap contents from
119      * @param proxyKey place to appear as the proxy
120      * @param requester the key of the remote directory that is requesting the local directory contents
121      * @return xml string representing the proxied keys
122      */
123     public static String toXmlString(final IDirectoryPlace dir, @Nullable final String proxyKey, final String requester) {
124         logger.debug("Building xml string for {}", requester);
125         final String xml;
126         if ((proxyKey == null) || !(dir instanceof IRemoteDirectory)) {
127             xml = toXmlString(dir);
128         } else {
129             final Document jdom = buildProxyDocument((IRemoteDirectory) dir, requester);
130             xml = SaferJDOMUtil.toString(jdom);
131         }
132         return xml;
133     }
134 
135     /**
136      * Build a DirectoryEntryList map from string xml
137      */
138     public static DirectoryEntryMap buildEntryListMap(final String xml) throws JDOMException {
139         final Document jdom = SaferJDOMUtil.createDocument(xml);
140         return buildEntryListMap(jdom);
141     }
142 
143     /**
144      * Build a DirectoryEntryList map from a JDOM document
145      */
146     public static DirectoryEntryMap buildEntryListMap(final Document jdom) {
147         final Element el = jdom.getRootElement();
148         return buildEntryListMap(el);
149     }
150 
151     /**
152      * Build a DirectoryEntryMap from a JDOM Element
153      */
154     public static DirectoryEntryMap buildEntryListMap(final Element el) {
155         final DirectoryEntryMap map = new DirectoryEntryMap();
156         final List<Element> entryLists = el.getChildren(DirectoryEntryList.ENTRYLIST);
157         for (final Element listElement : entryLists) {
158             final DirectoryEntryList d = DirectoryEntryList.fromXml(listElement);
159             final String dataId = listElement.getAttributeValue(DATAID_ATTR);
160             map.put(dataId, d);
161         }
162         logger.debug("Constructed map of {} directory entry lists from xml", map.size());
163 
164         return map;
165     }
166 
167     /** This class is not meant to be instantiated. */
168     private DirectoryXmlContainer() {}
169 }