org.nuxeo.ecm.webapp.liveedit.LiveEditBootstrapHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.nuxeo.ecm.webapp.liveedit.LiveEditBootstrapHelper.java

Source

/*
 * (C) Copyright 2006-2007 Nuxeo SA (http://nuxeo.com/) and others.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributors:
 *     Nuxeo - initial API and implementation
 *
 * $Id: LiveEditBootstrapHelper.java 30586 2008-02-26 14:30:17Z ogrisel $
 */

package org.nuxeo.ecm.webapp.liveedit;

import static org.jboss.seam.ScopeType.EVENT;

import java.io.IOException;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.faces.context.FacesContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.QName;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Factory;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.web.RequestParameter;
import org.jboss.seam.annotations.Scope;
import org.nuxeo.ecm.core.api.Blob;
import org.nuxeo.ecm.core.api.CoreInstance;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentNotFoundException;
import org.nuxeo.ecm.core.api.IdRef;
import org.nuxeo.ecm.core.api.LifeCycleConstants;
import org.nuxeo.ecm.core.api.NuxeoException;
import org.nuxeo.ecm.core.api.PropertyException;
import org.nuxeo.ecm.core.api.security.SecurityConstants;
import org.nuxeo.ecm.core.schema.FacetNames;
import org.nuxeo.ecm.platform.mimetype.interfaces.MimetypeEntry;
import org.nuxeo.ecm.platform.mimetype.interfaces.MimetypeRegistry;
import org.nuxeo.ecm.platform.ui.web.api.NavigationContext;
import org.nuxeo.ecm.platform.ui.web.tag.fn.LiveEditConstants;
import org.nuxeo.ecm.platform.ui.web.util.BaseURL;
import org.nuxeo.runtime.api.Framework;

/**
 * The LiveEdit bootstrap procedure works as follows:
 * <ul>
 * <li>browsed page calls a JSF function from the DocumentModelFunctions class (edit a document, create new document,
 * etc.) to generate;</li>
 * <li>composing a specific URL as result, triggering the bootstrap addon to popup;</li>
 * <li>the addon come back with the URL composed allowing the present seam component to create the bootstrap file. The
 * file contains various data as requested in the URL;</li>
 * <li>the XML file is now available to addon which presents it to the client plugin.</li>
 * </ul>
 * Please refer to the nuxeo book chapter on desktop integration for details on the format of the nxedit URLs and the
 * XML bootstrap file.
 *
 * @author Thierry Delprat NXP-1959 the bootstrap file is managing the 'create new document [from template]' case too.
 *         The URL is containing an action identifier.
 * @author Rux rdarlea@nuxeo.com
 * @author Olivier Grisel ogrisel@nuxeo.com (split url functions into JSF DocumentModelFunctions module)
 */
@Scope(EVENT)
@Name("liveEditHelper")
public class LiveEditBootstrapHelper implements Serializable, LiveEditConstants {

    protected static final String MODIFIED_FIELD = "modified";

    protected static final String DUBLINCORE_SCHEMA = "dublincore";

    private static final Log log = LogFactory.getLog(LiveEditBootstrapHelper.class);

    private static final long serialVersionUID = 876879071L;

    @In(create = true)
    protected transient NavigationContext navigationContext;

    @In(create = true, required = false)
    protected transient CoreSession documentManager;

    @RequestParameter
    protected String action;

    @RequestParameter
    protected String repoID;

    @RequestParameter
    protected String templateRepoID;

    @RequestParameter
    protected String docRef;

    @RequestParameter
    protected String templateDocRef;

    @In(create = true)
    protected LiveEditClientConfig liveEditClientConfig;

    /**
     * @deprecated use blobPropertyField and filenamePropertyField instead
     */
    @Deprecated
    @RequestParameter
    protected String schema;

    @RequestParameter
    protected String templateSchema;

    /**
     * @deprecated use blobPropertyField instead
     */
    @Deprecated
    @RequestParameter
    protected String blobField;

    @RequestParameter
    protected String blobPropertyName;

