use of org.eclipse.winery.common.ids.definitions.imports.GenericImportId in project winery by eclipse.
the class CsarImporter method importTypes.
/**
* Imports the specified types into the repository. The types are converted to an import statement
*
* @param errors Container for error messages
*/
private void importTypes(TDefinitions defs, final List<String> errors) {
Types typesContainer = defs.getTypes();
if (typesContainer != null) {
List<Object> types = typesContainer.getAny();
for (Object type : types) {
if (type instanceof Element) {
Element element = (Element) type;
// generate id part of ImportId out of definitions' id
// we do not use the name as the name has to be URLencoded again and we have issues with the interplay with org.eclipse.winery.common.ids.definitions.imports.GenericImportId.getId(TImport) then.
String id = defs.getId();
// try to make the id unique by hashing the "content" of the definition
id = id + "-" + Integer.toHexString(element.hashCode());
// set importId
DefinitionsChildId importId;
String ns;
if (element.getNamespaceURI().equals(XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
ns = element.getAttribute("targetNamespace");
importId = new XSDImportId(ns, id, false);
} else {
// Quick hack for non-XML-Schema-definitions
ns = "unknown";
importId = new GenericImportId(ns, id, false, element.getNamespaceURI());
}
// Following code is adapted from importOtherImports
TDefinitions wrapperDefs = BackendUtils.createWrapperDefinitions(importId);
TImport imp = new TImport();
String fileName = id + ".xsd";
imp.setLocation(fileName);
imp.setImportType(XMLConstants.W3C_XML_SCHEMA_NS_URI);
imp.setNamespace(ns);
wrapperDefs.getImport().add(imp);
CsarImporter.storeDefinitions(importId, wrapperDefs);
// put the file itself to the repo
// ref is required to generate fileRef
RepositoryFileReference ref = BackendUtils.getRefOfDefinitions(importId);
RepositoryFileReference fileRef = new RepositoryFileReference(ref.getParent(), fileName);
// convert element to document
// QUICK HACK. Alternative: Add new method RepositoryFactory.getRepository().getOutputStream and transform DOM node to OuptputStream
String content = Util.getXMLAsString(element);
try {
RepositoryFactory.getRepository().putContentToFile(fileRef, content, MediaTypes.MEDIATYPE_TEXT_XML);
} catch (IOException e) {
CsarImporter.LOGGER.debug("Could not put XML Schema definition to file " + fileRef.toString(), e);
errors.add("Could not put XML Schema definition to file " + fileRef.toString());
}
// add import to definitions
// adapt path - similar to importOtherImport
String newLoc = "../" + Util.getUrlPath(fileRef);
imp.setLocation(newLoc);
defs.getImport().add(imp);
} else {
// This is a known type. Otherwise JAX-B would render it as Element
errors.add("There is a Type of class " + type.getClass().toString() + " which is unknown to Winery. The type element is imported as is");
}
}
}
}
use of org.eclipse.winery.common.ids.definitions.imports.GenericImportId in project winery by eclipse.
the class WriterUtils method storeTypes.
public static void storeTypes(Path path, String namespace, String id) {
LOGGER.debug("Store type: {}", id);
try {
MediaType mediaType = MediaTypes.MEDIATYPE_XSD;
TImport.Builder builder = new TImport.Builder(Namespaces.XML_NS);
builder.setNamespace(namespace);
builder.setLocation(id + ".xsd");
GenericImportId rid = new XSDImportId(namespace, id, false);
TDefinitions definitions = BackendUtils.createWrapperDefinitions(rid);
definitions.getImport().add(builder.build());
CsarImporter.storeDefinitions(rid, definitions);
RepositoryFileReference ref = BackendUtils.getRefOfDefinitions(rid);
List<File> files = Files.list(path).filter(Files::isRegularFile).map(Path::toFile).collect(Collectors.toList());
for (File file : files) {
BufferedInputStream stream = new BufferedInputStream(new FileInputStream(file));
RepositoryFileReference fileRef = new RepositoryFileReference(ref.getParent(), file.getName());
RepositoryFactory.getRepository().putContentToFile(fileRef, stream, mediaType);
}
} catch (IllegalArgumentException | IOException e) {
throw new IllegalStateException(e);
}
}
use of org.eclipse.winery.common.ids.definitions.imports.GenericImportId in project winery by eclipse.
the class ToscaExportUtil method writeDefinitionsElement.
/**
* Writes the Definitions belonging to the given definitgion children to the output stream
*
* @return a collection of DefinitionsChildIds referenced by the given component
* @throws RepositoryCorruptException if tcId does not exist
*/
private Collection<DefinitionsChildId> writeDefinitionsElement(IRepository repository, DefinitionsChildId tcId, OutputStream out) throws JAXBException, RepositoryCorruptException, IOException {
if (!repository.exists(tcId)) {
String error = "Component instance " + tcId.toReadableString() + " does not exist.";
ToscaExportUtil.LOGGER.error(error);
throw new RepositoryCorruptException(error);
}
this.getPrepareForExport(repository, tcId);
Definitions entryDefinitions = repository.getDefinitions(tcId);
// BEGIN: Definitions modification
// the "imports" collection contains the imports of Definitions, not of other definitions
// the other definitions are stored in entryDefinitions.getImport()
// we modify the internal definitions object directly. It is not written back to the storage. Therefore, we do not need to clone it
// the imports (pointing to not-definitions (xsd, wsdl, ...)) already have a correct relative URL. (quick hack)
URI uri = (URI) this.exportConfiguration.get(ToscaExportUtil.ExportProperties.REPOSITORY_URI.toString());
if (uri != null) {
// we are in the plain-XML mode, the URLs of the imports have to be adjusted
for (TImport i : entryDefinitions.getImport()) {
String loc = i.getLocation();
if (!loc.startsWith("../")) {
LOGGER.warn("Location is not relative for id " + tcId.toReadableString());
}
;
loc = loc.substring(3);
loc = uri + loc;
// now the location is an absolute URL
i.setLocation(loc);
}
}
// files of imports have to be added to the CSAR, too
for (TImport i : entryDefinitions.getImport()) {
String loc = i.getLocation();
if (Util.isRelativeURI(loc)) {
// locally stored, add to CSAR
GenericImportId iid = new GenericImportId(i);
String fileName = Util.getLastURIPart(loc);
fileName = Util.URLdecode(fileName);
RepositoryFileReference ref = new RepositoryFileReference(iid, fileName);
this.putRefAsReferencedItemInCsar(ref);
}
}
Collection<DefinitionsChildId> referencedDefinitionsChildIds = repository.getReferencedDefinitionsChildIds(tcId);
// adjust imports: add imports of definitions to it
Collection<TImport> imports = new ArrayList<>();
for (DefinitionsChildId id : referencedDefinitionsChildIds) {
this.addToImports(repository, id, imports);
}
entryDefinitions.getImport().addAll(imports);
if (entryDefinitions.getElement() instanceof TEntityType) {
TEntityType entityType = (TEntityType) entryDefinitions.getElement();
// we have an entity type with a possible properties definition
WinerysPropertiesDefinition wpd = entityType.getWinerysPropertiesDefinition();
if (wpd != null) {
if (wpd.getIsDerivedFromXSD() == null) {
// Write WPD only to file if it exists and is NOT derived from an XSD (which may happen during import)
String wrapperElementNamespace = wpd.getNamespace();
String wrapperElementLocalName = wpd.getElementName();
// BEGIN: add import and put into CSAR
TImport imp = new TImport();
entryDefinitions.getImport().add(imp);
// fill known import values
imp.setImportType(XMLConstants.W3C_XML_SCHEMA_NS_URI);
imp.setNamespace(wrapperElementNamespace);
// add "winerysPropertiesDefinition" flag to import tag to support
Map<QName, String> otherAttributes = imp.getOtherAttributes();
otherAttributes.put(QNames.QNAME_WINERYS_PROPERTIES_DEFINITION_ATTRIBUTE, "true");
// Determine location
String loc = BackendUtils.getImportLocationForWinerysPropertiesDefinitionXSD((EntityTypeId) tcId, uri, wrapperElementLocalName);
if (uri == null) {
ToscaExportUtil.LOGGER.trace("CSAR Export mode. Putting XSD into CSAR");
// CSAR Export mode
// XSD has to be put into the CSAR
Document document = ModelUtilities.getWinerysPropertiesDefinitionXsdAsDocument(wpd);
// loc in import is URLencoded, loc on filesystem isn't
String locInCSAR = Util.URLdecode(loc);
// furthermore, the path has to start from the root of the CSAR; currently, it starts from Definitions/
locInCSAR = locInCSAR.substring(3);
ToscaExportUtil.LOGGER.trace("Location in CSAR: {}", locInCSAR);
this.referencesToPathInCSARMap.put(new DummyRepositoryFileReferenceForGeneratedXSD(document), locInCSAR);
}
imp.setLocation(loc);
// END: add import and put into CSAR
// BEGIN: generate TOSCA conforming PropertiesDefinition
PropertiesDefinition propertiesDefinition = new PropertiesDefinition();
propertiesDefinition.setType(new QName(wrapperElementNamespace, wrapperElementLocalName));
entityType.setPropertiesDefinition(propertiesDefinition);
// END: generate TOSCA conforming PropertiesDefinition
} else {
// noinspection StatementWithEmptyBody
// otherwise WPD exists, but is derived from XSD
// we DO NOT have to remove the winery properties definition from the output to allow "debugging" of the CSAR
}
}
}
// END: Definitions modification
this.writeDefinitionsElement(entryDefinitions, out);
return referencedDefinitionsChildIds;
}
use of org.eclipse.winery.common.ids.definitions.imports.GenericImportId in project winery by eclipse.
the class CsarImporter method importOtherImport.
/**
* SIDE EFFECT: modifies the location of imp to point to the correct relative location (when read from the exported
* CSAR)
*
* @param rootPath the absolute path where to resolve files from
*/
private void importOtherImport(Path rootPath, TImport imp, final List<String> errors, String type, boolean overwrite) {
assert (!type.equals(Namespaces.TOSCA_NAMESPACE));
String loc = imp.getLocation();
if (!Util.isRelativeURI(loc)) {
// This is just an information message
errors.add("Absolute URIs are not resolved by Winery (" + loc + ")");
return;
}
// location URLs are encoded: http://www.w3.org/TR/2001/WD-charmod-20010126/#sec-URIs, RFC http://www.ietf.org/rfc/rfc2396.txt
loc = Util.URLdecode(loc);
Path path;
try {
path = rootPath.resolve(loc);
} catch (Exception e) {
// java.nio.file.InvalidPathException could be thrown which is a RuntimeException
errors.add(e.getMessage());
return;
}
if (!Files.exists(path)) {
// fallback for older CSARs, where the location is given from the root
path = rootPath.getParent().resolve(loc);
if (!Files.exists(path)) {
errors.add(String.format("File %1$s does not exist", loc));
return;
}
}
String namespace = imp.getNamespace();
String fileName = path.getFileName().toString();
String id = fileName;
id = FilenameUtils.removeExtension(id);
// Convention: id of import is filename without extension
GenericImportId rid;
if (type.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
rid = new XSDImportId(namespace, id, false);
} else {
rid = new GenericImportId(namespace, id, false, type);
}
boolean importDataExistsInRepo = RepositoryFactory.getRepository().exists(rid);
if (!importDataExistsInRepo) {
// We have to
// a) create a .definitions file
// b) put the file itself in the repo
// Create the definitions file
TDefinitions defs = BackendUtils.createWrapperDefinitions(rid);
defs.getImport().add(imp);
// QUICK HACK: We change the imp object's location here and below again
// This is "OK" as "storeDefinitions" serializes the current state and not the future state of the imp object
// change the location to point to the file in the folder of the .definitions file
imp.setLocation(fileName);
// put the definitions file to the repository
CsarImporter.storeDefinitions(rid, defs);
}
// put the file itself to the repo
// ref is required to generate fileRef
RepositoryFileReference ref = BackendUtils.getRefOfDefinitions(rid);
RepositoryFileReference fileRef = new RepositoryFileReference(ref.getParent(), fileName);
// location is relative to Definitions/
// even if the import already exists, we have to adapt the path
// URIs are encoded
String newLoc = "../" + Util.getUrlPath(fileRef);
imp.setLocation(newLoc);
if (!importDataExistsInRepo || overwrite) {
// finally write the file to the storage
try (InputStream is = Files.newInputStream(path);
BufferedInputStream bis = new BufferedInputStream(is)) {
MediaType mediaType;
if (type.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
mediaType = MediaTypes.MEDIATYPE_XSD;
} else {
mediaType = BackendUtils.getMimeType(bis, path.getFileName().toString());
}
RepositoryFactory.getRepository().putContentToFile(fileRef, bis, mediaType);
} catch (IllegalArgumentException | IOException e) {
throw new IllegalStateException(e);
}
// we have to update the cache in case of a new XSD to speedup usage of winery
if (rid instanceof XSDImportId) {
// We do the initialization asynchronously
// We do not check whether the XSD has already been checked
// We cannot just checck whether an XSD already has been handled since the XSD could change over time
// Synchronization at org.eclipse.winery.repository.resources.imports.xsdimports.XSDImportResource.getAllDefinedLocalNames(short) also isn't feasible as the backend doesn't support locks
CsarImporter.xsdParsingService.submit(() -> {
CsarImporter.LOGGER.debug("Updating XSD import cache data");
// We call the queries without storing the result:
// We use the SIDEEFFECT that a cache is created
final XsdImportManager xsdImportManager = RepositoryFactory.getRepository().getXsdImportManager();
xsdImportManager.getAllDeclaredElementsLocalNames();
xsdImportManager.getAllDefinedTypesLocalNames();
CsarImporter.LOGGER.debug("Updated XSD import cache data");
});
}
}
}
Aggregations