From 1c2c16858e95db9ae90726fa0da69b88457c1807 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Wed, 5 Dec 2012 13:09:49 +0100 Subject: o More common XML parsing and HTTP client code. o Reimplemented the Nexus code to consume the timeline instead of calculating its own diff. --- pom.xml | 2 +- .../esper/testing/EasySSLSocketFactory.java | 104 ----------- .../esper/testing/EasyX509TrustManager.java | 76 -------- src/main/java/io/trygvis/esper/testing/Http.java | 26 --- .../java/io/trygvis/esper/testing/HttpClient.java | 87 --------- .../gitorious/GitoriousProjectDiscovery.java | 7 +- .../esper/testing/jenkins/JenkinsClient.java | 87 +++------ .../esper/testing/jenkins/JenkinsImporter.java | 6 +- .../trygvis/esper/testing/jenkins/JenkinsJob.java | 3 +- .../trygvis/esper/testing/nexus/ArtifactDto.java | 30 +-- .../trygvis/esper/testing/nexus/NexusClient.java | 23 ++- .../io/trygvis/esper/testing/nexus/NexusDao.java | 208 ++++++++++++--------- .../esper/testing/nexus/NexusFeedParser.java | 132 +++++++++++++ .../trygvis/esper/testing/nexus/NexusImporter.java | 198 +++++++++++++------- .../trygvis/esper/testing/object/ObjectUtil.java | 28 ++- .../esper/testing/util/EasySSLSocketFactory.java | 104 +++++++++++ .../esper/testing/util/EasyX509TrustManager.java | 76 ++++++++ .../io/trygvis/esper/testing/util/HttpClient.java | 123 ++++++++++++ .../trygvis/esper/testing/util/XmlHttpClient.java | 27 +++ .../io/trygvis/esper/testing/util/XmlParser.java | 66 +++++++ src/main/resources/ddl-jenkins.sql | 9 + src/main/resources/ddl-nexus.sql | 77 ++++---- .../esper/testing/nexus/TestXmlParsing.java | 19 ++ .../resources/nexus/recentlyDeployedArtifacts.xml | 24 +++ src/test/resources/nexus/search-1.xml | 1 - 25 files changed, 952 insertions(+), 591 deletions(-) delete mode 100755 src/main/java/io/trygvis/esper/testing/EasySSLSocketFactory.java delete mode 100755 src/main/java/io/trygvis/esper/testing/EasyX509TrustManager.java delete mode 100755 src/main/java/io/trygvis/esper/testing/Http.java delete mode 100755 src/main/java/io/trygvis/esper/testing/HttpClient.java mode change 100644 => 100755 src/main/java/io/trygvis/esper/testing/jenkins/JenkinsClient.java mode change 100644 => 100755 src/main/java/io/trygvis/esper/testing/jenkins/JenkinsJob.java mode change 100644 => 100755 src/main/java/io/trygvis/esper/testing/nexus/ArtifactDto.java create mode 100755 src/main/java/io/trygvis/esper/testing/nexus/NexusFeedParser.java create mode 100755 src/main/java/io/trygvis/esper/testing/util/EasySSLSocketFactory.java create mode 100755 src/main/java/io/trygvis/esper/testing/util/EasyX509TrustManager.java create mode 100755 src/main/java/io/trygvis/esper/testing/util/HttpClient.java create mode 100755 src/main/java/io/trygvis/esper/testing/util/XmlHttpClient.java create mode 100755 src/main/java/io/trygvis/esper/testing/util/XmlParser.java create mode 100755 src/main/resources/ddl-jenkins.sql create mode 100755 src/test/resources/nexus/recentlyDeployedArtifacts.xml diff --git a/pom.xml b/pom.xml index 89934ee..73ab2b8 100755 --- a/pom.xml +++ b/pom.xml @@ -38,7 +38,7 @@ org.jdom jdom - 2.0.2 + 2.0.4 com.jolbox diff --git a/src/main/java/io/trygvis/esper/testing/EasySSLSocketFactory.java b/src/main/java/io/trygvis/esper/testing/EasySSLSocketFactory.java deleted file mode 100755 index b8a2904..0000000 --- a/src/main/java/io/trygvis/esper/testing/EasySSLSocketFactory.java +++ /dev/null @@ -1,104 +0,0 @@ -package io.trygvis.esper.testing; - -/* - * ==================================================================== - * - * 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. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - -import java.io.*; -import java.net.*; -import javax.net.ssl.*; -import org.apache.http.conn.*; -import org.apache.http.conn.scheme.*; -import org.apache.http.params.*; - -public class EasySSLSocketFactory implements SocketFactory, LayeredSocketFactory { - - private SSLContext sslcontext = null; - - private static SSLContext createEasySSLContext() throws IOException { - try { - SSLContext context = SSLContext.getInstance("TLS"); - context.init(null, new TrustManager[]{new EasyX509TrustManager(null)}, null); - return context; - } catch (Exception e) { - throw new IOException(e.getMessage()); - } - } - - private SSLContext getSSLContext() throws IOException { - if (this.sslcontext == null) { - this.sslcontext = createEasySSLContext(); - } - return this.sslcontext; - } - - public Socket connectSocket(Socket sock, String host, int port, InetAddress localAddress, int localPort, - HttpParams params) throws IOException, ConnectTimeoutException { - int connTimeout = HttpConnectionParams.getConnectionTimeout(params); - int soTimeout = HttpConnectionParams.getSoTimeout(params); - InetSocketAddress remoteAddress = new InetSocketAddress(host, port); - SSLSocket sslSocket = (SSLSocket) ((sock != null) ? sock : createSocket()); - - if ((localAddress != null) || (localPort > 0)) { - // we need to bind explicitly - if (localPort < 0) { - localPort = 0; // indicates "any" - } - InetSocketAddress isa = new InetSocketAddress(localAddress, localPort); - sslSocket.bind(isa); - } - - sslSocket.connect(remoteAddress, connTimeout); - sslSocket.setSoTimeout(soTimeout); - - return sslSocket; - } - - public Socket createSocket() throws IOException { - return getSSLContext().getSocketFactory().createSocket(); - } - - public boolean isSecure(Socket socket) throws IllegalArgumentException { - return true; - } - - public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException { - return getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose); - } - - // ------------------------------------------------------------------- - // javadoc in org.apache.http.conn.scheme.SocketFactory says : - // Both Object.equals() and Object.hashCode() must be overridden - // for the correct operation of some connection managers - // ------------------------------------------------------------------- - - public boolean equals(Object obj) { - return ((obj != null) && obj.getClass().equals(EasySSLSocketFactory.class)); - } - - public int hashCode() { - return EasySSLSocketFactory.class.hashCode(); - } -} diff --git a/src/main/java/io/trygvis/esper/testing/EasyX509TrustManager.java b/src/main/java/io/trygvis/esper/testing/EasyX509TrustManager.java deleted file mode 100755 index 1762c6f..0000000 --- a/src/main/java/io/trygvis/esper/testing/EasyX509TrustManager.java +++ /dev/null @@ -1,76 +0,0 @@ -package io.trygvis.esper.testing; - -/* - * ==================================================================== - * - * 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. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; - - -public class EasyX509TrustManager implements X509TrustManager -{ - private X509TrustManager standardTrustManager = null; - - public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException { - super(); - TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - factory.init(keystore); - TrustManager[] trustmanagers = factory.getTrustManagers(); - if (trustmanagers.length == 0) { - throw new NoSuchAlgorithmException("no trust manager found"); - } - this.standardTrustManager = (X509TrustManager)trustmanagers[0]; - } - - public void checkClientTrusted(X509Certificate[] certificates,String authType) throws CertificateException { - standardTrustManager.checkClientTrusted(certificates,authType); - } - - public void checkServerTrusted(X509Certificate[] certificates,String authType) throws CertificateException { -// if (certificates != null) { -// System.out.println("Server certificate chain:"); -// for (int i = 0; i < certificates.length; i++) { -// System.out.println("X509Certificate[" + i + "]=" + certificates[i]); -// } -// } - - if ((certificates != null) && (certificates.length == 1)) { - certificates[0].checkValidity(); - } else { - standardTrustManager.checkServerTrusted(certificates,authType); - } - } - - public X509Certificate[] getAcceptedIssuers() { - return this.standardTrustManager.getAcceptedIssuers(); - } -} diff --git a/src/main/java/io/trygvis/esper/testing/Http.java b/src/main/java/io/trygvis/esper/testing/Http.java deleted file mode 100755 index 38a66a4..0000000 --- a/src/main/java/io/trygvis/esper/testing/Http.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.trygvis.esper.testing; - -import org.apache.http.conn.scheme.*; -import org.apache.http.conn.ssl.*; -import org.apache.http.impl.client.*; -import org.apache.http.impl.conn.tsccm.*; -import org.apache.http.params.*; -import org.codehaus.httpcache4j.cache.*; -import org.codehaus.httpcache4j.resolver.*; - -public class Http { - - public static final HTTPCache http; - - static { - SchemeRegistry schemeRegistry = new SchemeRegistry(); - schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); - schemeRegistry.register(new Scheme("https", new EasySSLSocketFactory(), 443)); - - BasicHttpParams params = new BasicHttpParams(); - ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, schemeRegistry); - DefaultHttpClient httpClient = new DefaultHttpClient(cm, params); - HTTPClientResponseResolver resolver = new HTTPClientResponseResolver(httpClient); - http = new HTTPCache(new MemoryCacheStorage(), resolver); - } -} diff --git a/src/main/java/io/trygvis/esper/testing/HttpClient.java b/src/main/java/io/trygvis/esper/testing/HttpClient.java deleted file mode 100755 index ff2effd..0000000 --- a/src/main/java/io/trygvis/esper/testing/HttpClient.java +++ /dev/null @@ -1,87 +0,0 @@ -package io.trygvis.esper.testing; - -import static java.lang.System.*; - -import org.apache.http.conn.scheme.*; -import org.apache.http.impl.client.*; -import org.apache.http.impl.conn.tsccm.*; -import org.apache.http.params.*; -import org.codehaus.httpcache4j.*; -import org.codehaus.httpcache4j.cache.*; -import org.codehaus.httpcache4j.resolver.*; - -import java.io.*; - -public class HttpClient { - - public static HTTPCache createHttpClient(Config config) { - SchemeRegistry schemeRegistry = new SchemeRegistry(); - schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); - schemeRegistry.register(new Scheme("https", new EasySSLSocketFactory(), 443)); - BasicHttpParams params = new BasicHttpParams(); - ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, schemeRegistry); - ResponseResolver responseResolver = new HTTPClientResponseResolver(new DefaultHttpClient(cm, new BasicHttpParams())); - - if (config.gitorious.sessionValue.isSome()) { - responseResolver = new GitoriousResponseResolver(config.gitorious.sessionValue.some(), responseResolver); - } - - responseResolver = new TimingResponseResolver(responseResolver); - - return new HTTPCache(new MemoryCacheStorage(), responseResolver); - } - - private static class TimingResponseResolver implements ResponseResolver { - private final ResponseResolver r; - - private TimingResponseResolver(ResponseResolver r) { - this.r = r; - } - - public HTTPResponse resolve(HTTPRequest request) throws IOException { - System.out.println(request.getRequestURI() + ": Executing"); - long start = currentTimeMillis(); - Status status = null; - try { - HTTPResponse response = r.resolve(request); - status = response.getStatus(); - return response; - } finally { - long end = currentTimeMillis(); - - String s = request.getRequestURI() + ": Executed in " + (end - start) + "ms, "; - - if (status != null) { - s += "response: " + status.getCode() + " " + status.getName(); - } else { - s += "with exception"; - } - - System.out.println(s); - } - } - - public void shutdown() { - r.shutdown(); - } - } - - private static class GitoriousResponseResolver implements ResponseResolver { - private final String gitoriousSessionValue; - private final ResponseResolver responseResolver; - - public GitoriousResponseResolver(String gitoriousSessionValue, ResponseResolver responseResolver) { - this.gitoriousSessionValue = gitoriousSessionValue; - this.responseResolver = responseResolver; - } - - public HTTPResponse resolve(HTTPRequest request) throws IOException { - request = request.addHeader("Cookie", "_gitorious_sess=" + gitoriousSessionValue); - return responseResolver.resolve(request); - } - - public void shutdown() { - responseResolver.shutdown(); - } - } -} diff --git a/src/main/java/io/trygvis/esper/testing/gitorious/GitoriousProjectDiscovery.java b/src/main/java/io/trygvis/esper/testing/gitorious/GitoriousProjectDiscovery.java index a236e45..9bafc17 100755 --- a/src/main/java/io/trygvis/esper/testing/gitorious/GitoriousProjectDiscovery.java +++ b/src/main/java/io/trygvis/esper/testing/gitorious/GitoriousProjectDiscovery.java @@ -10,6 +10,7 @@ import io.trygvis.esper.testing.object.ObjectManager; import io.trygvis.esper.testing.object.ObjectUtil; import io.trygvis.esper.testing.object.TransactionalActor; +import io.trygvis.esper.testing.util.*; import static java.lang.System.*; import org.apache.abdera.parser.*; @@ -31,7 +32,7 @@ public class GitoriousProjectDiscovery { public GitoriousProjectDiscovery(final Config config) throws Exception { boneCp = config.createBoneCp(); - gitoriousClient = new GitoriousClient(HttpClient.createHttpClient(config), config.gitorious.url); + gitoriousClient = new GitoriousClient(HttpClient.createHttpCache(config), config.gitorious.url); final ScheduledThreadPoolExecutor service = new ScheduledThreadPoolExecutor(1); @@ -44,11 +45,11 @@ public class GitoriousProjectDiscovery { final ObjectManager> repositoryManager = new ObjectManager<>("", repositories, new ObjectFactory>() { public ActorRef create(GitoriousRepositoryDto repository) { - return ObjectUtil.scheduledActorWithFixedDelay(service, 0, 60, TimeUnit.SECONDS, boneCp, new GitoriousRepository(gitoriousClient, repository)); + return ObjectUtil.scheduledActorWithFixedDelay(service, 0, 60, TimeUnit.SECONDS, boneCp, "Gitorious", new GitoriousRepository(gitoriousClient, repository)); } }); - ObjectUtil.scheduledActorWithFixedDelay(service, config.gitorious.projectListUpdateDelay, config.gitorious.projectListUpdateInterval, TimeUnit.MILLISECONDS, boneCp, new TransactionalActor() { + ObjectUtil.scheduledActorWithFixedDelay(service, config.gitorious.projectListUpdateDelay, config.gitorious.projectListUpdateInterval, TimeUnit.MILLISECONDS, boneCp, "Gitorious", new TransactionalActor() { @Override public void act(Connection c) throws Exception { Daos daos = new Daos(c); diff --git a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsClient.java b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsClient.java old mode 100644 new mode 100755 index ed4cb59..e31fcfe --- a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsClient.java +++ b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsClient.java @@ -5,38 +5,32 @@ import fj.data.*; import io.trygvis.esper.testing.*; import static io.trygvis.esper.testing.Util.*; import io.trygvis.esper.testing.jenkins.JenkinsJobXml.*; -import static java.lang.Integer.parseInt; +import io.trygvis.esper.testing.util.*; import static org.apache.commons.lang.StringUtils.*; -import org.codehaus.httpcache4j.*; import org.codehaus.httpcache4j.cache.*; -import org.h2.util.*; import org.jdom2.*; -import org.jdom2.input.*; -import javax.xml.stream.*; import java.io.*; import java.net.*; import java.util.*; import java.util.List; +import javax.xml.stream.*; public class JenkinsClient { - private static final XMLInputFactory xmlReader = XMLInputFactory.newFactory(); - private static final StAXStreamBuilder streamBuilder = new StAXStreamBuilder(); - private final HTTPCache http; - - private boolean debugXml; + private final XmlHttpClient xmlHttpClient; public JenkinsClient(HTTPCache http) { - this.http = http; - this.debugXml = false; - } - - public void setDebugXml(boolean debugXml) { - this.debugXml = debugXml; + this.xmlHttpClient = new XmlHttpClient(http); } public JenkinsXml fetchJobs(URI uri) throws XMLStreamException, JDOMException, IOException { - Element root = fetchXml(uri).getRootElement(); + Option d = xmlHttpClient.fetch(uri); + + if(d.isNone()) { + return new JenkinsXml(Option.none(), Option.none(), Option.none(), Collections.emptyList()); + } + + Element root = d.some().getRootElement(); List jobs = new ArrayList<>(); for (Element job : root.getChildren("job")) { @@ -57,60 +51,25 @@ public class JenkinsClient { Option.fromNull(root.getChildText("description")), jobs); } - public JenkinsJobXml fetchJob(URI uri) throws IOException, JDOMException, XMLStreamException { - Element root = fetchXml(uri).getRootElement(); + public Option fetchJob(URI uri) throws IOException, JDOMException, XMLStreamException { + Option d = xmlHttpClient.fetch(uri); + + if(d.isNone()) { + return Option.none(); + } + + Element root = d.some().getRootElement(); String name = root.getName(); switch (name) { case "freeStyleProject": - return JenkinsJobXml.parse(uri, JenkinsJobType.FREE_STYLE, root); + return Option.some(JenkinsJobXml.parse(uri, JenkinsJobType.FREE_STYLE, root)); case "mavenModuleSet": - return JenkinsJobXml.parse(uri, JenkinsJobType.MAVEN, root); + return Option.some(JenkinsJobXml.parse(uri, JenkinsJobType.MAVEN, root)); default: - throw new IOException("Unknown project type: " + name); - } - } - - private Document fetchXml(URI uri) throws IOException, XMLStreamException, JDOMException { - HTTPResponse response = null; - - try { - response = http.execute(new HTTPRequest(uri)); - - if (response.getStatus().getCode() != 200) { - throw new IOException("Did not get 200 back, got " + response.getStatus().getCode()); - } - - InputStream stream = response.getPayload().getInputStream(); - - if (debugXml) { - int size; - try { - size = parseInt(response.getHeaders().getFirstHeader("Content-Length").getValue()); - } catch (Throwable e) { - size = 10 * 1024; - } - - // TODO: Pretty print - - ByteArrayOutputStream buffer = new ByteArrayOutputStream(size); - IOUtils.copy(stream, buffer); - byte[] bytes = buffer.toByteArray(); - System.out.println("------------------------------------------------"); - System.out.write(bytes); - System.out.println(); - System.out.println("------------------------------------------------"); - stream = new ByteArrayInputStream(bytes); - } - - return streamBuilder.build(xmlReader.createXMLStreamReader(stream)); - } catch (HTTPException e) { - throw new IOException(e); - } finally { - if (response != null) { - response.consume(); - } + System.out.println("Unknown project type: " + name); + return Option.none(); } } } diff --git a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsImporter.java b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsImporter.java index b929576..6be720f 100755 --- a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsImporter.java +++ b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsImporter.java @@ -4,7 +4,9 @@ import fj.*; import fj.data.*; import io.trygvis.esper.testing.*; import io.trygvis.esper.testing.object.*; +import io.trygvis.esper.testing.util.*; import static java.lang.Thread.currentThread; +import org.codehaus.httpcache4j.cache.*; import org.joda.time.*; import java.net.URI; @@ -16,9 +18,9 @@ public class JenkinsImporter { public static void main(String[] args) throws Exception { Config config = Config.loadFromDisk(); - final JenkinsClient jenkinsClient = new JenkinsClient(HttpClient.createHttpClient(config)); + HTTPCache httpCache = HttpClient.createHttpCache(config); - jenkinsClient.setDebugXml(false); + final JenkinsClient jenkinsClient = new JenkinsClient(httpCache); HashSet servers = new HashSet<>(); servers.add(URI.create("https://builds.apache.org")); diff --git a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsJob.java b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsJob.java old mode 100644 new mode 100755 index 9aad891..7a7f6af --- a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsJob.java +++ b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsJob.java @@ -8,7 +8,6 @@ import org.slf4j.*; import java.io.*; import java.net.*; -import java.util.*; import java.util.concurrent.*; public class JenkinsJob implements Closeable { @@ -49,7 +48,7 @@ public class JenkinsJob implements Closeable { try { logger.info("Updating " + name); long start = currentTimeMillis(); - latestStatus = some(client.fetchJob(uri)); + latestStatus = client.fetchJob(uri); long end = currentTimeMillis(); logger.info("Updated " + name + " in " + (end - start) + "ms"); } catch (Throwable e) { diff --git a/src/main/java/io/trygvis/esper/testing/nexus/ArtifactDto.java b/src/main/java/io/trygvis/esper/testing/nexus/ArtifactDto.java old mode 100644 new mode 100755 index 144913e..b732bfa --- a/src/main/java/io/trygvis/esper/testing/nexus/ArtifactDto.java +++ b/src/main/java/io/trygvis/esper/testing/nexus/ArtifactDto.java @@ -2,32 +2,20 @@ package io.trygvis.esper.testing.nexus; import fj.data.*; -import java.net.*; +import java.util.*; public class ArtifactDto implements Comparable { - public final URI serverUrl; + public final UUID uuid; public final String repositoryId; public final ArtifactId id; - public ArtifactDto(URI serverUrl, String repositoryId, ArtifactId id) { - this.serverUrl = serverUrl; + public ArtifactDto(UUID uuid, String repositoryId, ArtifactId id) { + this.uuid = uuid; this.repositoryId = repositoryId; this.id = id; } public int compareTo(ArtifactDto o) { - int i = serverUrl.compareTo(o.serverUrl); - - if (i != 0) { - return i; - } - - i = repositoryId.compareTo(o.repositoryId); - - if (i != 0) { - return i; - } - return id.compareTo(o.id); } @@ -37,17 +25,11 @@ public class ArtifactDto implements Comparable { ArtifactDto that = (ArtifactDto) o; - if (!serverUrl.equals(that.serverUrl)) return false; - if (!repositoryId.equals(that.repositoryId)) return false; - - return id.equals(that.id); + return uuid.equals(that.uuid); } public int hashCode() { - int result = serverUrl.hashCode(); - result = 31 * result + repositoryId.hashCode(); - result = 31 * result + id.hashCode(); - return result; + return uuid.hashCode(); } } diff --git a/src/main/java/io/trygvis/esper/testing/nexus/NexusClient.java b/src/main/java/io/trygvis/esper/testing/nexus/NexusClient.java index 9b2b899..02dc28c 100755 --- a/src/main/java/io/trygvis/esper/testing/nexus/NexusClient.java +++ b/src/main/java/io/trygvis/esper/testing/nexus/NexusClient.java @@ -3,31 +3,52 @@ package io.trygvis.esper.testing.nexus; import fj.data.*; import static fj.data.Option.*; import static io.trygvis.esper.testing.nexus.SearchNGResponseParser.*; +import io.trygvis.esper.testing.util.*; import org.apache.commons.io.*; import org.apache.commons.lang.*; import static org.codehaus.httpcache4j.HTTPMethod.*; import org.codehaus.httpcache4j.*; import org.codehaus.httpcache4j.cache.*; import org.codehaus.httpcache4j.util.*; +import org.jdom2.*; import java.io.*; import java.net.*; +import java.util.*; import javax.xml.stream.*; public class NexusClient { private final HTTPCache http; + private final URI nexusUrl; + private final XmlHttpClient xmlHttpClient; + public NexusClient(HTTPCache http, URI nexusUrl) { this.http = http; this.nexusUrl = nexusUrl; + this.xmlHttpClient = new XmlHttpClient(http); + } + + public NexusFeed fetchTimeline(String timeline) throws IOException { + URI uri = URI.create(nexusUrl.toASCIIString() + "/service/local/feeds/" + timeline); + + Option d = xmlHttpClient.fetch(uri); + + if (d.isNone()) { + return new NexusFeed(Collections.emptyList()); + } + + Document document = d.some(); + + return NexusFeedParser.parseDocument(document); } public ArtifactSearchResult fetchIndex(String groupId, Option repositoryId) throws IOException { ArtifactSearchResult aggregate = fetchIndexPage(groupId, repositoryId, Option.none()); ArtifactSearchResult result = aggregate; - while(result.artifacts.size() > 0) { + while (result.artifacts.size() > 0) { result = fetchIndexPage(groupId, repositoryId, some(aggregate.artifacts.size())); aggregate = aggregate.append(result); } diff --git a/src/main/java/io/trygvis/esper/testing/nexus/NexusDao.java b/src/main/java/io/trygvis/esper/testing/nexus/NexusDao.java index c5e8742..cb93a63 100755 --- a/src/main/java/io/trygvis/esper/testing/nexus/NexusDao.java +++ b/src/main/java/io/trygvis/esper/testing/nexus/NexusDao.java @@ -3,8 +3,7 @@ package io.trygvis.esper.testing.nexus; import fj.data.*; import static fj.data.Option.*; import io.trygvis.esper.testing.*; -import static io.trygvis.esper.testing.DaoUtil.timestampToLocalDateTime; -import org.joda.time.*; +import static java.lang.System.currentTimeMillis; import java.net.*; import java.sql.*; @@ -13,6 +12,14 @@ import java.util.Date; import java.util.List; public class NexusDao { + public static final String NEXUS_SERVER = "uuid, url, name"; + + public static final String NEXUS_REPOSITORY = "uuid, server, id, group_ids"; + + private final String NEXUS_ARTIFACT_ID = "group_id, artifact_id, version"; + + private final String NEXUS_ARTIFACT = "uuid, repository, " + NEXUS_ARTIFACT_ID; + private final Connection c; public NexusDao(Connection c) { @@ -28,59 +35,65 @@ public class NexusDao { } } + private static ArtifactDto artifactDto(ResultSet rs) throws SQLException { + int i = 1; + + return new ArtifactDto( + UUID.fromString(rs.getString(i++)), + rs.getString(i++), + new ArtifactId(rs.getString(i++), + rs.getString(i++), + rs.getString(i))); + } + private NexusRepositoryDto nexusRepositoryDto(ResultSet rs) throws SQLException { int i = 1; return new NexusRepositoryDto( - rs.getString(i++), - uri(rs.getString(i++)), - (String[]) rs.getArray(i++).getArray(), - fromNull(rs.getTimestamp(i++)).map(timestampToLocalDateTime), - fromNull(rs.getTimestamp(i++)).map(timestampToLocalDateTime), - fromNull(rs.getTimestamp(i)).map(timestampToLocalDateTime) + UUID.fromString(rs.getString(i++)), + UUID.fromString(rs.getString(i++)), + rs.getString(i++), + (String[]) rs.getArray(i).getArray() ); } - /* - public void insertRepository(String repositoryId, URI nexusUri, LocalDateTime discoveryDate) throws SQLException { - int i = 1; - try (PreparedStatement s = prepareStatement("INSERT INTO nexus_repository(id, uri, discovered_date) VALUES(?, ?, ?)")) { - s.setString(i++, repositoryId); - s.setString(i++, nexusUri.toASCIIString()); - s.setTimestamp(i, new Timestamp(discoveryDate.toDateTime().getMillis())); - s.executeUpdate(); - } - } - */ + // ----------------------------------------------------------------------- + // Nexus Artifact + // ----------------------------------------------------------------------- public List selectServer() throws SQLException { - try (PreparedStatement s = c.prepareStatement("SELECT url, name FROM nexus_server")) { + try (PreparedStatement s = c.prepareStatement("SELECT " + NEXUS_SERVER + " FROM nexus_server")) { ResultSet rs = s.executeQuery(); List servers = new ArrayList<>(); while (rs.next()) { - servers.add(new NexusServerDto(uri(rs.getString(1)), rs.getString(2))); + int i = 1; + servers.add(new NexusServerDto( + UUID.fromString(rs.getString(i++)), + uri(rs.getString(i++)), + rs.getString(i))); } return servers; } } - public Option findRepository(String repositoryId) throws SQLException { - try (PreparedStatement s = c.prepareStatement("SELECT id, server_url, group_ids, discovery_date, last_update, last_successful_update FROM nexus_repository WHERE id=?")) { - s.setString(1, repositoryId); + public Option findRepository(UUID server, String repositoryId) throws SQLException { + try (PreparedStatement s = c.prepareStatement("SELECT " + NEXUS_REPOSITORY + " FROM nexus_repository WHERE server=? AND id=?")) { + s.setString(1, server.toString()); + s.setString(2, repositoryId); - try (ResultSet rs = s.executeQuery()) { - if (!rs.next()) { - return Option.none(); - } + ResultSet rs = s.executeQuery(); - return some(nexusRepositoryDto(rs)); + if (!rs.next()) { + return Option.none(); } + + return some(nexusRepositoryDto(rs)); } } public List findRepositories(URI nexusUrl) throws SQLException { - try (PreparedStatement s = c.prepareStatement("SELECT id, server_url, group_ids, created_date, last_update, last_successful_update FROM nexus_repository WHERE server_url=?")) { + try (PreparedStatement s = c.prepareStatement("SELECT " + NEXUS_REPOSITORY + " FROM nexus_repository WHERE server=?")) { s.setString(1, nexusUrl.toASCIIString()); List list = new ArrayList<>(); @@ -94,14 +107,6 @@ public class NexusDao { } } - // ----------------------------------------------------------------------- - // Nexus Artifact - // ----------------------------------------------------------------------- - - private final String NEXUS_ARTIFACT_ID = "group_id, artifact_id, version"; - - private final String NEXUS_ARTIFACT = NEXUS_ARTIFACT_ID + ", snapshot_version, classifiers, packagings, created_date"; - private int setArtifactId(int i, PreparedStatement s, ArtifactId id) throws SQLException { s.setString(i++, id.groupId); s.setString(i++, id.artifactId); @@ -109,45 +114,24 @@ public class NexusDao { return i; } - private static ArtifactDto artifactDto(URI serverUrl, String repositoryId, ResultSet rs) throws SQLException { - int i = 1; + public UUID insertArtifact(UUID repository, ArtifactId id) throws SQLException { + try (PreparedStatement s = c.prepareStatement("INSERT INTO nexus_artifact(" + NEXUS_ARTIFACT + ") VALUES(?, ?, ?, ?, ?)")) { + UUID uuid = UUID.randomUUID(); - return new ArtifactDto( - serverUrl, - repositoryId, - new ArtifactId(rs.getString(i++), - rs.getString(i++), - rs.getString(i))); - } - - public void insertArtifact(URI nexusUrl, String repositoryId, ArtifactId id, Option snapshotVersion, List files, Date createdDate) throws SQLException { - String[] classifiers = new String[files.size()]; - String[] packagings = new String[files.size()]; - - for (int i = 0; i < files.size(); i++) { - classifiers[i] = files.get(i).classifier.toNull(); - packagings[i] = files.get(i).extension; - } - - int i = 1; - try (PreparedStatement s = c.prepareStatement("INSERT INTO nexus_artifact(server_url, repository_id, " + NEXUS_ARTIFACT + ") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)")) { - s.setString(i++, nexusUrl.toASCIIString()); - s.setString(i++, repositoryId); - i = setArtifactId(i, s, id); - s.setString(i++, snapshotVersion.toNull()); - s.setArray(i++, c.createArrayOf("varchar", classifiers)); - s.setArray(i++, c.createArrayOf("varchar", packagings)); - s.setTimestamp(i, DaoUtil.dateToTimestamp.f(createdDate)); + int i = 1; + s.setString(i++, uuid.toString()); + s.setString(i++, repository.toString()); + setArtifactId(i, s, id); s.executeUpdate(); + + return uuid; } } - public void deleteArtifact(URI nexusUrl, String repositoryId, ArtifactId id) throws SQLException { + public void deleteArtifact(UUID uuid) throws SQLException { int i = 1; - try (PreparedStatement s = c.prepareStatement("DELETE FROM nexus_artifact WHERE server_url=? AND repository_id=? AND group_id=? AND artifact_id=? AND version=?")) { - s.setString(i++, nexusUrl.toASCIIString()); - s.setString(i++, repositoryId); - i += setArtifactId(i, s, id); + try (PreparedStatement s = c.prepareStatement("DELETE FROM nexus_artifact WHERE uuid=?")) { + s.setString(i, uuid.toString()); s.executeUpdate(); } } @@ -160,53 +144,101 @@ public class NexusDao { List list = new ArrayList<>(); while (rs.next()) { - list.add(artifactDto(url, repositoryId, rs)); + list.add(artifactDto(rs)); } return list; } } + + public Option findArtifact(UUID repository, ArtifactId id) throws SQLException { + try (PreparedStatement s = c.prepareStatement("SELECT " + NEXUS_ARTIFACT + " FROM nexus_artifact WHERE repository=? AND group_id=? AND artifact_id=? AND version =?")) { + int i = 1; + s.setString(i++, repository.toString()); + setArtifactId(i, s, id); + + ResultSet rs = s.executeQuery(); + if (!rs.next()) { + return none(); + } + + return some(artifactDto(rs)); + } + } + +// public void updateSnapshotTimestamp(UUID uuid, String snapshotTimestamp) throws SQLException { +// try(PreparedStatement s = c.prepareStatement("UPDATE nexus_artifact SET snapshot_timestamp=? WHERE uuid=?")) { +// s.setString(1, snapshotTimestamp); +// s.setString(2, uuid.toString()); +// s.executeUpdate(); +// } +// } + + public UUID insertNewSnapshotEvent(UUID artifact, String guid, String file, String snapshotTimestamp) throws SQLException { + try(PreparedStatement s = c.prepareStatement("INSERT INTO nexus_event(uuid, artifact, timestamp, guid, type, snapshot_timestamp, file) VALUES(?, ?, ?, ?, ?, ?, ?)")) { + UUID uuid = UUID.randomUUID(); + int i = 1; + s.setString(i++, uuid.toString()); + s.setString(i++, artifact.toString()); + s.setTimestamp(i++, new Timestamp(currentTimeMillis())); + s.setString(i++, guid); + s.setString(i++, "new_snapshot"); + s.setString(i++, snapshotTimestamp); + s.setString(i, file); + s.executeUpdate(); + return uuid; + } + } + + public int countEventByGuid(String guid) throws SQLException { + try (PreparedStatement s = c.prepareStatement("SELECT count(guid) FROM nexus_event WHERE guid=?")) { + s.setString(1, guid); + ResultSet rs = s.executeQuery(); + rs.next(); + return rs.getInt(1); + } + } } class NexusServerDto { + public final UUID uuid; + public final URI url; + public final String name; - NexusServerDto(URI url, String name) { + NexusServerDto(UUID uuid, URI url, String name) { + this.uuid = uuid; this.url = url; this.name = name; } public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof NexusServerDto)) return false; + if (o == null || getClass() != o.getClass()) return false; NexusServerDto that = (NexusServerDto) o; - if (!url.equals(that.url)) return false; - - return true; + return uuid.equals(that.uuid); } public int hashCode() { - return url.hashCode(); + return uuid.hashCode(); } } class NexusRepositoryDto { + public final UUID uuid; + + public final UUID server; + public final String repositoryId; - public final URI nexusUrl; + public final String[] groupIds; - public final Option discoveryDate; - public final Option lastUpdate; - public final Option lastSuccessfulUpdate; - NexusRepositoryDto(String repositoryId, URI nexusUrl, String[] groupIds, Option discoveryDate, Option lastUpdate, Option lastSuccessfulUpdate) { + NexusRepositoryDto(UUID uuid, UUID server, String repositoryId, String[] groupIds) { + this.uuid = uuid; + this.server = server; this.repositoryId = repositoryId; - this.nexusUrl = nexusUrl; this.groupIds = groupIds; - this.discoveryDate = discoveryDate; - this.lastUpdate = lastUpdate; - this.lastSuccessfulUpdate = lastSuccessfulUpdate; } } - diff --git a/src/main/java/io/trygvis/esper/testing/nexus/NexusFeedParser.java b/src/main/java/io/trygvis/esper/testing/nexus/NexusFeedParser.java new file mode 100755 index 0000000..d85803f --- /dev/null +++ b/src/main/java/io/trygvis/esper/testing/nexus/NexusFeedParser.java @@ -0,0 +1,132 @@ +package io.trygvis.esper.testing.nexus; + +import fj.*; +import fj.data.*; +import static fj.data.Option.*; +import org.jdom2.*; +import static org.jdom2.filter.Filters.*; +import org.joda.time.*; +import org.joda.time.format.*; + +import java.net.*; +import java.util.*; +import java.util.List; +import java.util.regex.*; + +public class NexusFeedParser { + private static Namespace dc = Namespace.getNamespace("http://purl.org/dc/elements/1.1/"); + + public static NexusFeed parseDocument(Document document) { + List channels = document.getRootElement().getContent(element("channel")); + + List events = new ArrayList<>(); + + if (channels.size() != 1) { + return new NexusFeed(events); + } + + Element channel = channels.get(0); + + for (Element item : channel.getContent(element("item"))) { + Option e = parseEvent(item); + + if (e.isNone()) { + continue; + } + + events.add(e.some()); + } + + return new NexusFeed(events); + } + + public static Option parseEvent(Element item) { + String title = item.getChildText("title"); + + Option guid = Option.fromNull(item.getChildText("guid")); + Option creator = Option.fromNull(item.getChildText("creator", dc)); + Option date = Option.fromNull(item.getChildText("date", dc)).bind(new F>() { + @Override + public Option f(String s) { + try { + return some(ISODateTimeFormat.dateTimeNoMillis().parseDateTime(s)); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + return Option.none(); + } + } + }); + + String[] strings = title.split(":"); + + String groupId; + String artifactId; + String version; + Option classifier; + + if (strings.length == 3) { + groupId = strings[0]; + artifactId = strings[1]; + version = strings[2]; + classifier = Option.none(); + } else if (strings.length == 4) { + groupId = strings[0]; + artifactId = strings[1]; + version = strings[2]; + classifier = some(strings[3]); + } else { + return null; + } + + if (guid.isNone() || creator.isNone() || date.isNone()) { + return null; + } + + Pattern regexp = Pattern.compile("(.*)-([0-9]{8}\\.[0-9]{6}-[0-9]*)$"); + + Matcher matcher = regexp.matcher(version); + + if (matcher.matches()) { + ArtifactId id = new ArtifactId(groupId, artifactId, matcher.group(1) + "-SNAPSHOT"); + return Option.some(new NewSnapshotEvent(guid.some(), id, classifier, creator.some(), + date.some(), matcher.group(2), URI.create(item.getChildText("link")))); + } + + return none(); + } +} + +class NexusFeed { + List events = new ArrayList<>(); + + NexusFeed(List events) { + this.events = events; + } +} + +abstract class NexusEvent { + public final String guid; + public final ArtifactId artifactId; + public final Option classifier; + public final String creator; + public final DateTime date; + + NexusEvent(String guid, ArtifactId artifactId, Option classifier, String creator, DateTime date) { + this.guid = guid; + this.artifactId = artifactId; + this.classifier = classifier; + this.creator = creator; + this.date = date; + } +} + +class NewSnapshotEvent extends NexusEvent { + public final String snapshotTimestamp; + public final URI url; + + NewSnapshotEvent(String guid, ArtifactId artifactId, Option classifier, String creator, DateTime date, String snapshotTimestamp, URI url) { + super(guid, artifactId, classifier, creator, date); + this.snapshotTimestamp = snapshotTimestamp; + this.url = url; + } +} diff --git a/src/main/java/io/trygvis/esper/testing/nexus/NexusImporter.java b/src/main/java/io/trygvis/esper/testing/nexus/NexusImporter.java index ea57c43..8e49074 100755 --- a/src/main/java/io/trygvis/esper/testing/nexus/NexusImporter.java +++ b/src/main/java/io/trygvis/esper/testing/nexus/NexusImporter.java @@ -2,34 +2,34 @@ package io.trygvis.esper.testing.nexus; import com.jolbox.bonecp.*; import fj.data.*; -import static fj.data.Option.*; import io.trygvis.esper.testing.*; import io.trygvis.esper.testing.object.*; +import io.trygvis.esper.testing.util.*; import static java.lang.Thread.*; +import static java.util.regex.Pattern.quote; import org.codehaus.httpcache4j.cache.*; import java.sql.*; import java.util.*; -import java.util.Date; -import java.util.HashMap; -import java.util.TreeMap; +import java.util.List; import java.util.concurrent.atomic.*; public class NexusImporter { public static void main(String[] args) throws Exception { final Config config = Config.loadFromDisk(); - - final HTTPCache http = HttpClient.createHttpClient(config); - + final HTTPCache http = HttpClient.createHttpCache(config); + final XmlParser xmlParser = new XmlParser(); final BoneCPDataSource boneCp = config.createBoneCp(); + XmlParser.debugXml = true; + ObjectManager> serverManager = new ObjectManager<>("Nexus server", Collections.emptySet(), new ObjectFactory>() { public ActorRef create(NexusServerDto server) { final NexusClient client = new NexusClient(http, server.url); String name = server.name; - return ObjectUtil.threadedActor(name, config.nexusUpdateInterval, boneCp, new NexusServer(client, server)); + return ObjectUtil.threadedActor(name, config.nexusUpdateInterval, boneCp, "Nexus Server: " + name, new NexusServer(client, server, xmlParser)); } }); @@ -38,9 +38,13 @@ public class NexusImporter { while (shouldRun.get()) { try { + List newKeys; + try (Connection c = boneCp.getConnection()) { - serverManager.update(new NexusDao(c).selectServer()); + newKeys = new NexusDao(c).selectServer(); } + + serverManager.update(newKeys); } catch (SQLException e) { e.printStackTrace(System.out); } @@ -58,92 +62,156 @@ class NexusServer implements TransactionalActor { public final NexusClient client; public final NexusServerDto server; + public final XmlParser xmlParser; - NexusServer(NexusClient client, NexusServerDto server) { + NexusServer(NexusClient client, NexusServerDto server, XmlParser xmlParser) { this.client = client; this.server = server; + this.xmlParser = xmlParser; } + @Override public void act(Connection c) throws Exception { - Date timestamp = new Date(); + NexusDao dao = new NexusDao(c); - String p = server.name; + NexusFeed feed = client.fetchTimeline("recentlyDeployedArtifacts"); - for (NexusRepositoryDto repository : dao.findRepositories(server.url)) { - String p2 = p + "/" + repository.repositoryId; + int newEvents = 0, oldEvents = 0; - System.out.println(p2 + ": Updating repository: " + repository.repositoryId); + for (NexusEvent event : feed.events) { - TreeMap artifactsInNexus = new TreeMap<>(); + if(dao.countEventByGuid(event.guid) != 0) { + oldEvents++; + continue; + } - for (String groupId : repository.groupIds) { - String p3 = p2 + "/" + groupId; + newEvents++; - System.out.println(p3 + ": Updating group id"); - ArtifactSearchResult result = client.fetchIndex(groupId, some(repository.repositoryId)); - System.out.println(p3 + ": Found " + result.artifacts.size() + " artifacts"); + String repositoryId = event.guid.replaceAll("^" + quote(server.url.toASCIIString()) + "/content/repositories/([-a-zA-Z0-9]*)/.*", "$1"); - for (ArtifactXml xml : result.artifacts) { - artifactsInNexus.put(xml.id, xml); - } + if(repositoryId.length() == 0) { + continue; + } - System.out.println(p3 + ": Updating everything under group id"); - result = client.fetchIndex(groupId + ".*", some(repository.repositoryId)); - System.out.println(p3 + ": Found " + result.artifacts.size() + " artifacts"); + Option r = dao.findRepository(server.uuid, repositoryId); - for (ArtifactXml xml : result.artifacts) { - artifactsInNexus.put(xml.id, xml); - } + if(r.isNone()) { + continue; } - Map artifactsInDatabase = new HashMap<>(); - for (ArtifactDto dto : dao.findArtifactsInRepository(server.url, repository.repositoryId)) { - artifactsInDatabase.put(dto.id, dto); - } + NexusRepositoryDto repository = r.some(); - ArrayList created = new ArrayList<>(); - ArrayList kept = new ArrayList<>(); - ArrayList removed = new ArrayList<>(); + Option a = dao.findArtifact(repository.uuid, event.artifactId); - for (ArtifactXml xml : artifactsInNexus.values()) { - Option o = xml.flatten(repository.repositoryId); + if(event instanceof NewSnapshotEvent) { + NewSnapshotEvent newSnapshotEvent = (NewSnapshotEvent) event; - if(o.isNone()) { - continue; - } + Option snapshotTimestamp = Option.some(newSnapshotEvent.snapshotTimestamp); - FlatArtifact artifact = o.some(); + UUID uuid; - if(!artifactsInDatabase.containsKey(xml.id)) { - created.add(artifact); + if(a.isNone()) { + System.out.println("New artifact: " + event.artifactId); + List files = Collections.emptyList(); + uuid = dao.insertArtifact(repository.uuid, event.artifactId); } else { - kept.add(artifact); - } - } - - for (ArtifactDto dto : artifactsInDatabase.values()) { - if(!artifactsInNexus.containsKey(dto.id)) { - removed.add(dto); - } - } + ArtifactDto artifact = a.some(); - System.out.println(p2 + ": found " + created.size() + " new artifacts, " + removed.size() + " removed artifacts and " + kept.size() + " existing artifacts."); + System.out.println("Updated artifact: " + event.artifactId); +// dao.updateSnapshotTimestamp(artifact.uuid, newSnapshotEvent.snapshotTimestamp); - System.out.println(p2 + ": inserting new artifacts"); - for (FlatArtifact artifact : created) { - dao.insertArtifact(repository.nexusUrl, repository.repositoryId, artifact.id, Option.none(), artifact.files, timestamp); - } - System.out.println(p2 + ": inserted"); + uuid = artifact.uuid; + } - System.out.println(p2 + ": deleting removed artifacts"); - for (ArtifactDto artifact : removed) { - dao.deleteArtifact(repository.nexusUrl, repository.repositoryId, artifact.id); + dao.insertNewSnapshotEvent(uuid, event.guid, newSnapshotEvent.url.toASCIIString(), newSnapshotEvent.snapshotTimestamp); } - System.out.println(p2 + ": deleted"); } - c.commit(); + System.out.println("Timeline updated. New=" + newEvents + ", old=" + oldEvents); } + +// public void act(Connection c) throws Exception { +// Date timestamp = new Date(); +// NexusDao dao = new NexusDao(c); +// +// String p = server.name; +// +// for (NexusRepositoryDto repository : dao.findRepositories(server.url)) { +// String p2 = p + "/" + repository.repositoryId; +// +// System.out.println(p2 + ": Updating repository: " + repository.repositoryId); +// +// TreeMap artifactsInNexus = new TreeMap<>(); +// +// for (String groupId : repository.groupIds) { +// String p3 = p2 + "/" + groupId; +// +// System.out.println(p3 + ": Updating group id"); +// ArtifactSearchResult result = client.fetchIndex(groupId, some(repository.repositoryId)); +// System.out.println(p3 + ": Found " + result.artifacts.size() + " artifacts"); +// +// for (ArtifactXml xml : result.artifacts) { +// artifactsInNexus.put(xml.id, xml); +// } +// +// System.out.println(p3 + ": Updating everything under group id"); +// result = client.fetchIndex(groupId + ".*", some(repository.repositoryId)); +// System.out.println(p3 + ": Found " + result.artifacts.size() + " artifacts"); +// +// for (ArtifactXml xml : result.artifacts) { +// artifactsInNexus.put(xml.id, xml); +// } +// } +// +// Map artifactsInDatabase = new HashMap<>(); +// for (ArtifactDto dto : dao.findArtifactsInRepository(server.url, repository.repositoryId)) { +// artifactsInDatabase.put(dto.id, dto); +// } +// +// ArrayList created = new ArrayList<>(); +// ArrayList kept = new ArrayList<>(); +// ArrayList removed = new ArrayList<>(); +// +// for (ArtifactXml xml : artifactsInNexus.values()) { +// Option o = xml.flatten(repository.repositoryId); +// +// if(o.isNone()) { +// continue; +// } +// +// FlatArtifact artifact = o.some(); +// +// if(!artifactsInDatabase.containsKey(xml.id)) { +// created.add(artifact); +// } +// else { +// kept.add(artifact); +// } +// } +// +// for (ArtifactDto dto : artifactsInDatabase.values()) { +// if(!artifactsInNexus.containsKey(dto.id)) { +// removed.add(dto); +// } +// } +// +// System.out.println(p2 + ": found " + created.size() + " new artifacts, " + removed.size() + " removed artifacts and " + kept.size() + " existing artifacts."); +// +// System.out.println(p2 + ": inserting new artifacts"); +// for (FlatArtifact artifact : created) { +// dao.insertArtifact(repository.nexusUrl, repository.repositoryId, artifact.id, Option.none(), artifact.files, timestamp); +// } +// System.out.println(p2 + ": inserted"); +// +// System.out.println(p2 + ": deleting removed artifacts"); +// for (ArtifactDto artifact : removed) { +// dao.deleteArtifact(repository.nexusUrl, repository.repositoryId, artifact.id); +// } +// System.out.println(p2 + ": deleted"); +// } +// +// c.commit(); +// } } diff --git a/src/main/java/io/trygvis/esper/testing/object/ObjectUtil.java b/src/main/java/io/trygvis/esper/testing/object/ObjectUtil.java index ecfaa34..93cc5fe 100755 --- a/src/main/java/io/trygvis/esper/testing/object/ObjectUtil.java +++ b/src/main/java/io/trygvis/esper/testing/object/ObjectUtil.java @@ -7,32 +7,42 @@ import java.util.concurrent.*; public class ObjectUtil { - public static ActorRef threadedActor(String threadName, long delay, DataSource dataSource, A actor) { - return new ThreadedActor<>(dataSource, threadName, actor, delay); + public static ActorRef threadedActor(String threadName, long delay, DataSource dataSource, String name, A actor) { + return new ThreadedActor<>(dataSource, threadName, name, actor, delay); } - public static ActorRef scheduledActorWithFixedDelay(ScheduledExecutorService scheduledExecutorService, long initialDelay, long delay, TimeUnit unit, DataSource dataSource, A actor) { - return new ScheduledActor<>(scheduledExecutorService, initialDelay, delay, unit, dataSource, actor); + public static ActorRef scheduledActorWithFixedDelay(ScheduledExecutorService scheduledExecutorService, long initialDelay, long delay, TimeUnit unit, DataSource dataSource, String name, A actor) { + return new ScheduledActor<>(scheduledExecutorService, initialDelay, delay, unit, dataSource, name, actor); } private static class TransactionalActorWrapper implements Runnable { private final DataSource dataSource; + private final String name; private final A actor; - TransactionalActorWrapper(DataSource dataSource, A actor) { + TransactionalActorWrapper(DataSource dataSource, String name, A actor) { this.dataSource = dataSource; + this.name = name; this.actor = actor; } public void run() { try { Connection c = dataSource.getConnection(); + try { + try (PreparedStatement s = c.prepareStatement("set application_name = 'Actor: " + name + "';")) { +// s.setString(1, "Actor: " + name); + s.executeUpdate(); + s.close(); + } + actor.act(c); c.commit(); } catch(SQLException e) { c.rollback(); + throw e; } finally { c.close(); } @@ -48,9 +58,9 @@ public class ObjectUtil { private final TransactionalActorWrapper actor; - ScheduledActor(ScheduledExecutorService executorService, long initialDelay, long delay, TimeUnit unit, DataSource dataSource, A actor) { + ScheduledActor(ScheduledExecutorService executorService, long initialDelay, long delay, TimeUnit unit, DataSource dataSource, String name, A actor) { future = executorService.scheduleWithFixedDelay(this, initialDelay, delay, unit); - this.actor = new TransactionalActorWrapper<>(dataSource, actor); + this.actor = new TransactionalActorWrapper<>(dataSource, name, actor); } public A underlying() { @@ -74,8 +84,8 @@ public class ObjectUtil { private final Thread thread; private boolean shouldRun = true; - ThreadedActor(DataSource dataSource, String threadName, A actor, long delay) { - this.actor = new TransactionalActorWrapper(dataSource, actor); + ThreadedActor(DataSource dataSource, String threadName, String name, A actor, long delay) { + this.actor = new TransactionalActorWrapper<>(dataSource, name, actor); this.delay = delay; thread = new Thread(this, threadName); thread.setDaemon(true); diff --git a/src/main/java/io/trygvis/esper/testing/util/EasySSLSocketFactory.java b/src/main/java/io/trygvis/esper/testing/util/EasySSLSocketFactory.java new file mode 100755 index 0000000..c1f1a7e --- /dev/null +++ b/src/main/java/io/trygvis/esper/testing/util/EasySSLSocketFactory.java @@ -0,0 +1,104 @@ +package io.trygvis.esper.testing.util; + +/* + * ==================================================================== + * + * 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +import java.io.*; +import java.net.*; +import javax.net.ssl.*; +import org.apache.http.conn.*; +import org.apache.http.conn.scheme.*; +import org.apache.http.params.*; + +public class EasySSLSocketFactory implements SocketFactory, LayeredSocketFactory { + + private SSLContext sslcontext = null; + + private static SSLContext createEasySSLContext() throws IOException { + try { + SSLContext context = SSLContext.getInstance("TLS"); + context.init(null, new TrustManager[]{new EasyX509TrustManager(null)}, null); + return context; + } catch (Exception e) { + throw new IOException(e.getMessage()); + } + } + + private SSLContext getSSLContext() throws IOException { + if (this.sslcontext == null) { + this.sslcontext = createEasySSLContext(); + } + return this.sslcontext; + } + + public Socket connectSocket(Socket sock, String host, int port, InetAddress localAddress, int localPort, + HttpParams params) throws IOException, ConnectTimeoutException { + int connTimeout = HttpConnectionParams.getConnectionTimeout(params); + int soTimeout = HttpConnectionParams.getSoTimeout(params); + InetSocketAddress remoteAddress = new InetSocketAddress(host, port); + SSLSocket sslSocket = (SSLSocket) ((sock != null) ? sock : createSocket()); + + if ((localAddress != null) || (localPort > 0)) { + // we need to bind explicitly + if (localPort < 0) { + localPort = 0; // indicates "any" + } + InetSocketAddress isa = new InetSocketAddress(localAddress, localPort); + sslSocket.bind(isa); + } + + sslSocket.connect(remoteAddress, connTimeout); + sslSocket.setSoTimeout(soTimeout); + + return sslSocket; + } + + public Socket createSocket() throws IOException { + return getSSLContext().getSocketFactory().createSocket(); + } + + public boolean isSecure(Socket socket) throws IllegalArgumentException { + return true; + } + + public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException { + return getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose); + } + + // ------------------------------------------------------------------- + // javadoc in org.apache.http.conn.scheme.SocketFactory says : + // Both Object.equals() and Object.hashCode() must be overridden + // for the correct operation of some connection managers + // ------------------------------------------------------------------- + + public boolean equals(Object obj) { + return ((obj != null) && obj.getClass().equals(EasySSLSocketFactory.class)); + } + + public int hashCode() { + return EasySSLSocketFactory.class.hashCode(); + } +} diff --git a/src/main/java/io/trygvis/esper/testing/util/EasyX509TrustManager.java b/src/main/java/io/trygvis/esper/testing/util/EasyX509TrustManager.java new file mode 100755 index 0000000..5a4c4d3 --- /dev/null +++ b/src/main/java/io/trygvis/esper/testing/util/EasyX509TrustManager.java @@ -0,0 +1,76 @@ +package io.trygvis.esper.testing.util; + +/* + * ==================================================================== + * + * 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + + +public class EasyX509TrustManager implements X509TrustManager +{ + private X509TrustManager standardTrustManager = null; + + public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException { + super(); + TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + factory.init(keystore); + TrustManager[] trustmanagers = factory.getTrustManagers(); + if (trustmanagers.length == 0) { + throw new NoSuchAlgorithmException("no trust manager found"); + } + this.standardTrustManager = (X509TrustManager)trustmanagers[0]; + } + + public void checkClientTrusted(X509Certificate[] certificates,String authType) throws CertificateException { + standardTrustManager.checkClientTrusted(certificates,authType); + } + + public void checkServerTrusted(X509Certificate[] certificates,String authType) throws CertificateException { +// if (certificates != null) { +// System.out.println("Server certificate chain:"); +// for (int i = 0; i < certificates.length; i++) { +// System.out.println("X509Certificate[" + i + "]=" + certificates[i]); +// } +// } + + if ((certificates != null) && (certificates.length == 1)) { + certificates[0].checkValidity(); + } else { + standardTrustManager.checkServerTrusted(certificates,authType); + } + } + + public X509Certificate[] getAcceptedIssuers() { + return this.standardTrustManager.getAcceptedIssuers(); + } +} diff --git a/src/main/java/io/trygvis/esper/testing/util/HttpClient.java b/src/main/java/io/trygvis/esper/testing/util/HttpClient.java new file mode 100755 index 0000000..ef6f2a9 --- /dev/null +++ b/src/main/java/io/trygvis/esper/testing/util/HttpClient.java @@ -0,0 +1,123 @@ +package io.trygvis.esper.testing.util; + +import fj.*; +import fj.data.*; +import io.trygvis.esper.testing.*; +import static java.lang.System.*; + +import org.apache.http.conn.scheme.*; +import org.apache.http.impl.client.*; +import org.apache.http.impl.conn.tsccm.*; +import org.apache.http.params.*; +import org.codehaus.httpcache4j.*; +import org.codehaus.httpcache4j.cache.*; +import org.codehaus.httpcache4j.resolver.*; +import org.jdom2.*; + +import java.io.*; +import java.net.*; +import javax.xml.stream.*; + +public class HttpClient { + + private final HTTPCache http; + private final F> f; + + public HttpClient(HTTPCache http, F> f) { + this.http = http; + this.f = f; + } + + public Option fetch(URI uri) throws IOException { + HTTPResponse response = null; + + try { + response = http.execute(new HTTPRequest(uri)); + + if (response.getStatus().getCode() != 200) { + throw new IOException("Did not get 200 back, got " + response.getStatus().getCode()); + } + +// return getDocument(response.getPayload().getInputStream()); + return f.f(response.getPayload().getInputStream()); + } catch (HTTPException e) { + throw new IOException(e); + } finally { + if (response != null) { + response.consume(); + } + } + } + + + public static HTTPCache createHttpCache(Config config) { + SchemeRegistry schemeRegistry = new SchemeRegistry(); + schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); + schemeRegistry.register(new Scheme("https", new EasySSLSocketFactory(), 443)); + BasicHttpParams params = new BasicHttpParams(); + ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, schemeRegistry); + ResponseResolver responseResolver = new HTTPClientResponseResolver(new DefaultHttpClient(cm, new BasicHttpParams())); + + if (config.gitorious.sessionValue.isSome()) { + responseResolver = new GitoriousResponseResolver(config.gitorious.sessionValue.some(), responseResolver); + } + + responseResolver = new TimingResponseResolver(responseResolver); + + return new HTTPCache(new MemoryCacheStorage(), responseResolver); + } + + private static class TimingResponseResolver implements ResponseResolver { + private final ResponseResolver r; + + private TimingResponseResolver(ResponseResolver r) { + this.r = r; + } + + public HTTPResponse resolve(HTTPRequest request) throws IOException { + System.out.println(request.getRequestURI() + ": Executing"); + long start = currentTimeMillis(); + Status status = null; + try { + HTTPResponse response = r.resolve(request); + status = response.getStatus(); + return response; + } finally { + long end = currentTimeMillis(); + + String s = request.getRequestURI() + ": Executed in " + (end - start) + "ms, "; + + if (status != null) { + s += "response: " + status.getCode() + " " + status.getName(); + } else { + s += "with exception"; + } + + System.out.println(s); + } + } + + public void shutdown() { + r.shutdown(); + } + } + + private static class GitoriousResponseResolver implements ResponseResolver { + private final String gitoriousSessionValue; + private final ResponseResolver responseResolver; + + public GitoriousResponseResolver(String gitoriousSessionValue, ResponseResolver responseResolver) { + this.gitoriousSessionValue = gitoriousSessionValue; + this.responseResolver = responseResolver; + } + + public HTTPResponse resolve(HTTPRequest request) throws IOException { + request = request.addHeader("Cookie", "_gitorious_sess=" + gitoriousSessionValue); + return responseResolver.resolve(request); + } + + public void shutdown() { + responseResolver.shutdown(); + } + } +} diff --git a/src/main/java/io/trygvis/esper/testing/util/XmlHttpClient.java b/src/main/java/io/trygvis/esper/testing/util/XmlHttpClient.java new file mode 100755 index 0000000..2c2f922 --- /dev/null +++ b/src/main/java/io/trygvis/esper/testing/util/XmlHttpClient.java @@ -0,0 +1,27 @@ +package io.trygvis.esper.testing.util; + +import fj.*; +import fj.data.*; +import org.codehaus.httpcache4j.cache.*; +import org.jdom2.*; + +import java.io.*; +import java.net.*; + +public class XmlHttpClient { + + private final HttpClient httpClient; + + public XmlHttpClient(HTTPCache http) { + final XmlParser parser = new XmlParser(); + httpClient = new HttpClient<>(http, new F>() { + public Option f(InputStream inputStream) { + return parser.parseDocument(inputStream); + } + }); + } + + public Option fetch(URI uri) throws IOException { + return httpClient.fetch(uri); + } +} diff --git a/src/main/java/io/trygvis/esper/testing/util/XmlParser.java b/src/main/java/io/trygvis/esper/testing/util/XmlParser.java new file mode 100755 index 0000000..e1b463f --- /dev/null +++ b/src/main/java/io/trygvis/esper/testing/util/XmlParser.java @@ -0,0 +1,66 @@ +package io.trygvis.esper.testing.util; + +import fj.data.*; +import static fj.data.Option.*; +import static javax.xml.stream.XMLStreamConstants.*; +import org.h2.util.*; +import org.jdom2.*; +import org.jdom2.input.*; + +import java.io.*; +import javax.xml.stream.*; + +public class XmlParser { + public static boolean debugXml; + + private final XMLInputFactory xmlInputFactory; + + private final StAXStreamBuilder streamBuilder = new StAXStreamBuilder(); + + public XmlParser() { + xmlInputFactory = XMLInputFactory.newFactory(); + } + + public Option parseDocument(InputStream stream) { + + try { + if (debugXml) { + // TODO: Pretty print + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + IOUtils.copy(stream, buffer); + byte[] bytes = buffer.toByteArray(); + System.out.println("------------------------------------------------"); + System.out.write(bytes); + System.out.println(); + System.out.println("------------------------------------------------"); + stream = new ByteArrayInputStream(bytes); + } + + // https://github.com/hunterhacker/jdom/issues/101 + XMLStreamReader readerX = xmlInputFactory.createXMLStreamReader(stream); + + XMLStreamReader reader = xmlInputFactory.createFilteredReader(readerX, new StreamFilter() { + + boolean seenStartDocument; + + @Override + public boolean accept(XMLStreamReader reader) { + if(reader.getEventType() == SPACE && !seenStartDocument) { + return false; + } + + if(reader.getEventType() == START_DOCUMENT) { + seenStartDocument = false; + } + + return true; + } + }); + + return some(streamBuilder.build(reader)); + } catch (Exception e) { + e.printStackTrace(); + return none(); + } + } +} diff --git a/src/main/resources/ddl-jenkins.sql b/src/main/resources/ddl-jenkins.sql new file mode 100755 index 0000000..37e82c1 --- /dev/null +++ b/src/main/resources/ddl-jenkins.sql @@ -0,0 +1,9 @@ +BEGIN; + +DROP TABLE IF EXISTS jenkins_server; + +CREATE TABLE jenkins_server( + url VARCHAR(1000) NOT NULL PRIMARY KEY +); + +COMMIT; diff --git a/src/main/resources/ddl-nexus.sql b/src/main/resources/ddl-nexus.sql index 15ed482..1f7514f 100755 --- a/src/main/resources/ddl-nexus.sql +++ b/src/main/resources/ddl-nexus.sql @@ -6,55 +6,56 @@ DROP TABLE IF EXISTS nexus_repository; DROP TABLE IF EXISTS nexus_server; CREATE TABLE nexus_server ( - url VARCHAR(1000) PRIMARY KEY, - name VARCHAR(100) NOT NULL + uuid CHAR(36) NOT NULL, + url VARCHAR(1000) NOT NULL, + name VARCHAR(1000) NOT NULL, + CONSTRAINT pk_nexus_server PRIMARY KEY (uuid), + CONSTRAINT uq_nexus_server_url UNIQUE (url) ); CREATE TABLE nexus_repository ( - id VARCHAR(1000), - server_url VARCHAR(1000) NOT NULL, - group_ids VARCHAR(100) [], - created_date TIMESTAMP, - last_update TIMESTAMP, - last_successful_update TIMESTAMP, - CONSTRAINT nexus_repository_pk PRIMARY KEY (id, server_url), - CONSTRAINT nexus_server_fk FOREIGN KEY (server_url) REFERENCES nexus_server (url) + uuid CHAR(36) NOT NULL, + server CHAR(36) NOT NULL, + id VARCHAR(100), + group_ids VARCHAR(100) [], + CONSTRAINT pk_nexus_repository PRIMARY KEY (uuid), + CONSTRAINT fk_nexus_server FOREIGN KEY (server) REFERENCES nexus_server (uuid), + CONSTRAINT uq_nexus_repository_id UNIQUE (server, id) ); CREATE TABLE nexus_artifact ( - server_url VARCHAR(1000) NOT NULL, - repository_id VARCHAR(1000) NOT NULL, - group_id VARCHAR(100) NOT NULL, - artifact_id VARCHAR(100) NOT NULL, - version VARCHAR(100) NOT NULL, - snapshot_version VARCHAR(100), - classifiers VARCHAR(100) [], - packagings VARCHAR(100) [], - created_date TIMESTAMP, - last_update TIMESTAMP, - last_successful_update TIMESTAMP, - CONSTRAINT nexus_artifact_pk PRIMARY KEY (server_url, repository_id, group_id, artifact_id, version), - CONSTRAINT nexus_repository_fk FOREIGN KEY (server_url, repository_id) REFERENCES nexus_repository (server_url, id) + uuid CHAR(36) NOT NULL, + repository CHAR(36) NOT NULL, + group_id VARCHAR(100) NOT NULL, + artifact_id VARCHAR(100) NOT NULL, + version VARCHAR(100) NOT NULL, + CONSTRAINT pk_nexus_artifact PRIMARY KEY (uuid), + CONSTRAINT uq_nexus_artifact_gid_aid_version UNIQUE (group_id, artifact_id, version), + CONSTRAINT fk_nexus_repository FOREIGN KEY (repository) REFERENCES nexus_repository (uuid) ); CREATE TABLE nexus_event ( - timestamp VARCHAR(100), - uuid VARCHAR(100), - server_url VARCHAR(1000) NOT NULL, - repository_id VARCHAR(1000) NOT NULL, - group_id VARCHAR(100) NOT NULL, - artifact_id VARCHAR(100) NOT NULL, - version VARCHAR(100) NOT NULL, - files VARCHAR(100) [], - CONSTRAINT nexus_event_pk PRIMARY KEY (timestamp, server_url, repository_id, group_id, artifact_id, version), - CONSTRAINT nexus_artifact_fk FOREIGN KEY (server_url, repository_id, group_id, artifact_id, version) REFERENCES nexus_artifact (server_url, repository_id, group_id, artifact_id, version) + uuid CHAR(36) NOT NULL, + artifact CHAR(36) NOT NULL, + timestamp VARCHAR(100), + guid VARCHAR(1000), + + type VARCHAR(100) NOT NULL, + +-- new snapshot event + snapshot_timestamp VARCHAR(1000), + file VARCHAR(1000), + CONSTRAINT pk_nexus_event PRIMARY KEY (uuid), + CONSTRAINT fk_nexus_artifact FOREIGN KEY (artifact) REFERENCES nexus_artifact (uuid), + CONSTRAINT uq_guid UNIQUE (guid), + CONSTRAINT check_event_type CHECK (type IN ('new_snapshot')) +-- CONSTRAINT pk_nexus_event PRIMARY KEY (timestamp, server_url, repository_id, group_id, artifact_id, version) ); -INSERT INTO nexus_server (url, name) VALUES ('https://oss.sonatype.org', 'Central Repository'); --- INSERT INTO nexus_repository (id, server_url, group_ids) VALUES ('releases', 'https://oss.sonatype.org', ARRAY ['io.trygvis', 'no.arktekk', 'org.codehaus']); -INSERT INTO nexus_repository (id, server_url, group_ids) VALUES ('releases', 'https://oss.sonatype.org', ARRAY ['io.trygvis', 'no.arktekk', 'org.codehaus']); +INSERT INTO nexus_server (uuid, url, name) VALUES ('4666dba4-3e2e-11e2-8a1b-0bd430e00b36', 'https://oss.sonatype.org', 'Central Repository'); +INSERT INTO nexus_repository (uuid, server, id, group_ids) VALUES ('4a2d7ab2-3e2f-11e2-af03-eb1ace2381bb', '4666dba4-3e2e-11e2-8a1b-0bd430e00b36', 'releases', ARRAY ['io.trygvis', 'no.arktekk', 'org.codehaus']); -INSERT INTO nexus_server (url, name) VALUES ('http://nexus.codehaus.org', 'Codehaus Snapshots'); -INSERT INTO nexus_repository (id, server_url, group_ids) VALUES ('snapshots', 'http://nexus.codehaus.org', ARRAY ['org.codehaus.mojo']); +INSERT INTO nexus_server (uuid, url, name) VALUES ('91d942d8-3e2f-11e2-aaa0-a70628365abd', 'http://nexus.codehaus.org', 'Codehaus Snapshots'); +INSERT INTO nexus_repository (uuid, server, id, group_ids) VALUES ('a2415b88-3e2f-11e2-a2b8-2f066b90cf13', '91d942d8-3e2f-11e2-aaa0-a70628365abd', 'snapshots', ARRAY ['org.codehaus.mojo']); COMMIT; diff --git a/src/test/java/io/trygvis/esper/testing/nexus/TestXmlParsing.java b/src/test/java/io/trygvis/esper/testing/nexus/TestXmlParsing.java index 6495d86..038de34 100755 --- a/src/test/java/io/trygvis/esper/testing/nexus/TestXmlParsing.java +++ b/src/test/java/io/trygvis/esper/testing/nexus/TestXmlParsing.java @@ -3,7 +3,9 @@ package io.trygvis.esper.testing.nexus; import static com.google.common.collect.Iterables.*; import static com.google.common.collect.Lists.*; import static io.trygvis.esper.testing.nexus.ArtifactXml.repositoryFilter; +import io.trygvis.esper.testing.util.*; import junit.framework.*; +import org.jdom2.*; import java.io.*; import java.util.*; @@ -44,4 +46,21 @@ public class TestXmlParsing extends TestCase { assertEquals(2, flatArtifact.files.size()); } } + + public void testTimelineParsing() throws Exception { + XmlParser parser = new XmlParser(); + + try (InputStream stream = getClass().getResourceAsStream("/nexus/recentlyDeployedArtifacts.xml")) { + Document document = parser.parseDocument(stream).some(); + + NexusEvent event = NexusFeedParser.parseEvent(document.getRootElement().getChild("channel").getChild("item")).some(); + + assertTrue(event instanceof NewSnapshotEvent); + NewSnapshotEvent nse = (NewSnapshotEvent) event; + assertEquals("org.example", nse.artifactId.groupId); + assertEquals("example", nse.artifactId.artifactId); + assertEquals("1.0-SNAPSHOT", nse.artifactId.version); + assertEquals("20121204.122640-536", nse.snapshotTimestamp); + } + } } diff --git a/src/test/resources/nexus/recentlyDeployedArtifacts.xml b/src/test/resources/nexus/recentlyDeployedArtifacts.xml new file mode 100755 index 0000000..1fe22d9 --- /dev/null +++ b/src/test/resources/nexus/recentlyDeployedArtifacts.xml @@ -0,0 +1,24 @@ + + + + New deployed artifacts + http://localhost:8081/repository/service/local/feeds/recentlyDeployedArtifacts + New deployed artifacts in all Nexus repositories (deployed). + Tue, 04 Dec 2012 12:26:41 GMT + Nexus 1.9.2.3 + 2012-12-04T12:26:41Z + + org.example:example:1.0-20121204.122640-536 + http://hostname/repository/content/repositories/snapshots/org/example/example/1.0-SNAPSHOT/example-1.0-20121204.122640-536.pom + + The artifact 'org.example:example:1.0-20121204.122640-536' in repository 'Snapshots' was + deployed.Action was initiated by user "developer". + Request originated from IP address 1.2.3.4. + + Tue, 04 Dec 2012 12:26:40 GMT + http://hostname/repository/content/repositories/snapshots/org/example/example/1.0-SNAPSHOT/example-1.0-20121204.122640-536.pom + developer + 2012-12-04T12:26:40Z + + + diff --git a/src/test/resources/nexus/search-1.xml b/src/test/resources/nexus/search-1.xml index b501491..75bfdc9 100755 --- a/src/test/resources/nexus/search-1.xml +++ b/src/test/resources/nexus/search-1.xml @@ -2674,4 +2674,3 @@ -- -- cgit v1.2.3