    @RequestParameter
    protected String templateBlobField;

    // TODO: to be deprecated once all filenames are stored in the blob itself
    /**
     * @deprecated use filenamePropertyField instead
     */
    @Deprecated
    @RequestParameter
    protected String filenameField;

    // TODO: to be deprecated once all filenames are stored in the blob itself
    @RequestParameter
    protected String filenamePropertyName;

    @RequestParameter
    protected String mimetype;

    @RequestParameter
    protected String docType;

    protected MimetypeRegistry mimetypeRegistry;

    // Event-long cache for mimetype lookups - no invalidation required
    protected final Map<String, Boolean> cachedEditableStates = new HashMap<String, Boolean>();

    // Event-long cache for document field lookups - no invalidation required
    protected final Map<String, Boolean> cachedEditableBlobs = new HashMap<String, Boolean>();

    /**
     * Creates the bootstrap file. It is called from the browser's addon. The URL composition tells the case and what to
     * create. The structure is depicted in the NXP-1881. Rux NXP-1959: add new tag on root level describing the action:
     * actionEdit, actionNew or actionFromTemplate.
     *
     * @return the bootstrap file content
     */
    public void getBootstrap() throws IOException {
        String currentRepoID = documentManager.getRepositoryName();

        CoreSession session = documentManager;
        CoreSession templateSession = documentManager;
        try {
            if (repoID != null && !currentRepoID.equals(repoID)) {
                session = CoreInstance.openCoreSession(repoID);
            }

            if (templateRepoID != null && !currentRepoID.equals(templateRepoID)) {
                templateSession = CoreInstance.openCoreSession(templateRepoID);
            }

            DocumentModel doc = null;
            DocumentModel templateDoc = null;
            String filename = null;
            if (ACTION_EDIT_DOCUMENT.equals(action)) {
                // fetch the document to edit to get its mimetype and document
                // type
                doc = session.getDocument(new IdRef(docRef));
                docType = doc.getType();
                Blob blob = null;
                if (blobPropertyName != null) {
                    blob = (Blob) doc.getPropertyValue(blobPropertyName);
                    if (blob == null) {
                        throw new NuxeoException(
                                String.format("could not find blob to edit with property '%s'", blobPropertyName));
                    }
                } else {
                    blob = (Blob) doc.getProperty(schema, blobField);
                    if (blob == null) {
                        throw new NuxeoException(String.format(
                                "could not find blob to edit with schema '%s' and field '%s'", schema, blobField));
                    }
                }
                mimetype = blob.getMimeType();
                if (filenamePropertyName != null) {
                    filename = (String) doc.getPropertyValue(filenamePropertyName);
                } else {
                    filename = (String) doc.getProperty(schema, filenameField);
                }
            } else if (ACTION_CREATE_DOCUMENT.equals(action)) {
                // creating a new document all parameters are read from the
                // request parameters
            } else if (ACTION_CREATE_DOCUMENT_FROM_TEMPLATE.equals(action)) {
                // fetch the template blob to get its mimetype
                templateDoc = templateSession.getDocument(new IdRef(templateDocRef));
                Blob blob = (Blob) templateDoc.getProperty(templateSchema, templateBlobField);
                if (blob == null) {
                    throw new NuxeoException(
                            String.format("could not find template blob with schema '%s' and field '%s'",
                                    templateSchema, templateBlobField));
                }
                mimetype = blob.getMimeType();
                // leave docType from the request query parameter
            } else {
                throw new NuxeoException(String.format(
                        "action '%s' is not a valid LiveEdit action: should be one of '%s', '%s' or '%s'", action,
                        ACTION_CREATE_DOCUMENT, ACTION_CREATE_DOCUMENT_FROM_TEMPLATE, ACTION_EDIT_DOCUMENT));
            }

            FacesContext context = FacesContext.getCurrentInstance();
            HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
            HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();

            Element root = DocumentFactory.getInstance().createElement(liveEditTag);
            root.addNamespace("", XML_LE_NAMESPACE);
            // RUX NXP-1959: action id
            Element actionInfo = root.addElement(actionSelectorTag);
            actionInfo.setText(action);

            // Document related informations
            Element docInfo = root.addElement(documentTag);
            addTextElement(docInfo, docRefTag, docRef);
            Element docPathT = docInfo.addElement(docPathTag);
            Element docTitleT = docInfo.addElement(docTitleTag);
            if (doc != null) {
                docPathT.setText(doc.getPathAsString());
                docTitleT.setText(doc.getTitle());
            }
            addTextElement(docInfo, docRepositoryTag, repoID);

            addTextElement(docInfo, docSchemaNameTag, schema);
            addTextElement(docInfo, docFieldNameTag, blobField);
            addTextElement(docInfo, docBlobFieldNameTag, blobField);
            Element docFieldPathT = docInfo.addElement(docfieldPathTag);
            Element docBlobFieldPathT = docInfo.addElement(docBlobFieldPathTag);
            if (blobPropertyName != null) {
                // FIXME AT: NXP-2306: send blobPropertyName correctly (?)
                docFieldPathT.setText(blobPropertyName);
                docBlobFieldPathT.setText(blobPropertyName);
            } else {
                if (schema != null && blobField != null) {
                    docFieldPathT.setText(schema + ':' + blobField);
                    docBlobFieldPathT.setText(schema + ':' + blobField);
                }
            }
            addTextElement(docInfo, docFilenameFieldNameTag, filenameField);
            Element docFilenameFieldPathT = docInfo.addElement(docFilenameFieldPathTag);
            if (filenamePropertyName != null) {
                docFilenameFieldPathT.setText(filenamePropertyName);
            } else {
                if (schema != null && blobField != null) {
                    docFilenameFieldPathT.setText(schema + ':' + filenameField);
                }
            }

            addTextElement(docInfo, docfileNameTag, filename);
            addTextElement(docInfo, docTypeTag, docType);
            addTextElement(docInfo, docMimetypeTag, mimetype);
            addTextElement(docInfo, docFileExtensionTag, getFileExtension(mimetype));

            Element docFileAuthorizedExtensions = docInfo.addElement(docFileAuthorizedExtensionsTag);
            List<String> authorizedExtensions = getFileExtensions(mimetype);
            if (authorizedExtensions != null) {
                for (String extension : authorizedExtensions) {
                    addTextElement(docFileAuthorizedExtensions, docFileAuthorizedExtensionTag, extension);
                }
            }

            Element docIsVersionT = docInfo.addElement(docIsVersionTag);
            Element docIsLockedT = docInfo.addElement(docIsLockedTag);
            if (ACTION_EDIT_DOCUMENT.equals(action)) {
                docIsVersionT.setText(Boolean.toString(doc.isVersion()));
                docIsLockedT.setText(Boolean.toString(doc.isLocked()));
            }

            // template information for ACTION_CREATE_DOCUMENT_FROM_TEMPLATE

            Element templateDocInfo = root.addElement(templateDocumentTag);
            addTextElement(templateDocInfo, docRefTag, templateDocRef);
            docPathT = templateDocInfo.addElement(docPathTag);
            docTitleT = templateDocInfo.addElement(docTitleTag);
            if (templateDoc != null) {
                docPathT.setText(templateDoc.getPathAsString());
                docTitleT.setText(templateDoc.getTitle());
            }
            addTextElement(templateDocInfo, docRepositoryTag, templateRepoID);
            addTextElement(templateDocInfo, docSchemaNameTag, templateSchema);
            addTextElement(templateDocInfo, docFieldNameTag, templateBlobField);
            addTextElement(templateDocInfo, docBlobFieldNameTag, templateBlobField);
            docFieldPathT = templateDocInfo.addElement(docfieldPathTag);
            docBlobFieldPathT = templateDocInfo.addElement(docBlobFieldPathTag);
            if (templateSchema != null && templateBlobField != null) {
                docFieldPathT.setText(templateSchema + ":" + templateBlobField);
                docBlobFieldPathT.setText(templateSchema + ":" + templateBlobField);
            }
            addTextElement(templateDocInfo, docMimetypeTag, mimetype);
            addTextElement(templateDocInfo, docFileExtensionTag, getFileExtension(mimetype));

            Element templateFileAuthorizedExtensions = templateDocInfo.addElement(docFileAuthorizedExtensionsTag);
            if (authorizedExtensions != null) {
                for (String extension : authorizedExtensions) {
                    addTextElement(templateFileAuthorizedExtensions, docFileAuthorizedExtensionTag, extension);
                }
            }

            // Browser request related informations
            Element requestInfo = root.addElement(requestInfoTag);
            Cookie[] cookies = request.getCookies();
            Element cookiesT = requestInfo.addElement(requestCookiesTag);
            for (Cookie cookie : cookies) {
                Element cookieT = cookiesT.addElement(requestCookieTag);
                cookieT.addAttribute("name", cookie.getName());
                cookieT.setText(cookie.getValue());
            }
            Element headersT = requestInfo.addElement(requestHeadersTag);
            Enumeration hEnum = request.getHeaderNames();
            while (hEnum.hasMoreElements()) {
                String hName = (String) hEnum.nextElement();
                if (!hName.equalsIgnoreCase("cookie")) {
                    Element headerT = headersT.addElement(requestHeaderTag);
                    headerT.addAttribute("name", hName);
                    headerT.setText(request.getHeader(hName));
                }
            }
            addTextElement(requestInfo, requestBaseURLTag, BaseURL.getBaseURL(request));

            // User related informations
            String username = context.getExternalContext().getUserPrincipal().getName();
            Element userInfo = root.addElement(userInfoTag);
            addTextElement(userInfo, userNameTag, username);
            addTextElement(userInfo, userPasswordTag, "");
            addTextElement(userInfo, userTokenTag, "");
            addTextElement(userInfo, userLocaleTag, context.getViewRoot().getLocale().toString());
            // Rux NXP-1882: the wsdl locations
            String baseUrl = BaseURL.getBaseURL(request);
            Element wsdlLocations = root.addElement(wsdlLocationsTag);
            Element wsdlAccessWST = wsdlLocations.addElement(wsdlAccessWebServiceTag);
            wsdlAccessWST.setText(baseUrl + "webservices/nuxeoAccess?wsdl");
            Element wsdlEEWST = wsdlLocations.addElement(wsdlLEWebServiceTag);
            wsdlEEWST.setText(baseUrl + "webservices/nuxeoLEWS?wsdl");

            // Server related informations
            Element serverInfo = root.addElement(serverInfoTag);
            Element serverVersionT = serverInfo.addElement(serverVersionTag);
            serverVersionT.setText("5.1"); // TODO: use a buildtime generated
            // version tag instead

            // Client related informations
            Element editId = root.addElement(editIdTag);
            editId.setText(getEditId(doc, session, username));

            // serialize bootstrap XML document in the response
            Document xmlDoc = DocumentFactory.getInstance().createDocument();
            xmlDoc.setRootElement(root);
            response.setContentType("text/xml; charset=UTF-8");

            // use a formatter to make it easier to debug live edit client
            // implementations
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("UTF-8");
            XMLWriter writer = new XMLWriter(response.getOutputStream(), format);
            writer.write(xmlDoc);

            response.flushBuffer();
            context.responseComplete();
        } finally {
            if (session != null && session != documentManager) {
                session.close();
            }
            if (templateSession != null && templateSession != documentManager) {
                templateSession.close();
            }
        }
    }

