/* * 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 com.ibm.wsdl.extensions.schema.SchemaImportImpl; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; 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.CarbonException; import org.wso2.carbon.registry.core.*; import org.wso2.carbon.registry.core.exceptions.RegistryException; import org.wso2.carbon.registry.core.jdbc.handlers.RequestContext; import org.wso2.carbon.registry.core.session.CurrentSession; import org.wso2.carbon.registry.core.utils.RegistryUtils; import org.wso2.carbon.registry.extensions.services.Utils; import org.wso2.carbon.registry.extensions.utils.CommonConstants; import org.wso2.carbon.registry.extensions.utils.CommonUtil; import org.wso2.carbon.registry.extensions.utils.WSDLUtil; import org.wso2.carbon.registry.extensions.utils.WSDLValidationInfo; import org.wso2.carbon.utils.CarbonUtils; import org.xml.sax.InputSource; import javax.wsdl.Types; import javax.wsdl.extensions.schema.Schema; import java.io.ByteArrayInputStream; import java.io.File; import java.net.URI; import java.net.URISyntaxException; import java.util.*; public class SchemaProcessor { private Registry registry; private Registry systemRegistry; private List<String> processedSchemas; private List<String> visitedSchemas; private Map<String, SchemaInfo> schemas; private List<Association> associations; private String baseURI = null; private WSDLValidationInfo validationInfo; private static final String SCHEMA_VALIDATION_MESSAGE = "Schema Validation Message "; private static final String SCHEMA_STATUS = "Schema Validation"; private boolean useOriginalSchema; private String resourceName = ""; private static final Log log = LogFactory.getLog(SchemaProcessor.class); private int i; private String absoluteFilePath = null;//to hold the absolute path of schema from the sourceuri public SchemaProcessor(RequestContext requestContext, WSDLValidationInfo validationInfo) { this.registry = requestContext.getRegistry(); try { this.systemRegistry = CommonUtil.getUnchrootedSystemRegistry(requestContext); } catch (RegistryException ignore) { this.systemRegistry = null; } i = 0; schemas = new LinkedHashMap<String, SchemaInfo> (); processedSchemas = new ArrayList<String>(); visitedSchemas = new ArrayList<String>(); associations = new ArrayList<Association>(); this.validationInfo = validationInfo; } public SchemaProcessor(RequestContext requestContext, WSDLValidationInfo validationInfo, boolean useOriginalSchema) { this(requestContext,validationInfo); this.useOriginalSchema = useOriginalSchema; } /* Save the schema, schema imports, associations in the registry. Intended to used by the XSD Media-type handler only. */ public String putSchemaToRegistry( RequestContext requestContext, String resourcePath, String commonLocation, boolean processIncludes,boolean disableSymlinkCreation) throws RegistryException { boolean isDefaultEnvironment = true; String currentSchemaLocation = null; String currentEnvironment = null; String masterVersion = null; List<String> dependeinciesList = new ArrayList<String>(); resourceName = resourcePath.substring(resourcePath.lastIndexOf(RegistryConstants.PATH_SEPARATOR) + 1); XmlSchemaCollection xmlSchemaCollection = new XmlSchemaCollection(); ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream((byte[])requestContext.getResource().getContent()); InputSource inputSource = new InputSource(byteArrayInputStream); String url = "http://this.schema.needs/a/valid/source/url/to/proceed.xsd"; String version = requestContext.getResource().getProperty("version"); if(version == null){ version = CommonConstants.SCHEMA_VERSION_DEFAULT_VALUE; requestContext.getResource().setProperty("version", version); } if(requestContext.getSourceURL() != null) { url = requestContext.getSourceURL(); } XmlSchema xmlSchema; try { xmlSchemaCollection.setBaseUri(url); xmlSchema = xmlSchemaCollection.read(inputSource, null); xmlSchema.setSourceURI(url); evaluateSchemasRecursively(xmlSchema, null, false, true); }catch (URISyntaxException e) { String msg = "Syntax error in the uri"; log.error(msg, e); throw new RegistryException(msg, e);//to preserver the exception handling execution path of the rest of the //application. }catch (RuntimeException re) { String msg = "Could not read the XML Schema Definition file. "; if (re.getCause() instanceof org.apache.ws.commons.schema.XmlSchemaException) { msg += re.getCause().getMessage(); log.error(msg, re); throw new RegistryException(msg); } throw new RegistryException(msg, re); } String path = null; // should depend on the central location / relative location flag if (!resourcePath.equals(RegistryConstants.PATH_SEPARATOR + resourceName) & !resourcePath.contains(commonLocation) & (registry.resourceExists(resourcePath))) { if (currentSchemaLocation == null) { currentEnvironment = resourcePath.substring(0, resourcePath.indexOf(CommonUtil. derivePathFragmentFromNamespace(xmlSchema.getTargetNamespace()).replace("//", "/"))); currentSchemaLocation = currentEnvironment.substring(RegistryConstants.GOVERNANCE_REGISTRY_BASE_PATH.length() + 1); } if (masterVersion == null) { String namespaceSegment = CommonUtil. derivePathFragmentFromNamespace(xmlSchema.getTargetNamespace()).replace("//", "/"); String suffix = resourcePath.substring(resourcePath.indexOf(namespaceSegment) + namespaceSegment.length()); masterVersion = suffix.substring(0, suffix.indexOf(RegistryConstants.PATH_SEPARATOR)); } isDefaultEnvironment = false; Association[] associations = registry.getAssociations(resourcePath, CommonConstants.DEPENDS); for (Association association : associations) { if (association.getSourcePath().equals(resourcePath)) { dependeinciesList.add(association.getDestinationPath()); } } dependeinciesList.add(resourcePath); // updateSchemaPaths(currentEnvironment,masterVersion,dependeinciesList); // updateSchemaInternalsAndAssociations(); String symlinkLocation = RegistryUtils.getAbsolutePath(requestContext.getRegistryContext(), requestContext.getResource().getProperty(RegistryConstants.SYMLINK_PROPERTY_NAME)); Resource metaResource = requestContext.getResource(); path = saveSchemasToRegistry(requestContext, currentEnvironment, symlinkLocation, metaResource, masterVersion, dependeinciesList,disableSymlinkCreation); persistAssociations(path); } else { updateSchemaPaths(commonLocation, version, requestContext); updateSchemaInternalsAndAssociations(); String symlinkLocation = RegistryUtils.getAbsolutePath(requestContext.getRegistryContext(), requestContext.getResource().getProperty(RegistryConstants.SYMLINK_PROPERTY_NAME)); Resource metaResource = requestContext.getResource(); path = saveSchemaToRegistry(requestContext, resourcePath, symlinkLocation, metaResource,disableSymlinkCreation); persistAssociations(path); } return path; } /* Save the schema, schema imports, associations in the registry. Intended to used by the XSD Media-type handler only. */ public String importSchemaToRegistry(RequestContext requestContext, String resourcePath, String commonLocation, boolean processIncludes,boolean disableSymlinkCreation) throws RegistryException { resourceName = resourcePath.substring(resourcePath.lastIndexOf(RegistryConstants.PATH_SEPARATOR) + 1); String url = requestContext.getSourceURL(); String version = requestContext.getResource().getProperty("version"); if(version == null){ version = CommonConstants.SCHEMA_VERSION_DEFAULT_VALUE; } XmlSchemaCollection xmlSchemaCollection = new XmlSchemaCollection(); xmlSchemaCollection.setBaseUri(url); baseURI = url; InputSource inputSource = new InputSource(url); try { // 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); evaluateSchemasRecursively(xmlSchema, null, false, true); }catch (URISyntaxException e) { String msg = "Syntax error in the uri"; log.error(msg, e); throw new RegistryException(msg, e);//to preserver the exception handling execution path of the rest of the //application. } catch (RuntimeException re) { String msg = "Could not read the XML Schema Definition file. "; if (re.getCause() instanceof org.apache.ws.commons.schema.XmlSchemaException) { msg += re.getCause().getMessage(); log.error(msg, re); throw new RegistryException(msg); } throw new RegistryException(msg, re); } updateSchemaPaths(commonLocation,version, requestContext); updateSchemaInternalsAndAssociations(); String symlinkLocation = requestContext.getResource().getProperty(RegistryConstants.SYMLINK_PROPERTY_NAME); Resource metaResource = requestContext.getResource(); String path = saveSchemaToRegistry(requestContext, resourcePath, symlinkLocation, metaResource,disableSymlinkCreation); // should depend on the central location / relative location flag persistAssociations(path); return path; } public void evaluateSchemas( Types types, String wsdlDocumentBaseURI, boolean evaluateImports, ArrayList<String> dependencies) throws RegistryException { baseURI = wsdlDocumentBaseURI; /* evaluating schemas found under wsdl:types tag in a wsdl */ if (types != null) { List extensibleElements = types.getExtensibilityElements(); Schema schema; Object extensionObject; XmlSchema xmlSchema; XmlSchemaCollection xmlSchemaCollection; wsdlDocumentBaseURI = wsdlDocumentBaseURI.substring(0, wsdlDocumentBaseURI.lastIndexOf("/") + 1); for (Object extensibleElement : extensibleElements) { extensionObject = extensibleElement; if (extensionObject instanceof Schema) { schema = (Schema)extensionObject; if (schema.getImports().size() > 0) { SchemaImportImpl schemaImport = (SchemaImportImpl) ((Vector) schema.getImports().values() .toArray()[0]).firstElement(); if (schemaImport.getReferencedSchema() != null) { // already added imported xsd CommonUtil.addImportedArtifact( new File(schemaImport.getReferencedSchema().getDocumentBaseURI()).toString()); } } xmlSchemaCollection = new XmlSchemaCollection(); /* setting base URI in the collection to load relative schemas */ xmlSchemaCollection.setBaseUri(wsdlDocumentBaseURI); xmlSchema = xmlSchemaCollection.read(schema.getElement()); try { evaluateSchemasRecursively(xmlSchema, dependencies, true, false); } catch (URISyntaxException e) { String msg = "Syntax error in the uri"; log.error(msg, e); throw new RegistryException(msg, e);//to preserver the exception handling execution path of the rest of the //application. } } } } } private void evaluateSchemasRecursively( XmlSchema xmlSchema, ArrayList<String> dependencies, boolean isWSDLInlineSchema, boolean isMasterSchema) throws RegistryException, URISyntaxException { // first process the imports and includes XmlSchemaObjectCollection includes = xmlSchema.getIncludes(); SchemaInfo schemaInfo = new SchemaInfo(); schemaInfo.setMasterSchema(isMasterSchema); if (xmlSchema.getSourceURI() != null) { // set this as an visited schema to stop infinite traversal visitedSchemas.add(xmlSchema.getSourceURI()); //Get the uri form of the sourceUri string. URI uri = new URI(xmlSchema.getSourceURI()); //Extract the absolute path of master schema which has 'file' uri. if (isMasterSchema && uri.getScheme().equals("file")) { String sourceUri = xmlSchema.getSourceURI(); absoluteFilePath = StringUtils.removeStart(sourceUri, "file:///");//gives the file path // without "file:///" prefix. } } 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(); if (innerSchema != null) { String sourceURI = innerSchema.getSourceURI(); if (isWSDLInlineSchema) { dependencies.add(sourceURI); } else { schemaInfo.getSchemaDependencies().add(sourceURI); } if (!visitedSchemas.contains(sourceURI)) { String dependencyAbsoluteFilePath = StringUtils.removeStart(sourceURI, "file:/");//gives // the file path without "file:/" prefix. if (!dependencyAbsoluteFilePath.equals(absoluteFilePath)) {//evaluate schema recursively if the //absolute filepaths are different. evaluateSchemasRecursively( innerSchema, null, /* passing null is safe since we are passing isWSDLSchema = false */ false, false); /* ignore inline schema and proceed with included ones */ } } } } } } if (!isWSDLInlineSchema) { // after processing includes and imports save the xml schema String sourceURI = xmlSchema.getSourceURI(); String fileNameToSave; if (isMasterSchema) { fileNameToSave = extractResourceFromURL(resourceName, ".xsd"); } else { fileNameToSave = extractResourceFromURL(sourceURI.substring(sourceURI.lastIndexOf(RegistryConstants.PATH_SEPARATOR) + 1), ".xsd"); } fileNameToSave = fileNameToSave.replace("?xsd=", "."); String originalName = fileNameToSave; while (processedSchemas.contains(fileNameToSave)) { fileNameToSave = fileNameToSave.substring(0, fileNameToSave.indexOf(".")) + ++i + ".xsd"; } // If this was the master schema, and we already have a schema by that name, simply swap // proposed names. But in the process, validate whether the schema that already exists // on the list is not a master schema, and thereby avoid any recursion. if (schemaInfo.isMasterSchema() && !originalName.equals(fileNameToSave)) { for (SchemaInfo schema : schemas.values()) { if (schema.getProposedResourceName().equals(originalName)) { if (!schema.isMasterSchema()) { schema.setProposedResourceName(fileNameToSave); fileNameToSave = originalName; } break; } } } // add this entry to the processed schema map processedSchemas.add(fileNameToSave); //schemaInfo.setProposedRegistryURL(fileNameToSave); schemaInfo.setProposedResourceName(fileNameToSave); schemaInfo.setSchema((xmlSchema)); schemaInfo.setOriginalURL(sourceURI); schemas.put(getAbsoluteSchemaURL(sourceURI), schemaInfo); } } public String getSchemaRegistryPath(String parentRegistryPath, String sourceURL) throws RegistryException { SchemaInfo schemaInfo = schemas.get(getAbsoluteSchemaURL(sourceURL)); if (schemaInfo != null) { //return WSDLUtil.getLocationPrefix(parentRegistryPath) + schemaInfo.getProposedRegistryURL(); return WSDLUtil.computeRelativePathWithVersion(parentRegistryPath, schemaInfo.getProposedRegistryURL(), systemRegistry); } return null; } public String getSchemaAssociationPath(String sourceURL) { SchemaInfo schemaInfo = schemas.get(sourceURL); if (schemaInfo != null) { String proposedRegistryURL = schemaInfo.getProposedRegistryURL(); return proposedRegistryURL.replaceAll("\\.\\./", ""); } return null; } /** * For each schema found in schemas, change corresponding schemaInfo's ProposedRegistryURL based on * commonSchemaLocation and mangled targetNamespace * @param commonSchemaLocation the location to store schemas * @throws RegistryException if the operation failed. */ private void updateSchemaPaths(String commonSchemaLocation, String version, RequestContext requestContext) throws RegistryException { /* i.e. ROOT/commonSchemaLocation */ if (!systemRegistry.resourceExists(commonSchemaLocation)) { systemRegistry.put(commonSchemaLocation, systemRegistry.newCollection()); } for (SchemaInfo schemaInfo: schemas.values()) { XmlSchema schema = schemaInfo.getSchema(); String targetNamespace = schema.getTargetNamespace(); if ((targetNamespace == null) || ("".equals(targetNamespace))) { targetNamespace = "unqualified"; } String schemaLocation = getSchemaLocation(requestContext, schemaInfo, targetNamespace, commonSchemaLocation, version); schemaInfo.setProposedRegistryURL(schemaLocation); } } private void updateSchemaPaths(String commonSchemaLocation,String version,List dependencies, RequestContext requestContext) throws RegistryException { /* i.e. ROOT/commonSchemaLocation */ if (!systemRegistry.resourceExists(commonSchemaLocation)) { systemRegistry.put(commonSchemaLocation, systemRegistry.newCollection()); } outerLoop: for (SchemaInfo schemaInfo: schemas.values()) { XmlSchema schema = schemaInfo.getSchema(); String targetNamespace = schema.getTargetNamespace(); if ((targetNamespace == null) || ("".equals(targetNamespace))) { targetNamespace = "unqualified"; } String schemaLocation = getSchemaLocation(requestContext, schemaInfo, targetNamespace,commonSchemaLocation, version); String regex = schemaLocation + "[\\d].[\\d].[\\d]" + RegistryConstants.PATH_SEPARATOR + schemaInfo.getProposedResourceName(); for (Object dependency : dependencies) { String path = dependency.toString(); if(path.matches(regex)){ schemaLocation = path; schemaInfo.setProposedRegistryURL(schemaLocation); continue outerLoop; } } schemaInfo.setProposedRegistryURL(schemaLocation); } } /** * This method used to populate registry location of the XSD * * @param requestContext Request Context * @param schemaInfo SchemaInfo * @param targetNamespace Target Namespace * @param commonSchemaLocation Common Schema Location * @param version Version * @return Registry path for XSD */ private String getSchemaLocation(RequestContext requestContext, SchemaInfo schemaInfo, String targetNamespace, String commonSchemaLocation, String version) { if (Utils.getRxtService() != null) { String pathExpression = Utils.getRxtService().getStoragePath(RegistryConstants.XSD_MEDIA_TYPE); pathExpression = CommonUtil.replaceExpressionOfPath(pathExpression, "name", schemaInfo.getProposedResourceName()); if (requestContext.getResource().getProperties().size() != 0) { pathExpression = CommonUtil.getPathFromPathExpression(pathExpression, requestContext.getResource().getProperties(), null); } String namespace = CommonUtil.derivePathFragmentFromNamespace(targetNamespace).replace("//", "/"); pathExpression = CommonUtil.replaceExpressionOfPath(pathExpression, "namespace", namespace); pathExpression = CommonUtil.replaceExpressionOfPath(pathExpression, "version", version); String schemaPath = RegistryUtils.getAbsolutePath(requestContext.getRegistryContext(), pathExpression.replace("//", "/")); /** * Fix for the REGISTRY-3052 : validation is to check the whether this invoked by ZIPWSDLMediaTypeHandler * Setting the registry and absolute paths to current session to avoid incorrect resource path entry in REG_LOG table */ if (CurrentSession.getLocalPathMap() != null && !Boolean.valueOf(CurrentSession.getLocalPathMap().get(CommonConstants.ARCHIEVE_UPLOAD))) { schemaPath = CommonUtil.getRegistryPath(requestContext.getRegistry().getRegistryContext(), schemaPath); if (log.isDebugEnabled()) { log.debug("Saving current session local paths, key: " + schemaPath + " | value: " + pathExpression); } CurrentSession.getLocalPathMap().put(schemaPath, pathExpression); } return schemaPath; } else { String schemaLocation = (commonSchemaLocation + CommonUtil.derivePathFragmentFromNamespace(targetNamespace)) .replace("//", "/"); schemaLocation += requestContext.getResource().getProperty("version") + "/" + schemaInfo.getProposedResourceName(); return schemaLocation; } } /** * Update the schema's internal import location according to the new registry URLs. * Furthermore, fill the associations arraylist according to the detectored associations. */ private void updateSchemaInternalsAndAssociations() throws RegistryException { for (SchemaInfo schemaInfo: schemas.values()) { XmlSchema schema = schemaInfo.getSchema(); XmlSchemaObjectCollection includes = schema.getIncludes(); if (includes != null) { for (Iterator iter = includes.getIterator(); iter.hasNext();) { Object externalComponent = iter.next(); if (externalComponent instanceof XmlSchemaExternal) { XmlSchemaExternal xmlSchemaExternal = (XmlSchemaExternal)externalComponent; XmlSchema schema1 = xmlSchemaExternal.getSchema(); if (schema1 != null) { String sourceURI = getAbsoluteSchemaURL(schema1.getSourceURI()); if (schemas.containsKey(sourceURI)) { SchemaInfo info = schemas.get(sourceURI); String relativeSchemaPath = WSDLUtil.computeRelativePathWithVersion(schemaInfo.getProposedRegistryURL(), info.getProposedRegistryURL(), registry); xmlSchemaExternal.setSchemaLocation(relativeSchemaPath); } } } } } // creating associations for(String associatedTo : schemaInfo.getSchemaDependencies()) { SchemaInfo schemaInfoAssociated = schemas.get(associatedTo); if (schemaInfoAssociated != null) { associations.add(new Association(schemaInfo.getProposedRegistryURL(), schemaInfoAssociated.getProposedRegistryURL(), CommonConstants.DEPENDS)); associations.add(new Association(schemaInfoAssociated.getProposedRegistryURL(), schemaInfo.getProposedRegistryURL(), CommonConstants.USED_BY)); } } } } public String saveSchemasToRegistry(RequestContext requestContext, String commonSchemaLocation, String symlinkLocation, Resource metaResource,boolean disableSymlinkCreation) throws RegistryException { updateSchemaPaths(commonSchemaLocation,requestContext.getResource().getProperty("version"), requestContext); updateSchemaInternalsAndAssociations(); String path = saveSchemaToRegistry(requestContext, null, symlinkLocation, metaResource,disableSymlinkCreation); persistAssociations(path); return path; } public String saveSchemasToRegistry(RequestContext requestContext, String commonSchemaLocation, String symlinkLocation, Resource metaResource,String version,List dependencies,boolean disableSymlinkCreation) throws RegistryException { updateSchemaPaths(commonSchemaLocation,version,dependencies, requestContext); updateSchemaInternalsAndAssociations(); String path = saveSchemaToRegistry(requestContext, null, symlinkLocation, metaResource,disableSymlinkCreation); persistAssociations(path); return path; } @SuppressWarnings("unchecked") private String saveSchemaToRegistry(RequestContext requestContext, String resourcePath, String symlinkLocation, Resource metaResource,boolean disableSymlinkCreation) throws RegistryException { String path = resourcePath; for (SchemaInfo schemaInfo: schemas.values()) { XmlSchema schema = schemaInfo.getSchema(); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); schema.write(byteArrayOutputStream); byte[] xsdContent = byteArrayOutputStream.toByteArray(); String schemaPath = schemaInfo.getProposedRegistryURL(); Resource xsdResource; if (metaResource != null && registry.resourceExists(schemaPath)) { xsdResource = registry.get(schemaPath); } else { xsdResource = new ResourceImpl(); if (metaResource != null) { Properties properties = metaResource.getProperties(); if (properties != null) { List<String> linkProperties = Arrays.asList( RegistryConstants.REGISTRY_LINK, RegistryConstants.REGISTRY_USER, RegistryConstants.REGISTRY_MOUNT, RegistryConstants.REGISTRY_AUTHOR, RegistryConstants.REGISTRY_MOUNT_POINT, RegistryConstants.REGISTRY_TARGET_POINT, RegistryConstants.REGISTRY_ACTUAL_PATH, RegistryConstants.REGISTRY_REAL_PATH); for (Map.Entry<Object, Object> e : properties.entrySet()) { String key = (String) e.getKey(); if (!linkProperties.contains(key)) { xsdResource.setProperty(key, (List<String>) e.getValue()); } } } } } xsdResource.setMediaType("application/x-xsd+xml"); if (this.useOriginalSchema) { try { xsdResource.setContent(CarbonUtils.getBytesFromFile(new File(new URI(schemaInfo.getOriginalURL())))); } catch (CarbonException e) { String errMsg = "Trying to store original schema in registry failed while " + "generating the content from original schema."; log.error(errMsg, e); throw new RegistryException(errMsg, e); } catch (URISyntaxException e) { String errMsg = "Trying to store original schema in registry failed due to error " + "occurred in file url:" + schemaInfo.getOriginalURL(); log.error(errMsg, e); throw new RegistryException(errMsg, e); } } else { xsdResource.setContent(xsdContent); } if(metaResource != null){ xsdResource.setDescription(metaResource.getDescription()); } String targetNamespace = schema.getTargetNamespace(); xsdResource.setProperty("targetNamespace", targetNamespace); if (metaResource == null || metaResource.getProperty(CommonConstants.SOURCE_PROPERTY) == null){ xsdResource.setProperty(CommonConstants.SOURCE_PROPERTY, CommonConstants.SOURCE_AUTO); }else { xsdResource.setProperty(CommonConstants.SOURCE_PROPERTY, metaResource.getProperty(CommonConstants.SOURCE_PROPERTY)); } if (schemaInfo.isMasterSchema() && validationInfo != null) { ArrayList<String> messages = validationInfo.getValidationMessages(); if (messages.size() > 0) { xsdResource.setProperty(SCHEMA_STATUS, WSDLUtils.INVALID); } else { xsdResource.setProperty(SCHEMA_STATUS, WSDLUtils.VALID); } int i = 1; for (String message : messages) { if (message == null) { continue; } if (message.length() > 1000) { message = message.substring(0, 997) + "..."; } xsdResource.setProperty(SCHEMA_VALIDATION_MESSAGE + i, message); i++; } } if(schemaInfo.isMasterSchema()){ // persisting the UUID for master schema xsdResource.setUUID(metaResource.getUUID()); // if there is a change in the path, we delete the old resource if(path != null && !schemaPath.equals(path) && registry.resourceExists(path)){ Resource oldResource = registry.get(path); if(oldResource.getProperty("registry.resource.symlink.path") != null){ registry.delete(oldResource.getProperty("registry.resource.symlink.path")); } registry.delete(path); } } boolean newSchemaUpload = !registry.resourceExists(schemaPath); saveToRepositorySafely(requestContext, schemaInfo.getOriginalURL(), schemaPath, xsdResource); if (symlinkLocation == null && resourcePath != null && !(resourcePath.equals("/") || resourcePath.equals(schemaPath) || resourcePath.equals(""))) { symlinkLocation = RegistryUtils.getParentPath(resourcePath); } if (schemaInfo.isMasterSchema() && symlinkLocation != null) { if (registry.resourceExists(symlinkLocation)) { Resource resource = registry.get(symlinkLocation); if (resource != null) { String isLink = resource.getProperty("registry.link"); String mountPoint = resource.getProperty("registry.mountpoint"); String targetPoint = resource.getProperty("registry.targetpoint"); String actualPath = resource.getProperty("registry.actualpath"); if (isLink != null && mountPoint != null && targetPoint != null) { // symlinkLocation = symlinkLocation.replace(mountPoint, targetPoint); symlinkLocation = actualPath + RegistryConstants.PATH_SEPARATOR; } } } // 1. New resource: resourcePath = /foo, schemaPath = /ns/name.xsd, symlinkPath = /foo, resourceExist = false, resourceIsSymLink = false, createSymlink = true. DoWork = true // 2. New resource, existing symlink: resourcePath = /foo, xsdPath = /ns/name.xsd, symlinkPath = /foo, resourceExist = false, resourceIsSymLink = true, createSymlink = false // 3. Edit from symlink: resourcePath = /foo, schemaPath = /ns/name.xsd, symlinkPath = /foo, resourceExist = true, resourceIsSymLink = true, createSymlink = false, // 4. Edit from resource: resourcePath = /ns/name.xsd, schemaPath = /ns/name.xsd, symlinkPath = /ns/name.xsd, resourceExist = true, resourceIsSymLink = false, createSymlink = false, // 5. Edit from resource, change ns: resourcePath = /ns/name.xsd, schemaPath = /ns2/name.xsd, symlinkPath = /ns/name.xsd, resourceExist = true, resourceIsSymLink = false, createSymlink = false, deleteResource = true. DoWork = true // 6. Edit from symlink, change ns: resourcePath = /ns/name.xsd, schemaPath = /ns2/name.xsd, symlinkPath = /ns/name.xsd, resourceExist = true, resourceIsSymLink = true, createSymlink = delete and add, deleteResource = true. DoWork = true if (!symlinkLocation.endsWith(RegistryConstants.PATH_SEPARATOR)) { symlinkLocation = symlinkLocation + RegistryConstants.PATH_SEPARATOR; } /* String symLinkTargetNs = ""; if(!symlinkLocation.startsWith("/_system/governance")) { if (targetNamespace.startsWith("http://")) { symLinkTargetNs = targetNamespace.replaceAll("http://", "").replaceAll("\\.", "_") + "_"; } else if (targetNamespace.startsWith("https://")) { symLinkTargetNs = targetNamespace.replaceAll("https://", "").replaceAll("\\.", "_") + "_"; } } String symlinkPath = symlinkLocation + symLinkTargetNs +resourceName; */ String symlinkPath = symlinkLocation + extractResourceFromURL(resourceName,".xsd"); int j = 0; if(!disableSymlinkCreation) { while (true) { if (!registry.resourceExists(symlinkPath)) { if (CommonUtil.isSymbolicLinkMapExisting()) { CommonUtil.addToSymbolicLinkMap(symlinkPath, schemaPath); } else { systemRegistry.createLink(symlinkPath, schemaPath); } break; } else if (newSchemaUpload) { if (registry.get(symlinkPath).getProperty(RegistryConstants.REGISTRY_LINK) != null) { //only symlinks can be exist in the root String actualPath = registry.get(symlinkPath).getProperty(RegistryConstants.REGISTRY_ACTUAL_PATH); if (schemaPath.equals(actualPath)) { break; } } } else { break; } j++; symlinkPath = RegistryConstants.ROOT_PATH + extractResourceFromURL(resourceName,"-"+j+".xsd"); } } } if (schemaInfo.isMasterSchema()) { path = schemaPath; } } return path; } /** * Save associations to the registry if they do not exist. * Execution time could be improved if registry provides a better way to check existing associations. * * @throws RegistryException */ private void persistAssociations(String schemaPath) throws RegistryException { // until registry provides a functionality to check existing associations, this method will consume a LOT of time for (Association association: associations) { boolean isAssociationExist = false; Association[] existingAssociations = registry.getAllAssociations(association.getSourcePath()); if (existingAssociations != null) { for (Association currentAssociation: existingAssociations) { if (currentAssociation.getDestinationPath().equals(association.getDestinationPath()) && currentAssociation.getAssociationType().equals(association.getAssociationType())) { isAssociationExist = true; break; } } } if (!isAssociationExist) { registry.addAssociation(association.getSourcePath(), association.getDestinationPath(), association.getAssociationType()); } } // this code was added to fix CARBON-11188 if( schemaPath!= null && associations.isEmpty()) { Association[] dependencies = registry.getAssociations(schemaPath, CommonConstants.DEPENDS); for(Association dependency : dependencies) { if(dependency.getSourcePath().equals(schemaPath)) { registry.removeAssociation(dependency.getSourcePath(), dependency.getDestinationPath(), CommonConstants.DEPENDS); registry.removeAssociation(dependency.getDestinationPath(), dependency.getSourcePath(), CommonConstants.USED_BY); } } } } /** * Saves the resource iff the resource is not already existing in the repository * @param path: resource path * @param resource: resource object * @throws RegistryException */ private void saveToRepositorySafely(RequestContext context, String url, String path, Resource resource) throws RegistryException { String schemaId = resource.getUUID(); if (schemaId == null) { // generate a service id schemaId = UUID.randomUUID().toString(); resource.setUUID(schemaId); } // if (systemRegistry != null) { // CommonUtil.addGovernanceArtifactEntryWithAbsoluteValues(systemRegistry, schemaId, path); // } if (!registry.resourceExists(path)) { addSchemaToRegistry(context, path, url, resource, registry); } else { log.debug("A Resource already exists at given location. Overwriting resource content."); addSchemaToRegistry(context, path, url, resource, registry); } // if (!(resource instanceof Collection) && // ((ResourceImpl) resource).isVersionableChange()) { // registry.createVersion(path); // } String relativeArtifactPath = RegistryUtils.getRelativePath(registry.getRegistryContext(), path); // adn then get the relative path to the GOVERNANCE_BASE_PATH relativeArtifactPath = RegistryUtils.getRelativePathToOriginal(relativeArtifactPath, RegistryConstants.GOVERNANCE_REGISTRY_BASE_PATH); ((ResourceImpl)resource).setPath(relativeArtifactPath); } /** * Method that gets called instructing a schema to be added the registry. * * @param context the request context for this request. * @param path the path to add the resource to. * @param url the path from which the resource was imported from. * @param resource the resource to be added. * @param registry the registry instance to use. * * @throws RegistryException if the operation failed. */ protected void addSchemaToRegistry(RequestContext context, String path, String url, Resource resource, Registry registry) throws RegistryException { registry.put(path, resource); } private String extractResourceFromURL(String wsdlURL, String suffix) { String resourceName = wsdlURL; if (wsdlURL.indexOf("?") > 0) { resourceName = wsdlURL.substring(0, wsdlURL.indexOf("?")) + suffix; } else if (wsdlURL.indexOf(".") > 0) { resourceName = wsdlURL.substring(0, wsdlURL.lastIndexOf(".")) + suffix; } else if (!wsdlURL.endsWith(suffix)) { resourceName = wsdlURL + suffix; } return resourceName; } private String getAbsoluteSchemaURL(String schemaLocation) throws RegistryException { if (schemaLocation != null && baseURI != null) { try { URI uri = new URI(baseURI); URI absoluteURI = uri.resolve(schemaLocation); return absoluteURI.toString(); } catch (URISyntaxException e) { throw new RegistryException(e.getMessage(), e); } } return schemaLocation; } }