/* * 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; import org.apache.axiom.om.OMElement; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.uddi.api_v3.AuthToken; import org.wso2.carbon.registry.common.utils.artifact.manager.ArtifactManager; import org.wso2.carbon.registry.core.*; import org.wso2.carbon.registry.core.exceptions.RegistryException; import org.wso2.carbon.registry.core.jdbc.handlers.Handler; import org.wso2.carbon.registry.core.jdbc.handlers.RequestContext; import org.wso2.carbon.registry.core.utils.RegistryUtils; import org.wso2.carbon.registry.extensions.beans.BusinessServiceInfo; import org.wso2.carbon.registry.extensions.handlers.utils.*; import org.wso2.carbon.registry.extensions.utils.CommonConstants; import org.wso2.carbon.registry.extensions.utils.CommonUtil; import org.wso2.carbon.registry.extensions.utils.WSDLValidationInfo; import org.wso2.carbon.registry.uddi.utils.UDDIUtil; import javax.xml.namespace.QName; import java.io.*; import java.util.*; @SuppressWarnings("unused") public class WSDLMediaTypeHandler extends Handler { private static final Log log = LogFactory.getLog(WSDLMediaTypeHandler.class); protected String locationTag = "location"; private String wsdlLocation = "/wsdls/"; // location will always has a leading '/' and trailing '/' private OMElement wsdlLocationConfiguration; protected String schemaLocation = "/schema/"; // location will always has a leading '/' and trailing '/' private OMElement schemaLocationConfiguration; protected String policyLocation = "/policy/"; // location will always has a leading '/' and trailing '/' private OMElement policyLocationConfiguration; private boolean disableSymlinkCreation = true; private String defaultWsdlVersion = CommonConstants.WSDL_VERSION_DEFAULT_VALUE; public boolean getCreateService() { return createService; } public void setCreateService(String createService) { this.createService = Boolean.valueOf(createService); } private boolean createService = true; private boolean createSOAPService = true; public boolean isCreateSOAPService() { return createSOAPService; } public void setCreateSOAPService(String createSOAPService) { this.createSOAPService = Boolean.valueOf(createSOAPService); } private boolean disableWSDLValidation = false; public OMElement getWsdlLocationConfiguration() { return wsdlLocationConfiguration; } public boolean isDisableSymlinkCreation() { return disableSymlinkCreation; } public void setDisableSymlinkCreation(String disableSymlinkCreation) { this.disableSymlinkCreation = Boolean.toString(true).equals(disableSymlinkCreation); } public void setDefaultServiceVersion(String defaultWsdlVersion) { this.defaultWsdlVersion = defaultWsdlVersion; } public void setWsdlLocationConfiguration(OMElement locationConfiguration) throws RegistryException { Iterator confElements = locationConfiguration.getChildElements(); while (confElements.hasNext()) { OMElement confElement = (OMElement)confElements.next(); if (confElement.getQName().equals(new QName(locationTag))) { wsdlLocation = confElement.getText(); if (!wsdlLocation.startsWith(RegistryConstants.PATH_SEPARATOR)) { wsdlLocation = RegistryConstants.PATH_SEPARATOR + wsdlLocation; } if (!wsdlLocation.endsWith(RegistryConstants.PATH_SEPARATOR)) { wsdlLocation = wsdlLocation + RegistryConstants.PATH_SEPARATOR; } } } WSDLProcessor.setCommonWSDLLocation(wsdlLocation); this.wsdlLocationConfiguration = locationConfiguration; } public OMElement getSchemaLocationConfiguration() { return schemaLocationConfiguration; } public void setSchemaLocationConfiguration(OMElement locationConfiguration) throws RegistryException { Iterator confElements = locationConfiguration.getChildElements(); while (confElements.hasNext()) { OMElement confElement = (OMElement)confElements.next(); if (confElement.getQName().equals(new QName(locationTag))) { schemaLocation = confElement.getText(); if (!schemaLocation.startsWith(RegistryConstants.PATH_SEPARATOR)) { schemaLocation = RegistryConstants.PATH_SEPARATOR + schemaLocation; } if (!schemaLocation.endsWith(RegistryConstants.PATH_SEPARATOR)) { schemaLocation = schemaLocation + RegistryConstants.PATH_SEPARATOR; } } } WSDLProcessor.setCommonSchemaLocation(schemaLocation); this.schemaLocationConfiguration = locationConfiguration; } public OMElement getPolicyLocationConfiguration() { return policyLocationConfiguration; } public void setPolicyLocationConfiguration(OMElement locationConfiguration) throws RegistryException { Iterator confElements = locationConfiguration.getChildElements(); while (confElements.hasNext()) { OMElement confElement = (OMElement)confElements.next(); if (confElement.getQName().equals(new QName(locationTag))) { policyLocation = confElement.getText(); if (!policyLocation.startsWith(RegistryConstants.PATH_SEPARATOR)) { policyLocation = RegistryConstants.PATH_SEPARATOR + policyLocation; } if (!policyLocation.endsWith(RegistryConstants.PATH_SEPARATOR)) { policyLocation = policyLocation + RegistryConstants.PATH_SEPARATOR; } } } WSDLProcessor.setCommonPolicyLocation(policyLocation); this.policyLocationConfiguration = locationConfiguration; } public void makeDir(File file) throws IOException { if (file != null && !file.exists() && !file.mkdir()) { log.warn("Failed to create directory at path: " + file.getAbsolutePath()); } } public void makeDirs(File file) throws IOException { if (file != null && !file.exists() && !file.mkdirs()) { log.warn("Failed to create directories at path: " + file.getAbsolutePath()); } } public void delete(File file) throws IOException { if (file != null && file.exists() && !file.delete()) { log.warn("Failed to delete file/directory at path: " + file.getAbsolutePath()); } } /** * Method that will executed after the put operation has been done. * * @param path the path of the resource. * @param addedResources the resources that have been added to the registry. * @param otherResources the resources that have not been added to the registry. * @param requestContext the request context for the put operation. * @throws RegistryException if the operation failed. */ @SuppressWarnings("unused") protected void onPutCompleted(String path, Map<String, String> addedResources, List<String> otherResources, RequestContext requestContext) throws RegistryException { } public void put(RequestContext requestContext) throws RegistryException { if (!CommonUtil.isUpdateLockAvailable()) { return; } CommonUtil.acquireUpdateLock(); WSDLProcessor wsdlProcessor=null; try { Resource metadata = requestContext.getResource(); String path = requestContext.getResourcePath().getPath(); try { // If the WSDL is already there, we don't need to re-run this handler unless the content is changed. // Re-running this handler causes issues with downstream handlers and other behaviour (ex:- lifecycles). // If you need to do a replace pragmatically, delete-then-replace. if (metadata == null) { // will go with the default processing return; } Registry registry = requestContext.getRegistry(); // This is to distinguish operations on xsd and wsdl on remote mounting. String remotePut = metadata.getProperty(RegistryConstants.REMOTE_MOUNT_OPERATION); if (remotePut != null) { CommonUtil.releaseUpdateLock(); metadata.removeProperty(RegistryConstants.REMOTE_MOUNT_OPERATION); registry.put(path, metadata); requestContext.setProcessingComplete(true); ArtifactManager.getArtifactManager().getTenantArtifactRepository(). addArtifact(path); return; } if (registry.resourceExists(path)) { // logic to compare content, and return only if the content didn't change. Object newContent = metadata.getContent(); Resource oldResource = registry.get(path); //if the oldResource is a SymLink, then we need to obtain the actual resource path, rather than the //path of the symlink, if("true".equals(oldResource.getProperty("registry.link"))) { path = oldResource.getProperty("registry.actualpath"); } Object oldContent = oldResource.getContent(); String newContentString = null; String oldContentString = null; if (newContent != null) { if (newContent instanceof String) { newContentString = (String) newContent; } else { newContentString = RegistryUtils.decodeBytes((byte[]) newContent); } } if (oldContent != null) { if (oldContent instanceof String) { oldContentString = (String) oldContent; } else { oldContentString = RegistryUtils.decodeBytes((byte[]) oldContent); } } if ((newContent == null && oldContent == null) || (newContentString != null && newContentString.equals(oldContentString))) { // this will continue adding from the default path. return; } // so we creating temp files for the wsdl and all the dependencies. Set<String> registryPaths = new LinkedHashSet<String>(); // the first path is the current resource path. registryPaths.add(path); // get the associations. Association[] dependencies = CommonUtil.getDependenciesRecursively(registry, path); if (dependencies != null) { for (Association dependency: dependencies) { String targetPath = dependency.getDestinationPath(); if (targetPath.startsWith(RegistryConstants.ROOT_PATH)) { registryPaths.add(targetPath); } } } File referenceTempFile = File.createTempFile("wsdl", ".ref"); File tempDir = new File(referenceTempFile.getAbsolutePath().substring(0, referenceTempFile.getAbsolutePath().length() - ".ref".length())); String tempDirPath = tempDir.getAbsolutePath(); // now add each of the registry paths to the the tempDir List<File> tempFiles = new ArrayList<File>(); for (String registryPath: registryPaths) { if (!registryPath.startsWith(RegistryConstants.ROOT_PATH)) { continue; } String filePath = tempDirPath + registryPath; File tempFile = new File(filePath); makeDirs(tempFile.getParentFile()); Object resourceContent; if (registryPath.equals(path)) { // this is the wsdl we want to update. resourceContent = metadata.getContent(); } else { if (!registry.resourceExists(registryPath)) { continue; } Resource r = registry.get(registryPath); if (r == null) { continue; } resourceContent = r.getContent(); } byte[] resourceContentBytes; if (resourceContent == null) { resourceContentBytes = new byte[0]; } else if (resourceContent instanceof byte[]) { resourceContentBytes = (byte[])resourceContent; } else if (resourceContent instanceof String) { resourceContentBytes = RegistryUtils.encodeString(((String)resourceContent)); } else { String msg = "Unknown type for the content path: " + path + ", content type: " + resourceContent.getClass().getName() + "."; log.error(msg); throw new RegistryException(msg); } InputStream in = new ByteArrayInputStream(resourceContentBytes); BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(tempFile)); byte[] contentChunk = new byte[1024]; int byteCount; while ((byteCount = in.read(contentChunk)) != -1) { out.write(contentChunk, 0, byteCount); } out.flush(); out.close(); tempFiles.add(tempFile); } if (tempFiles.size() == 0) { // unreachable state, anyway better log and return. String msg = "Temporary files count is zero, when updating a wsdl. " + "wsdl path: " + path + "."; log.error(msg); // we are just returning, as the put operation will continue in its default path. return; } File tempFile = tempFiles.get(0); String uri = tempFile.toURI().toString(); if (uri.startsWith("file:")) { uri = uri.substring(5); } while (uri.startsWith("/")) { uri = uri.substring(1); } uri = "file:///" + uri; String wsdlPath = null; if (uri != null) { requestContext.setSourceURL(uri); requestContext.setResource(metadata); wsdlProcessor = buildWSDLProcessor(requestContext); wsdlPath = processWSDLImport(requestContext, wsdlProcessor, metadata, uri); } // now we will delete each temp files, ref file and the temp directory. for (File temp : tempFiles) { FileUtils.forceDelete(temp); } FileUtils.deleteDirectory(tempDir); FileUtils.forceDelete(referenceTempFile); if (wsdlPath != null) { onPutCompleted(path, Collections.singletonMap(uri, wsdlPath), Collections.<String>emptyList(), requestContext); requestContext.setActualPath(wsdlPath); } requestContext.setProcessingComplete(true); ArtifactManager.getArtifactManager().getTenantArtifactRepository(). addArtifact(path); return; } } catch (IOException e) { String msg = "Error in updating the wsdl. wsdl path: " + path + "."; log.error(msg, e); throw new RegistryException(msg, e); } requestContext.setSourceURL(requestContext. getResource().getProperty(CommonConstants.SOURCEURL_PARAMETER_NAME)); if (StringUtils.isNotBlank(requestContext.getSourceURL())) { requestContext.setResource(metadata); String sourceURL = requestContext.getSourceURL(); wsdlProcessor = buildWSDLProcessor(requestContext); String wsdlPath = processWSDLImport(requestContext, wsdlProcessor, metadata, sourceURL); onPutCompleted(path, Collections.singletonMap(sourceURL, wsdlPath), Collections.<String>emptyList(), requestContext); requestContext.setActualPath(wsdlPath); } else { try { Object resourceContent = metadata.getContent(); byte[] resourceContentBytes; if (resourceContent == null) { resourceContentBytes = new byte[0]; } else if (resourceContent instanceof byte[]) { resourceContentBytes = (byte[]) resourceContent; } else if (resourceContent instanceof String) { resourceContentBytes = RegistryUtils.encodeString((String) resourceContent); } else { String msg = "Unknown type for the content path: " + path + ", content type: " + resourceContent.getClass().getName() + "."; log.error(msg); throw new RegistryException(msg); } InputStream in = new ByteArrayInputStream(resourceContentBytes); File tempFile = File.createTempFile("wsdl", ".wsdl"); BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(tempFile)); String uri = null; try { byte[] contentChunk = new byte[1024]; int byteCount; while ((byteCount = in.read(contentChunk)) != -1) { out.write(contentChunk, 0, byteCount); } uri = tempFile.toURI().toString(); } finally { if (in != null) { in.close(); } if (out != null) { out.flush(); out.close(); } } if (StringUtils.isNotBlank(uri) && uri.startsWith("file:")) { uri = uri.substring(5); } while (uri.startsWith("/")) { uri = uri.substring(1); } String wsdlPath = null; if (StringUtils.isNotBlank(uri)) { uri = "file:///" + uri; requestContext.setSourceURL(uri); requestContext.setResource(metadata); wsdlProcessor = buildWSDLProcessor(requestContext); wsdlPath = processWSDLImport(requestContext, wsdlProcessor, metadata, uri); } delete(tempFile); if (wsdlPath != null) { onPutCompleted(path, Collections.singletonMap(uri, wsdlPath), Collections.<String>emptyList(), requestContext); requestContext.setActualPath(wsdlPath); } /*WSDLProcessor wsdlProcessor = buildWSDLProcessor(requestContext); wsdlProcessor .addWSDLToRegistry( requestContext, null, metadata, true, true);*/ } catch (IOException e) { String msg = "An error occurred while uploading WSDL file or " + "deleting the temporary files from local file system."; throw new RegistryException(msg, e); } } requestContext.setProcessingComplete(true); if (wsdlProcessor != null && CommonConstants.ENABLE.equals(System.getProperty(CommonConstants.UDDI_SYSTEM_PROPERTY)) && !org.wso2.carbon.registry.common.CommonConstants.isExternalUDDIInvoke.get()) { AuthToken authToken = UDDIUtil.getPublisherAuthToken(); if(authToken ==null){ return; } BusinessServiceInfo businessServiceInfo = new BusinessServiceInfo(); WSDLInfo wsdlInfo = wsdlProcessor.getMasterWSDLInfo(); businessServiceInfo.setServiceWSDLInfo(wsdlInfo); UDDIPublisher publisher = new UDDIPublisher(); publisher.publishBusinessService(authToken,businessServiceInfo); } } finally { CommonUtil.releaseUpdateLock(); } } /** * Method to customize the WSDL Processor. * @param requestContext the request context for the import/put operation * @return the WSDL Processor instance. */ @SuppressWarnings("unused") protected WSDLProcessor buildWSDLProcessor(RequestContext requestContext) { WSDLProcessor wsdlProcessor = new WSDLProcessor(requestContext); wsdlProcessor.setCreateService(getCreateService()); wsdlProcessor.setCreateSOAPService(isCreateSOAPService()); return wsdlProcessor; } /** * Method to customize the WSDL Processor. * @param requestContext the request context for the import/put operation * @param useOriginalSchema whether the schema to be original * @return the WSDL Processor instance. */ @SuppressWarnings("unused") protected WSDLProcessor buildWSDLProcessor(RequestContext requestContext, boolean useOriginalSchema) { WSDLProcessor wsdlProcessor = new WSDLProcessor(requestContext, useOriginalSchema); wsdlProcessor.setCreateService(getCreateService()); wsdlProcessor.setCreateSOAPService(isCreateSOAPService()); return wsdlProcessor; } /** * Method to customize the Schema Processor. * @param requestContext the request context for the import/put operation. * @param validationInfo the WSDL validation information. * @return the Schema Processor instance. */ @SuppressWarnings("unused") protected SchemaProcessor buildSchemaProcessor(RequestContext requestContext, WSDLValidationInfo validationInfo) { return new SchemaProcessor(requestContext, validationInfo); } /** * Method to customize the Schema Processor. * @param requestContext the request context for the import/put operation. * @param validationInfo the WSDL validation information. * @param useOriginalSchema whether the schema to be original * @return the Schema Processor instance. */ @SuppressWarnings("unused") protected SchemaProcessor buildSchemaProcessor(RequestContext requestContext, WSDLValidationInfo validationInfo, boolean useOriginalSchema) { return new SchemaProcessor(requestContext, validationInfo, useOriginalSchema); } public void importResource(RequestContext requestContext) throws RegistryException { if (!CommonUtil.isUpdateLockAvailable()) { return; } CommonUtil.acquireUpdateLock(); WSDLProcessor wsdlProcessor=null; try { Resource metadata = requestContext.getResource(); String sourceURL = requestContext.getSourceURL(); if (requestContext.getSourceURL() != null && requestContext.getSourceURL().toLowerCase().startsWith("file:")) { String msg = "The source URL must not be file in the server's local file system"; throw new RegistryException(msg); } try { wsdlProcessor = buildWSDLProcessor(requestContext); String wsdlPath = processWSDLImport(requestContext, wsdlProcessor, metadata, sourceURL); ResourcePath resourcePath = requestContext.getResourcePath(); String path = null; if (resourcePath != null) { path = resourcePath.getPath(); } onPutCompleted(path, Collections.singletonMap(sourceURL, wsdlPath), Collections.<String>emptyList(), requestContext); requestContext.setActualPath(wsdlPath); } catch (Exception e) { throw new RegistryException(e.getMessage(), e); } requestContext.setProcessingComplete(true); if (wsdlProcessor != null && CommonConstants.ENABLE.equals(System.getProperty(CommonConstants.UDDI_SYSTEM_PROPERTY)) && !org.wso2.carbon.registry.common.CommonConstants.isExternalUDDIInvoke.get()) { AuthToken authToken = UDDIUtil.getPublisherAuthToken(); if(authToken == null){ return; } BusinessServiceInfo businessServiceInfo = new BusinessServiceInfo(); businessServiceInfo.setServiceWSDLInfo(wsdlProcessor.getMasterWSDLInfo()); UDDIPublisher publisher = new UDDIPublisher(); publisher.publishBusinessService(authToken, businessServiceInfo); } } finally { CommonUtil.releaseUpdateLock(); } } /** * Method that runs the WSDL import/upload procedure. * * @param requestContext the request context for the import/put operation * @param metadata the resource metadata * @param sourceURL the URL from which the WSDL is imported * @param wsdlProcessor the WSDL Processor instance, used for upload and validation * * @return the path at which the WSDL was uploaded to * * @throws RegistryException if the operation failed. */ protected String processWSDLImport(RequestContext requestContext, WSDLProcessor wsdlProcessor, Resource metadata, String sourceURL) throws RegistryException { return wsdlProcessor.addWSDLToRegistry(requestContext, sourceURL, metadata, false, true, disableWSDLValidation,disableSymlinkCreation); } public void setDisableWSDLValidation(String disableWSDLValidation) { this.disableWSDLValidation = Boolean.toString(true).equals(disableWSDLValidation); } @Override public void delete(RequestContext requestContext) throws RegistryException { if (!CommonUtil.isUpdateLockAvailable()) { return; } CommonUtil.acquireUpdateLock(); try { Registry registry = requestContext.getRegistry(); ResourcePath resourcePath = requestContext.getResourcePath(); if (resourcePath == null) { throw new RegistryException("The resource path is not available."); } Resource resource = registry.get(resourcePath.getPath()); } finally { CommonUtil.releaseUpdateLock(); } } }