    protected String getFileExtension(String mimetype) {
        if (mimetype == null) {
            return null;
        }
        MimetypeRegistry mimetypeRegistry = Framework.getService(MimetypeRegistry.class);
        List<String> extensions = mimetypeRegistry.getExtensionsFromMimetypeName(mimetype);
        if (extensions != null && !extensions.isEmpty()) {
            return extensions.get(0);
        } else {
            return null;
        }
    }

    protected List<String> getFileExtensions(String mimetype) {
        if (mimetype == null) {
            return null;
        }
        MimetypeRegistry mimetypeRegistry = Framework.getService(MimetypeRegistry.class);
        List<String> extensions = mimetypeRegistry.getExtensionsFromMimetypeName(mimetype);
        return extensions;
    }

    protected static Element addTextElement(Element parent, QName newElementName, String value) {
        Element element = parent.addElement(newElementName);
        if (value != null) {
            element.setText(value);
        }
        return element;
    }

    // TODO: please explain what is the use of the "editId" tag here
    protected static String getEditId(DocumentModel doc, CoreSession session, String userName) {
        StringBuilder sb = new StringBuilder();

        if (doc != null) {
            sb.append(doc.getId());
        } else {
            sb.append("NewDocument");
        }
        sb.append('-');
        sb.append(session.getRepositoryName());
        sb.append('-');
        sb.append(userName);
        Calendar modified = null;
        if (doc != null) {
            try {
                modified = (Calendar) doc.getProperty(DUBLINCORE_SCHEMA, MODIFIED_FIELD);
            } catch (PropertyException e) {
                modified = null;
            }
        }
        if (modified == null) {
            modified = Calendar.getInstance();
        }
        sb.append('-');
        sb.append(modified.getTimeInMillis());
        return sb.toString();
    }

