Java tutorial
/* * 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.karaf.itests; import java.io.File; import java.io.IOException; import java.net.ServerSocket; import java.util.Arrays; import java.util.Dictionary; import java.util.LinkedList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import javax.inject.Inject; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.FileUtils; import org.eclipse.jetty.server.NetworkConnector; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.Configuration; import org.ops4j.pax.exam.Option; import org.ops4j.pax.exam.ProbeBuilder; import org.ops4j.pax.exam.TestProbeBuilder; import org.ops4j.pax.exam.junit.PaxExam; import org.ops4j.pax.exam.karaf.options.LogLevelOption; import org.ops4j.pax.exam.options.MavenArtifactUrlReference; import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; import org.ops4j.pax.exam.spi.reactors.PerClass; import org.ops4j.pax.url.mvn.MavenResolver; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.ServiceEvent; import org.osgi.framework.ServiceListener; import org.osgi.service.cm.ConfigurationAdmin; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.apache.karaf.itests.KarafTestSupport.*; import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.*; import static org.ops4j.pax.exam.CoreOptions.*; import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.*; import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut; import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.logLevel; @RunWith(PaxExam.class) @ExamReactorStrategy(PerClass.class) public class MavenTest /*extends KarafTestSupport*/ { public static Logger LOG = LoggerFactory.getLogger(MavenTest.class); private static Server server; private static int port; private static ExecutorService pool = Executors.newFixedThreadPool(1); private static AtomicBoolean requestAtPort3333Done = new AtomicBoolean(false); @Inject protected BundleContext bundleContext; // don't extend, because we don't want @Rule Retry private static KarafTestSupport karafTestSupport = new KarafTestSupport(); /** * This server will act as HTTP proxy. @Test methods will change maven settings, where proxy is configured * and update <code>org.ops4j.pax.ul.mvn</code> PID, which will republish {@link MavenResolver} service. * @throws Exception */ @BeforeClass public static void startJetty() throws Exception { server = new Server(0); server.setHandler(new AbstractHandler() { @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { try { int port = baseRequest.getServerPort(); if (port == 3333 && request.getRequestURI().endsWith(".jar")) { if (!requestAtPort3333Done.get()) { requestAtPort3333Done.set(true); // explicit timeout at first attempt - higher than the one set by Aether Thread.sleep(4000); } response.setStatus(HttpServletResponse.SC_OK); response.getOutputStream().write(0x42); } else { response.setStatus(HttpServletResponse.SC_NOT_FOUND); } } catch (Exception ignored) { } finally { baseRequest.setHandled(true); } } }); server.start(); port = ((NetworkConnector) server.getConnectors()[0]).getLocalPort(); } @AfterClass public static void stopJetty() throws Exception { server.stop(); pool.shutdown(); } @ProbeBuilder public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) { probe.setHeader(Constants.DYNAMICIMPORT_PACKAGE, "*,org.apache.felix.service.*;status=provisional"); return probe; } private int getAvailablePort(int min, int max) { for (int i = min; i <= max; i++) { try { ServerSocket socket = new ServerSocket(i); return socket.getLocalPort(); } catch (Exception ignored) { } } throw new IllegalStateException("Can't find available network ports"); } @Configuration public Option[] config() { MavenArtifactUrlReference karafUrl = maven().groupId("org.apache.karaf").artifactId("apache-karaf") .versionAsInProject().type("tar.gz"); String httpPort = Integer .toString(getAvailablePort(Integer.parseInt(MIN_HTTP_PORT), Integer.parseInt(MAX_HTTP_PORT))); String rmiRegistryPort = Integer .toString(getAvailablePort(Integer.parseInt(MIN_RMI_REG_PORT), Integer.parseInt(MAX_RMI_REG_PORT))); String rmiServerPort = Integer.toString( getAvailablePort(Integer.parseInt(MIN_RMI_SERVER_PORT), Integer.parseInt(MAX_RMI_SERVER_PORT))); String sshPort = Integer .toString(getAvailablePort(Integer.parseInt(MIN_SSH_PORT), Integer.parseInt(MAX_SSH_PORT))); Option[] baseOptions = new Option[] { karafDistributionConfiguration().frameworkUrl(karafUrl).name("Apache Karaf") .unpackDirectory(new File("target/exam")), // enable JMX RBAC security, thanks to the KarafMBeanServerBuilder configureSecurity().disableKarafMBeanServerBuilder(), keepRuntimeFolder(), logLevel(LogLevelOption.LogLevel.INFO), replaceConfigurationFile("etc/org.ops4j.pax.logging.cfg", new File("src/test/resources/etc/org.ops4j.pax.logging.cfg")), editConfigurationFilePut("etc/org.apache.karaf.features.cfg", "updateSnapshots", "none"), editConfigurationFilePut("etc/org.ops4j.pax.web.cfg", "org.osgi.service.http.port", httpPort), editConfigurationFilePut("etc/org.apache.karaf.management.cfg", "rmiRegistryPort", rmiRegistryPort), editConfigurationFilePut("etc/org.apache.karaf.management.cfg", "rmiServerPort", rmiServerPort), editConfigurationFilePut("etc/org.apache.karaf.shell.cfg", "sshPort", sshPort), }; List<Option> options = new LinkedList<>(Arrays.asList(baseOptions)); // Prepare default pax-url-aether configuration options.addAll(Arrays.asList( // new TimeoutOption(3600000), // KarafDistributionOption.debugConfiguration("8889", false), bundle("mvn:commons-io/commons-io/2.5"), mavenBundle(maven().groupId("javax.servlet").artifactId("javax.servlet-api").versionAsInProject()) .noStart(), mavenBundle(maven().groupId("org.eclipse.jetty").artifactId("jetty-server").versionAsInProject()) .noStart(), mavenBundle(maven().groupId("org.eclipse.jetty").artifactId("jetty-http").versionAsInProject()) .noStart(), mavenBundle(maven().groupId("org.eclipse.jetty").artifactId("jetty-util").versionAsInProject()) .noStart(), mavenBundle(maven().groupId("org.eclipse.jetty").artifactId("jetty-io").versionAsInProject()) .noStart(), replaceConfigurationFile("etc/maven-settings.xml", new File("src/test/resources/etc/maven-settings.xml")), replaceConfigurationFile("etc/org.ops4j.pax.url.mvn.cfg", new File("src/test/resources/etc/org.ops4j.pax.url.mvn.cfg")))); return options.toArray(new Option[options.size()]); } @Test public void smartRetriesTest() throws Exception { karafTestSupport.bundleContext = bundleContext; final ConfigurationAdmin cm = karafTestSupport.getOsgiService(ConfigurationAdmin.class, 3000); updateSettings(); awaitMavenResolver(new Runnable() { @Override public void run() { try { org.osgi.service.cm.Configuration config = cm.getConfiguration("org.ops4j.pax.url.mvn", null); Dictionary<String, Object> props = config.getProperties(); props.put("org.ops4j.pax.url.mvn.globalChecksumPolicy", "ignore"); props.put("org.ops4j.pax.url.mvn.socket.readTimeout", "2000"); props.put("org.ops4j.pax.url.mvn.connection.retryCount", "0"); props.put("org.ops4j.pax.url.mvn.repositories", "http://localhost:1111/repository@id=r1," + "http://localhost:2222/repository@id=r2," + "http://localhost:3333/repository@id=r3"); config.update(props); } catch (Exception e) { fail(e.getMessage()); } } }); // grab modified resolver MavenResolver resolver = karafTestSupport.getOsgiService(MavenResolver.class, 15000); try { resolver.resolve("mvn:commons-universalis/commons-universalis/42"); fail("Should fail at first attempt"); } catch (IOException e) { File f = resolver.resolve("mvn:commons-universalis/commons-universalis/42", e); byte[] commonsUniversalis = FileUtils.readFileToByteArray(f); assertThat(commonsUniversalis.length, equalTo(1)); assertThat(commonsUniversalis[0], equalTo((byte) 0x42)); } } private void updateSettings() throws IOException { File settingsFile = new File(System.getProperty("karaf.home"), "etc/maven-settings.xml"); String settings = FileUtils.readFileToString(settingsFile); settings = settings.replace("@@port@@", Integer.toString(port)); FileUtils.write(settingsFile, settings); } /** * Invoke config admin task and await reregistration of {@link MavenResolver} service */ private void awaitMavenResolver(Runnable task) throws Exception { CountDownLatch latch = new CountDownLatch(2); ServiceListener listener = new ServiceListener() { @Override public void serviceChanged(ServiceEvent event) { if (event.getType() == ServiceEvent.UNREGISTERING || event.getType() == ServiceEvent.REGISTERED) { latch.countDown(); } } }; bundleContext.addServiceListener(listener, "(objectClass=org.ops4j.pax.url.mvn.MavenResolver)"); try { task.run(); assertTrue(latch.await(5, TimeUnit.SECONDS)); } finally { bundleContext.removeServiceListener(listener); } } }