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 java.io.IOException; 018 import java.util.ArrayList; 019 import java.util.List; 020 021 import javax.xml.XMLConstants; 022 import javax.xml.transform.stream.StreamSource; 023 import javax.xml.validation.Schema; 024 import javax.xml.validation.SchemaFactory; 025 026 import org.apache.hadoop.conf.Configuration; 027 import org.apache.oozie.ErrorCode; 028 import org.apache.oozie.util.IOUtils; 029 import org.xml.sax.SAXException; 030 031 /** 032 * Service that loads Oozie workflow definition schema and registered extension 033 * schemas. 034 */ 035 public class SchemaService implements Service { 036 037 public static final String CONF_PREFIX = Service.CONF_PREFIX + "SchemaService."; 038 039 public static final String WF_CONF_EXT_SCHEMAS = CONF_PREFIX + "wf.ext.schemas"; 040 041 public static final String COORD_CONF_EXT_SCHEMAS = CONF_PREFIX + "coord.ext.schemas"; 042 043 public static final String BUNDLE_CONF_EXT_SCHEMAS = CONF_PREFIX + "bundle.ext.schemas"; 044 045 public static final String SLA_CONF_EXT_SCHEMAS = CONF_PREFIX + "sla.ext.schemas"; 046 047 public static final String SLA_NAME_SPACE_URI = "uri:oozie:sla:0.1"; 048 049 public static final String COORDINATOR_NAMESPACE_URI_1 = "uri:oozie:coordinator:0.1"; 050 051 private Schema wfSchema; 052 053 private Schema coordSchema; 054 055 private Schema bundleSchema; 056 057 private Schema slaSchema; 058 059 private static final String OOZIE_WORKFLOW_XSD[] = { "oozie-workflow-0.1.xsd", "oozie-workflow-0.2.xsd", 060 "oozie-workflow-0.2.5.xsd" }; 061 private static final String OOZIE_COORDINATOR_XSD[] = { "oozie-coordinator-0.1.xsd", "oozie-coordinator-0.2.xsd" }; 062 private static final String OOZIE_BUNDLE_XSD[] = { "oozie-bundle-0.1.xsd" }; 063 private static final String OOZIE_SLA_SEMANTIC_XSD[] = { "gms-oozie-sla-0.1.xsd" }; 064 065 private Schema loadSchema(Configuration conf, String[] baseSchemas, String extSchema) throws SAXException, 066 IOException { 067 List<StreamSource> sources = new ArrayList<StreamSource>(); 068 for (String baseSchema : baseSchemas) { 069 sources.add(new StreamSource(IOUtils.getResourceAsStream(baseSchema, -1))); 070 } 071 String[] schemas = conf.getStrings(extSchema); 072 if (schemas != null) { 073 for (String schema : schemas) { 074 sources.add(new StreamSource(IOUtils.getResourceAsStream(schema, -1))); 075 } 076 } 077 SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 078 return factory.newSchema(sources.toArray(new StreamSource[sources.size()])); 079 } 080 081 /** 082 * Initialize the service. 083 * 084 * @param services services instance. 085 * @throws ServiceException thrown if the service could not be initialized. 086 */ 087 public void init(Services services) throws ServiceException { 088 try { 089 wfSchema = loadSchema(services.getConf(), OOZIE_WORKFLOW_XSD, WF_CONF_EXT_SCHEMAS); 090 coordSchema = loadSchema(services.getConf(), OOZIE_COORDINATOR_XSD, COORD_CONF_EXT_SCHEMAS); 091 bundleSchema = loadSchema(services.getConf(), OOZIE_BUNDLE_XSD, BUNDLE_CONF_EXT_SCHEMAS); 092 slaSchema = loadSchema(services.getConf(), OOZIE_SLA_SEMANTIC_XSD, SLA_CONF_EXT_SCHEMAS); 093 bundleSchema = loadSchema(services.getConf(), OOZIE_BUNDLE_XSD, BUNDLE_CONF_EXT_SCHEMAS); 094 } 095 catch (SAXException ex) { 096 throw new ServiceException(ErrorCode.E0130, ex.getMessage(), ex); 097 } 098 catch (IOException ex) { 099 throw new ServiceException(ErrorCode.E0131, ex.getMessage(), ex); 100 } 101 } 102 103 /** 104 * Return the public interface of the service. 105 * 106 * @return {@link SchemaService}. 107 */ 108 public Class<? extends Service> getInterface() { 109 return SchemaService.class; 110 } 111 112 /** 113 * Destroy the service. 114 */ 115 public void destroy() { 116 wfSchema = null; 117 bundleSchema = null; 118 slaSchema = null; 119 coordSchema = null; 120 } 121 122 /** 123 * Return the schema for XML validation of application definitions. 124 * 125 * @param schemaName: Name of schema definition (i.e. 126 * WORKFLOW/COORDINATOR/BUNDLE) 127 * @return the schema for XML validation of application definitions. 128 */ 129 public Schema getSchema(SchemaName schemaName) { 130 Schema returnSchema = null; 131 if (schemaName == SchemaName.WORKFLOW) { 132 returnSchema = wfSchema; 133 } 134 else if (schemaName == SchemaName.COORDINATOR) { 135 returnSchema = coordSchema; 136 } 137 else if (schemaName == SchemaName.BUNDLE) { 138 returnSchema = bundleSchema; 139 } 140 else if (schemaName == SchemaName.SLA_ORIGINAL) { 141 returnSchema = slaSchema; 142 } 143 else { 144 throw new RuntimeException("No schema found with name " + schemaName); 145 } 146 return returnSchema; 147 } 148 149 public enum SchemaName { 150 WORKFLOW(1), COORDINATOR(2), SLA_ORIGINAL(3), BUNDLE(4); 151 private final int id; 152 153 private SchemaName(int id) { 154 this.id = id; 155 } 156 157 public int getId() { 158 return id; 159 } 160 } 161 }