    //
    // Methods to check whether or not to display live edit links
    //

    /**
     * @deprecated use {@link #isLiveEditable(DocumentModel doc, String blobXpath)}
     */
    @Deprecated
    public boolean isLiveEditable(Blob blob) {
        if (blob == null) {
            return false;
        }
        String mimetype = blob.getMimeType();
        return isMimeTypeLiveEditable(mimetype);
    }

    /**
     * @param document the document to edit.
     * @param blobXPath XPath to the blob property
     * @return true if the document is immutable and the blob's mime type is supported, false otherwise.
     * @since 5.4
     */
    public boolean isLiveEditable(DocumentModel document, Blob blob) {
        if (document.isImmutable()) {
            return false;
        }
        // NXP-14476: Testing lifecycle state is part of the "mutable_document" filter
        if (document.getCurrentLifeCycleState().equals(LifeCycleConstants.DELETED_STATE)) {
            return false;
        }
        if (blob == null) {
            return false;
        }
        String mimetype = blob.getMimeType();
        return isMimeTypeLiveEditable(mimetype);
    }

    public boolean isMimeTypeLiveEditable(Blob blob) {
        if (blob == null) {
            return false;
        }
        String mimetype = blob.getMimeType();
        return isMimeTypeLiveEditable(mimetype);
    }

