Search in sources :

Example 1 with GenericImportId

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");
            }
        }
    }
}
Also used : Types(org.eclipse.winery.model.tosca.TDefinitions.Types) MediaTypes(org.eclipse.winery.repository.backend.constants.MediaTypes) XSDImportId(org.eclipse.winery.common.ids.definitions.imports.XSDImportId) RepositoryFileReference(org.eclipse.winery.common.RepositoryFileReference) Element(org.w3c.dom.Element) IOException(java.io.IOException) GenericImportId(org.eclipse.winery.common.ids.definitions.imports.GenericImportId)

Example 2 with GenericImportId

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);
    }
}
Also used : XSDImportId(org.eclipse.winery.common.ids.definitions.imports.XSDImportId) TImport(org.eclipse.winery.model.tosca.TImport) GenericImportId(org.eclipse.winery.common.ids.definitions.imports.GenericImportId) RepositoryFileReference(org.eclipse.winery.common.RepositoryFileReference) MediaType(org.apache.tika.mime.MediaType) Files(java.nio.file.Files) TDefinitions(org.eclipse.winery.model.tosca.TDefinitions)

Example 3 with GenericImportId

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;
}
Also used : TEntityType(org.eclipse.winery.model.tosca.TEntityType) QName(javax.xml.namespace.QName) Definitions(org.eclipse.winery.model.tosca.Definitions) TImport(org.eclipse.winery.model.tosca.TImport) WinerysPropertiesDefinition(org.eclipse.winery.model.tosca.kvproperties.WinerysPropertiesDefinition) Document(org.w3c.dom.Document) URI(java.net.URI) GenericImportId(org.eclipse.winery.common.ids.definitions.imports.GenericImportId) RepositoryFileReference(org.eclipse.winery.common.RepositoryFileReference) PropertiesDefinition(org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition) WinerysPropertiesDefinition(org.eclipse.winery.model.tosca.kvproperties.WinerysPropertiesDefinition) RepositoryCorruptException(org.eclipse.winery.repository.exceptions.RepositoryCorruptException)

Example 4 with GenericImportId

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");
            });
        }
    }
}
Also used : XSDImportId(org.eclipse.winery.common.ids.definitions.imports.XSDImportId) BufferedInputStream(java.io.BufferedInputStream) ZipInputStream(java.util.zip.ZipInputStream) InputStream(java.io.InputStream) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) JAXBException(javax.xml.bind.JAXBException) ConfigurationException(org.apache.commons.configuration.ConfigurationException) IOException(java.io.IOException) GenericImportId(org.eclipse.winery.common.ids.definitions.imports.GenericImportId) RepositoryFileReference(org.eclipse.winery.common.RepositoryFileReference) BufferedInputStream(java.io.BufferedInputStream) MediaType(org.apache.tika.mime.MediaType) XsdImportManager(org.eclipse.winery.repository.backend.xsd.XsdImportManager)

Aggregations

RepositoryFileReference (org.eclipse.winery.common.RepositoryFileReference)4 GenericImportId (org.eclipse.winery.common.ids.definitions.imports.GenericImportId)4 XSDImportId (org.eclipse.winery.common.ids.definitions.imports.XSDImportId)3 IOException (java.io.IOException)2 MediaType (org.apache.tika.mime.MediaType)2 TImport (org.eclipse.winery.model.tosca.TImport)2 BufferedInputStream (java.io.BufferedInputStream)1 InputStream (java.io.InputStream)1 URI (java.net.URI)1 URISyntaxException (java.net.URISyntaxException)1 Files (java.nio.file.Files)1 ZipInputStream (java.util.zip.ZipInputStream)1 JAXBException (javax.xml.bind.JAXBException)1 QName (javax.xml.namespace.QName)1 ConfigurationException (org.apache.commons.configuration.ConfigurationException)1 Definitions (org.eclipse.winery.model.tosca.Definitions)1 TDefinitions (org.eclipse.winery.model.tosca.TDefinitions)1 Types (org.eclipse.winery.model.tosca.TDefinitions.Types)1 TEntityType (org.eclipse.winery.model.tosca.TEntityType)1 PropertiesDefinition (org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition)1