/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF 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.apache.axis2.deployment; import org.apache.axis2.AxisFault; import org.apache.axis2.Constants; import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.deployment.repository.util.ArchiveReader; import org.apache.axis2.deployment.repository.util.DeploymentFileData; import org.apache.axis2.deployment.repository.util.WSInfo; import org.apache.axis2.deployment.scheduler.DeploymentIterator; import org.apache.axis2.deployment.scheduler.Scheduler; import org.apache.axis2.deployment.scheduler.SchedulerTask; import org.apache.axis2.deployment.util.Utils; import org.apache.axis2.description.AxisModule; import org.apache.axis2.description.AxisOperation; import org.apache.axis2.description.AxisService; import org.apache.axis2.description.AxisServiceGroup; import org.apache.axis2.description.Flow; import org.apache.axis2.description.Parameter; import org.apache.axis2.engine.AxisConfiguration; import org.apache.axis2.i18n.Messages; import org.apache.axis2.util.FaultyServiceData; import org.apache.axis2.util.JavaUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamException; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; public abstract class DeploymentEngine implements DeploymentConstants { private static final Log log = LogFactory.getLog(DeploymentEngine.class); /** * Indicates that the deployment task is running */ public static final String DEPLOYMENT_TASK_RUNNING = "deployment.task.running"; private static final String MODULE_DEPLOYER = "moduleDeployer"; //to keep the web resource location if any protected static String webLocationString = null; protected Scheduler scheduler; private SchedulerTask schedulerTask; public static void setWebLocationString(String webLocationString) { DeploymentEngine.webLocationString = webLocationString; } /** * Support for hot update is controlled by this flag */ protected boolean hotUpdate = true; /** * Support for hot deployment is controlled by this flag */ protected boolean hotDeployment = true; /** * Stores all the web Services to deploy. */ protected List<DeploymentFileData> wsToDeploy = new ArrayList<DeploymentFileData>(); /** * Stores all the web Services to undeploy. */ protected List<WSInfo> wsToUnDeploy = new ArrayList<WSInfo>(); /** * to keep a ref to engine register * this ref will pass to engine when it call start() * method */ protected AxisConfiguration axisConfig; protected ConfigurationContext configContext; protected RepositoryListener repoListener; protected String servicesPath = null; protected File servicesDir = null; protected String modulesPath = null; protected File modulesDir = null; private File repositoryDir = null; //to deploy service (both aar and expanded) protected ServiceDeployer serviceDeployer; //To deploy modules (both mar and expanded) protected ModuleDeployer moduleDeployer; private Map<String, Map<String, Deployer>> deployerMap = new HashMap<String, Map<String, Deployer>>(); private Lock lock = new ReentrantLock(); public void loadServices() { repoListener.checkServices(); if (hotDeployment) { startSearch(repoListener); } } public void loadRepository(String repoDir) throws DeploymentException { File axisRepo = new File(repoDir); if (!axisRepo.exists()) { throw new DeploymentException( Messages.getMessage("cannotfindrepo", repoDir)); } setDeploymentFeatures(); prepareRepository(repoDir); // setting the CLs setClassLoaders(repoDir); repoListener = new RepositoryListener(this, false); org.apache.axis2.util.Utils .calculateDefaultModuleVersion(axisConfig.getModules(), axisConfig); try { try { axisConfig.setRepository(axisRepo.toURI().toURL()); } catch (MalformedURLException e) { log.info(e.getMessage()); } axisConfig.validateSystemPredefinedPhases(); } catch (AxisFault axisFault) { throw new DeploymentException(axisFault); } } public void loadFromClassPath() throws DeploymentException { //loading modules from the classpath new RepositoryListener(this, true); org.apache.axis2.util.Utils.calculateDefaultModuleVersion( axisConfig.getModules(), axisConfig); axisConfig.validateSystemPredefinedPhases(); try { engageModules(); } catch (AxisFault axisFault) { log.info(Messages.getMessage(DeploymentErrorMsgs.MODULE_VALIDATION_FAILED, axisFault.getMessage())); throw new DeploymentException(axisFault); } } private void loadCustomServices(URL repoURL) { for (Map.Entry<String, Map<String, Deployer>> entry : getDeployers().entrySet()) { String directory = entry.getKey(); Map<String, Deployer> extensionMap = entry.getValue(); try { String listName; if (!directory.endsWith("/")) { listName = directory + ".list"; directory += "/"; } else { listName = directory.replaceAll("/", "") + ".list"; } String repoPath = repoURL.getPath(); if (!repoPath.endsWith("/")) { repoPath += "/"; repoURL = new URL(repoURL.getProtocol() + "://" + repoPath); } URL servicesDir = new URL(repoURL, directory); URL filelisturl = new URL(servicesDir, listName); List<String> files = getFileList(filelisturl); for (Object file : files) { String fileName = (String) file; String extension = getExtension(fileName); Deployer deployer = extensionMap.get(extension); if (deployer == null) { continue; } URL servicesURL = new URL(servicesDir, fileName); // We are calling reflection code here , to avoid changes to the interface Class<?> classToLoad = deployer.getClass(); // We can not call classToLoad.getDeclaredMethed() , since there // can be insatnce where mutiple services extends using one class // just for init and other reflection methods Method method = null; try { method = classToLoad.getMethod("deployFromURL", URL.class); } catch (Exception e) { //We do not need to inform this to user , since this something // Axis2 is checking to support Session. So if the method is // not there we should ignore that } if (method != null) { try { method.invoke(deployer, servicesURL); } catch (Exception e) { log.info( "Exception trying to call " + "deployFromURL for the deployer" + deployer.getClass(), e); } } } } catch (MalformedURLException e) { //I am just ignoring the error at the moment , but need to think how to handle this } } } private String getExtension(String fileName) { int lastIndex = fileName.lastIndexOf("."); return fileName.substring(lastIndex + 1); } public void loadServicesFromUrl(URL repoURL) { try { String path = servicesPath == null ? DeploymentConstants.SERVICE_PATH : servicesPath; if (!path.endsWith("/")) { path += "/"; } String repoPath = repoURL.getPath(); if (!repoPath.endsWith("/")) { repoPath += "/"; repoURL = new URL(repoURL.getProtocol() + "://" + repoPath); } URL servicesDir = new URL(repoURL, path); URL filelisturl = new URL(servicesDir, "services.list"); ArrayList<String> files = getFileList(filelisturl); repoListener = new RepositoryListener(this, false); for (Object file : files) { String fileUrl = (String) file; if (fileUrl.endsWith(".aar")) { URL servicesURL = new URL(servicesDir, fileUrl); repoListener.addURLToDeploy(servicesURL, getServiceDeployer(), WSInfo.TYPE_SERVICE); } } repoListener.update(); //Loading other type of services such as custom deployers loadCustomServices(repoURL); } catch (MalformedURLException e) { log.error(e.getMessage(), e); } } public void loadRepositoryFromURL(URL repoURL) throws DeploymentException { try { setDeploymentFeatures(); String path = modulesPath == null ? DeploymentConstants.MODULE_PATH : modulesPath; if (!path.endsWith("/")) { path = path + "/"; } String repoPath = repoURL.getPath(); if (!repoPath.endsWith("/")) { repoPath += "/"; repoURL = new URL(repoURL.getProtocol() + "://" + repoPath); } URL moduleDir = new URL(repoURL, path); URL filelisturl = new URL(moduleDir, "modules.list"); Iterator<String> fileIterator = getFileList(filelisturl).iterator(); axisConfig.setRepository(repoURL); repoListener = new RepositoryListener(this, false); while (fileIterator.hasNext()) { String fileUrl = (String) fileIterator.next(); if (fileUrl.endsWith(".mar")) { URL moduleurl = new URL(moduleDir, fileUrl); repoListener.addURLToDeploy(moduleurl, getModuleDeployer(), WSInfo.TYPE_MODULE); } } repoListener.update(); org.apache.axis2.util.Utils.calculateDefaultModuleVersion(axisConfig.getModules(), axisConfig); axisConfig.validateSystemPredefinedPhases(); } catch (MalformedURLException e) { throw new DeploymentException(e); } catch (IOException e) { throw new DeploymentException(e); } } public static void addNewModule(AxisModule modulemetadata, AxisConfiguration axisConfiguration) throws AxisFault { Flow inflow = modulemetadata.getInFlow(); ClassLoader moduleClassLoader = modulemetadata.getModuleClassLoader(); if (inflow != null) { Utils.addFlowHandlers(inflow, moduleClassLoader); } Flow outFlow = modulemetadata.getOutFlow(); if (outFlow != null) { Utils.addFlowHandlers(outFlow, moduleClassLoader); } Flow faultInFlow = modulemetadata.getFaultInFlow(); if (faultInFlow != null) { Utils.addFlowHandlers(faultInFlow, moduleClassLoader); } Flow faultOutFlow = modulemetadata.getFaultOutFlow(); if (faultOutFlow != null) { Utils.addFlowHandlers(faultOutFlow, moduleClassLoader); } axisConfiguration.addModule(modulemetadata); log.debug(Messages.getMessage(DeploymentErrorMsgs.ADDING_NEW_MODULE)); synchronized (axisConfiguration.getFaultyServicesDuetoModules()) { //Check whether there are faulty services due to this module HashMap<String, FaultyServiceData> faultyServices = (HashMap<String, FaultyServiceData>) axisConfiguration.getFaultyServicesDuetoModule( modulemetadata.getName()); faultyServices = (HashMap<String, FaultyServiceData>) faultyServices.clone(); // Here iterating a cloned hashmap and modifying the original hashmap. // To avoid the ConcurrentModificationException. for (FaultyServiceData faultyServiceData : faultyServices.values()) { axisConfiguration.removeFaultyServiceDuetoModule(modulemetadata.getName(), faultyServiceData .getServiceGroup().getServiceGroupName()); //Recover the faulty serviceGroup. addServiceGroup(faultyServiceData.getServiceGroup(), faultyServiceData.getServiceList(), faultyServiceData.getServiceLocation(), faultyServiceData.getCurrentDeploymentFile(), axisConfiguration); } } } public static void addServiceGroup(AxisServiceGroup serviceGroup, ArrayList<AxisService> serviceList, URL serviceLocation, DeploymentFileData currentDeploymentFile, AxisConfiguration axisConfiguration) throws AxisFault { if (isServiceGroupReadyToDeploy(serviceGroup, serviceList, serviceLocation, currentDeploymentFile, axisConfiguration)) { fillServiceGroup(serviceGroup, serviceList, serviceLocation, axisConfiguration); axisConfiguration.addServiceGroup(serviceGroup); if (currentDeploymentFile != null) { addAsWebResources(currentDeploymentFile.getFile(), serviceGroup.getServiceGroupName(), serviceGroup); // let the system have hidden services if (!JavaUtils.isTrueExplicitly(serviceGroup.getParameterValue( Constants.HIDDEN_SERVICE_PARAM_NAME))) { log.info(Messages.getMessage(DeploymentErrorMsgs.DEPLOYING_WS, currentDeploymentFile.getName(), serviceLocation.toString())); } } else if (!JavaUtils.isTrueExplicitly(serviceGroup.getParameterValue( Constants.HIDDEN_SERVICE_PARAM_NAME))) { log.info(Messages.getMessage(DeploymentErrorMsgs.DEPLOYING_WS, serviceGroup.getServiceGroupName(), "")); } } } /** * Performs a check routine, in order to identify whether all the serviceGroup, service and * operation level modules are available. If a referenced module is not deployed yet, the * serviceGroup is added as a faulty service. * * @param serviceGroup the AxisServiceGroup we're checking * @param serviceList a List of AxisServices to check * @param serviceLocation the URL of the service (only used if there's a problem) * @param currentDeploymentFile the current DeploymentFileData object (only used if there's a * problem) * @param axisConfig the active AxisConfiguration * @return boolean * @throws AxisFault */ protected static boolean isServiceGroupReadyToDeploy(AxisServiceGroup serviceGroup, ArrayList<AxisService> serviceList, URL serviceLocation, DeploymentFileData currentDeploymentFile, AxisConfiguration axisConfig) throws AxisFault { synchronized (axisConfig.getFaultyServicesDuetoModules()) { String moduleName; ArrayList<String> groupModules = serviceGroup.getModuleRefs(); for (Object groupModule : groupModules) { moduleName = (String) groupModule; AxisModule module = axisConfig.getModule(moduleName); if (module == null) { axisConfig.addFaultyServiceDuetoModule(moduleName, new FaultyServiceData(serviceGroup, serviceList, serviceLocation, currentDeploymentFile)); if (log.isDebugEnabled()) { log.debug("Service: " + serviceGroup.getServiceGroupName() + " becomes faulty due to Module: " + moduleName); } return false; } } for (Object aServiceList : serviceList) { AxisService axisService = (AxisService) aServiceList; // modules from <service> ArrayList<String> list = axisService.getModules(); for (Object aList : list) { moduleName = (String) aList; AxisModule module = axisConfig.getModule(moduleName); if (module == null) { axisConfig.addFaultyServiceDuetoModule(moduleName, new FaultyServiceData(serviceGroup, serviceList, serviceLocation, currentDeploymentFile)); if (log.isDebugEnabled()) { log.debug("Service: " + serviceGroup.getServiceGroupName() + " becomes faulty due to Module: " + moduleName); } return false; } } for (Iterator<AxisOperation> iterator = axisService.getOperations(); iterator.hasNext();) { AxisOperation opDesc = (AxisOperation) iterator.next(); ArrayList<String> modules = opDesc.getModuleRefs(); for (Object module1 : modules) { moduleName = (String) module1; AxisModule module = axisConfig.getModule(moduleName); if (module == null) { axisConfig.addFaultyServiceDuetoModule(moduleName, new FaultyServiceData( serviceGroup, serviceList, serviceLocation, currentDeploymentFile)); if (log.isDebugEnabled()) { log.debug("Service: " + serviceGroup.getServiceGroupName() + " becomes faulty due to Module: " + moduleName); } return false; } } } } } return true; } protected static void fillServiceGroup(AxisServiceGroup serviceGroup, ArrayList<AxisService> serviceList, URL serviceLocation, AxisConfiguration axisConfig) throws AxisFault { // serviceGroup.setParent(axisConfig); // module from services.xml at serviceGroup level ArrayList<String> groupModules = serviceGroup.getModuleRefs(); serviceGroup.setParent(axisConfig); for (Object groupModule : groupModules) { String moduleName = (String) groupModule; AxisModule module = axisConfig.getModule(moduleName); if (module != null) { serviceGroup.engageModule(axisConfig.getModule(moduleName)); } else { throw new DeploymentException( Messages.getMessage( DeploymentErrorMsgs.BAD_MODULE_FROM_SERVICE, serviceGroup.getServiceGroupName(), moduleName)); } } Iterator<AxisService> services = serviceList.iterator(); while (services.hasNext()) { AxisService axisService = (AxisService) services.next(); axisService.setUseDefaultChains(false); axisService.setFileName(serviceLocation); serviceGroup.addService(axisService); // modules from <service> ArrayList<String> list = axisService.getModules(); for (Object aList : list) { AxisModule module = axisConfig.getModule((String) aList); if (module == null) { throw new DeploymentException( Messages.getMessage( DeploymentErrorMsgs.BAD_MODULE_FROM_SERVICE, axisService.getName(), ((QName) aList).getLocalPart())); } axisService.engageModule(module); } for (Iterator<AxisOperation> iterator = axisService.getOperations(); iterator.hasNext();) { AxisOperation opDesc = (AxisOperation) iterator.next(); ArrayList<String> modules = opDesc.getModuleRefs(); for (Object module1 : modules) { String moduleName = (String) module1; AxisModule module = axisConfig.getModule(moduleName); if (module != null) { opDesc.engageModule(module); } else { throw new DeploymentException( Messages.getMessage( DeploymentErrorMsgs.BAD_MODULE_FROM_OPERATION, opDesc.getName().getLocalPart(), moduleName)); } } } } } /** * @param file ArchiveFileData */ public synchronized void addWSToDeploy(DeploymentFileData file) { wsToDeploy.add(file); } /** * @param file WSInfo */ public synchronized void addWSToUndeploy(WSInfo file){ wsToUnDeploy.add(file); } public synchronized void doDeploy() { try { if (wsToDeploy.size() > 0) { for (Object aWsToDeploy : wsToDeploy) { DeploymentFileData fileToDeploy = (DeploymentFileData) aWsToDeploy; try { fileToDeploy.deploy(); } catch (DeploymentException e) { // TODO : This probably isn't sufficient. Maybe provide an option to stop? log.info(e); } } } } finally { wsToDeploy.clear(); } } /** * Checks if the modules, referred by server.xml, exist or that they are deployed. * * @throws org.apache.axis2.AxisFault : If smt goes wrong */ public void engageModules() throws AxisFault { axisConfig.engageGlobalModules(); } /** * To get AxisConfiguration for a given inputStream this method can be used. * The inputstream should be a valid axis2.xml , else you will be getting * DeploymentExceptions. * <p/> * First creat a AxisConfiguration using given inputSream , and then it will * try to find the repository location parameter from AxisConfiguration, so * if user has add a parameter with the name "repository" , then the value * specified by that parameter will be the repository and system will try to * load modules and services from that repository location if it a valid * location. hot deployment and hot update will work as usual in this case. * <p/> * You will be getting AxisConfiguration corresponding to given inputstream * if it is valid , if something goes wrong you will be getting * DeploymentException * * @param in : InputStream to axis2.xml * @return a populated AxisConfiguration * @throws DeploymentException : If something goes wrong */ public AxisConfiguration populateAxisConfiguration(InputStream in) throws DeploymentException { axisConfig = new AxisConfiguration(); AxisConfigBuilder builder = new AxisConfigBuilder(in, axisConfig, this); builder.populateConfig(); try { if (in != null) { in.close(); } } catch (IOException e) { log.info("error in closing input stream"); } moduleDeployer = new ModuleDeployer(axisConfig); return axisConfig; } /** * Starts the Deployment engine to perform Hot deployment and so on. * * @param listener : RepositoryListener */ protected void startSearch(RepositoryListener listener) { scheduler = new Scheduler(); schedulerTask = new SchedulerTask(listener, axisConfig); scheduler.schedule(schedulerTask, new DeploymentIterator()); } /** * Method to check whether the deployment task is currently running. Will be used is graceful * shutdown & restart scenarios. * * @return true - if the deployment task is running, false - otherwise */ public boolean isDeploymentTaskRunning() { synchronized (axisConfig) { Parameter deploymentTaskRunningParam = axisConfig.getParameter(DeploymentEngine.DEPLOYMENT_TASK_RUNNING); if (deploymentTaskRunningParam != null) { return (Boolean) deploymentTaskRunningParam.getValue(); } return false; } } public synchronized void unDeploy() { try { if (wsToUnDeploy.size() > 0) { for (Object aWsToUnDeploy : wsToUnDeploy) { WSInfo wsInfo = (WSInfo) aWsToUnDeploy; if (wsInfo.getType() == WSInfo.TYPE_SERVICE) { //No matter what we need to undeploy the service // if user has deleted the file from the repository serviceDeployer.undeploy(wsInfo.getFileName()); } else { //We need to undeploy the service whether we have enable hotUpdate or not , // o.w what happen if someone delete the service from the repo Deployer deployer = wsInfo.getDeployer(); if (deployer != null) { deployer.undeploy(wsInfo.getFileName()); } } } } } catch (Exception e) { log.info(e); } wsToUnDeploy.clear(); } /** * Gets AxisConfiguration. * * @return AxisConfiguration <code>AxisConfiguration</code> */ public AxisConfiguration getAxisConfig() { return axisConfig; } /** * Retrieves service name from the archive file name. * If the archive file name is service1.aar , then axis2 service name would be service1 * * @param fileName the archive file name * @return Returns String. */ public static String getAxisServiceName(String fileName) { char seperator = '.'; String value; int index = fileName.lastIndexOf(seperator); if (index > 0) { value = fileName.substring(0, index); return value; } return fileName; } public AxisModule getModule(String moduleName) throws AxisFault { return axisConfig.getModule(moduleName); } public boolean isHotUpdate() { return hotUpdate; } private static void addAsWebResources(File in, String serviceFileName, AxisServiceGroup serviceGroup) { try { if (webLocationString == null) { return; } if (in.isDirectory()) { return; } File webLocation = new File(webLocationString); File out = new File(webLocation, serviceFileName); int BUFFER = 1024; byte data[] = new byte[BUFFER]; FileInputStream fin = new FileInputStream(in); ZipInputStream zin = new ZipInputStream( fin); ZipEntry entry; while ((entry = zin.getNextEntry()) != null) { ZipEntry zip = new ZipEntry(entry); if (zip.getName().toUpperCase().startsWith("WWW")) { String fileName = zip.getName(); fileName = fileName.substring("WWW/".length(), fileName.length()); if (zip.isDirectory()) { new File(out, fileName).mkdirs(); } else { FileOutputStream tempOut = new FileOutputStream(new File(out, fileName)); int count; while ((count = zin.read(data, 0, BUFFER)) != -1) { tempOut.write(data, 0, count); } tempOut.close(); tempOut.flush(); } serviceGroup.setFoundWebResources(true); } } zin.close(); fin.close(); } catch (IOException e) { log.info(e.getMessage()); } } public static String getWebLocationString() { return webLocationString; } /** * To set the all the classLoader hierarchy this method can be used , the top most parent is * CCL then SCL(system Class Loader) * CCL * : * SCL * : : * MCCL SCCL * : : * MCL SCL * <p/> * <p/> * MCCL : module common class loader * SCCL : Service common class loader * MCL : module class loader * SCL : Service class loader * * @param axis2repoURI : The repository folder of Axis2 * @throws DeploymentException if there's a problem */ protected void setClassLoaders(String axis2repoURI) throws DeploymentException { if (axisConfig.getSystemClassLoader() == null) { ClassLoader sysClassLoader = Utils.getClassLoader(Thread.currentThread().getContextClassLoader(), axis2repoURI, axisConfig.isChildFirstClassLoading()); axisConfig.setSystemClassLoader(sysClassLoader); } if (servicesDir.exists()) { axisConfig.setServiceClassLoader( Utils.getClassLoader(axisConfig.getSystemClassLoader(), servicesDir, axisConfig.isChildFirstClassLoading())); } else { axisConfig.setServiceClassLoader(axisConfig.getSystemClassLoader()); } if (modulesDir.exists()) { axisConfig.setModuleClassLoader(Utils.getClassLoader(axisConfig.getSystemClassLoader(), modulesDir, axisConfig.isChildFirstClassLoading())); } else { axisConfig.setModuleClassLoader(axisConfig.getSystemClassLoader()); } } /** * Sets hotDeployment and hot update. */ protected void setDeploymentFeatures() { Parameter hotDeployment = axisConfig.getParameter(TAG_HOT_DEPLOYMENT); Parameter hotUpdate = axisConfig.getParameter(TAG_HOT_UPDATE); if (hotDeployment != null) { this.hotDeployment = JavaUtils.isTrue(hotDeployment.getValue(), true); } if (hotUpdate != null) { this.hotUpdate = JavaUtils.isTrue(hotUpdate.getValue(), true); } String serviceDirPara = (String) axisConfig.getParameterValue(DeploymentConstants.SERVICE_DIR_PATH); if (serviceDirPara != null) { servicesPath = serviceDirPara; } String moduleDirPara = (String) axisConfig.getParameterValue(DeploymentConstants.MODULE_DRI_PATH); if (moduleDirPara != null) { modulesPath = moduleDirPara; } } /** * Creates directories for modules/services, copies configuration xml from class loader if necessary * * @param repositoryName the pathname of the repository */ protected void prepareRepository(String repositoryName) { repositoryDir = new File(repositoryName); if (servicesPath != null) { servicesDir = new File(servicesPath); if (!servicesDir.exists()) { servicesDir = new File(repositoryDir, servicesPath); } } else { servicesDir = new File(repositoryDir, DeploymentConstants.SERVICE_PATH); } if (!servicesDir.exists()) { log.info(Messages.getMessage("noservicedirfound", getRepositoryPath(repositoryDir))); } if (modulesPath != null) { modulesDir = new File(modulesPath); if (!modulesDir.exists()) { modulesDir = new File(repositoryDir, modulesPath); } } else { modulesDir = new File(repositoryDir, DeploymentConstants.MODULE_PATH); } if (!modulesDir.exists()) { log.info(Messages.getMessage("nomoduledirfound", getRepositoryPath(repositoryDir))); } } protected String getRepositoryPath(File repository) { try { return repository.getCanonicalPath(); } catch (IOException e) { return repository.getAbsolutePath(); } } protected ArrayList<String> getFileList(URL fileListUrl) { ArrayList<String> fileList = new ArrayList<String>(); InputStream in; try { in = fileListUrl.openStream(); } catch (IOException e) { log.info(e.getMessage() + " - as per axis2.repository.url, the URL is "+fileListUrl+" that will be used relative to "+new File(".").getAbsolutePath()); return fileList; } BufferedReader input = null; try { input = new BufferedReader(new InputStreamReader(in)); String line; while ((line = input.readLine()) != null) { line = line.trim(); if (line.length() > 0 && line.charAt(0) != '#') { fileList.add(line); } } } catch (IOException ex) { ex.printStackTrace(); } finally { try { if (input != null) { input.close(); } } catch (IOException ex) { ex.printStackTrace(); } } return fileList; } public void setConfigContext(ConfigurationContext configContext) { this.configContext = configContext; initializeDeployers(this.configContext); } private void initializeDeployers(ConfigurationContext configContext) { for (Map<String, Deployer> extensionMap : deployerMap.values()) { for (Deployer deployer : extensionMap.values()) { deployer.init(configContext); if (deployer instanceof AbstractDeployer) { for (Iterator<ServiceBuilderExtension> sbeItr = ((AbstractDeployer) deployer) .getServiceBuilderExtensions().iterator(); sbeItr.hasNext();) { // init ServiceBuilderExtensions ServiceBuilderExtension builderExtension = sbeItr.next(); builderExtension.init(configContext); ((AbstractDeployer) deployer).addServiceBuilderExtensions(builderExtension); } /* * URL based deployment does not fully based on standard * deployment architecture hence it's require to set * serviceDeployer variable. serviceDeployer variable * set only if the ServiceDeployer has been registered * on axis2.xml file. */ if (deployer instanceof ServiceDeployer) { serviceDeployer = (ServiceDeployer) deployer; } } } } } /** * Builds an AxisModule for a given module archive file. This does not * called the init method since there is no reference to configuration context * so who ever create module using this has to called module.init if it is * required * * @param modulearchive : Actual module archive file * @param config : AxisConfiguration : for get classloaders etc.. * @return a complete AxisModule read from the file. * @throws org.apache.axis2.deployment.DeploymentException * if there's a problem */ public static AxisModule buildModule(File modulearchive, AxisConfiguration config) throws DeploymentException { AxisModule axismodule; ModuleDeployer deployer = (ModuleDeployer) config.getParameterValue(MODULE_DEPLOYER); try { if (deployer == null) { deployer = new ModuleDeployer(config); config.addParameter(MODULE_DEPLOYER, deployer); } DeploymentFileData currentDeploymentFile = new DeploymentFileData(modulearchive, deployer); axismodule = new AxisModule(); ArchiveReader archiveReader = new ArchiveReader(); currentDeploymentFile.setClassLoader(false, config.getModuleClassLoader(), null, config.isChildFirstClassLoading()); axismodule.setModuleClassLoader(currentDeploymentFile.getClassLoader()); archiveReader.readModuleArchive(currentDeploymentFile, axismodule, false, config); ClassLoader moduleClassLoader = axismodule.getModuleClassLoader(); Flow inflow = axismodule.getInFlow(); if (inflow != null) { Utils.addFlowHandlers(inflow, moduleClassLoader); } Flow outFlow = axismodule.getOutFlow(); if (outFlow != null) { Utils.addFlowHandlers(outFlow, moduleClassLoader); } Flow faultInFlow = axismodule.getFaultInFlow(); if (faultInFlow != null) { Utils.addFlowHandlers(faultInFlow, moduleClassLoader); } Flow faultOutFlow = axismodule.getFaultOutFlow(); if (faultOutFlow != null) { Utils.addFlowHandlers(faultOutFlow, moduleClassLoader); } } catch (AxisFault axisFault) { throw new DeploymentException(axisFault); } return axismodule; } /** * Fills an axisservice object using services.xml. First creates * an axisservice object using WSDL and then fills it using the given services.xml. * Loads all the required class and builds the chains, finally adds the * servicecontext to EngineContext and axisservice into EngineConfiguration. * * @param serviceInputStream InputStream containing configuration data * @param configCtx the ConfigurationContext in which we're deploying * @return Returns AxisService. * @throws DeploymentException if there's a problem */ public static AxisService buildService(InputStream serviceInputStream, ConfigurationContext configCtx) throws DeploymentException { AxisService axisService = new AxisService(); try { ServiceBuilder builder = new ServiceBuilder(serviceInputStream, configCtx, axisService); builder.populateService(builder.buildOM()); } catch (AxisFault axisFault) { throw new DeploymentException(axisFault); } catch (XMLStreamException e) { throw new DeploymentException(e); } return axisService; } /** * To build a AxisServiceGroup for a given services.xml * You have to add the created group into AxisConfig * * @param servicesxml InputStream created from services.xml or equivalent * @param classLoader ClassLoader to use * @param serviceGroupName name of the service group * @param configCtx the ConfigurationContext in which we're deploying * @param archiveReader the ArchiveReader we're working with * @param wsdlServices Map of existing WSDL services * @return a fleshed-out AxisServiceGroup * @throws AxisFault if there's a problem */ public static AxisServiceGroup buildServiceGroup(InputStream servicesxml, ClassLoader classLoader, String serviceGroupName, ConfigurationContext configCtx, ArchiveReader archiveReader, HashMap<String, AxisService> wsdlServices) throws AxisFault { DeploymentFileData currentDeploymentFile = new DeploymentFileData(null, null); currentDeploymentFile.setClassLoader(classLoader); AxisServiceGroup serviceGroup = new AxisServiceGroup(); serviceGroup.setServiceGroupClassLoader(classLoader); serviceGroup.setServiceGroupName(serviceGroupName); AxisConfiguration axisConfig = configCtx.getAxisConfiguration(); try { ArrayList<AxisService> serviceList = archiveReader.buildServiceGroup(servicesxml, currentDeploymentFile, serviceGroup, wsdlServices, configCtx); fillServiceGroup(serviceGroup, serviceList, null, axisConfig); return serviceGroup; } catch (XMLStreamException e) { throw AxisFault.makeFault(e); } } public static AxisServiceGroup loadServiceGroup(File serviceFile, ConfigurationContext configCtx) throws AxisFault { try { DeploymentFileData currentDeploymentFile = new DeploymentFileData(serviceFile, null); DeploymentClassLoader classLoader = Utils.createClassLoader(serviceFile, configCtx.getAxisConfiguration().isChildFirstClassLoading()); currentDeploymentFile.setClassLoader(classLoader); AxisServiceGroup serviceGroup = new AxisServiceGroup(); serviceGroup.setServiceGroupClassLoader(classLoader); // Drop the extension and take the name String fileName = serviceFile.getName(); String serviceGroupName = fileName.substring(0, fileName.lastIndexOf(".")); serviceGroup.setServiceGroupName(serviceGroupName); AxisConfiguration axisConfig = configCtx.getAxisConfiguration(); ArchiveReader archiveReader = new ArchiveReader(); HashMap<String, AxisService> wsdlServices = archiveReader.processWSDLs(currentDeploymentFile); InputStream serviceXml = classLoader.getResourceAsStream("META-INF/services.xml"); ArrayList<AxisService> serviceList = archiveReader.buildServiceGroup(serviceXml, currentDeploymentFile, serviceGroup, wsdlServices, configCtx); fillServiceGroup(serviceGroup, serviceList, null, axisConfig); return serviceGroup; } catch (Exception e) { throw new DeploymentException(e); } } public File getServicesDir() { return servicesDir; } public File getModulesDir() { return modulesDir; } public File getRepositoryDir() { return repositoryDir; } public void setDeployers(Map<String, Map<String, Deployer>> deployerMap) { this.deployerMap = deployerMap; } public Map<String, Map<String, Deployer>> getDeployers() { return this.deployerMap; } public RepositoryListener getRepoListener() { return repoListener; } public ServiceDeployer getServiceDeployer() { return serviceDeployer; } public ModuleDeployer getModuleDeployer() { return moduleDeployer; } public Deployer getDeployer(String directory, String extension) { Map<String, Deployer> extensionMap = deployerMap.get(directory); return (extensionMap != null) ? extensionMap.get(extension) : null; } private static void destroyClassLoader(ClassLoader classLoader) { if (classLoader instanceof DeploymentClassLoader) { try { ((DeploymentClassLoader)classLoader).close(); } catch (IOException ex) { log.warn("Failed to destroy class loader " + classLoader, ex); } } } /** * Clean up the mess */ public void cleanup() { destroyClassLoader(axisConfig.getModuleClassLoader()); destroyClassLoader(axisConfig.getServiceClassLoader()); destroyClassLoader(axisConfig.getSystemClassLoader()); if (scheduler != null) { scheduler.cleanup(schedulerTask); } for (Map<String, Deployer> stringDeployerMap : deployerMap.values()) { for (Deployer deployer : stringDeployerMap.values()) { try { deployer.cleanup(); } catch (DeploymentException e) { log.error("Error occurred while cleaning up deployer", e); } } } } /** * Add and initialize a new Deployer. * * @param deployer Deployer object to be registered * @param directory the directory which will be scanned for deployable artifacts * @param extension the extension of the deployable artifacts for this Deployer */ public void addDeployer(Deployer deployer, String directory, String extension) { if (deployer == null) { log.error("Failed to add Deployer : deployer is null"); return; } if (directory == null) { log.error("Failed to add Deployer " + deployer.getClass().getName() + ": missing 'directory' attribute"); return; } //Extention is optional if the extention is not provided deployer will deploy the directories if (extension != null) { // A leading dot is redundant, so strip it. So we allow either ".foo" or "foo", either // of which will result in extension="foo" if (extension.charAt(0) == '.') extension = extension.substring(1); } // If axis2 is not initialized, Axis2 will handle the deployer init() and relavent service deployment // If axis2 is initialized and hotDeployment is on, Axis2 will handle the relavent service deployments. // If axis2 is initialized and hotDeployment is off, we need to manually deploy the relavent service artifacts. if (configContext != null) { // Initialize the Deployer deployer.init(configContext); for (Iterator<ServiceBuilderExtension> sbeItr = ((AbstractDeployer) deployer) .getServiceBuilderExtensions().iterator(); sbeItr.hasNext();) { //init ServiceBuilderExtensions sbeItr.next().init(configContext); } if (!hotDeployment) { //TBD } } lock.lock(); try { Map<String, Deployer> extensionMap = deployerMap.get(directory); if (extensionMap == null) { extensionMap = new HashMap<String, Deployer>(); deployerMap.put(directory, extensionMap); } extensionMap.put(extension, deployer); } finally { lock.unlock(); } } /** * Remove any Deployer mapped for the given directory and extension * * @param directory the directory of deployables * @param extension the extension of deployables */ public void removeDeployer(String directory, String extension) { if (directory == null) { log.error("Failed to remove Deployer : missing 'directory' attribute"); return; } if (extension == null) { log.error("Failed to remove Deployer : Deployer missing 'extension' attribute"); return; } Map<String, Deployer> extensionMap = deployerMap.get(directory); if (extensionMap == null) { return; } lock.lock(); try { if (extensionMap.containsKey(extension)) { Deployer deployer = extensionMap.remove(extension); if (extensionMap.isEmpty()) { deployerMap.remove(directory); } if (log.isDebugEnabled()) { log.debug("Deployer " + deployer.getClass().getName() + " is removed"); } } } finally { lock.unlock(); } } }