    public boolean isMimeTypeLiveEditable(String mimetype) {

        Boolean isEditable = cachedEditableStates.get(mimetype);
        if (isEditable == null) {

            if (liveEditClientConfig.getLiveEditConfigurationPolicy()
                    .equals(LiveEditClientConfig.LE_CONFIG_CLIENTSIDE)) {
                // only trust client config
                isEditable = liveEditClientConfig.isMimeTypeLiveEditable(mimetype);
                cachedEditableStates.put(mimetype, isEditable);
                return isEditable;
            }

            MimetypeEntry mimetypeEntry = getMimetypeRegistry().getMimetypeEntryByMimeType(mimetype);
            if (mimetypeEntry == null) {
                isEditable = Boolean.FALSE;
            } else {
                isEditable = mimetypeEntry.isOnlineEditable();
            }

            if (liveEditClientConfig.getLiveEditConfigurationPolicy()
                    .equals(LiveEditClientConfig.LE_CONFIG_BOTHSIDES)) {
                boolean isEditableOnClient = liveEditClientConfig.isMimeTypeLiveEditable(mimetype);
                isEditable = isEditable && isEditableOnClient;
            }
            cachedEditableStates.put(mimetype, isEditable);
        }
        return isEditable;
    }

    @Factory(value = "msword_liveeditable", scope = ScopeType.SESSION)
    public boolean isMSWordLiveEdititable() {
        return isMimeTypeLiveEditable("application/msword");
    }

