001/**
002 * Copyright 2005-2016 The Kuali Foundation
003 *
004 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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 */
016package org.kuali.rice.kew.plugin;
017
018import org.apache.commons.lang.StringUtils;
019import org.jdom.Document;
020import org.jdom.Element;
021import org.jdom.JDOMException;
022import org.jdom.input.SAXBuilder;
023import org.kuali.rice.core.api.config.property.Config;
024import org.kuali.rice.core.api.util.xml.XmlException;
025
026import java.io.File;
027import java.io.IOException;
028import java.net.URL;
029import java.util.HashMap;
030import java.util.Iterator;
031import java.util.List;
032import java.util.Map;
033
034
035/**
036 * Parses a {@link PluginConfig} configuration from an XML file.
037 *
038 * @author Kuali Rice Team (rice.collab@kuali.org)
039 */
040public class PluginConfigParser {
041
042    private static final String PARAMETER_TAG = "parameter";
043    private static final String LISTENER_TAG = "listener";
044    private static final String LISTENER_CLASS_TAG = "listener-class";
045    private static final String RESOURCE_LOADER_TAG = "resourceLoader";
046
047    private static final String NAME_ATTRIBUTE = "name";
048    private static final String VALUE_ATTRIBUTE = "value";
049    private static final String CLASS_ATTRIBUTE = "class";
050
051    public PluginConfig parse(File configFile, Config parentConfig) throws IOException, XmlException {
052        return parse(configFile.toURI().toURL(), parentConfig);
053    }
054
055        public PluginConfig parse(URL url, Config parentConfig) throws IOException, XmlException {
056                SAXBuilder builder = new SAXBuilder(false);
057                try {
058            // NOTE: need to be wary of whether streams are closed properly
059            // by builder
060                        Document doc = builder.build(url);
061                        Element root = doc.getRootElement();
062                        PluginConfig pluginConfig = new PluginConfig(url, parentConfig);
063                        parseResourceLoader(root, pluginConfig);
064                        parseListeners(root, pluginConfig);
065                        return pluginConfig;
066                } catch (JDOMException e) {
067                    throw new PluginException("Error when parsing the plugin config file.", e);
068                }
069        }
070
071        public void parseResourceLoader(Element element, PluginConfig pluginConfig) throws XmlException {
072                List loaderElements = element.getChildren(RESOURCE_LOADER_TAG);
073                if (loaderElements.size() > 1) {
074                        throw new XmlException("Only one <resourceLoader> tag may be defined.");
075                } else if (!loaderElements.isEmpty()) {
076                        Element loaderElement = (Element)loaderElements.get(0);
077                        String attributeClass = loaderElement.getAttributeValue(CLASS_ATTRIBUTE);
078                        if (StringUtils.isEmpty(attributeClass)) {
079                                throw new XmlException("<resourceLoader> element must define a 'class' attribute.");
080                        }
081                        pluginConfig.setResourceLoaderClassname(attributeClass);
082                }
083        }
084
085        public void parseListeners(Element element, PluginConfig pluginConfig) throws XmlException {
086                List listeners = element.getChildren(LISTENER_TAG);
087                for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
088                    pluginConfig.addListener(parseListenerProperties((Element)iterator.next()));
089                }
090        }
091
092        private String parseListenerProperties(Element element) throws XmlException {
093                String listenerClass = element.getChildText(LISTENER_CLASS_TAG);
094                if (org.apache.commons.lang.StringUtils.isEmpty(listenerClass)) {
095                        throw new XmlException("Listener Class tag must have a class property defined");
096                }
097                return listenerClass;
098        }
099
100        public Map parseParameters(Element element) throws XmlException {
101        Map parsedParms = new HashMap();
102            List parameters = element.getChildren(PARAMETER_TAG);
103                for (Iterator iterator = parameters.iterator(); iterator.hasNext();) {
104                    String [] parm = parseParameter((Element)iterator.next());
105                    parsedParms.put(parm[0], parm[1]);
106                }
107                return parsedParms;
108        }
109
110        private String [] parseParameter(Element element) throws XmlException {
111                String name = element.getAttributeValue(NAME_ATTRIBUTE);
112                String value = element.getAttributeValue(VALUE_ATTRIBUTE);
113                if (org.apache.commons.lang.StringUtils.isEmpty(name)) {
114                        throw new XmlException("Parameter tag must have a name attribute defined");
115                }
116                if (org.apache.commons.lang.StringUtils.isEmpty(value)) {
117                        throw new XmlException("Parameter tag must have a value attribute defined");
118                }
119                return new String [] {name, value};
120        }
121
122
123}