Package org.wso2.carbon.registry.extensions.handlers.utils

Source Code of org.wso2.carbon.registry.extensions.handlers.utils.SchemaFileProcessor

/*
* Copyright (c) 2008, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.wso2.carbon.registry.extensions.handlers.utils;

import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.commons.schema.XmlSchemaCollection;
import org.apache.ws.commons.schema.XmlSchemaExternal;
import org.apache.ws.commons.schema.XmlSchemaObjectCollection;
import org.wso2.carbon.registry.core.*;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.extensions.utils.CommonConstants;
import org.xml.sax.InputSource;

import java.io.ByteArrayOutputStream;
import java.util.*;

public class SchemaFileProcessor {

    private Registry registry;
    private ArrayList schemaPath;

    /**
     * Buffer to hold associations untill all the resources are added. We should add associations
     * only after both ends (resources) of the association is added to the registry. Otherwise, it
     * will cause an error as the registry tries to find the both end resources before setting the
     * association.
     */
    private List<Association> associationsBuffer = new ArrayList<Association>();

    // remove this when it is not needed
    private int i;

    public SchemaFileProcessor(Registry registry) {
        this.registry = registry;
        schemaPath = new ArrayList();
    }

    /**
     * Import a schema file to the registry after saving all its includes and imports to the
     * registry and updating the schema locations accordingly.
     *
     * @param location         the original schema location
     * @param registryBasePath base path of the registry
     * @param processIncludes  true if we should recurse through includes
     * @param metadata         template Resource from which to obtain media-type, description, etc.
     * @return the resulting path of the new resource
     * @throws org.wso2.carbon.registry.core.exceptions.RegistryException
     *
     */
    public String saveSchemaFileToRegistry(String location,
                                           String registryBasePath,
                                           boolean processIncludes,
                                           Resource metadata)
            throws RegistryException {
        return saveSchemaFileToRegistry(location, new HashMap(), registryBasePath, processIncludes,
                                        metadata);
    }

    /**
     * Import a schema file to the registry after saving all its includes and imports to the
     * registry and updating the schema locations accordingly.
     *
     * @param location           the original schema location
     * @param processedSchemaMap a Map from original URI (String) to new schema location (String)
     * @param registryBasePath   base path of the registry
     * @param processIncludes    true if we should recurse through includes
     * @param metadata           template Resource from which to obtain media-type, description,
     *                           etc.
     * @return the resulting path of the new resource
     * @throws RegistryException
     */
    public String saveSchemaFileToRegistry(String location,
                                           Map processedSchemaMap,
                                           String registryBasePath,
                                           boolean processIncludes,
                                           Resource metadata)
            throws RegistryException {

        XmlSchemaCollection xmlSchemaCollection = new XmlSchemaCollection();
        InputSource inputSource = new InputSource(location);

        // Here we assue schema is correct. Schema validation is beyond our scope, so we don't
        // bother with a ValidationEventHandler.
        XmlSchema xmlSchema = xmlSchemaCollection.read(inputSource, null);

        String baseUri = xmlSchema.getSourceURI();
        String xsdFileName = baseUri.substring(baseUri.lastIndexOf("/") + 1);
        String savedName = xsdFileName.substring(0, xsdFileName.indexOf(".")) + ".xsd";

        // this is not an inline wsdl schema. so pass null to change map.
        calculateNewSchemaNames(xmlSchema, processedSchemaMap, new HashSet(), false,
                                processIncludes);
        saveSchemaFileToRegistry(xmlSchema, processedSchemaMap, null, new HashSet(), false,
                                 registryBasePath, processIncludes, metadata);
        return savedName;
    }

    /**
     * calculate the new schema file names to save the schema. Here we can not save the schema file
     * as it is since there may be recursive imports. So what we have to do is to first determine
     * the schema names to be saved and then change the schema locations accordingly. In this method
     * first we iterate through the imports and includes and find the names. have used the
     * visitedSchemas variable to keep track of the visited schemas to avoid the recursion.
     *
     * @param xmlSchema          the schema to we'd like to save into the registry
     * @param processedSchemaMap a Map from original URI (String) to new schema location (String)
     * @param visitedSchemas     a Set of previously visited schema source uris
     * @param isWSDLInlineSchema true if the given schema is an inline schema of a wsdl - if so, we
     *                           do not need to calculate a name for it
     * @param processIncludes    true if we should process includes
     */
    public void calculateNewSchemaNames(XmlSchema xmlSchema,
                                        Map processedSchemaMap,
                                        Set visitedSchemas,
                                        boolean isWSDLInlineSchema,
                                        boolean processIncludes) {

        if (processIncludes) {
            // first process the imports and includes
            XmlSchemaObjectCollection includes = xmlSchema.getIncludes();
            // set this as an visited schema to stop recursion
            visitedSchemas.add(xmlSchema.getSourceURI());
            if (includes != null) {
                Object externalComponent;
                XmlSchemaExternal xmlSchemaExternal;
                XmlSchema innerSchema;
                for (Iterator iter = includes.getIterator(); iter.hasNext();) {
                    externalComponent = iter.next();
                    if (externalComponent instanceof XmlSchemaExternal) {
                        xmlSchemaExternal = (XmlSchemaExternal)externalComponent;
                        innerSchema = xmlSchemaExternal.getSchema();
                        String sourceURI = innerSchema.getSourceURI();
                        // Process if we haven't already encountered this one
                        if (!processedSchemaMap.containsKey(sourceURI) &&
                            !visitedSchemas.contains(sourceURI)) {
                            calculateNewSchemaNames(innerSchema, processedSchemaMap, visitedSchemas,
                                                    false, processIncludes);
                        }
                    }
                }
            }
        }

        // after processing includes and imports save the xml schema
        if (!isWSDLInlineSchema) {
            String baseUri = xmlSchema.getSourceURI();
            String xsdFileName = baseUri.substring(baseUri.lastIndexOf("/") + 1);
            String fileNameToSave = xsdFileName.substring(0, xsdFileName.indexOf(".")) + ".xsd";
            while (processedSchemaMap.containsValue(fileNameToSave)) {
                fileNameToSave = xsdFileName.substring(0, xsdFileName.indexOf(".")) + ++i + ".xsd";
            }
            // add this entry to the processed wsdl map
            processedSchemaMap.put(baseUri, fileNameToSave);
        }
    }

    /**
     * Save the schemas to the registry. used the calculated names in the processedSchemaMap to
     * change the schema locations.
     *
     * @param xmlSchema          the schema to save
     * @param processedSchemaMap a Map from original URI (String) to new schema location (String)
     * @param changeSchemaNames  a Map from original URIs to changed URIs.  Used to update the WSDL
     *                           inline schema imports/includes when saving WSDLs.
     * @param visitedSchemas     a Set of schema URIs (Strings) that we've already visited
     * @param isWSDLInlineSchema true if this is an inline schema from a WSDL
     * @param registryBasePath   the base path of the registry
     * @param processIncludes    true if we should recurse into includes of this schema
     * @param metadata           template Resource for metadata (media-type, description)
     * @throws RegistryException
     */
    public void saveSchemaFileToRegistry(XmlSchema xmlSchema,
                                         Map processedSchemaMap,
                                         Map changeSchemaNames,
                                         Set visitedSchemas,
                                         boolean isWSDLInlineSchema,
                                         String registryBasePath,
                                         boolean processIncludes,
                                         Resource metadata) throws RegistryException {

        List associations = new ArrayList();
        if (processIncludes) {
            // first process the imports and includes
            XmlSchemaObjectCollection includes = xmlSchema.getIncludes();
            // set this as an visited schema to stop recursion
            visitedSchemas.add(xmlSchema.getSourceURI());
            if (includes != null) {
                for (Iterator iter = includes.getIterator(); iter.hasNext();) {
                    Object externalComponent = iter.next();
                    if (externalComponent instanceof XmlSchemaExternal) {
                        XmlSchemaExternal xmlSchemaExternal = (XmlSchemaExternal)externalComponent;
                        String sourceURI = xmlSchemaExternal.getSchema().getSourceURI();
                        if (!visitedSchemas.contains(sourceURI)) {
                            saveSchemaFileToRegistry(xmlSchemaExternal.getSchema(),
                                                     processedSchemaMap, null, visitedSchemas,
                                                     false, registryBasePath, processIncludes,
                                                     null);
                        }

                        // add the new name to changeschema map
                        // have to do before change the schema location
                        String newLocation = (String)processedSchemaMap.get(sourceURI);
                        if (isWSDLInlineSchema) {
                            changeSchemaNames.put(xmlSchemaExternal.getSchemaLocation(),
                                                  newLocation);
                        } else {

                        }
                        // set the new location
                        xmlSchemaExternal.setSchemaLocation(newLocation);
                        String innerFileNameToSave = (String)processedSchemaMap.get(sourceURI);
                        String innerXSDPath = getXSDPath(registryBasePath, innerFileNameToSave);
                        associations.add(innerXSDPath);
                    }
                }
            }
        }

        // after processing includes and imports save the xml schema
        if (!isWSDLInlineSchema) {
            String fileNameToSave = (String)processedSchemaMap.get(xmlSchema.getSourceURI());
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            xmlSchema.write(byteArrayOutputStream);
            byte[] xsdContent = byteArrayOutputStream.toByteArray();

            Resource xsdResource = new ResourceImpl();
            if (metadata != null) {
                xsdResource.setMediaType(metadata.getMediaType());
                xsdResource.setDescription(metadata.getDescription());
            }
            xsdResource.setContent(xsdContent);

            String xsdPath = getXSDPath(registryBasePath, fileNameToSave);
            String targetNamespace = xmlSchema.getTargetNamespace();
            xsdResource.addProperty("targetNamespace", targetNamespace);

            registry.put(xsdPath, xsdResource);
            schemaPath.add(xsdPath);
            String associationPath;
            for (Object association : associations) {
                associationPath = (String)association;
                associationsBuffer.add(new Association(xsdPath, associationPath,
                       CommonConstants.DEPENDS));
            }

        }
    }

    private String getXSDPath(String registryBasePath, String fileNameToSave) {
        String xsdPath;
        if (RegistryConstants.ROOT_PATH.equals(registryBasePath)) {
            xsdPath = RegistryConstants.ROOT_PATH + fileNameToSave;
        } else {
            xsdPath = registryBasePath + RegistryConstants.PATH_SEPARATOR + fileNameToSave;
        }
        return xsdPath;
    }

    public void persistAssociations() throws RegistryException {

        Iterator<Association> associationIterator = associationsBuffer.iterator();

        while (associationIterator.hasNext()) {

            Association association = associationIterator.next();
            registry.addAssociation(association.getSourcePath(), association.getDestinationPath(),
                                    association.getAssociationType());
        }
    }


    public ArrayList getSchemaPath() {
        return schemaPath;
    }
}
TOP

Related Classes of org.wso2.carbon.registry.extensions.handlers.utils.SchemaFileProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.