diff options
author | Trygve Laugstøl <trygvis@inamo.no> | 2012-12-05 13:09:49 +0100 |
---|---|---|
committer | Trygve Laugstøl <trygvis@inamo.no> | 2012-12-07 20:06:53 +0100 |
commit | 1c2c16858e95db9ae90726fa0da69b88457c1807 (patch) | |
tree | dca86c80f715281bf39388de2a42fdba9e0ceef7 /src/main/java/io/trygvis/esper/testing | |
parent | 6d1dc3b1ca077312674ef05cd88ca5a7858bffd2 (diff) | |
download | esper-testing-1c2c16858e95db9ae90726fa0da69b88457c1807.tar.gz esper-testing-1c2c16858e95db9ae90726fa0da69b88457c1807.tar.bz2 esper-testing-1c2c16858e95db9ae90726fa0da69b88457c1807.tar.xz esper-testing-1c2c16858e95db9ae90726fa0da69b88457c1807.zip |
o More common XML parsing and HTTP client code. o Reimplemented the Nexus code to consume the timeline instead of calculating its own diff.
Diffstat (limited to 'src/main/java/io/trygvis/esper/testing')
16 files changed, 598 insertions, 289 deletions
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/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<GitoriousRepositoryDto, ActorRef<GitoriousRepository>> repositoryManager = new ObjectManager<>("", repositories, new ObjectFactory<GitoriousRepositoryDto, ActorRef<GitoriousRepository>>() { public ActorRef<GitoriousRepository> 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 index ed4cb59..e31fcfe 100644..100755 --- 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<Document> d = xmlHttpClient.fetch(uri); + + if(d.isNone()) { + return new JenkinsXml(Option.<String>none(), Option.<String>none(), Option.<String>none(), Collections.<JenkinsJobEntryXml>emptyList()); + } + + Element root = d.some().getRootElement(); List<JenkinsJobEntryXml> 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<JenkinsJobXml> fetchJob(URI uri) throws IOException, JDOMException, XMLStreamException { + Option<Document> 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<URI> 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 index 9aad891..7a7f6af 100644..100755 --- 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 index 144913e..b732bfa 100644..100755 --- 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<ArtifactDto> { - 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> { 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<Document> d = xmlHttpClient.fetch(uri); + + if (d.isNone()) { + return new NexusFeed(Collections.<NexusEvent>emptyList()); + } + + Document document = d.some(); + + return NexusFeedParser.parseDocument(document); } public ArtifactSearchResult fetchIndex(String groupId, Option<String> repositoryId) throws IOException { ArtifactSearchResult aggregate = fetchIndexPage(groupId, repositoryId, Option.<Integer>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<NexusServerDto> 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<NexusServerDto> 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<NexusRepositoryDto> 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<NexusRepositoryDto> 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<NexusRepositoryDto> 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<NexusRepositoryDto> 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<String> snapshotVersion, List<ArtifactFile> 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<ArtifactDto> list = new ArrayList<>(); while (rs.next()) { - list.add(artifactDto(url, repositoryId, rs)); + list.add(artifactDto(rs)); } return list; } } + + public Option<ArtifactDto> 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<LocalDateTime> discoveryDate; - public final Option<LocalDateTime> lastUpdate; - public final Option<LocalDateTime> lastSuccessfulUpdate; - NexusRepositoryDto(String repositoryId, URI nexusUrl, String[] groupIds, Option<LocalDateTime> discoveryDate, Option<LocalDateTime> lastUpdate, Option<LocalDateTime> 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<Element> channels = document.getRootElement().getContent(element("channel")); + + List<NexusEvent> events = new ArrayList<>(); + + if (channels.size() != 1) { + return new NexusFeed(events); + } + + Element channel = channels.get(0); + + for (Element item : channel.getContent(element("item"))) { + Option<NexusEvent> e = parseEvent(item); + + if (e.isNone()) { + continue; + } + + events.add(e.some()); + } + + return new NexusFeed(events); + } + + public static Option<NexusEvent> parseEvent(Element item) { + String title = item.getChildText("title"); + + Option<String> guid = Option.fromNull(item.getChildText("guid")); + Option<String> creator = Option.fromNull(item.getChildText("creator", dc)); + Option<DateTime> date = Option.fromNull(item.getChildText("date", dc)).bind(new F<String, Option<DateTime>>() { + @Override + public Option<DateTime> 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<String> 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.<NexusEvent>some(new NewSnapshotEvent(guid.some(), id, classifier, creator.some(), + date.some(), matcher.group(2), URI.create(item.getChildText("link")))); + } + + return none(); + } +} + +class NexusFeed { + List<NexusEvent> events = new ArrayList<>(); + + NexusFeed(List<NexusEvent> events) { + this.events = events; + } +} + +abstract class NexusEvent { + public final String guid; + public final ArtifactId artifactId; + public final Option<String> classifier; + public final String creator; + public final DateTime date; + + NexusEvent(String guid, ArtifactId artifactId, Option<String> 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<String> 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<NexusServerDto, ActorRef<NexusServer>> serverManager = new ObjectManager<>("Nexus server", Collections.<NexusServerDto>emptySet(), new ObjectFactory<NexusServerDto, ActorRef<NexusServer>>() { public ActorRef<NexusServer> 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<NexusServerDto> 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<ArtifactId, ArtifactXml> 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<NexusRepositoryDto> r = dao.findRepository(server.uuid, repositoryId); - for (ArtifactXml xml : result.artifacts) { - artifactsInNexus.put(xml.id, xml); - } + if(r.isNone()) { + continue; } - Map<ArtifactId, ArtifactDto> artifactsInDatabase = new HashMap<>(); - for (ArtifactDto dto : dao.findArtifactsInRepository(server.url, repository.repositoryId)) { - artifactsInDatabase.put(dto.id, dto); - } + NexusRepositoryDto repository = r.some(); - ArrayList<FlatArtifact> created = new ArrayList<>(); - ArrayList<FlatArtifact> kept = new ArrayList<>(); - ArrayList<ArtifactDto> removed = new ArrayList<>(); + Option<ArtifactDto> a = dao.findArtifact(repository.uuid, event.artifactId); - for (ArtifactXml xml : artifactsInNexus.values()) { - Option<FlatArtifact> o = xml.flatten(repository.repositoryId); + if(event instanceof NewSnapshotEvent) { + NewSnapshotEvent newSnapshotEvent = (NewSnapshotEvent) event; - if(o.isNone()) { - continue; - } + Option<String> 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<ArtifactFile> 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.<String>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<ArtifactId, ArtifactXml> 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<ArtifactId, ArtifactDto> artifactsInDatabase = new HashMap<>(); +// for (ArtifactDto dto : dao.findArtifactsInRepository(server.url, repository.repositoryId)) { +// artifactsInDatabase.put(dto.id, dto); +// } +// +// ArrayList<FlatArtifact> created = new ArrayList<>(); +// ArrayList<FlatArtifact> kept = new ArrayList<>(); +// ArrayList<ArtifactDto> removed = new ArrayList<>(); +// +// for (ArtifactXml xml : artifactsInNexus.values()) { +// Option<FlatArtifact> 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.<String>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 <A extends TransactionalActor> ActorRef<A> threadedActor(String threadName, long delay, DataSource dataSource, A actor) { - return new ThreadedActor<>(dataSource, threadName, actor, delay); + public static <A extends TransactionalActor> ActorRef<A> threadedActor(String threadName, long delay, DataSource dataSource, String name, A actor) { + return new ThreadedActor<>(dataSource, threadName, name, actor, delay); } - public static <A extends TransactionalActor> ActorRef<A> scheduledActorWithFixedDelay(ScheduledExecutorService scheduledExecutorService, long initialDelay, long delay, TimeUnit unit, DataSource dataSource, A actor) { - return new ScheduledActor<>(scheduledExecutorService, initialDelay, delay, unit, dataSource, actor); + public static <A extends TransactionalActor> ActorRef<A> 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<A extends TransactionalActor> 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<A> 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<A>(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/EasySSLSocketFactory.java b/src/main/java/io/trygvis/esper/testing/util/EasySSLSocketFactory.java index b8a2904..c1f1a7e 100755 --- a/src/main/java/io/trygvis/esper/testing/EasySSLSocketFactory.java +++ b/src/main/java/io/trygvis/esper/testing/util/EasySSLSocketFactory.java @@ -1,4 +1,4 @@ -package io.trygvis.esper.testing; +package io.trygvis.esper.testing.util; /* * ==================================================================== diff --git a/src/main/java/io/trygvis/esper/testing/EasyX509TrustManager.java b/src/main/java/io/trygvis/esper/testing/util/EasyX509TrustManager.java index 1762c6f..5a4c4d3 100755 --- a/src/main/java/io/trygvis/esper/testing/EasyX509TrustManager.java +++ b/src/main/java/io/trygvis/esper/testing/util/EasyX509TrustManager.java @@ -1,4 +1,4 @@ -package io.trygvis.esper.testing; +package io.trygvis.esper.testing.util; /* * ==================================================================== diff --git a/src/main/java/io/trygvis/esper/testing/HttpClient.java b/src/main/java/io/trygvis/esper/testing/util/HttpClient.java index ff2effd..ef6f2a9 100755 --- a/src/main/java/io/trygvis/esper/testing/HttpClient.java +++ b/src/main/java/io/trygvis/esper/testing/util/HttpClient.java @@ -1,5 +1,8 @@ -package io.trygvis.esper.testing; +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.*; @@ -9,12 +12,45 @@ 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 { +public class HttpClient<A> { - public static HTTPCache createHttpClient(Config config) { + private final HTTPCache http; + private final F<InputStream, Option<A>> f; + + public HttpClient(HTTPCache http, F<InputStream, Option<A>> f) { + this.http = http; + this.f = f; + } + + public Option<A> 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)); 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<Document> httpClient; + + public XmlHttpClient(HTTPCache http) { + final XmlParser parser = new XmlParser(); + httpClient = new HttpClient<>(http, new F<InputStream, Option<Document>>() { + public Option<Document> f(InputStream inputStream) { + return parser.parseDocument(inputStream); + } + }); + } + + public Option<Document> 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<Document> 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(); + } + } +} |