001    /*
002     * $Revision: 1 $ $Date: 08.05.2009 15:51:37 $
003     *
004     * This file is part of ***  M y C o R e  ***
005     * See http://www.mycore.de/ for details.
006     *
007     * This program is free software; you can use it, redistribute it
008     * and / or modify it under the terms of the GNU General Public License
009     * (GPL) as published by the Free Software Foundation; either version 2
010     * of the License or (at your option) any later version.
011     *
012     * This program is distributed in the hope that it will be useful, but
013     * WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
015     * GNU General Public License for more details.
016     *
017     * You should have received a copy of the GNU General Public License
018     * along with this program, in a file called gpl.txt or license.txt.
019     * If not, write to the Free Software Foundation Inc.,
020     * 59 Temple Place - Suite 330, Boston, MA  02111-1307 USA
021     */
022    
023    package org.mycore.datamodel.metadata.validator;
024    
025    import static org.jdom.Namespace.XML_NAMESPACE;
026    import static org.mycore.common.MCRConstants.XLINK_NAMESPACE;
027    import static org.mycore.common.MCRConstants.XSI_NAMESPACE;
028    
029    import java.io.IOException;
030    import java.io.InputStream;
031    import java.util.ArrayList;
032    import java.util.Collection;
033    import java.util.Date;
034    import java.util.HashMap;
035    import java.util.Iterator;
036    import java.util.List;
037    import java.util.Map;
038    import java.util.Properties;
039    import java.util.Map.Entry;
040    
041    import org.apache.log4j.Logger;
042    import org.jdom.Document;
043    import org.jdom.Element;
044    import org.jdom.JDOMException;
045    import org.jdom.input.SAXBuilder;
046    import org.jdom.xpath.XPath;
047    import org.mycore.access.MCRAccessManager;
048    import org.mycore.common.MCRConfiguration;
049    import org.mycore.common.MCRException;
050    import org.mycore.common.MCRSessionMgr;
051    import org.mycore.common.MCRUtils;
052    import org.mycore.datamodel.metadata.MCRMetaAccessRule;
053    import org.mycore.datamodel.metadata.MCRMetaAddress;
054    import org.mycore.datamodel.metadata.MCRMetaBoolean;
055    import org.mycore.datamodel.metadata.MCRMetaClassification;
056    import org.mycore.datamodel.metadata.MCRMetaDerivateLink;
057    import org.mycore.datamodel.metadata.MCRMetaHistoryDate;
058    import org.mycore.datamodel.metadata.MCRMetaISBN;
059    import org.mycore.datamodel.metadata.MCRMetaISO8601Date;
060    import org.mycore.datamodel.metadata.MCRMetaInstitutionName;
061    import org.mycore.datamodel.metadata.MCRMetaInterface;
062    import org.mycore.datamodel.metadata.MCRMetaLangText;
063    import org.mycore.datamodel.metadata.MCRMetaLink;
064    import org.mycore.datamodel.metadata.MCRMetaLinkID;
065    import org.mycore.datamodel.metadata.MCRMetaNBN;
066    import org.mycore.datamodel.metadata.MCRMetaNumber;
067    import org.mycore.datamodel.metadata.MCRMetaPersonName;
068    import org.mycore.datamodel.metadata.MCRObject;
069    import org.mycore.datamodel.metadata.MCRObjectID;
070    import org.mycore.user.MCRUserMgr;
071    
072    /**
073     * @author Thomas Scheffler (yagee)
074     * @version $Revision: 1 $ $Date: 08.05.2009 15:51:37 $
075     */
076    public class MCREditorOutValidator {
077    
078        private static Logger LOGGER = Logger.getLogger(MCREditorOutValidator.class);
079    
080        private static Map<String, MCREditorMetadataValidator> VALIDATOR_MAP = getValidatorMap();
081    
082        private static Map<String, Class<? extends MCRMetaInterface>> CLASS_MAP = new HashMap<String, Class<? extends MCRMetaInterface>>();
083    
084        private static final String CONFIG_PREFIX = "MCR.EditorOutValidator.";
085    
086        private static final SAXBuilder SAX_BUILDER = new org.jdom.input.SAXBuilder();
087    
088        private Document input;
089    
090        private MCRObjectID id;
091    
092        private List<String> errorlog;
093    
094        /**
095         * instantiate the validator with the editor input <code>jdom_in</code>.
096         * 
097         * <code>id</code> will be set as the MCRObjectID for the resulting object
098         * that can be fetched with <code>generateValidMyCoReObject()</code>
099         * 
100         * @param jdom_in
101         *            editor input
102         * @throws IOException 
103         * @throws JDOMException 
104         */
105        public MCREditorOutValidator(Document jdom_in, MCRObjectID id) throws JDOMException, IOException {
106            this.errorlog = new ArrayList<String>();
107            this.input = jdom_in;
108            this.id = id;
109            if (LOGGER.isDebugEnabled()) {
110                LOGGER.debug("XML before validation:\n" + new String(MCRUtils.getByteArray(input)));
111            }
112            checkObject();
113            if (LOGGER.isDebugEnabled()) {
114                LOGGER.debug("XML after validation:\n" + new String(MCRUtils.getByteArray(input)));
115            }
116        }
117    
118        /**
119         * tries to generate a valid MCRObject as JDOM Document.
120         * 
121         * @return MCRObject
122         */
123        public Document generateValidMyCoReObject() {
124            MCRObject obj = new MCRObject();
125            try {
126                // load the JDOM object
127                XPath editorOutput = XPath.newInstance("/mycoreobject/*/*/*[@editor.output]");
128                for (Object node : editorOutput.selectNodes(input)) {
129                    Element e = (Element) node;
130                    LOGGER.debug("removing \"editor.output\" Attribute from " + e.getName());
131                    e.removeAttribute("editor.output");
132                }
133                byte[] xml = MCRUtils.getByteArray(input);
134                obj.setFromXML(xml, true);
135                Date curTime = new Date();
136                obj.getService().setDate("createdate", curTime);
137                obj.getService().setDate("modifydate", curTime);
138    
139                // return the XML tree
140                input = obj.createXML();
141            } catch (MCRException e) {
142                errorlog.add(e.getMessage());
143    
144                Exception ex = e.getException();
145    
146                if (ex != null) {
147                    errorlog.add(ex.getMessage());
148                }
149            } catch (JDOMException e) {
150                errorlog.add(e.getMessage());
151            }
152            return input;
153        }
154    
155        /**
156         * returns a List of Error log entries
157         * 
158         * @return log entries for the whole validation process
159         */
160        public List<String> getErrorLog() {
161            return errorlog;
162        }
163    
164        private static Map<String, MCREditorMetadataValidator> getValidatorMap() {
165            Map<String, MCREditorMetadataValidator> map = new HashMap<String, MCREditorMetadataValidator>();
166            map.put(MCRMetaBoolean.class.getSimpleName(), getObjectCheckInstance(MCRMetaBoolean.class));
167            map.put(MCRMetaPersonName.class.getSimpleName(), getObjectCheckWithLangInstance(MCRMetaPersonName.class));
168            map.put(MCRMetaInstitutionName.class.getSimpleName(), getObjectCheckWithLangInstance(MCRMetaInstitutionName.class));
169            map.put(MCRMetaAddress.class.getSimpleName(), new MCRMetaAdressCheck());
170            map.put(MCRMetaNumber.class.getSimpleName(), getObjectCheckWithLangNotEmptyInstance(MCRMetaNumber.class));
171            map.put(MCRMetaLinkID.class.getSimpleName(), getObjectCheckWithLinksInstance(MCRMetaLinkID.class));
172            map.put(MCRMetaDerivateLink.class.getSimpleName(), getObjectCheckWithLinksInstance(MCRMetaDerivateLink.class));
173            map.put(MCRMetaLink.class.getSimpleName(), getObjectCheckWithLinksInstance(MCRMetaLink.class));
174            map.put(MCRMetaISO8601Date.class.getSimpleName(), getObjectCheckWithLangNotEmptyInstance(MCRMetaISO8601Date.class));
175            map.put(MCRMetaLangText.class.getSimpleName(), getObjectCheckWithLangNotEmptyInstance(MCRMetaLangText.class));
176            map.put(MCRMetaAccessRule.class.getSimpleName(), getObjectCheckInstance(MCRMetaAccessRule.class));
177            map.put(MCRMetaNBN.class.getSimpleName(), getObjectCheckInstance(MCRMetaNBN.class));
178            map.put(MCRMetaISBN.class.getSimpleName(), getObjectCheckInstance(MCRMetaISBN.class));
179            map.put(MCRMetaClassification.class.getSimpleName(), new MCRMetaClassificationCheck());
180            map.put(MCRMetaHistoryDate.class.getSimpleName(), new MCRMetaHistoryDateCheck());
181            Properties props = MCRConfiguration.instance().getProperties(CONFIG_PREFIX + "class.");
182            for (Entry<Object, Object> entry : props.entrySet()) {
183                try {
184                    String className = entry.getKey().toString();
185                    className = className.substring(className.lastIndexOf('.') + 1);
186                    LOGGER.info("Adding Validator " + entry.getValue().toString() + " for class " + className);
187                    @SuppressWarnings("unchecked")
188                    Class<? extends MCREditorMetadataValidator> cl = (Class<? extends MCREditorMetadataValidator>) Class.forName(entry
189                            .getValue().toString());
190                    map.put(className, cl.newInstance());
191                } catch (Exception e) {
192                    final String msg = "Cannot instantiate " + entry.getValue() + " as validator for class " + entry.getKey();
193                    LOGGER.error(msg);
194                    throw new MCRException(msg, e);
195                }
196            }
197            return map;
198        }
199    
200        @SuppressWarnings("unchecked")
201        public static Class<? extends MCRMetaInterface> getClass(String mcrclass) throws ClassNotFoundException {
202            Class<? extends MCRMetaInterface> clazz = CLASS_MAP.get(mcrclass);
203            if (clazz == null) {
204                clazz = (Class<? extends MCRMetaInterface>) Class.forName("org.mycore.datamodel.metadata." + mcrclass);
205                CLASS_MAP.put(mcrclass, clazz);
206            }
207            return clazz;
208        }
209    
210        public static String checkMetaObject(Element datasubtag, Class<? extends MCRMetaInterface> metaClass, boolean keepLang) {
211            if (!keepLang) {
212                datasubtag.removeAttribute("lang", XML_NAMESPACE);
213            }
214            MCRMetaInterface test = null;
215            try {
216                test = metaClass.newInstance();
217            } catch (Exception e) {
218                throw new MCRException("Could not instantiate " + metaClass.getCanonicalName());
219            }
220            test.setFromDOM(datasubtag);
221    
222            if (!test.isValid()) {
223                throw new MCRException("Element " + datasubtag.getName() + " is not valid.");
224            }
225            return null;
226        }
227    
228        public static String checkMetaObjectWithLang(Element datasubtag, Class<? extends MCRMetaInterface> metaClass) {
229            if (datasubtag.getAttribute("lang") != null) {
230                datasubtag.getAttribute("lang").setNamespace(XML_NAMESPACE);
231                LOGGER.warn("namespace add for xml:lang attribute in " + datasubtag.getName());
232            }
233            return checkMetaObject(datasubtag, metaClass, true);
234        }
235    
236        public static String checkMetaObjectWithLangNotEmpty(Element datasubtag, Class<? extends MCRMetaInterface> metaClass) {
237            String text = datasubtag.getTextTrim();
238            if ((text == null) || (text.length() == 0)) {
239                return "Element " + datasubtag.getName() + " has no text.";
240            }
241            return checkMetaObjectWithLang(datasubtag, metaClass);
242        }
243    
244        public static String checkMetaObjectWithLinks(Element datasubtag, Class<? extends MCRMetaInterface> metaClass) {
245            if (datasubtag.getAttributeValue("href") == null && datasubtag.getAttributeValue("href", XLINK_NAMESPACE) == null) {
246                return datasubtag.getName() + " has no href attribute defined";
247            }
248            if (datasubtag.getAttribute("xtype") != null) {
249                datasubtag.getAttribute("xtype").setNamespace(XLINK_NAMESPACE).setName("type");
250            } else if (datasubtag.getAttribute("type") != null && datasubtag.getAttribute("type", XLINK_NAMESPACE) == null) {
251                datasubtag.getAttribute("type").setNamespace(XLINK_NAMESPACE);
252                LOGGER.warn("namespace add for xlink:type attribute in " + datasubtag.getName());
253            }
254            if (datasubtag.getAttribute("href") != null) {
255                datasubtag.getAttribute("href").setNamespace(XLINK_NAMESPACE);
256                LOGGER.warn("namespace add for xlink:href attribute in " + datasubtag.getName());
257            }
258    
259            if (datasubtag.getAttribute("title") != null) {
260                datasubtag.getAttribute("title").setNamespace(XLINK_NAMESPACE);
261                LOGGER.warn("namespace add for xlink:title attribute in " + datasubtag.getName());
262            }
263    
264            if (datasubtag.getAttribute("label") != null) {
265                datasubtag.getAttribute("label").setNamespace(XLINK_NAMESPACE);
266                LOGGER.warn("namespace add for xlink:label attribute in " + datasubtag.getName());
267            }
268            return checkMetaObject(datasubtag, metaClass, false);
269        }
270    
271        static MCREditorMetadataValidator getObjectCheckInstance(final Class<? extends MCRMetaInterface> clazz) {
272            return new MCREditorMetadataValidator() {
273                public String checkDataSubTag(Element datasubtag) {
274                    return MCREditorOutValidator.checkMetaObject(datasubtag, clazz, false);
275                }
276            };
277        }
278    
279        static MCREditorMetadataValidator getObjectCheckWithLangInstance(final Class<? extends MCRMetaInterface> clazz) {
280            return new MCREditorMetadataValidator() {
281                public String checkDataSubTag(Element datasubtag) {
282                    return MCREditorOutValidator.checkMetaObjectWithLang(datasubtag, clazz);
283                }
284            };
285        }
286    
287        static MCREditorMetadataValidator getObjectCheckWithLangNotEmptyInstance(final Class<? extends MCRMetaInterface> clazz) {
288            return new MCREditorMetadataValidator() {
289                public String checkDataSubTag(Element datasubtag) {
290                    return MCREditorOutValidator.checkMetaObjectWithLangNotEmpty(datasubtag, clazz);
291                }
292            };
293        }
294    
295        static MCREditorMetadataValidator getObjectCheckWithLinksInstance(final Class<? extends MCRMetaInterface> clazz) {
296            return new MCREditorMetadataValidator() {
297                public String checkDataSubTag(Element datasubtag) {
298                    return MCREditorOutValidator.checkMetaObjectWithLinks(datasubtag, clazz);
299                }
300            };
301        }
302    
303        static class MCRMetaHistoryDateCheck implements MCREditorMetadataValidator {
304            public String checkDataSubTag(Element datasubtag) {
305                @SuppressWarnings("unchecked")
306                List<Element> children = datasubtag.getChildren("text");
307                if (children.size() == 0)
308                    return "history date is empty";
309                for (int i = 0; i < children.size(); i++) {
310                    Element child = children.get(i);
311                    if (child.getAttribute("lang") != null) {
312                        child.getAttribute("lang").setNamespace(XML_NAMESPACE);
313                        LOGGER.warn("namespace add for xml:lang attribute in " + datasubtag.getName());
314                    }
315                }
316                return checkMetaObjectWithLang(datasubtag, MCRMetaHistoryDate.class);
317            }
318        }
319    
320        static class MCRMetaClassificationCheck implements MCREditorMetadataValidator {
321            public String checkDataSubTag(Element datasubtag) {
322                String categid = datasubtag.getAttributeValue("categid");
323                if (categid == null) {
324                    return "Attribute categid is empty";
325                }
326                return checkMetaObject(datasubtag, MCRMetaClassification.class, false);
327            }
328        }
329    
330        static class MCRMetaAdressCheck implements MCREditorMetadataValidator {
331            public String checkDataSubTag(Element datasubtag) {
332                if (datasubtag.getChildren().size() == 0)
333                    return "adress is empty";
334                return checkMetaObjectWithLang(datasubtag, MCRMetaAddress.class);
335            }
336        }
337    
338        /**
339         * @throws IOException 
340         * @throws JDOMException 
341         * 
342         */
343        private void checkObject() throws JDOMException, IOException {
344            // add the namespaces (this is a workaround)
345            org.jdom.Element root = input.getRootElement();
346            root.addNamespaceDeclaration(XLINK_NAMESPACE);
347            root.addNamespaceDeclaration(XSI_NAMESPACE);
348            // set the schema
349            String mcr_schema = "datamodel-" + id.getTypeId() + ".xsd";
350            root.setAttribute("noNamespaceSchemaLocation", mcr_schema, XSI_NAMESPACE);
351            // check the label
352            String label = root.getAttributeValue("label");
353            if ((label == null) || ((label = label.trim()).length() == 0)) {
354                root.setAttribute("label", id.getId());
355            }
356            // remove the path elements from the incoming
357            org.jdom.Element pathes = root.getChild("pathes");
358            if (pathes != null) {
359                root.removeChildren("pathes");
360            }
361            org.jdom.Element structure = root.getChild("structure");
362            if (structure == null) {
363                root.addContent(new Element("structure"));
364            } else {
365                checkObjectStructure(structure);
366            }
367            Element metadata = root.getChild("metadata");
368            checkObjectMetadata(metadata);
369            org.jdom.Element service = root.getChild("service");
370            checkObjectService(root, service);
371        }
372    
373        /**
374         * @param datatag
375         */
376        @SuppressWarnings("unchecked")
377        private boolean checkMetaTags(Element datatag) {
378            String mcrclass = datatag.getAttributeValue("class");
379            List datataglist = datatag.getChildren();
380            Iterator datatagIt = datataglist.iterator();
381    
382            while (datatagIt.hasNext()) {
383                Element datasubtag = (Element) datatagIt.next();
384                MCREditorMetadataValidator validator = VALIDATOR_MAP.get(mcrclass);
385                String returns = null;
386                if (validator != null) {
387                    returns = validator.checkDataSubTag(datasubtag);
388                } else {
389                    LOGGER.warn("Tag <" + datatag.getName() + "> of type " + mcrclass
390                            + " has no validator defined, fallback to default behaviour");
391                    // try to create MCRMetaInterface instance
392                    try {
393                        Class<? extends MCRMetaInterface> metaClass = getClass(mcrclass);
394                        // just checks if class would validate this element
395                        returns = checkMetaObject(datasubtag, metaClass, true);
396                    } catch (ClassNotFoundException e) {
397                        throw new MCRException("Failure while trying fallback. Class not found: " + mcrclass, e);
398                    }
399                }
400                if (returns != null) {
401                    datatagIt.remove();
402                    final String msg = datatag.getName() + ": " + returns;
403                    errorlog.add(msg);
404                }
405            }
406            if (datatag.getChildren().size() == 0) {
407                return false;
408            }
409            return true;
410        }
411    
412        /**
413         * @param service
414         * @throws IOException 
415         * @throws JDOMException 
416         */
417        @SuppressWarnings("unchecked")
418        private void checkObjectService(Element root, Element service) throws JDOMException, IOException {
419            if (service == null) {
420                service = new org.jdom.Element("service");
421                root.addContent(service);
422            }
423            List<Element> servicelist = service.getChildren();
424            boolean hasacls = false;
425            for (Element datatag : servicelist) {
426                checkMetaTags(datatag);
427            }
428            Collection<String> li = MCRAccessManager.getPermissionsForID(id.getId());
429            if ((li != null) && !li.isEmpty()) {
430                hasacls = true;
431            }
432            if (service.getChild("servacls") == null && !hasacls)
433                setDefaultObjectACLs(service);
434        }
435    
436        /**
437         * The method add a default ACL-block.
438         * 
439         * @param service
440         * @throws IOException 
441         * @throws JDOMException 
442         */
443        private void setDefaultObjectACLs(org.jdom.Element service) throws JDOMException, IOException {
444            if (!MCRConfiguration.instance().getBoolean("MCR.Access.AddObjectDefaultRule", true)) {
445                LOGGER.info("Adding object default acl rule is disabled.");
446                return;
447            }
448            String resourcetype = "/editor_default_acls_" + id.getTypeId() + ".xml";
449            String resourcebase = "/editor_default_acls_" + id.getBase() + ".xml";
450            // Read stylesheet and add user
451            InputStream aclxml = MCREditorOutValidator.class.getResourceAsStream(resourcebase);
452            if (aclxml == null) {
453                aclxml = MCREditorOutValidator.class.getResourceAsStream(resourcetype);
454                if (aclxml == null) {
455                    LOGGER.warn("Can't find default object ACL file " + resourcebase.substring(1) + " or " + resourcetype.substring(1));
456                    String resource = "/editor_default_acls.xml"; // fallback
457                    aclxml = MCREditorOutValidator.class.getResourceAsStream(resource);
458                    if (aclxml == null) {
459                        return;
460                    }
461                }
462            }
463            Document xml = SAX_BUILDER.build(aclxml);
464            Element acls = xml.getRootElement().getChild("servacls");
465            if (acls == null) {
466                return;
467            }
468            for (@SuppressWarnings("unchecked")
469            Iterator<Element> it = acls.getChildren().iterator(); it.hasNext();) {
470                Element acl = it.next();
471                Element condition = acl.getChild("condition");
472                if (condition == null) {
473                    continue;
474                }
475                Element rootbool = condition.getChild("boolean");
476                if (rootbool == null) {
477                    continue;
478                }
479                for (@SuppressWarnings("unchecked")
480                Iterator<Element> boolIt = rootbool.getChildren("boolean").iterator(); boolIt.hasNext();) {
481                    Element orbool = boolIt.next();
482                    for (@SuppressWarnings("unchecked")
483                    Iterator<Element> condIt = orbool.getChildren("condition").iterator(); condIt.hasNext();) {
484                        Element firstcond = condIt.next();
485                        if (firstcond == null) {
486                            continue;
487                        }
488                        String value = firstcond.getAttributeValue("value");
489                        if (value == null)
490                            continue;
491                        if (value.equals("$CurrentUser")) {
492                            String thisuser = MCRSessionMgr.getCurrentSession().getCurrentUserID();
493                            firstcond.setAttribute("value", thisuser);
494                            continue;
495                        }
496                        if (value.equals("$CurrentGroup")) {
497                            String thisuser = MCRSessionMgr.getCurrentSession().getCurrentUserID();
498                            String thisgroup = MCRUserMgr.instance().getPrimaryGroupIDOfUser(thisuser);
499                            firstcond.setAttribute("value", thisgroup);
500                            continue;
501                        }
502                        int i = value.indexOf("$CurrentIP");
503                        if (i != -1) {
504                            String thisip = MCRSessionMgr.getCurrentSession().getCurrentIP();
505                            StringBuffer sb = new StringBuffer(64);
506                            sb.append(value.substring(0, i)).append(thisip).append(value.substring(i + 10, value.length()));
507                            firstcond.setAttribute("value", sb.toString());
508                            continue;
509                        }
510                    }
511                }
512            }
513            service.addContent(acls.detach());
514        }
515    
516        /**
517         * @param metadata
518         */
519        @SuppressWarnings("unchecked")
520        private void checkObjectMetadata(Element metadata) {
521            if (metadata.getAttribute("lang") != null) {
522                metadata.getAttribute("lang").setNamespace(XML_NAMESPACE);
523            }
524    
525            List<Element> metadatalist = metadata.getChildren();
526            Iterator<Element> metaIt = metadatalist.iterator();
527    
528            while (metaIt.hasNext()) {
529                Element datatag = (Element) metaIt.next();
530                if (!checkMetaTags(datatag)) {
531                    // e.g. datatag is empty
532                    LOGGER.debug("Removing element :" + datatag.getName());
533                    metaIt.remove();
534                }
535            }
536        }
537    
538        /**
539         * @param structure
540         */
541        @SuppressWarnings("unchecked")
542        private void checkObjectStructure(Element structure) {
543            List<Element> structurelist = structure.getChildren();
544            Iterator<Element> structIt = structurelist.iterator();
545    
546            while (structIt.hasNext()) {
547                Element datatag = (Element) structIt.next();
548                if (!checkMetaTags(datatag)) {
549                    // e.g. datatag is empty
550                    structIt.remove();
551                }
552            }
553        }
554    
555        /**
556         * The method add a default ACL-block.
557         * 
558         * @param service
559         */
560        public static void setDefaultDerivateACLs(org.jdom.Element service) {
561            // Read stylesheet and add user
562            InputStream aclxml = MCREditorOutValidator.class.getResourceAsStream("/editor_default_acls_derivate.xml");
563            if (aclxml == null) {
564                LOGGER.warn("Can't find default derivate ACL file editor_default_acls_derivate.xml.");
565                return;
566            }
567            try {
568                org.jdom.Document xml = (SAX_BUILDER).build(aclxml);
569                org.jdom.Element acls = xml.getRootElement().getChild("servacls");
570                if (acls != null) {
571                    service.addContent(acls.detach());
572                }
573            } catch (Exception e) {
574                LOGGER.warn("Error while parsing file editor_default_acls_derivate.xml.");
575            }
576        }
577    
578    }