org.alfresco.repo.admin.patch.util.ImportFileUpdater.java Source code

Java tutorial

Introduction

Here is the source code for org.alfresco.repo.admin.patch.util.ImportFileUpdater.java

Source

/*
 * #%L
 * Alfresco Repository
 * %%
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 * %%
 * This file is part of the Alfresco software. 
 * If the software was purchased under a paid Alfresco license, the terms of 
 * the paid license agreement will prevail.  Otherwise, the software is 
 * provided under the following open source license terms:
 * 
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */
package org.alfresco.repo.admin.patch.util;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.ActionModel;
import org.alfresco.repo.rule.RuleModel;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.util.GUID;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.xml.sax.helpers.AttributesImpl;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

/**
 * Updates a XML import file to be compatable with the current version of the repository.
 * 
 * @author royw
 */
public class ImportFileUpdater {
    /** Indent size **/
    private static int INDENT_SIZE = 2;

    /** The destination export version number **/
    private static String EXPORT_VERSION = "1.4.0";

    /** Default encoding **/
    private static String DEFAULT_ENCODING = "UTF-8";

    /** File encoding */
    private String fileEncoding = DEFAULT_ENCODING;

    /** Element names **/
    private static String NAME_EXPORTER_VERSION = "exporterVersion";
    private static String NAME_RULE = "rule";

    /** The current import version number **/
    private String version;
    private boolean shownWarning = false;

    /**
     * Set the file encoding.
     * 
     * @param fileEncoding  the file encoding
     */
    public void setFileEncoding(String fileEncoding) {
        this.fileEncoding = fileEncoding;
    }

    /**
     * Updates the passed import file into the equivalent 1.4 format.
     * 
     * @param source      the source import file
     * @param destination   the destination import file
     */
    public void updateImportFile(String source, String destination) {
        XmlPullParser reader = getReader(source);
        XMLWriter writer = getWriter(destination);
        this.shownWarning = false;

        try {
            // Start the documentation
            writer.startDocument();

            // Start reading the document
            int eventType = reader.getEventType();
            while (eventType != XmlPullParser.END_DOCUMENT) {
                if (eventType == XmlPullParser.START_TAG) {
                    ImportFileUpdater.this.outputCurrentElement(reader, writer, new OutputChildren());
                }
                eventType = reader.next();
            }

            // End and close the document
            writer.endDocument();
            writer.close();
        } catch (Exception exception) {
            throw new AlfrescoRuntimeException("Unable to update import file.", exception);
        }

    }

    /**
     * Get the reader for the source import file
     * 
     * @param source   the source import file
     * @return         the XML pull parser used to read the file
     */
    private XmlPullParser getReader(String source) {
        try {
            XmlPullParserFactory factory = XmlPullParserFactory
                    .newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
            factory.setNamespaceAware(true);

            InputStream inputStream = new FileInputStream(source);
            Reader inputReader = new InputStreamReader(inputStream, this.fileEncoding);

            XmlPullParser xpp = factory.newPullParser();
            xpp.setInput(new BufferedReader(inputReader));

            return xpp;
        } catch (XmlPullParserException exception) {
            throw new AlfrescoRuntimeException("Unable to update import file.", exception);
        } catch (FileNotFoundException fileNotFound) {
            throw new AlfrescoRuntimeException("The source file could not be loaded.", fileNotFound);
        } catch (UnsupportedEncodingException exception) {
            throw new AlfrescoRuntimeException("Unsupported encoding", exception);
        }
    }

    /**
     * Get the writer for the import file
     * 
     * @param destination   the destination XML import file
     * @return            the XML writer
     */
    private XMLWriter getWriter(String destination) {
        try {
            // Define output format
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setNewLineAfterDeclaration(false);
            format.setIndentSize(INDENT_SIZE);
            format.setEncoding(this.fileEncoding);

            return new XMLWriter(new FileOutputStream(destination), format);
        } catch (Exception exception) {
            throw new AlfrescoRuntimeException("Unable to create XML writer.", exception);
        }
    }

    private void outputCurrentElement(XmlPullParser reader, XMLWriter writer, Work work) throws Exception {
        outputCurrentElement(reader, writer, work, true);
    }

