/**
* Copyright (c) 2013/2014 Verein zur Foerderung der IT-Sicherheit in Oesterreich (SBA).
* The work has been developed in the TIMBUS Project and the above-mentioned are Members of the TIMBUS Consortium.
* TIMBUS is supported by the European Union under the 7th Framework Programme for research and technological
* development and demonstration activities (FP7/2007-2013) under grant agreement no. 269940.
*
* Licensed 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, including without
* limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTIBITLY, or FITNESS FOR A PARTICULAR
* PURPOSE. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise,
* unless required by applicable law or agreed to in writing, shall any Contributor be liable for damages, including
* any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this
* License or out of the use or inability to use the Work.
* See the License for the specific language governing permissions and limitation under the License.
*/
package net.timbusproject.dpes.alternative;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.ws.BindingProvider;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.io.IRIDocumentSource;
import org.semanticweb.owlapi.io.OWLXMLOntologyFormat;
import org.semanticweb.owlapi.io.StringDocumentSource;
import org.semanticweb.owlapi.io.StringDocumentTarget;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.MissingImportHandlingStrategy;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.model.OWLOntologyLoaderConfiguration;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.model.OWLOntologyStorageException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* @author Rudolf Mayer
*/
public class PreservationIdentifierClient {
public static final String DEFAULT_ONTOLOGY = "http://timbus.teco.edu/ontologies/examples/MusicClassification/main.owl";
public static final String DEFAULT_ONTOLOGY_HTML = "http://timbus.teco.edu/ontologies/examples/MusicClassification/MusicClassificationDSOs_withHtmlFormat.owl";
public static final String DEFAULT_SERVER_ADDRESS = "http://testbed.timbusproject.net:7080/pi_latest/preservationIdentifier?wsdl";
public static final String DEFAULT_ALTERNATIVE_ONTOLOGIES_BASE_URL = "http://testbed.timbusproject.net/test";
public static void main(String[] args) throws OwlElementNotFoundException_Exception,
org.semanticweb.owlapi.model.OWLOntologyCreationException, IOException_Exception,
OWLOntologyStorageException_Exception, OWLOntologyCreationException_Exception, OWLOntologyStorageException {
String ontology;
String baseurl;
String serverAddress;
String riskFileName;
// CLI parsing
Options options = new Options();
Option[] allOptions = new Option[] {
new Option("o", "ontology", true, "The ontology to use. Defaults to " + DEFAULT_ONTOLOGY),
new Option("b", "baseurl", true, "The baseurl to use for alternative ontologies. Defaults to "
+ DEFAULT_ALTERNATIVE_ONTOLOGIES_BASE_URL),
new Option("a", "address", true, "The address of the server. Defaults to " + DEFAULT_SERVER_ADDRESS),
new Option("r", "risks", true, "The risks file to use") };
for (Option option : allOptions) {
options.addOption(option);
}
CommandLineParser parser = new BasicParser();
try {
CommandLine cmd = parser.parse(options, args);
ontology = cmd.getOptionValue("ontology");
baseurl = cmd.hasOption("baseurl") ? cmd.getOptionValue("baseurl")
: DEFAULT_ALTERNATIVE_ONTOLOGIES_BASE_URL;
serverAddress = cmd.hasOption("address") ? cmd.getOptionValue("address") : DEFAULT_SERVER_ADDRESS;
riskFileName = cmd.getOptionValue("risks");
} catch (ParseException e) {
System.err.println("CLI parsing failed. Reason: " + e.getMessage());
// automatically generate the help statement
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp("ant", options);
return;
}
// System.out.println(String.format("Using: \nontology: %s\nbaseurl: %s\nserver: %s", ontology, baseurl,
// serverAddress));
System.out.println(String.format("Using: \nbaseurl: %s\nserver: %s", baseurl, serverAddress));
String identifier = RandomStringUtils.randomAlphanumeric(20);
final ArrayList<Risk> identifiedRisks = new ArrayList<Risk>();
ArrayList<Integer> expectedAlternativeCount = new ArrayList<Integer>();
ArrayList<String> ontologies = new ArrayList<String>();
Map<String, String> owls = new HashMap<String, String>();
if (StringUtils.isNotBlank(ontology)) {
owls.put("main", ontology);
ontologies.add(ontology);
} else {
owls.put("main", ontologyToString(loadOntology(DEFAULT_ONTOLOGY)));
owls.put("html", ontologyToString(loadOntology(DEFAULT_ONTOLOGY_HTML)));
}
if (StringUtils.isNotBlank(riskFileName)) {
System.out.println("Risks file '" + riskFileName + "' provided, trying to load...");
File riskFile = new File(riskFileName);
if (riskFile.canRead()) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(riskFile);
XPathExpression exprRisks = xpath.compile("/businessProcess/risks/risk/id");
NodeList risks = (NodeList) exprRisks.evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < risks.getLength(); i++) {
Node riskNode = risks.item(i);
String riskID = riskNode.getFirstChild().getNodeValue();
// String expression = "/businessProcess/risks/risk/id[text()='" + riskID + "']";
//
// Node riskNode = (Node) xpath.compile("/businessProcess/risks/risk/id[text()='" + riskID +
// "']").evaluate(
// document, XPathConstants.NODE);
// String expression = "/businessProcess/risks/risk/id[text()='" + riskID +
// "']/occurInResource";
String riskByIdExpression = "/businessProcess/risks/risk/id[text()='" + riskID + "']";
String riskName = xpath.compile(riskByIdExpression + "/../name").evaluate(document).trim();
String resourceID = xpath.compile(riskByIdExpression + "/../occurInResource").evaluate(document);
String resourceByIdExpression = "/businessProcess/resources/resource/id[text()='" + resourceID
+ "']";
String resourceName = xpath.compile(resourceByIdExpression + "/../name").evaluate(document).trim();
String resourceURL = xpath.compile(resourceByIdExpression + "/../contextModelURI").evaluate(
document).trim();
// String x = xpath.compile(riskByIdExpression).evaluate(document);
//
// // attributes.getNamedItem("occurInResource").getTextContent();
// XPathExpression exprResourceName =
// xpath.compile("/businessProcess/resources/resource/topic[@id='"
// + resourceID + "']/name");
// String resourceName = exprResourceName.evaluate(document);
// XPathExpression exprResourceURL =
// xpath.compile("/businessProcess/resources/resource/topic[@id='"
// + resourceID + "']/contextModelURI");
// String resourceURL = exprResourceURL.evaluate(document);
// System.out.println();
Risk risk = createRisk(riskID, resourceURL);
risk.setRiskName(riskName);
identifiedRisks.add(risk);
}
// System.out.println(risks);
// System.out.println(risks.getClass());
// Node root = document.getFirstChild();
// root.get
// System.out.println(root.getTextContent());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (SAXException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (XPathExpressionException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (ParserConfigurationException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
}
} else {
System.out.println("Can't read from file.");
}
if (identifiedRisks.size() == 0) {
System.out.println("Couldn't find any risks in the file !");
} else {
System.out.println("Loaded " + identifiedRisks.size() + " risks.");
}
} else {
// Package Alternatives
identifiedRisks.add(createRisk("risk1", "openjdk-6-jre"));
expectedAlternativeCount.add(15);
ontologies.add(owls.get("main"));
// Software Alternatives
identifiedRisks.add(createRisk("risk2", "InternetExplorer"));
expectedAlternativeCount.add(13);
ontologies.add(owls.get("html"));
// File Alternatives
identifiedRisks.add(createRisk("risk3", "HTML_File"));
expectedAlternativeCount.add(25);
ontologies.add(owls.get("html"));
// Missing resource, causes entry in the shortLog property
identifiedRisks.add(createRisk("risk4", "DoesNotExist")); // causes entry in the shortLog property
expectedAlternativeCount.add(0);
ontologies.add(owls.get("html"));
// Get alternatives using IRI and label. Because the label resolves to InternetExplorer
// and the kblib expects Internet-Explorer this returns no alternatives.
identifiedRisks.add(createRisk(
"risk5",
"http://timbus.teco.edu/ontologies/examples/MusicClassification/MusicClassificationDSOs_withHtmlFormat.owl#Internet_Explorer"));
expectedAlternativeCount.add(0);
ontologies.add(owls.get("html"));
}
boolean success = true;
for (int i = 0; i < identifiedRisks.size(); ++i) {
int actual = getAlternatives(baseurl, serverAddress, identifier, identifiedRisks.get(i), ontologies.get(i));
if (actual != expectedAlternativeCount.get(i)) {
success = false;
System.out.println(String.format("Unexpected alternative count! %d expected, %d found",
expectedAlternativeCount.get(i), actual));
}
}
String result = success ? "Success." : "Failure! Check the output for details.";
System.out.println(result);
}
private static int getAlternatives(String baseurl, String serverAddress, String identifier,
final Risk identifiedRisk, String model) throws IOException_Exception,
OWLOntologyCreationException_Exception, OWLOntologyStorageException_Exception,
OwlElementNotFoundException_Exception, OWLOntologyCreationException {
System.out.println(String.format("Retrieving alternatives for %s...", identifiedRisk.getAffectedResource()));
PreservationIdentifierService pi = new PreservationIdentifierServiceService().getPreservationIdentifierServicePort();
((BindingProvider) pi).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, serverAddress);
PreservationAlternatives preservationAlternatives = pi.identifyPreservationAlternatives(model,
new ArrayList<Risk>() {
{
add(identifiedRisk);
}
}, baseurl, identifier);
System.out.println(String.format("Found %d alternatives...",
preservationAlternatives.getPreservationAlternatives().size()));
System.out.println("Writing alternatives...");
int index = 1;
for (PreservationAlternative preservationAlternative : preservationAlternatives.getPreservationAlternatives()) {
String path = System.getProperty("java.io.tmpdir") + "/pi-" + preservationAlternative.getRiskIdentifier()
+ "-" + index + "/";
// noinspection ResultOfMethodCallIgnored
new File(path).mkdirs();
writeToFile(path + "original.owl", preservationAlternative.getOriginalContextModel());
writeToFile(path + "modified.owl", preservationAlternative.getModifiedContextModel());
writeToFile(path + "changes.owl", preservationAlternative.getChanges());
for (String importedOntology : preservationAlternative.getModifiedImportedOntologies()) {
OWLOntology imported = OWLManager.createOWLOntologyManager().loadOntologyFromOntologyDocument(
new StringDocumentSource(importedOntology));
writeToFile(path + imported.getOntologyID().getOntologyIRI().getFragment(), importedOntology);
}
index++;
}
// System.out.println(String.format("Long log: \n%s", preservationAlternatives.getLongLog())); // detailed log
System.out.println(String.format("Short log: \n%s", preservationAlternatives.getShortLog()));
return index - 1;
}
private static OWLOntology loadOntology(String ontology) throws OWLOntologyCreationException {
OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
return manager.loadOntologyFromOntologyDocument(
new IRIDocumentSource(IRI.create(ontology)),
new OWLOntologyLoaderConfiguration().setMissingImportHandlingStrategy(MissingImportHandlingStrategy.THROW_EXCEPTION));
}
private static Risk createRisk(String identifier, String affectedResource) {
Risk identifiedRisk = new Risk();
identifiedRisk.setRiskIdentifier(identifier);
identifiedRisk.setAffectedResource(affectedResource);
return identifiedRisk;
}
public static void writeToFile(final String pathname, final String str) {
try {
FileUtils.write(new File(pathname), str);
System.out.println("Wrote ontology to " + pathname);
} catch (IOException e) {
e.printStackTrace();
}
}
public static String ontologyToString(OWLOntology ontology)
throws org.semanticweb.owlapi.model.OWLOntologyStorageException {
StringDocumentTarget stringDocumentTarget = new StringDocumentTarget();
OWLManager.createOWLOntologyManager().saveOntology(ontology, new OWLXMLOntologyFormat(), stringDocumentTarget);
return stringDocumentTarget.toString();
}
}