001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.oozie.servlet; 020 021import org.apache.hadoop.conf.Configuration; 022import org.apache.hadoop.fs.FileSystem; 023import org.apache.hadoop.fs.Path; 024import org.apache.oozie.ErrorCode; 025import org.apache.oozie.cli.OozieCLIException; 026import org.apache.oozie.client.rest.JsonTags; 027import org.apache.oozie.client.rest.RestConstants; 028import org.apache.oozie.service.HadoopAccessorService; 029import org.apache.oozie.service.SchemaService; 030import org.apache.oozie.service.Services; 031import org.apache.oozie.util.IOUtils; 032import org.json.simple.JSONObject; 033import org.xml.sax.SAXException; 034 035import javax.servlet.ServletException; 036import javax.servlet.http.HttpServletRequest; 037import javax.servlet.http.HttpServletResponse; 038import javax.xml.transform.stream.StreamSource; 039import javax.xml.validation.Schema; 040import javax.xml.validation.Validator; 041import java.io.IOException; 042import java.io.InputStreamReader; 043import java.io.Reader; 044import java.io.StringReader; 045import java.io.StringWriter; 046import java.net.URI; 047import java.util.Arrays; 048 049public class V2ValidateServlet extends JsonRestServlet { 050 private static final String INSTRUMENTATION_NAME = "v2validate"; 051 052 private static final ResourceInfo RESOURCE_INFO = 053 new ResourceInfo("", Arrays.asList("POST"), Arrays.asList( 054 new ParameterInfo(RestConstants.FILE_PARAM, String.class, true, Arrays.asList("POST")), 055 new ParameterInfo(RestConstants.USER_PARAM, String.class, true, Arrays.asList("POST")))); 056 057 058 public V2ValidateServlet() { 059 super(INSTRUMENTATION_NAME, RESOURCE_INFO); 060 } 061 062 /** 063 * Validate workflow definition. 064 */ 065 @Override 066 @SuppressWarnings("unchecked") 067 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 068 validateContentType(request, RestConstants.XML_CONTENT_TYPE); 069 070 String file = request.getParameter(RestConstants.FILE_PARAM); 071 String user = request.getParameter(RestConstants.USER_PARAM); 072 073 stopCron(); 074 075 StringWriter stringWriter = new StringWriter(); 076 if (file.startsWith("hdfs://")) { 077 try { 078 URI uri = new URI(file); 079 HadoopAccessorService has = Services.get().get(HadoopAccessorService.class); 080 Configuration fsConf = has.createConfiguration(uri.getAuthority()); 081 FileSystem fs = has.createFileSystem(user, uri, fsConf); 082 083 Path path = new Path(uri.getPath()); 084 IOUtils.copyCharStream(new InputStreamReader(fs.open(path)), stringWriter); 085 086 } catch (Exception e) { 087 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0505, 088 "File does not exist, "+ file); 089 } 090 } 091 else { 092 IOUtils.copyCharStream(new InputStreamReader(request.getInputStream()), stringWriter); 093 } 094 try { 095 validate(stringWriter.toString()); 096 } catch (Exception e) { 097 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0701, 098 file + ", " + e.toString()); 099 } 100 101 JSONObject json = createJSON("Valid workflow-app"); 102 startCron(); 103 sendJsonResponse(response, HttpServletResponse.SC_OK, json); 104 } 105 106 private void validate(String xml) throws Exception{ 107 SchemaService schemaService = Services.get().get(SchemaService.class); 108 Schema[] schemas = {schemaService.getSchema(SchemaService.SchemaName.WORKFLOW), 109 schemaService.getSchema(SchemaService.SchemaName.COORDINATOR), 110 schemaService.getSchema(SchemaService.SchemaName.BUNDLE), 111 schemaService.getSchema(SchemaService.SchemaName.SLA_ORIGINAL)}; 112 113 Exception exception = null; 114 for (int i = 0; i < schemas.length; i++) { 115 try{ 116 validateSchema(schemas[i], new StringReader(xml)); 117 exception = null; 118 break; 119 } catch (SAXException e) { 120 if (i == 0) { 121 exception = e; 122 } 123 // Check the root element declaration(workflow-app, coordinator-app, bundle-app). 124 // If invalid, move to next schema validation. 125 if (!e.getMessage().contains("cvc-elt.1")) { 126 exception = e; 127 break; 128 } 129 } catch (Exception e) { 130 exception = e; 131 break; 132 } 133 } 134 if (exception != null) { 135 throw exception; 136 } 137 } 138 139 private void validateSchema(Schema schema, Reader src) throws SAXException, IOException, OozieCLIException{ 140 Validator validator = schema.newValidator(); 141 validator.validate(new StreamSource(src)); 142 } 143 144 private JSONObject createJSON(String content) { 145 JSONObject jsonObject = new JSONObject(); 146 jsonObject.put(JsonTags.VALIDATE, content); 147 return jsonObject; 148 } 149 150}