    @Factory(value = "msexcel_liveeditable", scope = ScopeType.SESSION)
    public boolean isMSExcelLiveEdititable() {
        return isMimeTypeLiveEditable("application/vnd.ms-excel");
    }

    @Factory(value = "mspowerpoint_liveeditable", scope = ScopeType.SESSION)
    public boolean isMSPowerpointLiveEdititable() {
        return isMimeTypeLiveEditable("application/vnd.ms-powerpoint");
    }

    @Factory(value = "ootext_liveeditable", scope = ScopeType.SESSION)
    public boolean isOOTextLiveEdititable() {
        return isMimeTypeLiveEditable("application/vnd.oasis.opendocument.text");
    }

    @Factory(value = "oocalc_liveeditable", scope = ScopeType.SESSION)
    public boolean isOOCalcLiveEdititable() {
        return isMimeTypeLiveEditable("application/vnd.oasis.opendocument.spreadsheet");
    }

    @Factory(value = "oopresentation_liveeditable", scope = ScopeType.SESSION)
    public boolean isOOPresentationLiveEdititable() {
        return isMimeTypeLiveEditable("application/vnd.oasis.opendocument.presentation");
    }

    public boolean isCurrentDocumentLiveEditable() {
        return isDocumentLiveEditable(navigationContext.getCurrentDocument(), DEFAULT_SCHEMA, DEFAULT_BLOB_FIELD);
    }

    public boolean isCurrentDocumentLiveEditable(String schemaName, String fieldName) {
        return isDocumentLiveEditable(navigationContext.getCurrentDocument(), schemaName, fieldName);
    }

    public boolean isCurrentDocumentLiveEditable(String propertyName) {
        return isDocumentLiveEditable(navigationContext.getCurrentDocument(), propertyName);
    }

    public boolean isDocumentLiveEditable(DocumentModel documentModel, String schemaName, String fieldName) {
        return isDocumentLiveEditable(documentModel, schemaName + ":" + fieldName);
    }

    public boolean isDocumentLiveEditable(DocumentModel documentModel, String propertyName) {
        if (documentModel == null) {
            log.warn("cannot check live editable state of null DocumentModel");
            return false;
        }

        // NXP-14476: Testing lifecycle state is part of the "mutable_document" filter
        if (LifeCycleConstants.DELETED_STATE.equals(documentModel.getCurrentLifeCycleState())) {
            return false;
        }

        // check Client browser config
        if (!liveEditClientConfig.isLiveEditInstalled()) {
            return false;
        }

        String cacheKey = documentModel.getRef() + "__" + propertyName;
        Boolean cachedEditableBlob = cachedEditableBlobs.get(cacheKey);
        if (cachedEditableBlob == null) {

            if (documentModel.hasFacet(FacetNames.IMMUTABLE)) {
                return cacheBlobToFalse(cacheKey);
            }

            if (!documentManager.hasPermission(documentModel.getRef(), SecurityConstants.WRITE_PROPERTIES)) {
                // the lock state is check as a extension to the
                // SecurityPolicyManager
                return cacheBlobToFalse(cacheKey);
            }

            Blob blob;
            try {
                blob = documentModel.getProperty(propertyName).getValue(Blob.class);
            } catch (PropertyException e) {
                // this document cannot host a live editable blob is the
                // requested property, ignore
                return cacheBlobToFalse(cacheKey);
            }
            cachedEditableBlob = isLiveEditable(blob);
            cachedEditableBlobs.put(cacheKey, cachedEditableBlob);
        }
        return cachedEditableBlob;
    }

    protected boolean cacheBlobToFalse(String cacheKey) {
        cachedEditableBlobs.put(cacheKey, Boolean.FALSE);
        return false;
    }

    protected MimetypeRegistry getMimetypeRegistry() {
        if (mimetypeRegistry == null) {
            mimetypeRegistry = Framework.getService(MimetypeRegistry.class);
        }
        return mimetypeRegistry;
    }

}