001/*
002 * (C) Copyright 2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     tdelprat
018 *
019 */
020package org.nuxeo.wizard.download;
021
022import java.io.InputStream;
023import java.util.ArrayList;
024import java.util.List;
025
026import org.apache.commons.logging.Log;
027import org.apache.commons.logging.LogFactory;
028import org.dom4j.Document;
029import org.dom4j.DocumentException;
030import org.dom4j.Element;
031import org.dom4j.io.SAXReader;
032
033/**
034 * Simple DOM4J parser to read the {@link DownloadPackage} list from an XML stream
035 *
036 * @author Tiry (tdelprat@nuxeo.com)
037 */
038public class DownloadDescriptorParser {
039
040    protected static final Log log = LogFactory.getLog(DownloadDescriptorParser.class);
041
042    public static Document parse(InputStream in) {
043        Document document = null;
044        SAXReader reader = new SAXReader();
045        try {
046            document = reader.read(in);
047        } catch (DocumentException e) {
048            log.error(e, e);
049        }
050        return document;
051    }
052
053    public static DownloadablePackageOptions parsePackages(InputStream in) {
054
055        DownloadablePackageOptions options = new DownloadablePackageOptions();
056
057        List<DownloadPackage> pkgs = new ArrayList<>();
058        Document document = parse(in);
059        if (document != null) {
060
061            String baseUrl = document.getRootElement().element("packageDefinitions").attributeValue("baseUrl");
062
063            // parse package definition
064            for (Object el : document.getRootElement().element("packageDefinitions").elements("package")) {
065                DownloadPackage pkg = readPackageDefinition((Element) el, baseUrl);
066                if (pkg != null) {
067                    pkgs.add(pkg);
068                }
069            }
070
071            options.setAllPackages(pkgs);
072
073            Element install = document.getRootElement().element("install");
074
075            // get common packages
076            if (install.element("common") != null) {
077                for (Object el : install.element("common").elements("package")) {
078                    DownloadPackage pkg = readCommonPackage((Element) el, pkgs);
079                    if (pkg != null) {
080                        options.addCommonPackage(pkg);
081                    }
082                }
083            }
084
085            nodeCounter = 0;
086            // get package Options
087            for (Object el : install.element("packageOptions").elements("package")) {
088                DownloadablePackageOption pkg = readPackageOptions((Element) el, pkgs);
089                if (pkg != null) {
090                    options.addOptions(pkg);
091                }
092            }
093
094            // get presets
095            if (document.getRootElement().element("presets") != null) {
096                for (Object el : document.getRootElement().element("presets").elements("preset")) {
097                    Element preset = (Element) el;
098                    String presetId = preset.attribute("id").getValue();
099                    String presetLabel = preset.attribute("label").getValue();
100                    String pkgList = preset.getText().trim();
101                    String[] presetPackages = pkgList.split(",");
102                    options.addPreset(presetId, presetLabel, presetPackages);
103                }
104            }
105        }
106        return options;
107    }
108
109    protected static int nodeCounter = 0;
110
111    protected static DownloadPackage readPackageDefinition(Element el, String baseUrl) {
112        String id = el.attribute("id").getValue();
113        if (id != null) {
114            DownloadPackage pkg = new DownloadPackage(id);
115            String bUrl = el.attributeValue("baseUrl");
116            if (bUrl == null) {
117                bUrl = baseUrl;
118            }
119            pkg.setLabel(el.attributeValue("label"));
120            pkg.setFilename(el.attributeValue("filename"));
121            pkg.setMd5(el.attributeValue("md5"));
122            pkg.setVirtual(Boolean.parseBoolean(el.attributeValue("virtual")));
123            pkg.setBaseUrl(bUrl);
124            pkg.setColor(el.attributeValue("color"));
125            pkg.setTextColor(el.attributeValue("textcolor"));
126            pkg.setShortLabel(el.attributeValue("shortlabel"));
127            pkg.setDescription(el.attributeValue("desc"));
128            String url = el.attributeValue("url");
129            if (url != null) {
130                pkg.setDownloadUrl(url);
131            }
132
133            String implies = el.attributeValue("implies");
134            if (implies != null && !implies.trim().equals("")) {
135                String[] deps = implies.split(",");
136                pkg.addDeps(deps);
137            }
138            return pkg;
139        }
140        return null;
141    }
142
143    protected static DownloadPackage readCommonPackage(Element el, List<DownloadPackage> pkgs) {
144        String ref = el.attributeValue("ref");
145        for (DownloadPackage pkg : pkgs) {
146            if (pkg.getId().equals(ref)) {
147                return pkg;
148            }
149        }
150        log.error("Unable to find common package for ref " + ref);
151        return null;
152    }
153
154    protected static DownloadablePackageOption readPackageOptions(Element el, List<DownloadPackage> pkgs) {
155
156        String ref = el.attributeValue("ref");
157        DownloadPackage targetPkg = null;
158
159        if (ref != null) {
160            for (DownloadPackage pkg : pkgs) {
161                if (pkg.getId().equals(ref)) {
162                    targetPkg = pkg;
163                    break;
164                }
165            }
166            if (targetPkg == null) {
167                log.error("Unable to find package for ref " + ref);
168                return null;
169            }
170        }
171
172        String id = el.attributeValue("ref");
173        if (id == null) {
174            id = ref;
175        }
176        DownloadablePackageOption pkgOption;
177        nodeCounter++;
178
179        if (id != null) {
180            pkgOption = new DownloadablePackageOption(targetPkg, id);
181        } else {
182            pkgOption = new DownloadablePackageOption(targetPkg, nodeCounter);
183        }
184
185        String label = el.attributeValue("label");
186        if (label != null) {
187            pkgOption.setLabel(label);
188        }
189        pkgOption.setExclusive(el.attributeValue("exclusive"));
190        pkgOption.setSelectionType(el.attributeValue("selectionType"));
191
192        for (Object child : el.elements()) {
193            DownloadablePackageOption childPkg = readPackageOptions((Element) child, pkgs);
194            if (childPkg != null) {
195                pkgOption.addChildPackage(childPkg);
196            }
197        }
198        return pkgOption;
199    }
200}