/*
* ProActive Parallel Suite(TM):
* The Open Source library for parallel and distributed
* Workflows & Scheduling, Orchestration, Cloud Automation
* and Big Data Analysis on Enterprise Grids & Clouds.
*
* Copyright (c) 2007 - 2017 ActiveEon
* Contact: contact@activeeon.com
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation: version 3 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* If needed, contact us to obtain a release under GPL Version 2 or 3
* or a different license than the AGPL.
*/
package org.ow2.proactive.scheduler.common.job.factories.spi.stax;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.events.XMLEvent;
import org.ow2.proactive.scheduler.common.exception.JobValidationException;
import org.ow2.proactive.scheduler.common.job.TaskFlowJob;
import org.ow2.proactive.scheduler.common.job.factories.Schemas;
import org.ow2.proactive.scheduler.common.job.factories.ValidationUtil;
import org.ow2.proactive.scheduler.common.job.factories.XMLTags;
import org.ow2.proactive.scheduler.common.job.factories.spi.JobValidatorService;
/**
* Job XML Validator which validates against the XML schema
*/
public class StaxJobValidatorServiceProvider implements JobValidatorService {
private XMLInputFactory xmlInputFactory = null;
public StaxJobValidatorServiceProvider() {
System.setProperty("javax.xml.stream.XMLInputFactory", "com.ctc.wstx.stax.WstxInputFactory");
xmlInputFactory = XMLInputFactory.newInstance();
xmlInputFactory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
xmlInputFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.TRUE);
xmlInputFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.TRUE);
xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
}
@Override
public File validateJob(File jobFile) throws JobValidationException {
String findSchemaByNamespaceUsed;
try {
findSchemaByNamespaceUsed = findSchemaByNamespaceUsed(jobFile);
InputStream schemaStream = this.getClass().getResourceAsStream(findSchemaByNamespaceUsed);
ValidationUtil.validate(jobFile, schemaStream);
} catch (Exception e) {
// wrap all occurring exceptions as a schema exception
throw new JobValidationException(true, e);
}
return jobFile;
}
@Override
public TaskFlowJob validateJob(TaskFlowJob job) throws JobValidationException {
// validate any job
return job;
}
private String findSchemaByNamespaceUsed(File file)
throws FileNotFoundException, XMLStreamException, JobValidationException {
XMLStreamReader cursorRoot = xmlInputFactory.createXMLStreamReader(new FileInputStream(file));
try {
while (cursorRoot.hasNext()) {
String namespace = advanceCursorAndFindSchema(cursorRoot);
if (namespace != null)
return namespace;
}
return Schemas.SCHEMA_LATEST.getLocation();
} catch (Exception e) {
throw new JobValidationException(e.getMessage(), e);
} finally {
if (cursorRoot != null) {
cursorRoot.close();
}
}
}
private String advanceCursorAndFindSchema(XMLStreamReader cursorRoot) throws XMLStreamException {
int eventType;
String current;
eventType = cursorRoot.next();
if (eventType == XMLEvent.START_ELEMENT) {
current = cursorRoot.getLocalName();
if (XMLTags.JOB.matches(current)) {
String namespace = cursorRoot.getName().getNamespaceURI();
return Schemas.getSchemaByNamespace(namespace).getLocation();
}
}
return null;
}
}