diff --git a/wlp-managed-8.5/src/main/java/org/jboss/arquillian/container/was/wlp_managed_8_5/WLPManagedContainer.java b/wlp-managed-8.5/src/main/java/org/jboss/arquillian/container/was/wlp_managed_8_5/WLPManagedContainer.java index ed4e2b7..a09829e 100644 --- a/wlp-managed-8.5/src/main/java/org/jboss/arquillian/container/was/wlp_managed_8_5/WLPManagedContainer.java +++ b/wlp-managed-8.5/src/main/java/org/jboss/arquillian/container/was/wlp_managed_8_5/WLPManagedContainer.java @@ -30,6 +30,13 @@ import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; import org.jboss.arquillian.container.spi.client.container.DeployableContainer; import org.jboss.arquillian.container.spi.client.container.DeploymentException; @@ -41,6 +48,10 @@ import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.exporter.ZipExporter; import org.jboss.shrinkwrap.descriptor.api.Descriptor; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; import com.sun.tools.attach.VirtualMachine; import com.sun.tools.attach.VirtualMachineDescriptor; @@ -228,7 +239,7 @@ private String findVirtualMachineIdByName(String serverName) { return null; } - + public ProtocolMetaData deploy(final Archive archive) throws DeploymentException { if (log.isLoggable(Level.FINER)) { @@ -237,25 +248,56 @@ public ProtocolMetaData deploy(final Archive archive) throws DeploymentExcept log.finer("Archive provided to deploy method: " + archive.toString(true)); } - // Save the archive to disk so it can be loaded by the container. - String dropInDir = getDropInDirectory(); - File exportedArchiveLocation = new File(dropInDir, archive.getName()); - archive.as(ZipExporter.class).exportTo(exportedArchiveLocation, true); - - // Wait until the application is deployed and available - waitForApplicationTargetState(createDeploymentName(archive.getName()), true, containerConfiguration.getAppDeployTimeout()); - - // Return metadata on how to contact the deployed application - ProtocolMetaData metaData = new ProtocolMetaData(); - HTTPContext httpContext = new HTTPContext("localhost", containerConfiguration.getHttpPort()); - httpContext.add(new Servlet("ArquillianServletRunner", createDeploymentName(archive.getName()))); - metaData.addContext(httpContext); + String archiveName = archive.getName(); + String archiveType = createDeploymentType(archiveName); + String deployName = createDeploymentName(archiveName); - if (log.isLoggable(Level.FINER)) { - log.exiting(className, "deploy"); + try { + // If the deployment is to server.xml, then update server.xml with the application information + if (containerConfiguration.isDeployTypeXML()) { + // Throw error if deployment type is not ear, war, or eba + if (!archiveType.equalsIgnoreCase("ear") && !archiveType.equalsIgnoreCase("war") && !archiveType.equalsIgnoreCase("eba")) + throw new DeploymentException("Invalid archive type: " + archiveType + ". Valid archive types are ear, war, and eba."); + + // Save the archive to disk so it can be loaded by the container. + String appDir = getAppDirectory(); + File exportedArchiveLocation = new File(appDir, archiveName); + archive.as(ZipExporter.class).exportTo(exportedArchiveLocation, true); + + // Read server.xml file into Memory + Document document = readServerXML(); + + // Add the archive as appropriate to the server.xml file + addApplication(document, deployName, archiveName, archiveType); + + // Update server.xml on file system + writeServerXML(document); + } + // Otherwise put the application in the dropins directory + else { + // Save the archive to disk so it can be loaded by the container. + String dropInDir = getDropInDirectory(); + File exportedArchiveLocation = new File(dropInDir, archiveName); + archive.as(ZipExporter.class).exportTo(exportedArchiveLocation, true); + } + + // Wait until the application is deployed and available + waitForApplicationTargetState(deployName, true, containerConfiguration.getAppDeployTimeout()); + + // Return metadata on how to contact the deployed application + ProtocolMetaData metaData = new ProtocolMetaData(); + HTTPContext httpContext = new HTTPContext("localhost", containerConfiguration.getHttpPort()); + httpContext.add(new Servlet("ArquillianServletRunner", deployName)); + metaData.addContext(httpContext); + + if (log.isLoggable(Level.FINER)) { + log.exiting(className, "deploy"); + } + + return metaData; + } catch (Exception e) { + throw new DeploymentException("Exception while deploying application.", e); } - - return metaData; } public void undeploy(final Archive archive) throws DeploymentException @@ -263,21 +305,51 @@ public void undeploy(final Archive archive) throws DeploymentException if (log.isLoggable(Level.FINER)) { log.entering(className, "undeploy"); } - - // Remove archive from the dropIn directory, which causes undeploy - String dropInDir = getDropInDirectory(); - File exportedArchiveLocation = new File(dropInDir, archive.getName()); - if (!exportedArchiveLocation.delete()) - throw new DeploymentException("Unable to delete archive from dropIn directory"); + + String archiveName = archive.getName(); + String deployName = createDeploymentName(archiveName); + + try { + //If deploy type is xml, then remove the application from the xml file, which causes undeploy + if (containerConfiguration.isDeployTypeXML()) { + // Read the server.xml file into Memory + Document document = readServerXML(); - // Wait until the application is undeployed - waitForApplicationTargetState(createDeploymentName(archive.getName()), false, containerConfiguration.getAppUndeployTimeout()); + // Remove the archive from the server.xml file + removeApplication(document); - if (log.isLoggable(Level.FINER)) { + // Update server.xml on file system + writeServerXML(document); + + // Wait until the application is undeployed + waitForApplicationTargetState(deployName, false, containerConfiguration.getAppUndeployTimeout()); + + // Remove archive from the apps directory + String appDir = getAppDirectory(); + File exportedArchiveLocation = new File(appDir, archiveName); + if (!exportedArchiveLocation.delete()) + throw new DeploymentException("Unable to delete archive from apps directory"); + } + else { + // Remove archive from the dropIn directory, which causes undeploy + String dropInDir = getDropInDirectory(); + File exportedArchiveLocation = new File(dropInDir, archiveName); + if (!exportedArchiveLocation.delete()) + throw new DeploymentException("Unable to delete archive from dropIn directory"); + + // Wait until the application is undeployed + waitForApplicationTargetState(deployName, false, containerConfiguration.getAppUndeployTimeout()); + } + + } catch (Exception e) { + throw new DeploymentException("Exception while undeploying application.", e); + } + + if (log.isLoggable(Level.FINER)) { log.exiting(className, "undeploy"); - } + } } - + private String getDropInDirectory() { String dropInDir = containerConfiguration.getWlpHome() + "/usr/servers/" + containerConfiguration.getServerName() + "/dropins"; @@ -286,11 +358,91 @@ private String getDropInDirectory() { return dropInDir; } + private String getAppDirectory() { + String appDir = containerConfiguration.getWlpHome() + "/usr/servers/" + + containerConfiguration.getServerName() + "/apps"; + if (log.isLoggable(Level.FINER)) + log.finer("appDir: " + appDir); + return appDir; + } + + private String getServerXML() { + String serverXML = containerConfiguration.getWlpHome() + "/usr/servers/" + + containerConfiguration.getServerName() + "/server.xml"; + if (log.isLoggable(Level.FINER)) + log.finer("server.xml: " + serverXML); + return serverXML; + } + private String createDeploymentName(String archiveName) { return archiveName.substring(0, archiveName.lastIndexOf(".")); } + private String createDeploymentType(String archiveName) + { + return archiveName.substring(archiveName.lastIndexOf(".")+1); + } + + private Document readServerXML() throws DeploymentException { + try { + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + return documentBuilder.parse(new File(getServerXML())); + } catch (Exception e) { + throw new DeploymentException("Exception while reading server.xml file.", e); + } + } + + private void writeServerXML(Document doc) throws DeploymentException { + try { + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer tr = tf.newTransformer(); + tr.setOutputProperty(OutputKeys.INDENT, "yes"); + DOMSource source = new DOMSource(doc); + StreamResult res = new StreamResult(new File(getServerXML())); + tr.transform(source, res); + } catch (Exception e) { + throw new DeploymentException("Exception wile writing server.xml file.", e); + } + } + + private Element createApplication(Document doc, String deploymentName, String archiveName, String type) { + + //create new Application + Element application = doc.createElement("application"); + application.setAttribute("id", deploymentName); + application.setAttribute("location", archiveName); + application.setAttribute("name", deploymentName); + application.setAttribute("type", type); + + //create shared library + if (containerConfiguration.getSharedLib() != null) { + Element sharedLib = doc.createElement("classloader"); + sharedLib.setAttribute("commonLibraryRef", containerConfiguration.getSharedLib()); + application.appendChild(sharedLib); + } + + return application; + } + + private void addApplication(Document doc, String deployName, String archiveName, String type) { + NodeList rootList = doc.getElementsByTagName("server"); + Node root = rootList.item(0); + root.appendChild(createApplication(doc, deployName, archiveName, type)); + } + + private void removeApplication(Document doc) { + Node server = doc.getElementsByTagName("server").item(0); + NodeList serverlist = server.getChildNodes(); + for (int i=0; serverlist.getLength() > i; i++) { + Node node = serverlist.item(i); + if (node.getNodeName().equals("application")) { + node.getParentNode().removeChild(node); + } + } + } + private void waitForApplicationTargetState(String applicationName, boolean targetState, int timeout) throws DeploymentException { if (log.isLoggable(Level.FINER)) { log.entering(className, "waitForMBeanTargetState"); @@ -311,7 +463,7 @@ private void waitForApplicationTargetState(String applicationName, boolean targe try { int timeleft = timeout * 1000; while(mbsc.isRegistered(appMBean) != targetState) { - Thread.sleep(100); + Thread.sleep(1000); if (timeleft <= 0) throw new DeploymentException("Timeout while waiting for ApplicationMBean to reach targetState"); timeleft -= 100; diff --git a/wlp-managed-8.5/src/main/java/org/jboss/arquillian/container/was/wlp_managed_8_5/WLPManagedContainerConfiguration.java b/wlp-managed-8.5/src/main/java/org/jboss/arquillian/container/was/wlp_managed_8_5/WLPManagedContainerConfiguration.java index 1275da1..b0e09a8 100644 --- a/wlp-managed-8.5/src/main/java/org/jboss/arquillian/container/was/wlp_managed_8_5/WLPManagedContainerConfiguration.java +++ b/wlp-managed-8.5/src/main/java/org/jboss/arquillian/container/was/wlp_managed_8_5/WLPManagedContainerConfiguration.java @@ -36,6 +36,8 @@ public class WLPManagedContainerConfiguration implements private int serverStartTimeout = 30; private int appDeployTimeout = 2; private int appUndeployTimeout = 2; + private String sharedLib = null; + private String deployType = "dropins"; private boolean allowConnectingToRunningServer = Boolean.parseBoolean( System.getProperty("org.jboss.arquillian.container.was.wlp_managed_8_5.allowConnectingToRunningServer", "false")); @@ -56,6 +58,19 @@ public void validate() throws ConfigurationException { // Validate httpPort if (httpPort > 65535 || httpPort <= 0) throw new ConfigurationException("httpPort provided is not valid: " + httpPort); + + // Validate deployType + if (!deployType.equalsIgnoreCase("xml") && !deployType.equalsIgnoreCase("dropins")) + throw new ConfigurationException("deployType provided is not valid: " + deployType + ". deployType should be xml or dropins."); + + //Validate sharedLib + if (!sharedLib.equals(null)) { + if (!sharedLib.isEmpty()) { + if (!deployType.equalsIgnoreCase("xml")) + throw new ConfigurationException("deployType must be set to xml when sharedLib is not empty"); + } + } + } public String getWlpHome() { @@ -81,7 +96,22 @@ public int getHttpPort() { public void setHttpPort(int httpPort) { this.httpPort = httpPort; } + + public void setSharedLib(String sharedLib) { + this.sharedLib = sharedLib; + } + + public String getSharedLib() { + return sharedLib; + } + public void setDeployType(String deployType) { + this.deployType = deployType; + } + + public String getDeployType() { + return deployType; + } public boolean isAllowConnectingToRunningServer() { return allowConnectingToRunningServer; } @@ -117,5 +147,19 @@ public int getAppUndeployTimeout() { public void setAppUndeployTimeout(int appUndeployTimeout) { this.appUndeployTimeout = appUndeployTimeout; } + + public boolean isDeployTypeXML() { + if (deployType.equalsIgnoreCase("xml")) + return true; + else + return false; + } + + public boolean isDeployTypeDropins() { + if (deployType.equalsIgnoreCase("dropins")) + return true; + else + return false; + } }