001    /**
002     * Copyright (c) 2010 Yahoo! Inc. All rights reserved.
003     * Licensed under the Apache License, Version 2.0 (the "License");
004     * you may not use this file except in compliance with the License.
005     * You may obtain a copy of the License at
006     *
007     *   http://www.apache.org/licenses/LICENSE-2.0
008     *
009     *  Unless required by applicable law or agreed to in writing, software
010     *  distributed under the License is distributed on an "AS IS" BASIS,
011     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012     *  See the License for the specific language governing permissions and
013     *  limitations under the License. See accompanying LICENSE file.
014     */
015    package org.apache.oozie.service;
016    
017    import org.apache.hadoop.conf.Configuration;
018    import org.apache.oozie.ErrorCode;
019    import org.apache.oozie.service.Service;
020    import org.apache.oozie.service.ServiceException;
021    import org.apache.oozie.service.Services;
022    import org.apache.oozie.util.IOUtils;
023    import org.xml.sax.SAXException;
024    
025    import javax.xml.XMLConstants;
026    import javax.xml.transform.stream.StreamSource;
027    import javax.xml.validation.Schema;
028    import javax.xml.validation.SchemaFactory;
029    import java.io.IOException;
030    import java.util.ArrayList;
031    import java.util.List;
032    
033    /**
034     * Service that loads Oozie workflow definition schema and registered extension schemas.
035     */
036    public class SchemaService implements Service {
037    
038        public static final String CONF_PREFIX = Service.CONF_PREFIX + "SchemaService.";
039    
040        public static final String WF_CONF_EXT_SCHEMAS = CONF_PREFIX + "wf.ext.schemas";
041    
042        public static final String COORD_CONF_EXT_SCHEMAS = CONF_PREFIX + "coord.ext.schemas";
043    
044        public static final String SLA_CONF_EXT_SCHEMAS = CONF_PREFIX + "sla.ext.schemas";
045    
046        public static final String SLA_NAME_SPACE_URI = "uri:oozie:sla:0.1";
047    
048        private Schema wfSchema;
049    
050        private Schema coordSchema;
051    
052        private Schema slaSchema;
053    
054        private static final String OOZIE_WORKFLOW_XSD[] = {"oozie-workflow-0.1.xsd", "oozie-workflow-0.2.xsd"};
055        private static final String OOZIE_COORDINATOR_XSD[] = {"oozie-coordinator-0.1.xsd"};
056        private static final String OOZIE_SLA_SEMANTIC_XSD[] = {"gms-oozie-sla-0.1.xsd"};
057    
058        private Schema loadSchema(Configuration conf, String[] baseSchemas, String extSchema) throws SAXException,
059                IOException {
060            List<StreamSource> sources = new ArrayList<StreamSource>();
061            for (String baseSchema : baseSchemas) {
062                sources.add(new StreamSource(IOUtils.getResourceAsStream(baseSchema, -1)));
063            }
064            String[] schemas = conf.getStrings(extSchema);
065            if (schemas != null) {
066                for (String schema : schemas) {
067                    sources.add(new StreamSource(IOUtils.getResourceAsStream(schema, -1)));
068                }
069            }
070            SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
071            return factory.newSchema(sources.toArray(new StreamSource[sources.size()]));
072        }
073    
074        /**
075         * Initialize the service.
076         *
077         * @param services services instance.
078         * @throws ServiceException thrown if the service could not be initialized.
079         */
080        public void init(Services services) throws ServiceException {
081            try {
082                wfSchema = loadSchema(services.getConf(), OOZIE_WORKFLOW_XSD, WF_CONF_EXT_SCHEMAS);
083                coordSchema = loadSchema(services.getConf(), OOZIE_COORDINATOR_XSD, COORD_CONF_EXT_SCHEMAS);
084                slaSchema = loadSchema(services.getConf(), OOZIE_SLA_SEMANTIC_XSD, SLA_CONF_EXT_SCHEMAS);
085            }
086            catch (SAXException ex) {
087                throw new ServiceException(ErrorCode.E0130, ex.getMessage(), ex);
088            }
089            catch (IOException ex) {
090                throw new ServiceException(ErrorCode.E0131, ex.getMessage(), ex);
091            }
092        }
093    
094        /**
095         * Return the public interface of the service.
096         *
097         * @return {@link SchemaService}.
098         */
099        public Class<? extends Service> getInterface() {
100            return SchemaService.class;
101        }
102    
103        /**
104         * Destroy the service.
105         */
106        public void destroy() {
107            wfSchema = null;
108        }
109    
110        /**
111         * Return the schema for XML validation of application definitions.
112         *
113         * @param schemaName: Name of schema definition (i.e. WORKFLOW/COORDINATOR)
114         * @return the schema for XML validation of application definitions.
115         */
116        public Schema getSchema(SchemaName schemaName) {
117            if (schemaName == SchemaName.WORKFLOW) {
118                return wfSchema;
119            }
120            else {
121                if (schemaName == SchemaName.COORDINATOR) {
122                    return coordSchema;
123                }
124                else {
125                    if (schemaName == SchemaName.SLA_ORIGINAL) {
126                        return slaSchema;
127                    }
128                    else {
129                        throw new RuntimeException("No schema found with name " + schemaName);
130                    }
131                }
132            }
133        }
134    
135        public enum SchemaName {
136            WORKFLOW(1), COORDINATOR(2), SLA_ORIGINAL(3);
137            private int id;
138    
139            private SchemaName(int id) {
140                this.id = id;
141            }
142    
143            public int getId() {
144                return id;
145            }
146        }
147    }