    private void outputCurrentElement(XmlPullParser reader, XMLWriter writer, Work work, boolean checkForCallbacks)
            throws Exception {
        if (checkForCallbacks == false || checkForCallbacks(reader, writer) == false) {
            //   Get the name details of the element
            String name = reader.getName();
            String namespace = reader.getNamespace();
            String prefix = reader.getPrefix();

            // Sort out namespaces
            Map<String, String> nss = new HashMap<String, String>();
            int nsStart = reader.getNamespaceCount(reader.getDepth() - 1);
            int nsEnd = reader.getNamespaceCount(reader.getDepth());
            for (int i = nsStart; i < nsEnd; i++) {
                String nsPrefix = reader.getNamespacePrefix(i);
                String ns = reader.getNamespaceUri(i);
                nss.put(nsPrefix, ns);
            }

            // Sort out attributes
            AttributesImpl attributes = new AttributesImpl();
            for (int i = 0; i < reader.getAttributeCount(); i++) {
                String attributeName = reader.getAttributeName(i);
                String attributeNamespace = reader.getAttributeNamespace(i);
                String attributePrefix = reader.getAttributePrefix(i);
                String attributeType = reader.getAttributeType(i);
                String attributeValue = reader.getAttributeValue(i);

                attributes.addAttribute(attributeNamespace, attributeName, attributePrefix + ":" + attributeName,
                        attributeType, attributeValue);
            }

            // Start the namespace prefixes
            for (Map.Entry<String, String> entry : nss.entrySet()) {
                writer.startPrefixMapping(entry.getKey(), entry.getValue());
            }

            // Write the start of the element
            writer.startElement(namespace, name, prefix + ":" + name, attributes);

            // Do the work
            work.doWork(reader, writer);

            // Write the end of the element
            writer.endElement(namespace, name, prefix + ":" + name);

            // End the namespace prefixes
            for (String nsPrefix : nss.keySet()) {
                writer.endPrefixMapping(nsPrefix);
            }
        }
    }

    private boolean checkForCallbacks(XmlPullParser reader, XMLWriter writer) throws Exception {
        boolean result = false;
        if (reader.getName().equals(NAME_EXPORTER_VERSION) == true) {
            new ImportVersionLabelCallback().doCallback(reader, writer);
            result = true;
        } else if (reader.getName().equals(NAME_RULE) == true) {
            if (this.shownWarning == false && this.version == null) {
                System.out.println(
                        "WARNING:  No version information has been found in this import file.  It will be presumed it has been exported from 1.3");
                this.shownWarning = true;
            }
            if (this.version == null || this.version.startsWith("1.3") == true
                    || this.version.startsWith("1.2") == true) {
                new RuleCallback().doCallback(reader, writer);
                result = true;
            } else {
                throw new RuntimeException(
                        "Import files of version " + this.version + " are not supported by this tool.");
            }
        }
        return result;
    }

    private interface Work {
        void doWork(XmlPullParser reader, XMLWriter writer) throws Exception;
    }

    private class OutputChildren implements Work {
        public void doWork(XmlPullParser reader, XMLWriter writer) throws Exception {
            // Deal with the contents of the tag
            int eventType = reader.getEventType();
            while (eventType != XmlPullParser.END_TAG) {
                eventType = reader.next();
                if (eventType == XmlPullParser.START_TAG) {
                    ImportFileUpdater.this.outputCurrentElement(reader, writer, new OutputChildren());
                } else if (eventType == XmlPullParser.TEXT) {
                    // Write the text to the output file
                    writer.write(reader.getText());
                }
            }
        }
    }

    @SuppressWarnings("unused")
    private class IgnoreChildren implements Work {
        public void doWork(XmlPullParser reader, XMLWriter writer) throws Exception {
            int eventType = reader.getEventType();
            while (eventType != XmlPullParser.END_TAG) {
                eventType = reader.next();
                if (eventType == XmlPullParser.START_TAG) {
                    doWork(reader, writer);
                }
            }
        }
    }

    private interface ImportUpdaterCallback {
        void doCallback(XmlPullParser reader, XMLWriter writer) throws Exception;
    }

