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 schema = schema.replace("\n", "").trim(); 068 if (schema.length() > 0) { 069 sources.add(new StreamSource(IOUtils.getResourceAsStream(schema, -1))); 070 } 071 } 072 } 073 SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 074 return factory.newSchema(sources.toArray(new StreamSource[sources.size()])); 075 } 076 077 /** 078 * Initialize the service. 079 * 080 * @param services services instance. 081 * @throws ServiceException thrown if the service could not be initialized. 082 */ 083 public void init(Services services) throws ServiceException { 084 try { 085 wfSchema = loadSchema(services.getConf(), OOZIE_WORKFLOW_XSD, WF_CONF_EXT_SCHEMAS); 086 coordSchema = loadSchema(services.getConf(), OOZIE_COORDINATOR_XSD, COORD_CONF_EXT_SCHEMAS); 087 slaSchema = loadSchema(services.getConf(), OOZIE_SLA_SEMANTIC_XSD, SLA_CONF_EXT_SCHEMAS); 088 } 089 catch (SAXException ex) { 090 throw new ServiceException(ErrorCode.E0130, ex.getMessage(), ex); 091 } 092 catch (IOException ex) { 093 throw new ServiceException(ErrorCode.E0131, ex.getMessage(), ex); 094 } 095 } 096 097 /** 098 * Return the public interface of the service. 099 * 100 * @return {@link SchemaService}. 101 */ 102 public Class<? extends Service> getInterface() { 103 return SchemaService.class; 104 } 105 106 /** 107 * Destroy the service. 108 */ 109 public void destroy() { 110 wfSchema = null; 111 } 112 113 /** 114 * Return the schema for XML validation of application definitions. 115 * 116 * @param schemaName: Name of schema definition (i.e. WORKFLOW/COORDINATOR) 117 * @return the schema for XML validation of application definitions. 118 */ 119 public Schema getSchema(SchemaName schemaName) { 120 if (schemaName == SchemaName.WORKFLOW) { 121 return wfSchema; 122 } 123 else { 124 if (schemaName == SchemaName.COORDINATOR) { 125 return coordSchema; 126 } 127 else { 128 if (schemaName == SchemaName.SLA_ORIGINAL) { 129 return slaSchema; 130 } 131 else { 132 throw new RuntimeException("No schema found with name " + schemaName); 133 } 134 } 135 } 136 } 137 138 public enum SchemaName { 139 WORKFLOW(1), COORDINATOR(2), SLA_ORIGINAL(3); 140 private int id; 141 142 private SchemaName(int id) { 143 this.id = id; 144 } 145 146 public int getId() { 147 return id; 148 } 149 } 150 }