| // |
| // ======================================================================== |
| // Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. |
| // ------------------------------------------------------------------------ |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // The Apache License v2.0 is available at |
| // http://www.opensource.org/licenses/apache2.0.php |
| // |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.overlays; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.OutputStream; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.util.Set; |
| import java.util.concurrent.BlockingQueue; |
| import java.util.concurrent.ConcurrentLinkedQueue; |
| import java.util.concurrent.LinkedBlockingQueue; |
| import java.util.concurrent.TimeUnit; |
| |
| import org.eclipse.jetty.util.IO; |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| |
| |
| public class OverlayedAppProviderTest |
| { |
| File _tmp; |
| File _scan; |
| File _webapps; |
| File _templates; |
| File _nodes; |
| File _instances; |
| |
| @Before |
| public void before() throws Exception |
| { |
| _tmp=File.createTempFile("OAPTest",null); |
| if (_tmp.exists()) |
| IO.delete(_tmp); |
| _tmp.mkdir(); |
| |
| _scan = new File(_tmp,"scan").getCanonicalFile(); |
| _webapps = new File(_scan,OverlayedAppProvider.WEBAPPS); |
| _templates = new File(_scan,OverlayedAppProvider.TEMPLATES); |
| _nodes = new File(_scan,OverlayedAppProvider.NODES); |
| _instances = new File(_scan,OverlayedAppProvider.INSTANCES); |
| _webapps.mkdirs(); |
| _templates.mkdir(); |
| _nodes.mkdir(); |
| _instances.mkdir(); |
| } |
| |
| @After |
| public void after() throws Exception |
| { |
| if (_tmp.exists()) |
| IO.delete(_tmp); |
| } |
| |
| @Test |
| public void testScanForWars() throws Exception |
| { |
| final ConcurrentLinkedQueue<Set<String>> scanned = new ConcurrentLinkedQueue<Set<String>>(); |
| OverlayedAppProvider provider = new OverlayedAppProvider() |
| { |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.overlays.OverlayedAppProvider#updateLayers(java.util.Set) |
| */ |
| @Override |
| protected void updateLayers(Set<String> filenames) |
| { |
| scanned.offer(filenames); |
| } |
| }; |
| provider.setScanInterval(0); |
| |
| |
| provider.setScanDir(_scan); |
| provider.start(); |
| provider.scan(); |
| provider.scan(); |
| |
| assertTrue(scanned.isEmpty()); |
| |
| |
| // Check scanning for archives |
| File war = new File(_webapps,"foo-1.2.3.war"); |
| touch(war); |
| File template = new File(_templates,"foo=foo-1.2.3.war"); |
| touch(template); |
| File node = new File(_nodes,"nodeA.war"); |
| touch(node); |
| File instance = new File(_instances,"foo=instance.war"); |
| touch(instance); |
| |
| provider.scan(); |
| provider.scan(); |
| |
| Set<String> results = scanned.poll(); |
| assertTrue(results!=null); |
| assertEquals(4,results.size()); |
| assertTrue(results.contains("webapps/foo-1.2.3.war")); |
| assertTrue(results.contains("templates/foo=foo-1.2.3.war")); |
| assertTrue(results.contains("nodes/nodeA.war")); |
| assertTrue(results.contains("instances/foo=instance.war")); |
| |
| provider.scan(); |
| provider.scan(); |
| assertTrue(scanned.isEmpty()); |
| |
| IO.delete(war); |
| IO.delete(template); |
| IO.delete(node); |
| IO.delete(instance); |
| |
| provider.scan(); |
| provider.scan(); |
| results = scanned.poll(); |
| assertTrue(results!=null); |
| assertEquals(4,results.size()); |
| assertTrue(results.contains("webapps/foo-1.2.3.war")); |
| assertTrue(results.contains("templates/foo=foo-1.2.3.war")); |
| assertTrue(results.contains("nodes/nodeA.war")); |
| assertTrue(results.contains("instances/foo=instance.war")); |
| |
| } |
| |
| @Test |
| public void testScanForDirs() throws Exception |
| { |
| final ConcurrentLinkedQueue<Set<String>> scanned = new ConcurrentLinkedQueue<Set<String>>(); |
| OverlayedAppProvider provider = new OverlayedAppProvider() |
| { |
| /* ------------------------------------------------------------ */ |
| /** |
| * @see org.eclipse.jetty.overlays.OverlayedAppProvider#updateLayers(java.util.Set) |
| */ |
| @Override |
| protected void updateLayers(Set<String> filenames) |
| { |
| scanned.offer(filenames); |
| } |
| }; |
| provider.setScanInterval(0); |
| |
| |
| provider.setScanDir(_scan); |
| provider.start(); |
| provider.scan(); |
| |
| assertTrue(scanned.isEmpty()); |
| |
| |
| // Check scanning for directories |
| File war = new File(_webapps,"foo-1.2.3"); |
| war.mkdir(); |
| File template = new File(_templates,"foo=foo-1.2.3"); |
| template.mkdir(); |
| File node = new File(_nodes,"nodeA"); |
| node.mkdir(); |
| File instance = new File(_instances,"foo=instance"); |
| instance.mkdir(); |
| for (File f : new File[] { war,template,node,instance } ) |
| { |
| File webinf = new File(f,"WEB-INF"); |
| webinf.mkdir(); |
| touch(webinf,"web.xml"); |
| } |
| |
| provider.scan(); |
| provider.scan(); |
| |
| Set<String> results = scanned.poll(); |
| assertTrue(results!=null); |
| assertEquals(4,results.size()); |
| assertTrue(results.contains("webapps/foo-1.2.3")); |
| assertTrue(results.contains("templates/foo=foo-1.2.3")); |
| assertTrue(results.contains("nodes/nodeA")); |
| assertTrue(results.contains("instances/foo=instance")); |
| |
| provider.scan(); |
| provider.scan(); |
| assertTrue(scanned.isEmpty()); |
| |
| |
| // Touch everything |
| touch(war,"WEB-INF/web.xml"); |
| touch(war,"WEB-INF/spring.XML"); |
| touch(war,"WEB-INF/other"); |
| touch(war,"WEB-INF/lib/bar.jar"); |
| touch(war,"WEB-INF/classes/bar.class"); |
| |
| for (File d : new File[]{template,node,instance}) |
| { |
| touch(d,"WEB-INF/web-fragment.xml"); |
| touch(d,"WEB-INF/overlay.xml"); |
| touch(d,"WEB-INF/other"); |
| touch(d,"WEB-INF/lib/bar.jar"); |
| } |
| |
| provider.scan(); |
| provider.scan(); |
| results = scanned.poll(); |
| assertTrue(results!=null); |
| assertEquals(4,results.size()); |
| assertTrue(results.contains("webapps/foo-1.2.3")); |
| assertTrue(results.contains("templates/foo=foo-1.2.3")); |
| assertTrue(results.contains("nodes/nodeA")); |
| assertTrue(results.contains("instances/foo=instance")); |
| |
| |
| // Touch xml |
| Thread.sleep(1000); // needed so last modified is different |
| for (File d : new File[]{war,template,node,instance}) |
| touch(d,"WEB-INF/web.xml"); |
| provider.scan(); |
| provider.scan(); |
| results = scanned.poll(); |
| assertTrue(results!=null); |
| assertEquals(4,results.size()); |
| assertTrue(results.contains("webapps/foo-1.2.3")); |
| assertTrue(results.contains("templates/foo=foo-1.2.3")); |
| assertTrue(results.contains("nodes/nodeA")); |
| assertTrue(results.contains("instances/foo=instance")); |
| |
| // Touch XML |
| Thread.sleep(1000); |
| for (File d : new File[]{war,template,node,instance}) |
| touch(d,"WEB-INF/spring.XML"); |
| provider.scan(); |
| provider.scan(); |
| results = scanned.poll(); |
| assertTrue(results!=null); |
| assertEquals(4,results.size()); |
| assertTrue(results.contains("webapps/foo-1.2.3")); |
| assertTrue(results.contains("templates/foo=foo-1.2.3")); |
| assertTrue(results.contains("nodes/nodeA")); |
| assertTrue(results.contains("instances/foo=instance")); |
| |
| |
| // Touch unrelated |
| for (File d : new File[]{war,template,node,instance}) |
| touch(d,"index.html"); |
| provider.scan(); |
| provider.scan(); |
| results = scanned.poll(); |
| assertEquals(null,results); |
| |
| // Touch jar |
| Thread.sleep(1000); |
| for (File d : new File[]{war,template,node,instance}) |
| touch(d,"WEB-INF/lib/bar.jar"); |
| provider.scan(); |
| provider.scan(); |
| results = scanned.poll(); |
| assertTrue(results!=null); |
| assertEquals(4,results.size()); |
| assertTrue(results.contains("webapps/foo-1.2.3")); |
| assertTrue(results.contains("templates/foo=foo-1.2.3")); |
| assertTrue(results.contains("nodes/nodeA")); |
| assertTrue(results.contains("instances/foo=instance")); |
| |
| // touch other class |
| Thread.sleep(1000); |
| for (File d : new File[]{war,template,node,instance}) |
| touch(d,"index.html"); |
| provider.scan(); |
| provider.scan(); |
| results = scanned.poll(); |
| assertTrue(scanned.isEmpty()); |
| |
| |
| // delete all |
| IO.delete(war); |
| IO.delete(template); |
| IO.delete(node); |
| IO.delete(instance); |
| |
| provider.scan(); |
| provider.scan(); |
| results = scanned.poll(); |
| assertTrue(results!=null); |
| assertEquals(4,results.size()); |
| assertTrue(results.contains("webapps/foo-1.2.3")); |
| assertTrue(results.contains("templates/foo=foo-1.2.3")); |
| assertTrue(results.contains("nodes/nodeA")); |
| assertTrue(results.contains("instances/foo=instance")); |
| |
| } |
| |
| |
| @Test |
| public void testTriageURI() throws Exception |
| { |
| final BlockingQueue<String> scanned = new LinkedBlockingQueue<String>(); |
| OverlayedAppProvider provider = new OverlayedAppProvider() |
| { |
| protected void removeInstance(String name) |
| { |
| scanned.add("removeInstance "+name); |
| } |
| protected Instance loadInstance(String name, File origin) |
| { |
| scanned.add("loadInstance "+name); |
| scanned.add(origin.getAbsolutePath()); |
| return null; |
| } |
| protected void removeNode() |
| { |
| scanned.add("removeNode"); |
| } |
| protected Node loadNode(File origin) |
| { |
| scanned.add("loadNode"); |
| scanned.add(origin.getAbsolutePath()); |
| return null; |
| } |
| protected void removeTemplate(String name) |
| { |
| scanned.add("removeTemplate "+name); |
| } |
| protected Template loadTemplate(String name, File origin) |
| { |
| scanned.add("loadTemplate "+name); |
| scanned.add(origin.getAbsolutePath()); |
| return null; |
| } |
| protected void removeWebapp(String name) |
| { |
| scanned.add("removeWebapp "+name); |
| } |
| protected Webapp loadWebapp(String name, File origin) |
| { |
| scanned.add("loadWebapp "+name); |
| scanned.add(origin.getAbsolutePath()); |
| return null; |
| } |
| |
| protected void redeploy() |
| { |
| } |
| |
| }; |
| provider.setScanInterval(0); |
| provider.setNodeName("nodeA"); |
| |
| |
| provider.setScanDir(_scan); |
| provider.start(); |
| provider.scan(); |
| |
| assertTrue(scanned.isEmpty()); |
| |
| // Add a war |
| File war = new File(_webapps,"foo-1.2.3.war"); |
| touch(war); |
| provider.scan(); |
| provider.scan(); |
| assertEquals("loadWebapp foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS)); |
| assertEquals(war.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS)); |
| |
| |
| // Add a template |
| File template = new File(_templates,"foo=foo-1.2.3.war"); |
| touch(template); |
| provider.scan(); |
| provider.scan(); |
| assertEquals("loadTemplate foo=foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS)); |
| assertEquals(template.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS)); |
| |
| // Add a node |
| File nodeA = new File(_nodes,"nodeA.war"); |
| touch(nodeA); |
| provider.scan(); |
| provider.scan(); |
| assertEquals("loadNode",scanned.poll(1,TimeUnit.SECONDS)); |
| assertEquals(nodeA.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS)); |
| |
| // Add another node |
| File nodeB = new File(_nodes,"nodeB.war"); |
| provider.scan(); |
| provider.scan(); |
| assertTrue(scanned.isEmpty()); |
| |
| // Add an instance |
| File instance = new File(_instances,"foo=instance.war"); |
| touch(instance); |
| provider.scan(); |
| provider.scan(); |
| assertEquals("loadInstance foo=instance",scanned.poll(1,TimeUnit.SECONDS)); |
| assertEquals(instance.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS)); |
| |
| |
| // Add a war dir |
| File warDir = new File(_webapps,"foo-1.2.3"); |
| warDir.mkdir(); |
| File warDirWI = new File(warDir,"WEB-INF"); |
| warDirWI.mkdir(); |
| touch(warDirWI,"web.xml"); |
| provider.scan(); |
| provider.scan(); |
| assertEquals("loadWebapp foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS)); |
| assertEquals(warDir.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS)); |
| |
| // Add a template dir |
| File templateDir = new File(_templates,"foo=foo-1.2.3"); |
| templateDir.mkdir(); |
| File templateDirWI = new File(templateDir,"WEB-INF"); |
| templateDirWI.mkdir(); |
| touch(templateDirWI,"web.xml"); |
| provider.scan(); |
| provider.scan(); |
| assertEquals("loadTemplate foo=foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS)); |
| assertEquals(templateDir.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS)); |
| |
| // Add a node dir |
| File nodeADir = new File(_nodes,"nodeA"); |
| nodeADir.mkdir(); |
| File nodeADirWI = new File(nodeADir,"WEB-INF"); |
| nodeADirWI.mkdir(); |
| touch(nodeADirWI,"web.xml"); |
| provider.scan(); |
| provider.scan(); |
| assertEquals("loadNode",scanned.poll(1,TimeUnit.SECONDS)); |
| assertEquals(nodeADir.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS)); |
| |
| // Add another node dir |
| File nodeBDir = new File(_nodes,"nodeB"); |
| nodeBDir.mkdir(); |
| File nodeBDirWI = new File(nodeBDir,"WEB-INF"); |
| nodeBDirWI.mkdir(); |
| touch(nodeBDirWI,"web.xml"); |
| provider.scan(); |
| provider.scan(); |
| assertTrue(scanned.isEmpty()); |
| |
| // Add an instance dir |
| File instanceDir = new File(_instances,"foo=instance"); |
| instanceDir.mkdir(); |
| File instanceDirWI = new File(instanceDir,"WEB-INF"); |
| instanceDirWI.mkdir(); |
| touch(instanceDirWI,"web.xml"); |
| provider.scan(); |
| provider.scan(); |
| assertEquals("loadInstance foo=instance",scanned.poll(1,TimeUnit.SECONDS)); |
| assertEquals(instanceDir.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS)); |
| |
| |
| // touch archives will be ignored. |
| Thread.sleep(1000); |
| touch(war); |
| touch(template); |
| touch(nodeA); |
| touch(nodeB); |
| touch(instance); |
| provider.scan(); |
| provider.scan(); |
| assertTrue(scanned.isEmpty()); |
| |
| // Touch directories |
| for (File d : new File[]{warDir,templateDir,nodeADir,nodeBDir,instanceDir}) |
| touch(d,"WEB-INF/web.xml"); |
| provider.scan(); |
| provider.scan(); |
| assertEquals(8,scanned.size()); |
| scanned.clear(); |
| |
| // Remove web dir |
| IO.delete(warDir); |
| provider.scan(); |
| provider.scan(); |
| assertEquals("removeWebapp foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS)); |
| assertEquals("loadWebapp foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS)); |
| assertEquals(war.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS)); |
| |
| // Remove template dir |
| IO.delete(templateDir); |
| provider.scan(); |
| provider.scan(); |
| assertEquals("removeTemplate foo=foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS)); |
| assertEquals("loadTemplate foo=foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS)); |
| assertEquals(template.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS)); |
| |
| // Remove nodeA dir |
| IO.delete(nodeADir); |
| provider.scan(); |
| provider.scan(); |
| assertEquals("removeNode",scanned.poll(1,TimeUnit.SECONDS)); |
| assertEquals("loadNode",scanned.poll(1,TimeUnit.SECONDS)); |
| assertEquals(nodeA.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS)); |
| |
| // Remove nodeB dir |
| IO.delete(nodeBDir); |
| provider.scan(); |
| provider.scan(); |
| assertTrue(scanned.isEmpty()); |
| |
| |
| // Remove instance dir |
| IO.delete(instanceDir); |
| provider.scan(); |
| provider.scan(); |
| assertEquals("removeInstance foo=instance",scanned.poll(1,TimeUnit.SECONDS)); |
| assertEquals("loadInstance foo=instance",scanned.poll(1,TimeUnit.SECONDS)); |
| assertEquals(instance.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS)); |
| |
| // Remove web |
| IO.delete(war); |
| provider.scan(); |
| provider.scan(); |
| assertEquals("removeWebapp foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS)); |
| |
| // Remove template |
| IO.delete(template); |
| provider.scan(); |
| provider.scan(); |
| assertEquals("removeTemplate foo=foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS)); |
| |
| // Remove nodeA dir |
| IO.delete(nodeA); |
| provider.scan(); |
| provider.scan(); |
| assertEquals("removeNode",scanned.poll(1,TimeUnit.SECONDS)); |
| |
| // Remove nodeB dir |
| IO.delete(nodeB); |
| provider.scan(); |
| provider.scan(); |
| assertTrue(scanned.isEmpty()); |
| |
| // Remove instance dir |
| IO.delete(instance); |
| provider.scan(); |
| provider.scan(); |
| assertEquals("removeInstance foo=instance",scanned.poll(1,TimeUnit.SECONDS)); |
| |
| provider.scan(); |
| provider.scan(); |
| assertTrue(scanned.isEmpty()); |
| |
| } |
| |
| |
| private void touch(File base,String path) |
| { |
| try |
| { |
| File target = new File(new URI(base.toURI().toString()+path)); |
| target.getParentFile().mkdirs(); |
| touch(target); |
| } |
| catch (URISyntaxException e) |
| { |
| e.printStackTrace(); |
| } |
| } |
| |
| |
| private void touch(File file) |
| { |
| try |
| { |
| IO.delete(file); |
| try (OutputStream out = new FileOutputStream(file,false)) |
| { |
| out.write("<h1>Hello</h1>".getBytes()); |
| } |
| } |
| catch(Exception e) |
| { |
| e.printStackTrace(); |
| } |
| } |
| } |