Java tutorial
/* * Copyright 2014 Carsten Rambow, elomagic. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.elomagic.carafile.client; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.security.MessageDigest; import java.util.Arrays; import java.util.Collections; import java.util.Random; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; import org.apache.http.HttpHeaders; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.util.thread.ExecutorThreadPool; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import de.elomagic.carafile.share.ChunkData; import de.elomagic.carafile.share.JsonUtil; import de.elomagic.carafile.share.MetaData; import de.elomagic.carafile.share.PeerData; /** * * @author carsten.rambow */ public class CaraFileClientTest { private CaraFileClient client; private Server server; private final int PORT = 8895; private static final int DEFAULT_PIECE_SIZE = 1024 * 512; private final byte[] data0 = new byte[DEFAULT_PIECE_SIZE]; private final byte[] data1 = new byte[128]; private String id; private String chunkId0; private String chunkId1; @Before public void before() throws Exception { System.out.println("Starting HTTP server on port " + PORT + "..."); server = new Server(new ExecutorThreadPool(256)); ServerConnector connector = new ServerConnector(server); connector.setPort(PORT); server.setHandler(new SimpleHandler()); server.setConnectors(new Connector[] { connector }); //server.setThreadPool(new ExecutorThreadPool(256)); server.start(); System.out.println("HTTP server started."); client = new CaraFileClient(); } @After public void after() throws Exception { if (server != null) { System.out.println("Stopping HTTP server..."); server.stop(); System.out.println("HTTP server stopped."); } } private URI getURI() { try { return new URI("http://localhost:" + Integer.toString(PORT)); } catch (URISyntaxException ex) { ex.printStackTrace(System.err); return null; } } class SimpleHandler extends AbstractHandler { @Override public void handle(String path, Request rqst, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (path.equals("/registry/listPeers")) { PeerData pd = new PeerData(); pd.setPeerURI(getURI()); String json = JsonUtil.write(Collections.singleton(pd)); byte[] data = json.getBytes("utf-8"); response.setStatus(HttpServletResponse.SC_OK); response.setContentLength(data.length); response.getOutputStream().write(data); response.getOutputStream().flush(); } else if (path.equals("/peer/seedFile/abc.txt")) { String sha1 = DigestUtils.sha1Hex(request.getInputStream()); MetaData md = new MetaData(); md.setId(sha1); String json = JsonUtil.write(md); byte[] data = json.getBytes("utf-8"); response.setStatus(HttpServletResponse.SC_OK); response.setContentLength(data.length); response.getOutputStream().write(data); response.getOutputStream().flush(); } else if (path.startsWith("/registry/findFile/abc")) { MessageDigest messageDigest = DigestUtils.getSha1Digest(); messageDigest.update(data0); messageDigest.update(data1); MetaData md = new MetaData(); md.setId("abc"); md.addChunk(new ChunkData(DigestUtils.sha1Hex(data0), getURI())); md.addChunk(new ChunkData(DigestUtils.sha1Hex(data1), getURI())); md.setChunkSize(DEFAULT_PIECE_SIZE); md.setSize(md.getChunkSize() + 128); String json = JsonUtil.write(md); byte[] data = json.getBytes("utf-8"); response.setStatus(HttpServletResponse.SC_OK); response.setContentLength(data.length); response.getOutputStream().write(data); response.getOutputStream().flush(); } else if (path.startsWith("/registry/findFile/xyz")) { response.setStatus(HttpServletResponse.SC_NOT_FOUND); } else if (path.startsWith("/registry/findFile/" + id)) { MessageDigest messageDigest = DigestUtils.getSha1Digest(); messageDigest.update(data0); messageDigest.update(data1); MetaData md = new MetaData(); md.setId(id); md.addChunk(new ChunkData(DigestUtils.sha1Hex(data0), getURI())); md.addChunk(new ChunkData(DigestUtils.sha1Hex(data1), getURI())); md.setChunkSize(DEFAULT_PIECE_SIZE); md.setSize(md.getChunkSize() + 128); String json = JsonUtil.write(md); byte[] data = json.getBytes("utf-8"); response.setStatus(HttpServletResponse.SC_OK); response.setContentLength(data.length); response.getOutputStream().write(data); response.getOutputStream().flush(); } else if (path.equals("/registry/deleteFile/123")) { response.setStatus(HttpServletResponse.SC_OK); response.getOutputStream().flush(); } else if (path.equals("/registry/deleteFile/xyz")) { response.setStatus(HttpServletResponse.SC_NOT_FOUND); response.getOutputStream().flush(); } else if (path.startsWith("/peer/leechChunk/" + chunkId0)) { response.setStatus(HttpServletResponse.SC_OK); response.addHeader(HttpHeaders.CONTENT_LENGTH, Integer.toString(DEFAULT_PIECE_SIZE)); response.getOutputStream().write(data0); response.getOutputStream().flush(); } else if (path.startsWith("/peer/leechChunk/" + chunkId1)) { response.setStatus(HttpServletResponse.SC_OK); response.addHeader(HttpHeaders.CONTENT_LENGTH, "128"); response.getOutputStream().write(data1); response.getOutputStream().flush(); } else { response.setStatus(HttpServletResponse.SC_NOT_FOUND); } } } @Test public void testFindFile() throws Exception { MetaData md1 = client.setRegistryURI(getURI()).findFile("abc"); Assert.assertEquals("abc", md1.getId()); MetaData md2 = client.setRegistryURI(getURI()).findFile("xyz"); Assert.assertNull(md2); } @Test(expected = IOException.class) public void testDownload1() throws Exception { client.setRegistryURI(getURI()).downloadFile("xyz", new ByteArrayOutputStream()); } @Test public void testDownload2() throws Exception { Random random = new Random(); random.nextBytes(data0); random.nextBytes(data1); chunkId0 = Hex.encodeHexString(DigestUtils.sha1(data0)); chunkId1 = Hex.encodeHexString(DigestUtils.sha1(data1)); MessageDigest messageDigest = DigestUtils.getSha1Digest(); messageDigest.update(data0); messageDigest.update(data1); id = Hex.encodeHexString(messageDigest.digest()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); client.setRegistryURI(getURI()).downloadFile(id, baos); Assert.assertArrayEquals(data0, Arrays.copyOf(baos.toByteArray(), DEFAULT_PIECE_SIZE)); Assert.assertArrayEquals(data1, Arrays.copyOfRange(baos.toByteArray(), DEFAULT_PIECE_SIZE, DEFAULT_PIECE_SIZE + 128)); } @Test public void testUpload() throws Exception { byte[] data = new byte[DEFAULT_PIECE_SIZE + 128]; Random random = new Random(); random.nextBytes(data); client.setRegistryURI(getURI()).uploadFile(new ByteArrayInputStream(data), "abc.txt", data.length); } @Test public void testDelete1() throws Exception { client.setRegistryURI(getURI()).deleteFile("123", false); } @Test public void testDelete2() throws Exception { client.setRegistryURI(getURI()).deleteFile("xyz", true); } @Test(expected = FileNotFoundException.class) public void testDelete3() throws Exception { client.setRegistryURI(getURI()).deleteFile("xyz", false); } }