/******************************************************************************* * Copyright (c) 2010, 2011 SAP AG and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stefan Dimov (SAP AG) - initial API and implementation * Kaloyan Raev (SAP AG) *******************************************************************************/ package org.eclipse.libra.facet.test; import static org.eclipse.libra.facet.OSGiBundleFacetUtils.VIRTUAL_COMPONENT_PATH; import static org.eclipse.libra.facet.OSGiBundleFacetUtils.WEB_CONTEXT_PATH_HEADER; import static org.eclipse.libra.facet.OSGiBundleFacetUtils.getContextRootFromPDEModel; import static org.eclipse.libra.facet.OSGiBundleFacetUtils.getContextRootFromWTPModel; import static org.eclipse.libra.facet.OSGiBundleFacetUtils.setContextRootInPDEModel; import static org.eclipse.libra.facet.OSGiBundleFacetUtils.setContextRootInWTPModel; import static org.eclipse.wst.common.tests.OperationTestCase.deleteAllProjects; import static org.eclipse.wst.common.tests.OperationTestCase.waitOnJobs; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.wst.common.project.facet.core.FacetedProjectFramework; import org.eclipse.wst.common.project.facet.core.IFacetedProjectWorkingCopy; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class WebContextRootSynchronizerTest { private static final String APPEND = "Changed"; private static int MAX_ATTEMPTS = 20; private String expectedWebContextRoot; private IProject wabProject; @Before public void importProject() throws Exception { // clean up the workspace deleteAllProjects(); waitOnJobs(); // create new WAB project String projectName = "TestWAB" + System.currentTimeMillis(); expectedWebContextRoot = '/' + projectName + APPEND; wabProject = createWabProject(projectName); waitOnJobs(); } @After public void waitJobs() throws Exception { // Wait for all validation jobs to end before ending test.... waitOnJobs(); } @Test public void testPDEChangeLeadsToWTPChange() throws Exception { String newPDEWebContextPath = getContextRootFromPDEModel(wabProject) + APPEND; setContextRootInPDEModel(wabProject, newPDEWebContextPath, null); checkModels(wabProject, expectedWebContextRoot); } @Test public void testWTPChangeLeadsToPDEChange() throws Exception { String newWTPWebContextPath = getContextRootFromWTPModel(wabProject) + APPEND; setContextRootInWTPModel(wabProject, newWTPWebContextPath); checkModels(wabProject, expectedWebContextRoot); } @Test public void testSettingsFileChangeLeadsToModelChange() throws Exception { String newWTPWebContextPath = getContextRootFromWTPModel(wabProject) + APPEND; setWebContextRootInSettings(wabProject, newWTPWebContextPath); checkModels(wabProject, expectedWebContextRoot); } @Test public void testManifetsFileChangeLeadsToModelChange() throws Exception { String newPDEWebContextPath = getContextRootFromPDEModel(wabProject) + APPEND; setWebContextRootInManifest(wabProject, newPDEWebContextPath); checkModels(wabProject, expectedWebContextRoot); } @Test public void testRemoveWebContextRootFromPDEModel() throws Exception { setContextRootInPDEModel(wabProject, null, null); checkModels(wabProject, null); } @Test public void testRemoveWebContextRootFromWTPModel() throws Exception { setContextRootInWTPModel(wabProject, null); checkModels(wabProject, null); } // ------------------------------ private helper methods ---------------------------------------------- private IProject createWabProject(String projectName) throws CoreException { IFacetedProjectWorkingCopy wc = FacetedProjectFramework.createNewProject(); wc.setProjectName(projectName); wc.setSelectedPreset("osgi.web.bundle.preset"); wc.commitChanges(null); return wc.getProject(); } private boolean areModelsEqualToTheExpectedValue(IProject project, String expectedWebContextRoot) throws CoreException { String pdeWebContextPath = getContextRootFromPDEModel(project); String wtpWebContextPath = getContextRootFromWTPModel(project); if (expectedWebContextRoot == null) { return pdeWebContextPath == null && wtpWebContextPath == null; } else { return expectedWebContextRoot.equals(pdeWebContextPath) && expectedWebContextRoot.equals(wtpWebContextPath); } } private void checkModels(IProject wabProject, String expectedWebContextRoot) throws CoreException { boolean equal = false; for (int attempt = 0; attempt < MAX_ATTEMPTS && !equal; attempt++) { equal = areModelsEqualToTheExpectedValue(wabProject, expectedWebContextRoot); if (!equal) { // we need to wait for the other model to refresh wabProject.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); try { Thread.sleep(1000);// 1 second } catch (InterruptedException iexc) { System.out.println("Interrupted exception caught. Checking once more."); wabProject.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); equal = areModelsEqualToTheExpectedValue(wabProject, expectedWebContextRoot); } } } // check that both models are set to the new context root Assert.assertEquals(expectedWebContextRoot, getContextRootFromPDEModel(wabProject)); Assert.assertEquals(expectedWebContextRoot, getContextRootFromWTPModel(wabProject)); } private void setWebContextRootInSettings(IProject wabProject, String newValue) throws ParserConfigurationException, SAXException, IOException, TransformerException, CoreException { IFile settingsFile = wabProject.getFile(VIRTUAL_COMPONENT_PATH); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document xmlDocument = db.parse(settingsFile.getContents()); changeWebContextRootFromSettings(xmlDocument, newValue); InputStream is = new ByteArrayInputStream(saveDomToBytes(xmlDocument)); settingsFile.setContents(is, IResource.KEEP_HISTORY | IResource.FORCE, null); } private Element getWebModuleElement(Document xmlDocument) { Element root = xmlDocument.getDocumentElement(); NodeList children = root.getElementsByTagName("wb-module"); Element webModuleElem = (Element)children.item(0); return webModuleElem; } private Element getContextRootProperty(Element webModuleElement) { NodeList webModuleElementProperties = webModuleElement.getElementsByTagName("property"); for (int i = 0; i < webModuleElementProperties.getLength(); i++) { Element property = (Element) webModuleElementProperties.item(i); NamedNodeMap attributes = property.getAttributes(); Attr nameAttribute = (Attr) attributes.getNamedItem("name"); if (nameAttribute.getNodeValue().equals("context-root")) { return property; } } return null; } private Attr getValueAttribute(Element contextRootProperty) { NamedNodeMap attributes = contextRootProperty.getAttributes(); Attr valueAttribute = (Attr) attributes.getNamedItem("value"); if (valueAttribute != null) { return valueAttribute; } return null; } private void changeWebContextRootFromSettings(Document xmlDocument, String newValue) { Element webModuleElement = getWebModuleElement(xmlDocument); Element contextRootProperty = getContextRootProperty(webModuleElement); Attr valueAttribute = getValueAttribute(contextRootProperty); valueAttribute.setNodeValue(newValue); } private byte[] saveDomToBytes(Document xmlDocument) throws TransformerException { ByteArrayOutputStream os = new ByteArrayOutputStream(); TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); transformer.transform(new DOMSource(xmlDocument), new StreamResult(os)); return os.toByteArray(); } private void setWebContextRootInManifest(IProject wabProject, String newContextRoot) throws CoreException, IOException { IFile manifestFile = wabProject.getFile(new Path("WebContent/META-INF/MANIFEST.MF")); ByteArrayOutputStream os = new ByteArrayOutputStream(); PrintWriter pw = new PrintWriter(os); BufferedReader reader = new BufferedReader(new InputStreamReader(manifestFile.getContents())); String line; while ((line = reader.readLine()) != null) { if (line.startsWith(WEB_CONTEXT_PATH_HEADER)) { pw.println(WEB_CONTEXT_PATH_HEADER + ": " + newContextRoot); } else { pw.println(line); } } pw.flush(); InputStream is = new ByteArrayInputStream(os.toByteArray()); manifestFile.setContents(is, IResource.KEEP_HISTORY | IResource.FORCE, null); } }