blob: 8bddf1b9dfc9c99fb4355f90a7183c1f245790b5 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.oozie.servlet;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.oozie.ErrorCode;
import org.apache.oozie.cli.OozieCLIException;
import org.apache.oozie.client.rest.JsonTags;
import org.apache.oozie.client.rest.RestConstants;
import org.apache.oozie.service.HadoopAccessorService;
import org.apache.oozie.service.SchemaService;
import org.apache.oozie.service.Services;
import org.apache.oozie.util.IOUtils;
import org.json.simple.JSONObject;
import org.xml.sax.SAXException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.Validator;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
public class V2ValidateServlet extends JsonRestServlet {
private static final String INSTRUMENTATION_NAME = "v2validate";
private static final ResourceInfo RESOURCE_INFO =
new ResourceInfo("", Arrays.asList("POST"), Arrays.asList(
new ParameterInfo(RestConstants.FILE_PARAM, String.class, true, Arrays.asList("POST")),
new ParameterInfo(RestConstants.USER_PARAM, String.class, true, Arrays.asList("POST"))));
public static final String VALID_WORKFLOW_APP = "Valid workflow-app";
public V2ValidateServlet() {
super(INSTRUMENTATION_NAME, RESOURCE_INFO);
}
/**
* Validate workflow definition.
*/
@Override
@SuppressWarnings("unchecked")
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
validateContentType(request, RestConstants.XML_CONTENT_TYPE);
String file = request.getParameter(RestConstants.FILE_PARAM);
String user = request.getParameter(RestConstants.USER_PARAM);
stopCron();
StringWriter stringWriter = new StringWriter();
if (file.startsWith("hdfs://")) {
try {
URI uri = new URI(file);
HadoopAccessorService has = Services.get().get(HadoopAccessorService.class);
Configuration fsConf = has.createConfiguration(uri.getAuthority());
FileSystem fs = has.createFileSystem(user, uri, fsConf);
Path path = new Path(uri.getPath());
IOUtils.copyCharStream(new InputStreamReader(fs.open(path), StandardCharsets.UTF_8), stringWriter);
} catch (Exception e) {
throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0505,
"File does not exist, "+ file);
}
}
else {
IOUtils.copyCharStream(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8), stringWriter);
}
try {
validate(stringWriter.toString());
} catch (Exception e) {
throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0701,
file + ", " + e.toString());
}
JSONObject json = createJSON(VALID_WORKFLOW_APP);
startCron();
sendJsonResponse(response, HttpServletResponse.SC_OK, json);
}
public void validate(String xml) throws Exception {
SchemaService schemaService = Services.get().get(SchemaService.class);
Schema[] schemas = {schemaService.getSchema(SchemaService.SchemaName.WORKFLOW),
schemaService.getSchema(SchemaService.SchemaName.COORDINATOR),
schemaService.getSchema(SchemaService.SchemaName.BUNDLE),
schemaService.getSchema(SchemaService.SchemaName.SLA_ORIGINAL)};
Exception exception = null;
for (int i = 0; i < schemas.length; i++) {
try{
validateSchema(schemas[i], new StringReader(xml));
exception = null;
break;
} catch (SAXException e) {
if (i == 0) {
exception = e;
}
// Check the root element declaration(workflow-app, coordinator-app, bundle-app).
// If invalid, move to next schema validation.
if (!e.getMessage().contains("cvc-elt.1")) {
exception = e;
break;
}
} catch (Exception e) {
exception = e;
break;
}
}
if (exception != null) {
throw exception;
}
}
private void validateSchema(Schema schema, Reader src) throws SAXException, IOException, OozieCLIException{
Validator validator = SchemaService.getValidator(schema);
validator.validate(new StreamSource(src));
}
private JSONObject createJSON(String content) {
JSONObject jsonObject = new JSONObject();
jsonObject.put(JsonTags.VALIDATE, content);
return jsonObject;
}
}