/* * Copyright (c) 2005-2009, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you 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 java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamException; import org.apache.axiom.om.OMAbstractFactory; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.OMFactory; import org.apache.axiom.om.util.AXIOMUtil; import org.apache.commons.io.FileUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.xerces.xni.parser.XMLInputSource; import org.uddi.api_v3.AuthToken; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.registry.core.Registry; import org.wso2.carbon.registry.core.RegistryConstants; import org.wso2.carbon.registry.core.Resource; import org.wso2.carbon.registry.core.ResourcePath; import org.wso2.carbon.registry.core.config.RegistryContext; import org.wso2.carbon.registry.core.exceptions.RegistryException; import org.wso2.carbon.registry.core.internal.RegistryCoreServiceComponent; import org.wso2.carbon.registry.core.jdbc.handlers.RequestContext; import org.wso2.carbon.registry.core.jdbc.utils.Transaction; import org.wso2.carbon.registry.core.session.CurrentSession; import org.wso2.carbon.registry.core.session.UserRegistry; 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 org.wso2.carbon.user.core.UserRealm; @SuppressWarnings({"unused", "UnusedAssignment"}) public class ZipWSDLMediaTypeHandler extends WSDLMediaTypeHandler { // <handler class="org.wso2.carbon.registry.extensions.handlers.ZipWSDLMediaTypeHandler"> // <property name="wsdlMediaType">application/wsdl+xml</property> // <property name="schemaMediaType">application/xsd+xml</property> // <property name="threadPoolSize">50</property> // <property name="useOriginalSchema">true</property> // <!--property name="disableWSDLValidation">true</property> // <property name="disableSchemaValidation">true</property> // <property name="wsdlExtension">.wsdl</property> // <property name="schemaExtension">.xsd</property> // <property name="archiveExtension">.gar</property> // <property name="tempFilePrefix">wsdl</property--> // <property name="schemaLocationConfiguration" type="xml"> // <location>/governance/schemas/</location> // </property> // <property name="wsdlLocationConfiguration" type="xml"> // <location>/governance/wsdls/</location> // </property> // <filter class="org.wso2.carbon.registry.core.jdbc.handlers.filters.MediaTypeMatcher"> // <property name="mediaType">application/vnd.wso2.governance-archive</property> // </filter> // </handler> private String wsdlMediaType = "application/wsdl+xml"; private String wsdlExtension = ".wsdl"; private String xsdMediaType = "application/xsd+xml"; private String xsdExtension = ".xsd"; private String swaggerMediaType = "application/swagger+json"; private String swaggerExtension = ".json"; private String swaggerLocation = "/swagger/"; private String wadlMediaType = "application/wadl+xml"; private String wadlExtension = ".wadl"; private String wadlLocation = "/wadl/"; private OMElement wadlLocationConfiguration; private String archiveExtension = ".gar"; private String tempFilePrefix = "wsdl"; private boolean disableWSDLValidation = false; private boolean disableSchemaValidation = false; private boolean useOriginalSchema = false; private boolean createService = true; private boolean disableSymlinkCreation = true; private static int numberOfRetry = 5; private boolean disableWADLValidation = false; private static List<String> skipFileExtensions = new ArrayList<String>(); private String extensionsSeparator = ","; public void setNumberOfRetry(String numberOfRetry) { ZipWSDLMediaTypeHandler.numberOfRetry = Integer.parseInt(numberOfRetry); } public boolean isDisableSymlinkCreation() { return disableSymlinkCreation; } public void setDisableSymlinkCreation(String disableSymlinkCreation) { this.disableSymlinkCreation = Boolean.toString(true).equals(disableSymlinkCreation); } private int threadPoolSize = 50; private static final Log log = LogFactory.getLog(ZipWSDLMediaTypeHandler.class); public void setThreadPoolSize(String threadPoolSize) { this.threadPoolSize = Integer.parseInt(threadPoolSize); } public OMElement getWADLLocationConfiguration() { return wadlLocationConfiguration; } public void setWadlLocationConfiguration(OMElement locationConfiguration) throws RegistryException { Iterator confElements = locationConfiguration.getChildElements(); while (confElements.hasNext()) { OMElement confElement = (OMElement)confElements.next(); if (confElement.getQName().equals(new QName(locationTag))) { wadlLocation = confElement.getText(); if(!wadlLocation.startsWith(RegistryConstants.PATH_SEPARATOR)){ wadlLocation = RegistryConstants.PATH_SEPARATOR + wadlLocation; } if(wadlLocation.endsWith(RegistryConstants.PATH_SEPARATOR)){ wadlLocation = wadlLocation.substring(0, wadlLocation.length() - 1); } } } this.wadlLocationConfiguration = locationConfiguration; } /** * @return createService */ public boolean isCreateService() { return createService; } /** * Extracts createService property from the registry.xml * * @param createService createService property. */ public void setCreateService(String createService) { this.createService = Boolean.valueOf(createService); } public void put(RequestContext requestContext) throws RegistryException { if (!CommonUtil.isUpdateLockAvailable()) { return; } CommonUtil.acquireUpdateLock(); // setting up session local path map for mounted setup. boolean pathMapSet = setSessionLocalPathMap(requestContext); try { Resource resource = 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 programatically, delete-then-replace. if (requestContext.getRegistry().resourceExists(path)) { // TODO: Add logic to compare content, and return only if the content didn't change. return; } } catch (Exception ignore) { } try { if (resource != null) { Object resourceContent = resource.getContent(); InputStream in = new ByteArrayInputStream((byte[]) resourceContent); Stack<File> fileList = new Stack<File>(); List<String> uriList = new LinkedList<String>(); List<UploadTask> tasks = new LinkedList<UploadTask>(); int threadPoolSize = this.threadPoolSize; File tempFile = File.createTempFile(tempFilePrefix, archiveExtension); File tempDir = new File(tempFile.getAbsolutePath().substring(0, tempFile.getAbsolutePath().length() - archiveExtension.length())); try { BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(tempFile)); try { byte[] contentChunk = new byte[1024]; int byteCount; while ((byteCount = in.read(contentChunk)) != -1) { out.write(contentChunk, 0, byteCount); } out.flush(); } finally { out.close(); } ZipEntry entry; makeDir(tempDir); ZipInputStream zs; List<String> wsdlUriList = new LinkedList<String>(); List<String> xsdUriList = new LinkedList<String>(); List<String> wadlUriList = new LinkedList<String>(); List<String> swaggerUriList = new LinkedList<String>(); zs = new ZipInputStream(new FileInputStream(tempFile)); try { entry = zs.getNextEntry(); while (entry != null) { String entryName = entry.getName(); FileOutputStream os; File file = new File(tempFile.getAbsolutePath().substring(0, tempFile.getAbsolutePath().length() - archiveExtension.length()) + File.separator + entryName); if (entry.isDirectory()) { if (!file.exists()) { makeDirs(file); fileList.push(file); } entry = zs.getNextEntry(); continue; } File parentFile = file.getParentFile(); if (!parentFile.exists()) { makeDirs(parentFile); } os = new FileOutputStream(file); try { fileList.push(file); byte[] contentChunk = new byte[1024]; int byteCount; while ((byteCount = zs.read(contentChunk)) != -1) { os.write(contentChunk, 0, byteCount); } } finally { os.close(); } zs.closeEntry(); entry = zs.getNextEntry(); if (entryName != null && entryName.toLowerCase().endsWith(wsdlExtension)) { String uri = tempFile.toURI().toString(); uri = uri.substring(0, uri.length() - archiveExtension.length()) + "/" + entryName; if (uri.startsWith("file:")) { uri = uri.substring(5); } while (uri.startsWith("/")) { uri = uri.substring(1); } uri = "file:///" + uri; if (uri.endsWith("/")) { uri = uri.substring(0, uri.length() -1); } wsdlUriList.add(uri); } else if (entryName != null && entryName.toLowerCase().endsWith(xsdExtension)) { String uri = tempFile.toURI().toString(); uri = uri.substring(0, uri.length() - archiveExtension.length()) + "/" + entryName; if (uri.startsWith("file:")) { uri = uri.substring(5); } while (uri.startsWith("/")) { uri = uri.substring(1); } uri = "file:///" + uri; if (uri.endsWith("/")) { uri = uri.substring(0, uri.length() -1); } xsdUriList.add(uri); } else if(entryName != null && entryName.toLowerCase().endsWith(wadlExtension)){ String uri = tempFile.toURI().toString(); uri = uri.substring(0, uri.length() - archiveExtension.length()) + "/" + entryName; if (uri.startsWith("file:")) { uri = uri.substring(5); } while (uri.startsWith("/")) { uri = uri.substring(1); } uri = "file:///" + uri; if (uri.endsWith("/")) { uri = uri.substring(0, uri.length() -1); } wadlUriList.add(uri); } else if(entryName != null && entryName.toLowerCase().endsWith(swaggerExtension)){ String uri = tempFile.toURI().toString(); uri = uri.substring(0, uri.length() - archiveExtension.length()) + "/" + entryName; if (uri.startsWith("file:")) { uri = uri.substring(5); } while (uri.startsWith("/")) { uri = uri.substring(1); } uri = "file:///" + uri; if (uri.endsWith("/")) { uri = uri.substring(0, uri.length() -1); } swaggerUriList.add(uri); } else if (entryName != null) { boolean isSkipFileExtension = false; for (String extension : skipFileExtensions) { if (entryName.toLowerCase().endsWith(extension.toLowerCase())) { isSkipFileExtension = true; break; } } if(!isSkipFileExtension){ String uri = tempFile.toURI().toString(); uri = uri.substring(0, uri.length() - archiveExtension.length()) + "/" + entryName; if (uri.startsWith("file:")) { uri = uri.substring(5); } while (uri.startsWith("/")) { uri = uri.substring(1); } uri = "file:///" + uri; if (uri.endsWith("/")) { uri = uri.substring(0, uri.length() -1); } uriList.add(uri); } } } } finally { zs.close(); } Map<String, String> localPathMap = null; if (CurrentSession.getLocalPathMap() != null) { localPathMap = Collections.unmodifiableMap(CurrentSession.getLocalPathMap()); } if (wsdlUriList.isEmpty() && xsdUriList.isEmpty() && wadlUriList.isEmpty() && uriList.isEmpty() && swaggerUriList.isEmpty()) { throw new RegistryException( "No Files found in the given archive"); } for (String uri : wsdlUriList) { tasks.add(new UploadWSDLTask(requestContext, uri, CurrentSession.getTenantId(), CurrentSession.getUserRegistry(), CurrentSession.getUserRealm(), CurrentSession.getUser(), CurrentSession.getCallerTenantId(), localPathMap)); } for (String uri : xsdUriList) { tasks.add(new UploadXSDTask(requestContext, uri, CurrentSession.getTenantId(), CurrentSession.getUserRegistry(), CurrentSession.getUserRealm(), CurrentSession.getUser(), CurrentSession.getCallerTenantId(), localPathMap)); } for (String uri : wadlUriList) { tasks.add(new UploadWadlTask(requestContext, uri, CurrentSession.getTenantId(), CurrentSession.getUserRegistry(), CurrentSession.getUserRealm(), CurrentSession.getUser(), CurrentSession.getCallerTenantId(), localPathMap)); } for (String uri : swaggerUriList) { tasks.add(new UploadSwaggerTask(requestContext, uri, CurrentSession.getTenantId(), CurrentSession.getUserRegistry(), CurrentSession.getUserRealm(), CurrentSession.getUser(), CurrentSession.getCallerTenantId(), localPathMap)); } String mediaType = resource.getProperty("registry.mediaType"); if (mediaType != null) { for (String uri : uriList) { tasks.add(new UploadFileTask(requestContext, uri, CurrentSession.getTenantId(), CurrentSession.getUserRegistry(), CurrentSession.getUserRealm(), CurrentSession.getUser(), CurrentSession.getCallerTenantId(), localPathMap, mediaType)); } uriList.clear(); } // calculate thread pool size for efficient use of resources in concurrent // update scenarios. int toAdd = wsdlUriList.size() + xsdUriList.size(); if (toAdd < threadPoolSize) { if (toAdd < (threadPoolSize / 8)) { threadPoolSize = 0; } else if (toAdd < (threadPoolSize / 2)) { threadPoolSize = (threadPoolSize / 8); } else { threadPoolSize = (threadPoolSize / 4); } } } finally { in.close(); resourceContent = null; resource.setContent(null); } uploadFiles(tasks, tempFile, fileList, tempDir, threadPoolSize, path, uriList, requestContext); } } catch (IOException e) { throw new RegistryException("Error occurred while unpacking Governance Archive", e); } if (Transaction.isRollbacked()) { throw new RegistryException("A nested transaction was rollbacked and therefore " + "cannot proceed with this action."); } requestContext.setProcessingComplete(true); } finally { CommonUtil.releaseUpdateLock(); removeSessionLocalPathMap(pathMapSet); } } /** * remove the Local PathMap from the CurrentSession * @param pathMapSet whether pathMap is set or not */ private void removeSessionLocalPathMap(boolean pathMapSet) { if (pathMapSet) { CurrentSession.removeLocalPathMap(); } } /** * Method will add Local PathMap to the CurrentSession, if it is not exists * Set ARCHIEVE_UPLOAD param to true, it param is accessed to calculate registry path in mounted env. * @param requestContext the request context to get mount points * @return whether pathMap is set or not */ private boolean setSessionLocalPathMap(RequestContext requestContext) { boolean pathMapSet = false; if (CurrentSession.getLocalPathMap() == null) { RegistryContext registryContext = requestContext.getRegistry().getRegistryContext(); if (registryContext != null && registryContext.getMounts() != null && !registryContext.getMounts().isEmpty()) { Map<String, String> localPathMap = new HashMap<String, String>(); CurrentSession.setLocalPathMap(localPathMap); CurrentSession.getLocalPathMap().put(CommonConstants.ARCHIEVE_UPLOAD, "true"); pathMapSet = true; } } else { CurrentSession.getLocalPathMap().put(CommonConstants.ARCHIEVE_UPLOAD, "true"); } return pathMapSet; } /** * Method that runs the WSDL upload procedure. * * @param requestContext the request context for the import/put operation * @param uri the URL from which the WSDL is imported * * @return the path at which the WSDL was uploaded to * * @throws RegistryException if the operation failed. */ protected String addWSDLFromZip(RequestContext requestContext, String uri) throws RegistryException { if (uri != null) { Resource local = requestContext.getRegistry().newResource(); String version = requestContext.getResource().getProperty("version"); local.setMediaType(wsdlMediaType); local.setProperty("version", version); local.setProperties(requestContext.getResource().getProperties()); requestContext.setSourceURL(uri); requestContext.setResource(local); String path = requestContext.getResourcePath().getPath(); if (path.lastIndexOf("/") != -1) { path = path.substring(0, path.lastIndexOf("/")); } else { path = ""; } String wsdlName = uri; if (wsdlName.lastIndexOf("/") != -1) { wsdlName = wsdlName.substring(wsdlName.lastIndexOf("/")); } else { wsdlName = "/" + wsdlName; } path = path + wsdlName; requestContext.setResourcePath(new ResourcePath(path)); WSDLProcessor wsdlProcessor = buildWSDLProcessor(requestContext, this.useOriginalSchema); String addedPath = wsdlProcessor.addWSDLToRegistry(requestContext, uri, local, false, true, disableWSDLValidation,disableSymlinkCreation); if (CommonConstants.ENABLE.equals(System.getProperty( CommonConstants.UDDI_SYSTEM_PROPERTY))) { AuthToken authToken = UDDIUtil.getPublisherAuthToken(); if(authToken !=null){ BusinessServiceInfo businessServiceInfo = new BusinessServiceInfo(); WSDLInfo wsdlInfo = wsdlProcessor.getMasterWSDLInfo(); businessServiceInfo.setServiceWSDLInfo(wsdlInfo); UDDIPublisher publisher = new UDDIPublisher(); publisher.publishBusinessService(authToken,businessServiceInfo); } } log.debug("WSDL : " + addedPath); return addedPath; } return null; } /** * Method that runs the WADL upload procedure. * * @param requestContext requestContext the request context for the import/put operation * @param uri the URL from which the WADL is imported * * @return the path at which the WADL was uploaded to * * @throws RegistryException if the operation failed. */ protected String addWADLFromZip(RequestContext requestContext, String uri) throws RegistryException { if (uri != null) { Resource local = requestContext.getRegistry().newResource(); String version = requestContext.getResource().getProperty("version"); local.setMediaType(wadlMediaType); local.setProperty("version",version); requestContext.setSourceURL(uri); requestContext.setResource(local); String path = requestContext.getResourcePath().getPath(); if (path.lastIndexOf("/") != -1) { path = path.substring(0, path.lastIndexOf("/")); } else { path = ""; } String wadlName = uri; if (wadlName.lastIndexOf("/") != -1) { wadlName = wadlName.substring(wadlName.lastIndexOf("/")); } else { wadlName = "/" + wadlName; } path = path + wadlName; requestContext.setResourcePath(new ResourcePath(path)); WADLProcessor wadlProcessor = new WADLProcessor (requestContext); wadlProcessor.setCreateService(isCreateService()); return wadlProcessor.importWADLToRegistry(requestContext, disableWADLValidation); } return null; } /** * Method that runs the Swagger upload procedure. * * @param requestContext requestContext the request context for the import/put operation * @param uri the URL from which the swagger is imported * * @return the path at which the Swagger was uploaded to * * @throws RegistryException if the operation failed. */ protected String addSwaggerFromZip(RequestContext requestContext, String uri) throws RegistryException { if (uri != null) { Resource local = requestContext.getRegistry().newResource(); String version = requestContext.getResource().getProperty("version"); local.setMediaType(swaggerMediaType); local.setProperty("version",version); requestContext.setSourceURL(uri); requestContext.setResource(local); String path = requestContext.getResourcePath().getPath(); if (path.lastIndexOf("/") != -1) { path = path.substring(0, path.lastIndexOf("/")); } else { path = ""; } String swaggerName = uri; if (swaggerName.lastIndexOf("/") != -1) { swaggerName = swaggerName.substring(swaggerName.lastIndexOf("/")); } else { swaggerName = "/" + swaggerName; } path = path + swaggerName; requestContext.setResourcePath(new ResourcePath(path)); SwaggerProcessor swaggerProcessor = new SwaggerProcessor (requestContext, isCreateService()); InputStream inputStream = null; try { inputStream = new URL(uri).openStream(); return swaggerProcessor.processSwagger(inputStream, getChrootedSwaggerLocation(requestContext.getRegistryContext()), uri); } catch (IOException e) { throw new RegistryException("Swagger URI is invalid", e); } finally { if (inputStream != null){ try { inputStream.close(); } catch (IOException e) { log.warn("Error while deleting Swagger temp files"); } } } } return null; } /** * Method that runs the Schema upload procedure. * * @param requestContext the request context for the import/put operation * @param uri the URL from which the Schema is imported * * @return the path at which the schema was uploaded to * * @throws RegistryException if the operation failed. */ protected String addSchemaFromZip(RequestContext requestContext, String uri) throws RegistryException { if (uri != null) { Resource local = requestContext.getRegistry().newResource(); String version = requestContext.getResource().getProperty("version"); local.setMediaType(xsdMediaType); local.setProperty("version",version); local.setProperties(requestContext.getResource().getProperties()); requestContext.setSourceURL(uri); requestContext.setResource(local); String path = requestContext.getResourcePath().getPath(); if (path.lastIndexOf("/") != -1) { path = path.substring(0, path.lastIndexOf("/")); } else { path = ""; } String xsdName = uri; if (xsdName.lastIndexOf("/") != -1) { xsdName = xsdName.substring(xsdName.lastIndexOf("/")); } else { xsdName = "/" + xsdName; } path = path + xsdName; requestContext.setResourcePath(new ResourcePath(path)); WSDLValidationInfo validationInfo = null; try { if (!disableSchemaValidation) { validationInfo = SchemaValidator.validate(new XMLInputSource(null, uri, null)); } } catch (Exception e) { throw new RegistryException("Exception occured while validating the schema" , e); } SchemaProcessor schemaProcessor = buildSchemaProcessor(requestContext, validationInfo, this.useOriginalSchema); String addedPath = schemaProcessor .importSchemaToRegistry(requestContext, path, getChrootedSchemaLocation(requestContext.getRegistryContext()), true,disableSymlinkCreation); requestContext.setActualPath(addedPath); log.debug("XSD : " + addedPath); return addedPath; } return null; } private String getChrootedSchemaLocation(RegistryContext registryContext) { return RegistryUtils.getAbsolutePath(registryContext, RegistryConstants.GOVERNANCE_REGISTRY_BASE_PATH + schemaLocation); } private String getChrootedWADLLocation(RegistryContext registryContext) { return RegistryUtils.getAbsolutePath(registryContext, RegistryConstants.GOVERNANCE_REGISTRY_BASE_PATH + wadlLocation); } private String getChrootedSwaggerLocation(RegistryContext registryContext) { return RegistryUtils.getAbsolutePath(registryContext, RegistryConstants.GOVERNANCE_REGISTRY_BASE_PATH + swaggerLocation); } public void importResource(RequestContext context) { // We don't support importing .gar files. This is meant only for uploading WSDL files // and imports from the local filesystem. log.warn("The imported Governance Web Archive will not be extracted. To extract the content" + " upload the archive from the file system."); } public void setWsdlMediaType(String wsdlMediaType) { this.wsdlMediaType = wsdlMediaType; } public void setWsdlExtension(String wsdlExtension) { this.wsdlExtension = wsdlExtension; } public void setSchemaMediaType(String xsdMediaType) { this.xsdMediaType = xsdMediaType; } public void setSchemaExtension(String xsdExtension) { this.xsdExtension = xsdExtension; } public void setArchiveExtension(String archiveExtension) { this.archiveExtension = archiveExtension; } public void setTempFilePrefix(String tempFilePrefix) { this.tempFilePrefix = tempFilePrefix; } public void setDisableWSDLValidation(String disableWSDLValidation) { this.disableWSDLValidation = Boolean.toString(true).equals(disableWSDLValidation); } public void setDisableSchemaValidation(String disableSchemaValidation) { this.disableSchemaValidation = Boolean.toString(true).equals(disableSchemaValidation); } public void setDisableWADLValidation(String disableWADLValidation) { this.disableWADLValidation = Boolean.getBoolean(disableWADLValidation); } public void setUseOriginalSchema(String useOriginalSchema) { this.useOriginalSchema = Boolean.toString(true).equals(useOriginalSchema); } public void setSkipFileExtensions(String skipFileExtensions) { if (skipFileExtensions != null) { String[] extensions = skipFileExtensions.split(this.extensionsSeparator); this.skipFileExtensions = Arrays.asList(extensions); } } /** * {@inheritDoc} */ protected void onPutCompleted(String path, Map<String, String> addedResources, List<String> otherResources, RequestContext requestContext) //Final result printing in console. throws RegistryException { Registry configRegistry = RegistryCoreServiceComponent.getRegistryService().getConfigSystemRegistry(); String resourceName = RegistryUtils.getResourceName(requestContext.getResourcePath().getPath()); OMFactory factory = OMAbstractFactory.getOMFactory(); OMElement garElement = factory.createOMElement( new QName(CommonConstants.REG_GAR_PATH_MAPPING_RESOURCE)); garElement.addAttribute(factory.createOMAttribute( CommonConstants.REG_GAR_PATH_MAPPING_RESOURCE_ATTR_PATH, null, requestContext.getResourcePath().getPath())); log.info("Total Number of Files Uploaded: " + addedResources.size()); List<String> failures = new LinkedList<String>(); for (Map.Entry<String, String> e : addedResources.entrySet()) { if (e.getValue() == null) { failures.add(e.getKey()); log.info("Failure " + failures.size() + ": " + e.getKey()); } else { OMElement targetElement = factory.createOMElement( new QName(CommonConstants.REG_GAR_PATH_MAPPING_RESOURCE_TARGET)); targetElement.setText(e.getValue()); garElement.addChild(targetElement); } } String pathMappingResourceName = resourceName; if (resourceName.contains(".")){ pathMappingResourceName = resourceName.substring(0, resourceName.lastIndexOf(".")); } String pathMappingResourcePath = CommonConstants.REG_GAR_PATH_MAPPING + pathMappingResourceName; boolean garMappingExists = configRegistry.resourceExists(pathMappingResourcePath); if (garMappingExists) { Resource pathMappingResource = configRegistry.get(pathMappingResourcePath); try { OMElement garMappingElement = AXIOMUtil.stringToOM( new String((byte[]) pathMappingResource.getContent())); garMappingElement.addChild(garElement); pathMappingResource.setContent(garMappingElement.toString()); configRegistry.put(pathMappingResourcePath, pathMappingResource); } catch (XMLStreamException e) { log.warn("Error occurred while retrieving the content of GAR mapping file ", e); } } log.info("Total Number of Files Failed to Upload: " + failures.size()); if (otherResources.size() > 0) { log.info("Total Number of Files Not-Uploaded: " + otherResources.size()); } } protected void uploadFiles(List<UploadTask> tasks, File tempFile, Stack<File> fileList, File tempDir, int poolSize, String path, List<String> uriList, RequestContext requestContext) throws RegistryException { CommonUtil.loadImportedArtifactMap(); try { if (poolSize <= 0) { boolean updateLockAvailable = CommonUtil.isUpdateLockAvailable(); if (!updateLockAvailable) { CommonUtil.releaseUpdateLock(); } try { for (UploadTask task : tasks) { task.run(); } } finally { if (!updateLockAvailable) { CommonUtil.acquireUpdateLock(); } } } else { ExecutorService executorService = Executors.newFixedThreadPool(poolSize); if (!CommonUtil.isArtifactIndexMapExisting()) { CommonUtil.createArtifactIndexMap(); } if (!CommonUtil.isSymbolicLinkMapExisting()) { CommonUtil.createSymbolicLinkMap(); } for (UploadTask task : tasks) { executorService.submit(task); } executorService.shutdown(); while (!executorService.isTerminated()) { } } } finally { CommonUtil.clearImportedArtifactMap(); } try { if (CommonUtil.isArtifactIndexMapExisting()) { Map<String, String> artifactIndexMap = CommonUtil.getAndRemoveArtifactIndexMap(); if (log.isDebugEnabled()) { for (Map.Entry<String, String> entry : artifactIndexMap.entrySet()) { log.debug("Added Artifact Entry: " + entry.getKey()); } } // CommonUtil.addGovernanceArtifactEntriesWithRelativeValues( // CommonUtil.getUnchrootedSystemRegistry(requestContext), artifactIndexMap); } Registry registry = requestContext.getRegistry(); if (!isDisableSymlinkCreation() && CommonUtil.isSymbolicLinkMapExisting()) { Map<String, String> symbolicLinkMap = CommonUtil.getAndRemoveSymbolicLinkMap(); for (Map.Entry<String, String> entry : symbolicLinkMap.entrySet()) { if (log.isDebugEnabled()) { log.debug("Added Symbolic Link: " + entry.getKey()); } try { if (registry.resourceExists(entry.getKey())) { registry.removeLink(entry.getKey()); } } catch (RegistryException ignored) { // we are not bothered above errors in getting rid of symbolic links. } requestContext.getSystemRegistry().createLink(entry.getKey(), entry.getValue()); } } } catch (RegistryException e) { log.error("Unable to build artifact index.", e); } Map<String, String> taskResults = new LinkedHashMap<String, String>(); for (UploadTask task : tasks) { if (task.getFailed()) { taskResults.put(task.getUri(), null); } else { taskResults.put(task.getUri(), task.getResult()); } } onPutCompleted(path, taskResults, uriList, requestContext); try { delete(tempFile); while (!fileList.isEmpty()) { delete(fileList.pop()); } FileUtils.deleteDirectory(tempDir); } catch (IOException e) { log.error("Unable to cleanup temporary files", e); } log.info("Completed uploading files from archive file"); } protected static abstract class UploadTask implements Runnable { private String uri; private RequestContext requestContext; private int tenantId = -1; private UserRegistry userRegistry; private UserRealm userRealm; private String userId; private int callerTenantId; private Map<String, String> localPathMap; private Random random = new Random(10); protected String result = null; protected boolean failed = false; protected int retries = 0; public UploadTask(RequestContext requestContext, String uri, int tenantId, UserRegistry userRegistry, UserRealm userRealm, String userId, int callerTenantId, Map<String, String> localPathMap) { this.userRegistry = userRegistry; this.userRealm = userRealm; this.tenantId = tenantId; this.requestContext = requestContext; this.uri = uri; this.userId = userId; this.callerTenantId = callerTenantId; this.localPathMap = localPathMap; } public void run() { try { PrivilegedCarbonContext.startTenantFlow(); //This is for fixing CARBON-14469. PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true); //set user name to set in swagger import provider PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(userId); // File is already uploaded via wsdl or xsd imports those are skip if (CommonUtil.isImportedArtifactExisting(new File(uri).toString())) { failed = false; result = "added from import"; return; } doWork(); } finally { PrivilegedCarbonContext.endTenantFlow(); } } protected void retry() { //Number of retry can be configurable via handler configuration (<property name="numberOfRetry">1</property>) if (retries < ZipWSDLMediaTypeHandler.numberOfRetry) { ++retries; log.info("Retrying to upload resource: " + uri); int i = random.nextInt(10); if (log.isDebugEnabled()) { log.debug("Waiting for " + i + " seconds"); } try { Thread.sleep(1000 * i); } catch (InterruptedException ignored) { } doWork(); } else { failed = true; } } private void doWork() { CurrentSession.setTenantId(tenantId); CurrentSession.setUserRegistry(userRegistry); CurrentSession.setUserRealm(userRealm); CurrentSession.setUser(userId); CurrentSession.setCallerTenantId(callerTenantId); if (localPathMap != null) { CurrentSession.setLocalPathMap(localPathMap); } try { if (CommonUtil.isUpdateLockAvailable()) { CommonUtil.acquireUpdateLock(); try { RequestContext requestContext = new RequestContext(this.requestContext.getRegistry(), this.requestContext.getRepository(), this.requestContext.getVersionRepository()); requestContext.setResourcePath(this.requestContext.getResourcePath()); requestContext.setResource(this.requestContext.getResource()); requestContext.setOldResource(this.requestContext.getOldResource()); doProcessing(requestContext, uri); } finally { CommonUtil.releaseUpdateLock(); } } } catch (RegistryException e) { log.error("An error occurred while uploading "+uri, e); retry(); } catch (RuntimeException e) { log.error("An unhandled exception occurred while uploading " + uri, e); retry(); } finally { CurrentSession.removeUser(); CurrentSession.removeUserRealm(); CurrentSession.removeUserRegistry(); CurrentSession.removeTenantId(); CurrentSession.removeCallerTenantId(); if (localPathMap != null) { CurrentSession.removeLocalPathMap(); } // get rid of the reference to the request context at the end. requestContext = null; } } protected abstract void doProcessing(RequestContext requestContext, String uri) throws RegistryException; public String getUri() { return uri; } public String getResult() { return result; } public boolean getFailed() { return failed; } } protected class UploadFileTask extends UploadTask { String mediaType; public UploadFileTask(RequestContext requestContext, String uri, int tenantId, UserRegistry userRegistry, UserRealm userRealm, String userId, int callerTenantId, Map<String, String> localPathMap, String mediaType) { super(requestContext, uri, tenantId, userRegistry, userRealm, userId, callerTenantId, localPathMap); this.mediaType = mediaType; } protected void doProcessing(RequestContext requestContext, String uri) throws RegistryException { Registry registry = requestContext.getRegistry(); Resource resource = registry.newResource(); String version = requestContext.getResource().getProperty("version"); if (resource.getUUID() == null) { resource.setUUID(UUID.randomUUID().toString()); } if (version != null) { resource.setProperty("version", version); } resource.setMediaType(this.mediaType); InputStream inputStream; try { inputStream = new URL(uri).openStream(); } catch (IOException e) { throw new RegistryException("The URL " + uri + " is incorrect.", e); } ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); int nextChar; try { while ((nextChar = inputStream.read()) != -1) { outputStream.write(nextChar); } outputStream.flush(); } catch (IOException e) { throw new RegistryException("Failed to read content from URL " + uri, e); } resource.setContent(outputStream.toByteArray()); String path = RegistryUtils.getParentPath(requestContext.getResourcePath().getPath()) + RegistryConstants.PATH_SEPARATOR + RegistryUtils.getResourceName(uri); result = registry.put(path, resource); } } protected class UploadXSDTask extends UploadTask { public UploadXSDTask(RequestContext requestContext, String uri, int tenantId, UserRegistry userRegistry, UserRealm userRealm, String userId, int callerTenantId, Map<String, String> localPathMap) { super(requestContext, uri, tenantId, userRegistry, userRealm, userId, callerTenantId, localPathMap); } protected void doProcessing(RequestContext requestContext, String uri) throws RegistryException { result = addSchemaFromZip(requestContext, uri); } } protected class UploadWSDLTask extends UploadTask { public UploadWSDLTask(RequestContext requestContext, String uri, int tenantId, UserRegistry userRegistry, UserRealm userRealm, String userId, int callerTenantId, Map<String, String> localPathMap) { super(requestContext, uri, tenantId, userRegistry, userRealm, userId, callerTenantId, localPathMap); } protected void doProcessing(RequestContext requestContext, String uri) throws RegistryException { result = addWSDLFromZip(requestContext, uri); } } protected class UploadWadlTask extends UploadTask { public UploadWadlTask(RequestContext requestContext, String uri, int tenantId, UserRegistry userRegistry, UserRealm userRealm, String userId, int callerTenantId, Map<String, String> localPathMap) { super(requestContext, uri, tenantId, userRegistry, userRealm, userId, callerTenantId, localPathMap); } protected void doProcessing(RequestContext requestContext, String uri) throws RegistryException { result = addWADLFromZip(requestContext, uri); } } protected class UploadSwaggerTask extends UploadTask { public UploadSwaggerTask(RequestContext requestContext, String uri, int tenantId, UserRegistry userRegistry, UserRealm userRealm, String userId, int callerTenantId, Map<String, String> localPathMap) { super(requestContext, uri, tenantId, userRegistry, userRealm, userId, callerTenantId, localPathMap); } protected void doProcessing(RequestContext requestContext, String uri) throws RegistryException { result = addSwaggerFromZip(requestContext, uri); } } }