    private class ImportVersionLabelCallback implements ImportUpdaterCallback {
        public void doCallback(XmlPullParser reader, XMLWriter writer) throws Exception {
            ImportFileUpdater.this.outputCurrentElement(reader, writer, new Work() {
                public void doWork(XmlPullParser reader, XMLWriter writer) throws Exception {
                    reader.next();
                    ImportFileUpdater.this.version = reader.getText();
                    writer.write(EXPORT_VERSION);
                    reader.next();
                }
            }, false);
        }
    }

    private class RuleCallback implements ImportUpdaterCallback {
        public void doCallback(XmlPullParser reader, XMLWriter writer) throws Exception {
            // Get the name details of the element
            String name = reader.getName();
            String namespace = reader.getNamespace();
            String prefix = reader.getPrefix();

            // Rename the child assoc appropriately
            AttributesImpl attributes = new AttributesImpl();
            String attributeName = reader.getAttributeName(0);
            String attributeNamespace = reader.getAttributeNamespace(0);
            String attributePrefix = reader.getAttributePrefix(0);
            String attributeType = reader.getAttributeType(0);
            String attributeValue = reader.getAttributeValue(0) + GUID.generate();
            attributes.addAttribute(attributeNamespace, attributeName, attributePrefix + ":" + attributeName,
                    attributeType, attributeValue);

            // Output the rules element
            writer.startElement(namespace, name, prefix + ":" + name, attributes);

            int eventType = reader.getEventType();
            while (eventType != XmlPullParser.END_TAG) {
                eventType = reader.next();
                if (eventType == XmlPullParser.START_TAG) {
                    String childName = reader.getName();
                    if (childName.equals("aspects") == true) {
                        ImportFileUpdater.this.outputCurrentElement(reader, writer, new Work() {
                            public void doWork(XmlPullParser reader, XMLWriter writer) throws Exception {
                                // Add titled aspect
                                writer.startElement(ContentModel.ASPECT_TITLED.getNamespaceURI(),
                                        ContentModel.ASPECT_TITLED.getLocalName(),
                                        NamespaceService.CONTENT_MODEL_PREFIX + ":"
                                                + ContentModel.ASPECT_TITLED.getLocalName(),
                                        new AttributesImpl());
                                writer.endElement(ContentModel.ASPECT_TITLED.getNamespaceURI(),
                                        ContentModel.ASPECT_TITLED.getLocalName(),
                                        NamespaceService.CONTENT_MODEL_PREFIX + ":"
                                                + ContentModel.ASPECT_TITLED.getLocalName());

                                // Read the rest of the elements and output
                                int eventType = reader.getEventType();
                                while (eventType != XmlPullParser.END_TAG) {
                                    eventType = reader.next();
                                    if (eventType == XmlPullParser.START_TAG) {
                                        ImportFileUpdater.this.outputCurrentElement(reader, writer,
                                                new OutputChildren());
                                    }
                                }
                            }

                        }, false);
                    } else if (childName.equals("properties") == true) {
                        ImportFileUpdater.this.outputCurrentElement(reader, writer, new Work() {
                            public void doWork(XmlPullParser reader, XMLWriter writer) throws Exception {
                                int eventType = reader.getEventType();
                                while (eventType != XmlPullParser.END_TAG) {
                                    eventType = reader.next();
                                    if (eventType == XmlPullParser.START_TAG) {
                                        String propName = reader.getName();
                                        if (propName.equals("actionDescription") == true) {
                                            writer.startElement(ContentModel.PROP_DESCRIPTION.getNamespaceURI(),
                                                    ContentModel.PROP_DESCRIPTION.getLocalName(),
                                                    NamespaceService.CONTENT_MODEL_PREFIX + ":"
                                                            + ContentModel.PROP_DESCRIPTION.getLocalName(),
                                                    new AttributesImpl());

                                            // Output the value within
                                            new OutputChildren().doWork(reader, writer);

                                            writer.endElement(ContentModel.PROP_DESCRIPTION.getNamespaceURI(),
                                                    ContentModel.PROP_DESCRIPTION.getLocalName(),
                                                    NamespaceService.CONTENT_MODEL_PREFIX + ":"
                                                            + ContentModel.PROP_DESCRIPTION.getLocalName());
                                            eventType = reader.next();

                                        } else if (propName.equals("actionTitle") == true) {
                                            writer.startElement(ContentModel.PROP_TITLE.getNamespaceURI(),
                                                    ContentModel.PROP_TITLE.getLocalName(),
                                                    NamespaceService.CONTENT_MODEL_PREFIX + ":"
                                                            + ContentModel.PROP_TITLE.getLocalName(),
                                                    new AttributesImpl());

                                            // Output the value within
                                            new OutputChildren().doWork(reader, writer);

                                            writer.endElement(ContentModel.PROP_TITLE.getNamespaceURI(),
                                                    ContentModel.PROP_TITLE.getLocalName(),
                                                    NamespaceService.CONTENT_MODEL_PREFIX + ":"
                                                            + ContentModel.PROP_TITLE.getLocalName());
                                            eventType = reader.next();
                                        } else if (propName.equals("executeAsynchronously") == true) {
                                            writer.startElement(RuleModel.PROP_EXECUTE_ASYNC.getNamespaceURI(),
                                                    RuleModel.PROP_EXECUTE_ASYNC.getLocalName(),
                                                    RuleModel.RULE_MODEL_PREFIX + ":"
                                                            + RuleModel.PROP_EXECUTE_ASYNC.getLocalName(),
                                                    new AttributesImpl());

                                            // Output the value within
                                            new OutputChildren().doWork(reader, writer);

                                            writer.endElement(RuleModel.PROP_EXECUTE_ASYNC.getNamespaceURI(),
                                                    RuleModel.PROP_EXECUTE_ASYNC.getLocalName(),
                                                    RuleModel.RULE_MODEL_PREFIX + ":"
                                                            + RuleModel.PROP_EXECUTE_ASYNC.getLocalName());
                                            eventType = reader.next();
                                        } else if (propName.equals("ruleType") == true) {
                                            ImportFileUpdater.this.outputCurrentElement(reader, writer, new Work() {
                                                public void doWork(XmlPullParser reader, XMLWriter writer)
                                                        throws Exception {
                                                    // Output the elements that contain a multi values property
                                                    writer.startElement(NamespaceService.REPOSITORY_VIEW_1_0_URI,
                                                            "values", "view:values", new AttributesImpl());
                                                    writer.startElement(NamespaceService.REPOSITORY_VIEW_1_0_URI,
                                                            "value", "view:value", new AttributesImpl());

                                                    //   Output the value within
                                                    new OutputChildren().doWork(reader, writer);

                                                    // End the multi values elements
                                                    writer.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX,
                                                            "value", "view:value");
                                                    writer.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX,
                                                            "values", "view:values");
                                                }
                                            }, false);
                                        } else if (propName.equals("definitionName") == true) {
                                            // Skip past next end
                                            while (eventType != XmlPullParser.END_TAG) {
                                                eventType = reader.next();
                                            }
                                            eventType = reader.next();
                                        } else {
                                            ImportFileUpdater.this.outputCurrentElement(reader, writer,
                                                    new OutputChildren());
                                        }
                                    }
                                }

                                // Output value for the disabled property
                                writer.startElement(RuleModel.PROP_DISABLED.getNamespaceURI(),
                                        RuleModel.PROP_DISABLED.getLocalName(),
                                        RuleModel.RULE_MODEL_PREFIX + ":" + RuleModel.PROP_DISABLED.getLocalName(),
                                        new AttributesImpl());
                                writer.write("false");
                                writer.endElement(RuleModel.PROP_DISABLED.getNamespaceURI(),
                                        RuleModel.PROP_DISABLED.getLocalName(),
                                        RuleModel.RULE_MODEL_PREFIX + ":" + RuleModel.PROP_DISABLED.getLocalName());
                            }
                        }, false);
                    } else if (childName.equals("associations") == true) {
                        ImportFileUpdater.this.outputCurrentElement(reader, writer, new Work() {
                            public void doWork(XmlPullParser reader, XMLWriter writer) throws Exception {
                                // <rule:action>
                                writer.startElement(RuleModel.ASSOC_ACTION.getNamespaceURI(),
                                        RuleModel.ASSOC_ACTION.getLocalName(),
                                        RuleModel.RULE_MODEL_PREFIX + ":" + RuleModel.ASSOC_ACTION.getLocalName(),
                                        new AttributesImpl());

                                // <act:compositeaction view:childName="rule:action">
                                AttributesImpl attributes = new AttributesImpl();
                                attributes.addAttribute(NamespaceService.REPOSITORY_VIEW_1_0_URI, "childName",
                                        "view:childName", null, "rule:action");
                                writer.startElement(ActionModel.TYPE_COMPOSITE_ACTION.getNamespaceURI(),
                                        ActionModel.TYPE_COMPOSITE_ACTION.getLocalName(),
                                        ActionModel.ACTION_MODEL_PREFIX + ":"
                                                + ActionModel.TYPE_COMPOSITE_ACTION.getLocalName(),
                                        attributes);

                                // <view:properties>
                                writer.startElement(NamespaceService.REPOSITORY_VIEW_1_0_URI, "properties",
                                        "view:properties", new AttributesImpl());

                                // <act:definitionName>composite-action</definitionName>
                                writer.startElement(ActionModel.PROP_DEFINITION_NAME.getNamespaceURI(),
                                        ActionModel.PROP_DEFINITION_NAME.getLocalName(),
                                        ActionModel.ACTION_MODEL_PREFIX + ":"
                                                + ActionModel.PROP_DEFINITION_NAME.getLocalName(),
                                        new AttributesImpl());
                                writer.write("composite-action");
                                writer.endElement(ActionModel.PROP_DEFINITION_NAME.getNamespaceURI(),
                                        ActionModel.PROP_DEFINITION_NAME.getLocalName(),
                                        ActionModel.ACTION_MODEL_PREFIX + ":"
                                                + ActionModel.PROP_DEFINITION_NAME.getLocalName());

                                // </view:properties>
                                writer.endElement(NamespaceService.REPOSITORY_VIEW_1_0_URI, "properties",
                                        "view:properties");

                                // <view:association>
                                writer.startElement(NamespaceService.REPOSITORY_VIEW_1_0_URI, "associations",
                                        "view:associations", new AttributesImpl());

                                // Output the association details
                                new OutputChildren().doWork(reader, writer);

                                // </view:association>
                                writer.endElement(NamespaceService.REPOSITORY_VIEW_1_0_URI, "associations",
                                        "view:associations");

                                // </act:compositeaction>
                                writer.endElement(ActionModel.TYPE_COMPOSITE_ACTION.getNamespaceURI(),
                                        ActionModel.TYPE_COMPOSITE_ACTION.getLocalName(),
                                        ActionModel.ACTION_MODEL_PREFIX + ":"
                                                + ActionModel.TYPE_COMPOSITE_ACTION.getLocalName());

                                // </rule:action>
                                writer.endElement(RuleModel.ASSOC_ACTION.getNamespaceURI(),
                                        RuleModel.ASSOC_ACTION.getLocalName(),
                                        RuleModel.RULE_MODEL_PREFIX + ":" + RuleModel.ASSOC_ACTION.getLocalName());
                            }
                        }, false);
                    } else {
                        // Output anything else that might be hanging araound
                        ImportFileUpdater.this.outputCurrentElement(reader, writer, new OutputChildren());
                    }
                }
            }

            // End the rules element
            writer.endElement(namespace, name, prefix + ":" + name);
        }
    }

    public static void main(String[] args) {
        if (args.length == 2) {
            ImportFileUpdater util = new ImportFileUpdater();
            util.updateImportFile(args[0], args[1]);
        } else if (args.length == 3) {
            ImportFileUpdater util = new ImportFileUpdater();
            util.setFileEncoding(args[2]);
            util.updateImportFile(args[0], args[1]);
        } else {
            System.out.println(" ImportFileUpdater <source> <destination>");
            System.out.println("    source - 1.3 import file name to be updated");
            System.out.println("    destination - name of the generated 1.4 import file");
            System.out.println("    file encoding (optional) - the file encoding, default is UTF-8");
        }
    }

}