/** * Function that checks if given file is being searched Returners true if current file has a right * type and wasn't used more than _numOfMonth * * @param file - file to check. * @return true if given file fits users criteria for search */ private boolean isFileSearched(File file) { Path p = file.toPath(); long cutoff = System.currentTimeMillis() - ((long) _numOfMonth * 30 * 24 * 60 * 60 * 1000); try { FileTime time = (FileTime) Files.getAttribute(p, "lastAccessTime", LinkOption.NOFOLLOW_LINKS); long lastAccessed = time.toMillis(); if (lastAccessed <= cutoff && file.isHidden() == false) { if (_word) if (file.getName().endsWith(".doc") || file.getName().endsWith(".docx") || file.getName().endsWith(".DOC") || file.getName().endsWith(".DOCX")) return true; if (_exel) if (file.getName().endsWith(".xls") || file.getName().endsWith(".xlsx") || file.getName().endsWith(".XLS") || file.getName().endsWith(".XLSX")) return true; if (_pow) if (file.getName().endsWith(".ppt") || file.getName().endsWith(".pptx") || file.getName().endsWith(".PPT") || file.getName().endsWith(".PPTX")) return true; if (_pdf) if (file.getName().endsWith(".pdf") || file.getName().endsWith(".PDF")) return true; } } catch (IOException e) { return false; } return false; }
@Override public void initialize(URL location, ResourceBundle resources) { // TODO Auto-generated method stub this.tbViewColData.setCellValueFactory(cellData -> cellData.getValue().DataProperty()); this.tbViewColArquivo.setCellValueFactory(cellData -> cellData.getValue().FileNameProperty()); File file = new File("./relatorios/"); if (file.exists()) { File[] m = file.listFiles(); for (File f : m) { Path path = FileSystems.getDefault().getPath("./relatorios"); BasicFileAttributes attributes; try { attributes = Files.readAttributes(path, BasicFileAttributes.class); FileTime creationTime = attributes.creationTime(); data.add(new TableHistoricoData(creationTime.toString(), f.getPath())); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.tbViewHistorico.getItems().addAll(data); } this.tbViewHistorico.setRowFactory( tv -> { TableRow<TableHistoricoData> row = new TableRow<>(); row.setOnMouseClicked( event -> { if (event.getClickCount() == 2 && (!row.isEmpty())) { TableHistoricoData rowData = row.getItem(); try { Thread t = new Thread() { public void run() { if (Desktop.isDesktopSupported()) if (Desktop.getDesktop().isSupported(Action.OPEN)) { Desktop op = Desktop.getDesktop(); if (new File(rowData.getFileName()).exists()) { try { op.open(new File(rowData.getFileName())); } catch (IOException e) { e.printStackTrace(); } } } } }; t.start(); } catch (Exception e) { e.printStackTrace(); } } }); return row; }); }
@NewEnv(type = NewEnv.Type.NONE) @Test public void testGetLastModifiedTime() throws IOException { Assert.assertEquals(Long.MIN_VALUE, NettyRepository.getLastModifiedTime(null)); Assert.assertEquals(Long.MIN_VALUE, NettyRepository.getLastModifiedTime(Paths.get("Unknown"))); FileTime fileTime = Files.getLastModifiedTime(_repositoryPath); Assert.assertEquals(fileTime.toMillis(), NettyRepository.getLastModifiedTime(_repositoryPath)); }
@Override public void setTimes(FileTime lastModifiedTime, FileTime lastAccessTime, FileTime createTime) throws IOException { // null => don't change if (lastModifiedTime == null && lastAccessTime == null) { // no effect return; } // permission check file.checkWrite(); int fd = file.openForAttributeAccess(followLinks); try { // if not changing both attributes then need existing attributes if (lastModifiedTime == null || lastAccessTime == null) { try { UnixFileAttributes attrs = UnixFileAttributes.get(fd); if (lastModifiedTime == null) lastModifiedTime = attrs.lastModifiedTime(); if (lastAccessTime == null) lastAccessTime = attrs.lastAccessTime(); } catch (UnixException x) { x.rethrowAsIOException(file); } } // uptime times long modValue = lastModifiedTime.to(TimeUnit.MICROSECONDS); long accessValue = lastAccessTime.to(TimeUnit.MICROSECONDS); boolean retry = false; try { futimes(fd, accessValue, modValue); } catch (UnixException x) { // if futimes fails with EINVAL and one/both of the times is // negative then we adjust the value to the epoch and retry. if (x.errno() == UnixConstants.EINVAL && (modValue < 0L || accessValue < 0L)) { retry = true; } else { x.rethrowAsIOException(file); } } if (retry) { if (modValue < 0L) modValue = 0L; if (accessValue < 0L) accessValue = 0L; try { futimes(fd, accessValue, modValue); } catch (UnixException x) { x.rethrowAsIOException(file); } } } finally { close(fd); } }
public static void main(String[] args) throws IOException { Path dir = Paths.get(System.getProperty("user.home"), ".sandbox"); Files.createDirectories(dir); Path file = Paths.get(dir.toString(), "timestamp-test.txt"); List<String> lines = new ArrayList<>(); for (int i = 0; i < 10; i++) { lines.add(RandomStringUtils.randomAscii(20)); } Files.write(file, lines); FileTime fileTime = Files.getLastModifiedTime(file); System.out.println(fileTime); System.out.println(LocalDateTime.ofInstant(fileTime.toInstant(), ZoneId.systemDefault())); }
/** * May be called to refresh the state attributes used to detect changes e.g., file existence, size * and last-modified time once re-loading is successfully completed. If the file does not exist * then the attributes are reset to an "unknown" state. * * @throws IOException If failed to access the file (if exists) * @see #resetReloadAttributes() */ public void updateReloadAttributes() throws IOException { if (exists()) { long size = size(); FileTime modifiedTime = lastModified(); if (size >= 0L && modifiedTime != null) { lastExisted.set(true); lastSize.set(size); lastModified.set(modifiedTime.toMillis()); return; } } resetReloadAttributes(); }
public static boolean isModified(SyncFile syncFile, Path filePath) { if (filePath == null) { return true; } try { FileTime fileTime = Files.getLastModifiedTime(filePath); long modifiedTime = syncFile.getModifiedTime(); if (OSDetector.isUnix()) { modifiedTime = modifiedTime / 1000 * 1000; } if ((fileTime.toMillis() <= modifiedTime) && FileKeyUtil.hasFileKey(filePath, syncFile.getSyncFileId())) { return false; } } catch (IOException ioe) { if (_logger.isDebugEnabled()) { _logger.debug(ioe.getMessage(), ioe); } } try { if ((syncFile.getSize() > 0) && (syncFile.getSize() != Files.size(filePath))) { return true; } } catch (IOException ioe) { if (_logger.isDebugEnabled()) { _logger.debug(ioe.getMessage(), ioe); } } try { String checksum = getChecksum(filePath); return !checksumsEqual(checksum, syncFile.getChecksum()); } catch (IOException ioe) { if (_logger.isDebugEnabled()) { _logger.debug(ioe.getMessage(), ioe); } return true; } }
public FakeProjectFilesystem(Clock clock, Path root, Set<Path> files) { super(root); // We use LinkedHashMap to preserve insertion order, so the // behavior of this test is consistent across versions. (It also lets // us write tests which explicitly test iterating over entries in // different orders.) fileContents = new LinkedHashMap<>(); fileLastModifiedTimes = new LinkedHashMap<>(); FileTime modifiedTime = FileTime.fromMillis(clock.currentTimeMillis()); for (Path file : files) { fileContents.put(file, new byte[0]); fileLastModifiedTimes.put(file, modifiedTime); } fileAttributes = new LinkedHashMap<>(); symLinks = new LinkedHashMap<>(); directories = new LinkedHashSet<>(); directories.add(Paths.get("")); for (Path file : files) { Path dir = file.getParent(); while (dir != null) { directories.add(dir); dir = dir.getParent(); } } this.clock = Preconditions.checkNotNull(clock); // Generally, tests don't care whether files exist. ignoreValidityOfPaths = true; }
@Override public void execute() throws IOException { Attributes remoteAttributes = remoteIndex.get(path); Path rootDirectory = Registry.getInstance().getRootDirectory(); try { // TODO get rid of getRootDirectory, stupid (non)dependency new NetworkClient(rootDirectory).request(remoteAttributes.getAddress(), path); } catch (URISyntaxException e) { logger.error(e); } if (logger.isTraceEnabled()) {} logger.trace( String.format("Setting time on %1s to %2s", path, remoteAttributes.lastModifiedTime())); rootDirectory .resolve(path) .setAttribute( "basic:lastModifiedTime", FileTime.fromMillis(remoteAttributes.lastModifiedTime()), LinkOption.NOFOLLOW_LINKS); localIndex.addFromRemote(path, remoteAttributes); }
public void touch(Path fileToTouch) throws IOException { if (exists(fileToTouch)) { setLastModifiedTime(fileToTouch, FileTime.fromMillis(System.currentTimeMillis())); } else { createNewFile(fileToTouch); } }
@Override public void mkdirs(Path path) throws IOException { for (int i = 0; i < path.getNameCount(); i++) { Path subpath = path.subpath(0, i + 1); directories.add(subpath); fileLastModifiedTimes.put(subpath, FileTime.fromMillis(clock.currentTimeMillis())); } }
@Override public String toString() { if (!initialized) { return Constantes.OBJECT_NOT_INITIALIZED; } return String.format( "%s;%04X;%d;%s;%s", hash, flags, Long.valueOf(size), lastModif.toString(), name); }
@Override public boolean equals(Object o) { return o == this || o instanceof SourceId && getStorage().equals(((SourceId) o).getStorage()) && myModulePath.equals(((SourceId) o).myModulePath) && myMtime.equals(((SourceId) o).myMtime); }
// do not make updateLastAccessed synchronized public static void updateLastAccessed(File file) { try { Files.setAttribute( file.toPath(), "lastAccessTime", FileTime.fromMillis(new Date().getTime())); } catch (Exception e) { e.printStackTrace(); } }
public static void setModifiedTime(Path filePath, long modifiedTime) throws IOException { if (!Files.exists(filePath)) { return; } FileTime fileTime = FileTime.fromMillis(modifiedTime); Files.setLastModifiedTime(filePath, fileTime); }
/** * @return {@code true} if the watched file has probably been changed * @throws IOException If failed to query file data */ public boolean checkReloadRequired() throws IOException { boolean exists = exists(); // if existence state changed from last time if (exists != lastExisted.getAndSet(exists)) { return true; } if (!exists) { // file did not exist and still does not exist resetReloadAttributes(); return false; } long size = size(); if (size < 0L) { // means file no longer exists resetReloadAttributes(); return true; } // if size changed then obviously need reload if (size != lastSize.getAndSet(size)) { return true; } FileTime modifiedTime = lastModified(); if (modifiedTime == null) { // means file no longer exists resetReloadAttributes(); return true; } long timestamp = modifiedTime.toMillis(); if (timestamp != lastModified.getAndSet(timestamp)) { return true; } return false; }
@Test public void testFile() throws Exception { byte[] data = FileServerTestUtil.createRandomData(1024); long lastModified = FileServerTestUtil.getFileSystemTime(System.currentTimeMillis() - Time.DAY); FileResponse fileResponse = new FileResponse(_path, data.length, lastModified, false); NoticeableFuture<FileResponse> noticeableFuture = _asyncBroker.post(_path); _fileResponseChannelHandler.channelRead( _channelHandlerContext, fileResponse, FileServerTestUtil.wrapFirstHalf(data)); ChannelHandler channelHandler = _channelPipeline.first(); Assert.assertTrue(channelHandler instanceof FileUploadChannelHandler); FileUploadChannelHandler fileUploadChannelHandler = (FileUploadChannelHandler) channelHandler; _channelPipeline.fireChannelRead(FileServerTestUtil.wrapSecondHalf(data)); channelHandler = _channelPipeline.first(); Assert.assertFalse(channelHandler instanceof FileUploadChannelHandler); Assert.assertSame(fileResponse, fileUploadChannelHandler.fileResponse); Assert.assertSame(fileResponse, noticeableFuture.get()); Path localFile = fileResponse.getLocalFile(); Assert.assertNotNull(localFile); FileTime fileTime = Files.getLastModifiedTime(localFile); Assert.assertEquals(lastModified, fileTime.toMillis()); Assert.assertArrayEquals(data, Files.readAllBytes(localFile)); Files.delete(localFile); }
@Override public void writeBytesToPath(byte[] bytes, Path path, FileAttribute<?>... attrs) throws IOException { Path normalizedPath = MorePaths.normalize(path); fileContents.put(normalizedPath, Preconditions.checkNotNull(bytes)); fileAttributes.put(normalizedPath, ImmutableSet.copyOf(attrs)); Path directory = normalizedPath.getParent(); while (directory != null) { directories.add(directory); directory = directory.getParent(); } fileLastModifiedTimes.put(normalizedPath, FileTime.fromMillis(clock.currentTimeMillis())); }
/** * @param line structured as SHA256;0000;size;YYYY-MM-DDTHH:MM:SS;name * @throws IllegalArgumentException */ public FileInfo(String line) throws IllegalArgumentException { if (line == null) { throw new IllegalArgumentException("line must not be null"); } String[] fields = line.split(";"); if (fields.length < 5) { throw new IllegalArgumentException( String.format("line has %d fields instead of 5", fields.length)); } byte[] hex = null; try { hex = DatatypeConverter.parseHexBinary(fields[0]); } catch (IllegalArgumentException e) { // exception handled below } if (hex == null || hex.length != HASH_BYTES) { throw new IllegalArgumentException( String.format("%s is not a valid SHA-256 signature", fields[0])); } hash = fields[0]; int val = -1; try { val = Integer.parseInt(fields[1], 16); } catch (NumberFormatException e) { // exception handled below } if (val == -1 || fields[1].length() != 4) { throw new IllegalArgumentException( String.format("%s is not a valid 16 bit status", fields[1])); } flags = val; long len = -1; try { len = Long.parseLong(fields[2]); } catch (NumberFormatException e) { // exception handled below } if (len == -1) { throw new IllegalArgumentException(String.format("%s is not a valid size", fields[2])); } size = len; Instant instant = null; try { instant = Instant.parse(fields[3]); } catch (DateTimeParseException e) { // exception handled below } if (instant == null) { throw new IllegalArgumentException(String.format("%s is not a valid timestamp", fields[3])); } lastModif = FileTime.from(instant); StringBuffer finLigne = new StringBuffer(fields[4]); for (int i = 5; i < fields.length; i++) { finLigne.append(";").append(fields[i]); } if (finLigne.length() == 0) { throw new IllegalArgumentException(String.format("file name is empty")); } name = finLigne.toString(); initialized = true; }
public FileTime secondFileTime(FileTime lastModif) { long millis = lastModif.toMillis(); long diff = millis % 1000; return FileTime.fromMillis(millis - diff); }
/** Converts "standard Unix time"(in seconds, UTC/GMT) to FileTime */ public static final FileTime unixTimeToFileTime(long utime) { return FileTime.from(utime, TimeUnit.SECONDS); }
protected void sendFile( final ChannelHandlerContext channelHandlerContext, FullHttpRequest fullHttpRequest, SyncFile syncFile) throws Exception { Path path = Paths.get(syncFile.getFilePathName()); if (Files.notExists(path)) { _syncTrafficShapingHandler.decrementConnectionsCount(); if (_logger.isTraceEnabled()) { Channel channel = channelHandlerContext.channel(); _logger.trace("Client {}: file not found {}", channel.remoteAddress(), path); } _sendError(channelHandlerContext, NOT_FOUND); return; } if (_logger.isDebugEnabled()) { Channel channel = channelHandlerContext.channel(); _logger.debug("Client {}: sending file {}", channel.remoteAddress(), path); } long modifiedTime = syncFile.getModifiedTime(); long previousModifiedTime = syncFile.getPreviousModifiedTime(); if (OSDetector.isApple()) { modifiedTime = modifiedTime / 1000 * 1000; previousModifiedTime = previousModifiedTime / 1000 * 1000; } FileTime currentFileTime = Files.getLastModifiedTime(path, LinkOption.NOFOLLOW_LINKS); long currentTime = currentFileTime.toMillis(); if ((currentTime != modifiedTime) && (currentTime != previousModifiedTime)) { _syncTrafficShapingHandler.decrementConnectionsCount(); Channel channel = channelHandlerContext.channel(); _logger.error( "Client {}: file modified {}, currentTime {}, modifiedTime " + "{}, previousModifiedTime {}", channel.remoteAddress(), path, currentTime, modifiedTime, previousModifiedTime); _sendError(channelHandlerContext, NOT_FOUND); return; } HttpResponse httpResponse = new DefaultHttpResponse(HTTP_1_1, OK); long size = Files.size(path); HttpUtil.setContentLength(httpResponse, size); HttpHeaders httpHeaders = httpResponse.headers(); MimetypesFileTypeMap mimetypesFileTypeMap = new MimetypesFileTypeMap(); httpHeaders.set( HttpHeaderNames.CONTENT_TYPE, mimetypesFileTypeMap.getContentType(syncFile.getName())); if (HttpUtil.isKeepAlive(fullHttpRequest)) { httpHeaders.set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE); } channelHandlerContext.write(httpResponse); SyncChunkedFile syncChunkedFile = new SyncChunkedFile(path, size, 4 * 1024 * 1024, currentTime); ChannelFuture channelFuture = channelHandlerContext.writeAndFlush( new HttpChunkedInput(syncChunkedFile), channelHandlerContext.newProgressivePromise()); channelFuture.addListener( new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture channelFuture) throws Exception { _syncTrafficShapingHandler.decrementConnectionsCount(); if (channelFuture.isSuccess()) { return; } Throwable exception = channelFuture.cause(); Channel channel = channelHandlerContext.channel(); _logger.error( "Client {}: {}", channel.remoteAddress(), exception.getMessage(), exception); channelHandlerContext.close(); } }); if (!HttpUtil.isKeepAlive(fullHttpRequest)) { channelFuture.addListener(ChannelFutureListener.CLOSE); } }
public long getLastModified() { return myMtime.toMillis(); }
public SourceId locateModule(ModulePath modulePath, long mtime) { return new SourceId(modulePath, FileTime.fromMillis(mtime)); }
/** Converts FileTime to Windows time. */ public static final long fileTimeToWinTime(FileTime ftime) { return (ftime.to(TimeUnit.MICROSECONDS) - WINDOWS_EPOCH_IN_MICROSECONDS) * 10; }
/** @author Emmanuel Hugonnet (c) 2016 Red Hat, inc. */ public class ContentRepositoryTest { private static final boolean IS_WINDOWS = AccessController.doPrivileged( (PrivilegedAction<Boolean>) () -> System.getProperty("os.name", null) .toLowerCase(Locale.ENGLISH) .contains("windows")); private static final FileTime time = FileTime.from(Instant.parse("2007-12-03T10:15:30.00Z")); private ContentRepository repository; private final File rootDir = new File("target", "repository"); private final File tmpRootDir = new File("target", "tmp"); public ContentRepositoryTest() {} @Before public void createRepository() throws IOException { if (rootDir.exists()) { deleteRecursively(rootDir.toPath()); } rootDir.mkdirs(); if (tmpRootDir.exists()) { deleteRecursively(tmpRootDir.toPath()); } tmpRootDir.mkdirs(); repository = ContentRepository.Factory.create(rootDir, tmpRootDir, 0L); } @After public void destroyRepository() throws IOException { deleteRecursively(rootDir.toPath()); deleteRecursively(tmpRootDir.toPath()); repository = null; } private String readFileContent(Path path) throws Exception { try (InputStream in = getFileInputStream(path)) { return readFileContent(in); } } private String readFileContent(InputStream in) throws Exception { try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { byte[] buffer = new byte[8]; int length = 8; while ((length = in.read(buffer, 0, length)) > 0) { out.write(buffer, 0, length); } return out.toString("UTF-8"); } } /** Test of addContent method, of class ContentRepository. */ @Test public void testAddContent() throws Exception { try (InputStream stream = getResourceAsStream("overlay.xhtml")) { String expResult = "0c40ffacd15b0f66d5081a93407d3ff5e3c65a71"; byte[] result = repository.addContent(stream); assertThat(result, is(notNullValue())); assertThat(HashUtil.bytesToHexString(result), is(expResult)); } } /** Test of explodeContent method, of class ContentRepository. */ @Test public void testExplodeContent() throws Exception { byte[] archive = createArchive(Collections.singletonList("overlay.xhtml")); try (ByteArrayInputStream stream = new ByteArrayInputStream(archive)) { byte[] hash = repository.explodeContent(repository.addContent(stream)); String expResult = "b1f18e286615dda0643633ec31f1a17d90e48875"; // hash is different from the simple overlay.xhtml as we add the content folder name in the // computation assertThat(hash, is(notNullValue())); Path content = repository.getContent(hash).getPhysicalFile().toPath(); String contentHtml = readFileContent(content.resolve("overlay.xhtml")); String expectedContentHtml = readFileContent(getResourceAsStream("overlay.xhtml")); assertThat(contentHtml, is(expectedContentHtml)); assertThat(HashUtil.bytesToHexString(hash), is(expResult)); } } /** Test of explodeContent method, of class ContentRepository. */ @Test public void testExplodeSubContent() throws Exception { byte[] archive = createMultiLevelArchive(Collections.singletonList("overlay.xhtml"), "test/archive.zip"); try (ByteArrayInputStream stream = new ByteArrayInputStream(archive)) { byte[] originalHash = repository.addContent(stream); assertThat(originalHash, is(notNullValue())); assertThat( HashUtil.bytesToHexString(originalHash), is("f11be1883895957b06f7e46d784cad60dd015d71")); try { repository.explodeSubContent(originalHash, "test/archive.zip"); fail("Shouldn't be able to explode sub content of unexploded content"); } catch (ExplodedContentException ex) { } byte[] hash = repository.explodeContent(originalHash); // hash is different from the simple overlay.xhtml as we add the content folder name in the // computation assertThat(hash, is(notNullValue())); assertThat(HashUtil.bytesToHexString(hash), is("5ab326c763fadad903d0e9bbfecbb42e69a1b8b4")); Path content = repository.getContent(hash).getPhysicalFile().toPath(); String contentHtml = readFileContent(content.resolve("overlay.xhtml")); String expectedContentHtml = readFileContent(getResourceAsStream("overlay.xhtml")); assertThat(contentHtml, is(expectedContentHtml)); Path archiveFile = content.resolve("test").resolve("archive.zip"); assertTrue(Files.exists(archiveFile)); assertTrue(PathUtil.isArchive(archiveFile)); byte[] fullyExplodedHash = repository.explodeSubContent(hash, "test/archive.zip"); assertThat(fullyExplodedHash, is(notNullValue())); assertThat( HashUtil.bytesToHexString(fullyExplodedHash), is("231f4d042711f017d7f8c45aa4affcccbd4d67f4")); content = repository .getContent(repository.explodeSubContent(hash, "test/archive.zip")) .getPhysicalFile() .toPath(); Path directory = content.resolve("test").resolve("archive.zip"); assertTrue("Should not be a zip file", Files.isDirectory(directory)); assertThat(contentHtml, is(expectedContentHtml)); } } private byte[] createMultiLevelArchive(List<String> resources, String archivePath) throws IOException { try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()) { try (ZipOutputStream out = new ZipOutputStream(buffer)) { for (String resourcePath : resources) { ZipEntry entry = new ZipEntry(resourcePath); entry.setLastModifiedTime(time); out.putNextEntry(entry); try (InputStream in = getResourceAsStream(resourcePath)) { StreamUtils.copyStream(in, out); } out.closeEntry(); } ZipEntry entry = new ZipEntry("test/"); entry.setLastModifiedTime(time); out.putNextEntry(entry); out.closeEntry(); entry = new ZipEntry(archivePath); entry.setLastModifiedTime(time); out.putNextEntry(entry); try (InputStream in = new ByteArrayInputStream(createArchive(resources))) { StreamUtils.copyStream(in, out); } out.closeEntry(); } return buffer.toByteArray(); } } private byte[] createArchive(List<String> resources) throws IOException { try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()) { try (ZipOutputStream out = new ZipOutputStream(buffer)) { for (String resourcePath : resources) { ZipEntry entry = new ZipEntry(resourcePath); entry.setLastModifiedTime(time); out.putNextEntry(entry); try (InputStream in = getResourceAsStream(resourcePath)) { StreamUtils.copyStream(in, out); } out.closeEntry(); } } return buffer.toByteArray(); } } private byte[] createContentArchive() throws IOException { try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()) { try (ZipOutputStream out = new ZipOutputStream(buffer)) { ZipEntry entry = new ZipEntry("overlay.xhtml"); entry.setLastModifiedTime(time); out.putNextEntry(entry); try (InputStream in = getResourceAsStream("overlay.xhtml")) { StreamUtils.copyStream(in, out); } out.closeEntry(); entry = new ZipEntry("test.jsp"); entry.setLastModifiedTime(time); out.putNextEntry(entry); try (InputStream in = new ByteArrayInputStream("this is a test".getBytes(StandardCharsets.UTF_8))) { StreamUtils.copyStream(in, out); } out.closeEntry(); entry = new ZipEntry("empty-dir/"); entry.setLastModifiedTime(time); out.putNextEntry(entry); out.closeEntry(); assertTrue(entry.isDirectory()); entry = new ZipEntry("test/"); entry.setLastModifiedTime(time); out.putNextEntry(entry); out.closeEntry(); assertTrue(entry.isDirectory()); entry = new ZipEntry("test/empty-file.txt"); entry.setLastModifiedTime(time); out.putNextEntry(entry); try (InputStream in = HashUtil.emptyStream()) { StreamUtils.copyStream(in, out); } out.closeEntry(); } return buffer.toByteArray(); } } /** Test of explodeContent method, of class ContentRepository. */ @Test public void testChangeExplodedContent() throws Exception { byte[] archive = createArchive(Collections.singletonList("overlay.xhtml")); try (ByteArrayInputStream stream = new ByteArrayInputStream(archive)) { byte[] hash = repository.explodeContent(repository.addContent(stream)); String expResult = "b1f18e286615dda0643633ec31f1a17d90e48875"; // hash is different from the simple overlay.xhtml as we add the content folder name in the // computation assertThat(hash, is(notNullValue())); Path content = repository.getContent(hash).getPhysicalFile().toPath(); String contentHtml = readFileContent(content.resolve("overlay.xhtml")); String expectedContentHtml = readFileContent(getResourceAsStream("overlay.xhtml")); assertThat(contentHtml, is(expectedContentHtml)); assertThat(HashUtil.bytesToHexString(hash), is(expResult)); String updatedExpectedResult = "161a2c95b16d5ffede0721c2cec984ca51009082"; hash = repository.addContentToExploded( hash, Collections.singletonList( new ExplodedContent( "test.jsp", new ByteArrayInputStream("this is a test".getBytes(StandardCharsets.UTF_8)))), true); assertThat(hash, is(notNullValue())); assertThat(HashUtil.bytesToHexString(hash), is(updatedExpectedResult)); try (InputStream addedContent = repository.readContent(hash, "test.jsp")) { assertThat(addedContent, is(notNullValue())); assertThat(readFileContent(addedContent), is("this is a test")); } content = repository.getContent(hash).getPhysicalFile().toPath(); assertThat(content.toFile().list().length, is(2)); hash = repository.removeContentFromExploded(hash, Collections.singletonList("test.jsp")); assertThat(hash, is(notNullValue())); assertThat(HashUtil.bytesToHexString(hash), is(expResult)); updatedExpectedResult = "a44921155d75009d885db3357005b85b435cf59f"; hash = repository.addContentToExploded( hash, Collections.singletonList( new ExplodedContent( "test.jsp", new ByteArrayInputStream( "this is an overwrite test".getBytes(StandardCharsets.UTF_8)))), true); assertThat(hash, is(notNullValue())); assertThat(HashUtil.bytesToHexString(hash), is(updatedExpectedResult)); try (InputStream addedContent = repository.readContent(hash, "test.jsp")) { assertThat(addedContent, is(notNullValue())); assertThat(readFileContent(addedContent), is("this is an overwrite test")); } try { hash = repository.addContentToExploded( hash, Collections.singletonList( new ExplodedContent( "test.jsp", new ByteArrayInputStream( "this is a failure test".getBytes(StandardCharsets.UTF_8)))), false); fail("Overwritting shouldn't work"); } catch (ExplodedContentException ex) { } } } @Test public void testListContents() throws Exception { byte[] archive = createArchive(Collections.singletonList("overlay.xhtml")); try (ByteArrayInputStream stream = new ByteArrayInputStream(archive)) { byte[] hash = repository.explodeContent(repository.addContent(stream)); String expResult = "b1f18e286615dda0643633ec31f1a17d90e48875"; // hash is different from the simple overlay.xhtml as we add the content folder name in the // computation assertThat(hash, is(notNullValue())); Path content = repository.getContent(hash).getPhysicalFile().toPath(); String contentHtml = readFileContent(content.resolve("overlay.xhtml")); String expectedContentHtml = readFileContent(getResourceAsStream("overlay.xhtml")); assertThat(contentHtml, is(expectedContentHtml)); assertThat(HashUtil.bytesToHexString(hash), is(expResult)); String updatedExpectedResult = "161a2c95b16d5ffede0721c2cec984ca51009082"; hash = repository.addContentToExploded( hash, Collections.singletonList( new ExplodedContent( "test.jsp", new ByteArrayInputStream("this is a test".getBytes(StandardCharsets.UTF_8)))), true); assertThat(hash, is(notNullValue())); assertThat(HashUtil.bytesToHexString(hash), is(updatedExpectedResult)); List<String> contents = repository .listContent(hash, "", ContentFilter.Factory.createContentFilter(-1, false)) .stream() .map(ContentRepositoryElement::getPath) .collect(Collectors.toList()); assertThat(contents.size(), is(2)); assertThat(contents, CoreMatchers.hasItems("test.jsp", "overlay.xhtml")); hash = repository.addContentToExploded( hash, Collections.singletonList(new ExplodedContent("test/empty-file.txt", emptyStream())), true); hash = repository.addContentToExploded( hash, Collections.singletonList(new ExplodedContent("empty-dir", null)), true); contents = repository .listContent(hash, "", ContentFilter.Factory.createContentFilter(-1, false)) .stream() .map(ContentRepositoryElement::getPath) .collect(Collectors.toList()); assertThat(contents, is(notNullValue())); assertThat(contents.size(), is(5)); assertThat( contents, CoreMatchers.hasItems( "test.jsp", "overlay.xhtml", "test/empty-file.txt", "test/", "empty-dir/")); hash = repository.removeContentFromExploded(hash, Collections.singletonList("test.jsp")); contents = repository .listContent(hash, "", ContentFilter.Factory.createFileFilter(-1, false)) .stream() .map(ContentRepositoryElement::getPath) .collect(Collectors.toList()); assertThat(contents, is(notNullValue())); assertThat(contents.size(), is(2)); assertThat(contents, CoreMatchers.hasItems("overlay.xhtml", "test/empty-file.txt")); } } @Test public void testListArchiveContents() throws Exception { byte[] archive = createContentArchive(); try (ByteArrayInputStream stream = new ByteArrayInputStream(archive)) { byte[] hash = repository.addContent(stream); // hash is different from the simple overlay.xhtml as we add the content folder name in the // computation assertThat(hash, is(notNullValue())); List<String> contents = repository .listContent(hash, "", ContentFilter.Factory.createContentFilter(-1, false)) .stream() .map(ContentRepositoryElement::getPath) .collect(Collectors.toList()); assertThat(contents.size(), is(5)); assertThat( contents, CoreMatchers.hasItems( "test.jsp", "overlay.xhtml", "test/empty-file.txt", "test/", "empty-dir/")); hash = repository.addContentToExploded( hash, Collections.singletonList(new ExplodedContent("test/empty-file.txt", emptyStream())), true); hash = repository.addContentToExploded( hash, Collections.singletonList(new ExplodedContent("empty-dir", null)), true); contents = repository .listContent(hash, "", ContentFilter.Factory.createContentFilter(1, false)) .stream() .map(ContentRepositoryElement::getPath) .collect(Collectors.toList()); assertThat(contents, is(notNullValue())); assertThat(contents.size(), is(4)); assertThat( contents, CoreMatchers.hasItems("test.jsp", "overlay.xhtml", "test/", "empty-dir/")); contents = repository .listContent(hash, "", ContentFilter.Factory.createFileFilter(-1, false)) .stream() .map(ContentRepositoryElement::getPath) .collect(Collectors.toList()); assertThat(contents, is(notNullValue())); assertThat(contents.size(), is(3)); assertThat( contents, CoreMatchers.hasItems("test.jsp", "overlay.xhtml", "test/empty-file.txt")); } } /** Test of addContentReference method, of class ContentRepository. */ @Test public void testAddContentReference() throws Exception { try (InputStream stream = getResourceAsStream("overlay.xhtml")) { String expResult = "0c40ffacd15b0f66d5081a93407d3ff5e3c65a71"; byte[] result = repository.addContent(stream); assertThat(result, is(notNullValue())); assertThat(HashUtil.bytesToHexString(result), is(expResult)); ContentReference reference = new ContentReference("contentReferenceIdentifier", result); repository.addContentReference(reference); } } /** Test of getContent method, of class ContentRepository. */ @Test public void testGetContent() throws Exception { try (InputStream stream = getResourceAsStream("overlay.xhtml")) { String expResult = "0c40ffacd15b0f66d5081a93407d3ff5e3c65a71"; byte[] result = repository.addContent(stream); assertThat(result, is(notNullValue())); assertThat(HashUtil.bytesToHexString(result), is(expResult)); Path content = repository.getContent(result).getPhysicalFile().toPath(); String contentHtml = readFileContent(content); String expectedContentHtml = readFileContent(getResourceAsStream("overlay.xhtml")); assertThat(contentHtml, is(expectedContentHtml)); } } /** Test of hasContent method, of class ContentRepository. */ @Test public void testHasContent() throws Exception { String expResult = "0c40ffacd15b0f66d5081a93407d3ff5e3c65a71"; try (InputStream stream = getResourceAsStream("overlay.xhtml")) { assertThat(repository.hasContent(HashUtil.hexStringToByteArray(expResult)), is(false)); byte[] result = repository.addContent(stream); assertThat(result, is(notNullValue())); assertThat(HashUtil.bytesToHexString(result), is(expResult)); assertThat(repository.hasContent(HashUtil.hexStringToByteArray(expResult)), is(true)); } } /** Test of removeContent method, of class ContentRepository. */ @Test public void testRemoveContent() throws Exception { String expResult = "0c40ffacd15b0f66d5081a93407d3ff5e3c65a71"; Path grandparent = rootDir.toPath().resolve("0c"); Path parent = grandparent.resolve("40ffacd15b0f66d5081a93407d3ff5e3c65a71"); Path expectedContent = parent.resolve("content"); assertFalse(expectedContent + " shouldn't exist", Files.exists(expectedContent)); assertFalse(expectedContent.getParent() + " shouldn't exist", Files.exists(parent)); assertFalse( expectedContent.getParent().getParent() + " shouldn't exist", Files.exists(grandparent)); byte[] result; try (InputStream stream = getResourceAsStream("overlay.xhtml")) { assertThat(repository.hasContent(HashUtil.hexStringToByteArray(expResult)), is(false)); result = repository.addContent(stream); } assertThat(result, is(notNullValue())); assertThat(HashUtil.bytesToHexString(result), is(expResult)); assertThat(repository.hasContent(HashUtil.hexStringToByteArray(expResult)), is(true)); assertTrue(expectedContent + " should have been created", Files.exists(expectedContent)); assertTrue(parent + " should have been created", Files.exists(parent)); assertTrue(grandparent + " should have been created", Files.exists(grandparent)); repository.removeContent(new ContentReference("overlay.xhtml", expResult)); assertThat(repository.hasContent(HashUtil.hexStringToByteArray(expResult)), is(false)); assertFalse(expectedContent + " should have been deleted", Files.exists(expectedContent)); assertFalse(parent.toAbsolutePath() + " should have been deleted", Files.exists(parent)); assertFalse(grandparent + " should have been deleted", Files.exists(grandparent)); Path content = repository.getContent(result).getPhysicalFile().toPath(); assertFalse(Files.exists(content)); } /** Test that an empty dir will be removed during cleaning. */ @Test public void testCleanEmptyParentDir() throws Exception { File emptyGrandParent = new File(rootDir, "ae"); emptyGrandParent.mkdir(); File emptyParent = new File(emptyGrandParent, "ffacd15b0f66d5081a93407d3ff5e3c65a71"); emptyParent.mkdir(); assertThat(emptyGrandParent.exists(), is(true)); assertThat(emptyParent.exists(), is(true)); Map<String, Set<String>> result = repository.cleanObsoleteContent(); // To mark content for deletion assertThat(result.get(ContentRepository.MARKED_CONTENT).size(), is(1)); assertThat(result.get(ContentRepository.DELETED_CONTENT).size(), is(0)); assertThat( result.get(ContentRepository.MARKED_CONTENT).contains(emptyParent.getAbsolutePath()), is(true)); Thread.sleep(10); result = repository.cleanObsoleteContent(); assertThat(emptyGrandParent.exists(), is(false)); assertThat(emptyParent.exists(), is(false)); assertThat(result.get(ContentRepository.MARKED_CONTENT).size(), is(0)); assertThat(result.get(ContentRepository.DELETED_CONTENT).size(), is(1)); assertThat( result.get(ContentRepository.DELETED_CONTENT).contains(emptyParent.getAbsolutePath()), is(true)); } /** Test that an empty dir will be removed during cleaning. */ @Test public void testCleanEmptyGrandParentDir() throws Exception { File emptyGrandParent = new File(rootDir, "ae"); emptyGrandParent.mkdir(); assertThat(emptyGrandParent.exists(), is(true)); Map<String, Set<String>> result = repository.cleanObsoleteContent(); // Mark content for deletion assertThat(result.get(ContentRepository.MARKED_CONTENT).size(), is(1)); assertThat(result.get(ContentRepository.DELETED_CONTENT).size(), is(0)); assertThat( result.get(ContentRepository.MARKED_CONTENT).contains(emptyGrandParent.getAbsolutePath()), is(true)); Thread.sleep(10); result = repository.cleanObsoleteContent(); assertThat(emptyGrandParent.exists(), is(false)); assertThat(result.get(ContentRepository.DELETED_CONTENT).size(), is(1)); assertThat(result.get(ContentRepository.MARKED_CONTENT).size(), is(0)); assertThat( result.get(ContentRepository.DELETED_CONTENT).contains(emptyGrandParent.getAbsolutePath()), is(true)); } /** * Test that an empty dir with a system metadata file .DS_Store will be removed during cleaning. */ @Test public void testCleanEmptyParentDirWithSystemMetaDataFile() throws Exception { File emptyGrandParent = new File(rootDir, "ae"); emptyGrandParent.mkdir(); File metaDataFile = new File(emptyGrandParent, ".DS_Store"); metaDataFile.createNewFile(); assertThat(emptyGrandParent.exists(), is(true)); assertThat(metaDataFile.exists(), is(true)); Map<String, Set<String>> result = repository.cleanObsoleteContent(); // To mark content for deletion assertThat(result.get(ContentRepository.MARKED_CONTENT).size(), is(1)); assertThat(result.get(ContentRepository.DELETED_CONTENT).size(), is(0)); assertThat( result.get(ContentRepository.MARKED_CONTENT).contains(metaDataFile.getAbsolutePath()), is(true)); Thread.sleep(10); result = repository.cleanObsoleteContent(); assertThat(emptyGrandParent.exists(), is(false)); assertThat(metaDataFile.exists(), is(false)); assertThat(result.get(ContentRepository.MARKED_CONTENT).size(), is(0)); assertThat(result.get(ContentRepository.DELETED_CONTENT).size(), is(1)); assertThat( result.get(ContentRepository.DELETED_CONTENT).contains(metaDataFile.getAbsolutePath()), is(true)); } /** Test that an empty dir will be removed during cleaning. */ @Test public void testCleanNotEmptyGrandParentDir() throws Exception { String expResult = "0c40ffacd15b0f66d5081a93407d3ff5e3c65a71"; Path grandparent = rootDir.toPath().resolve("0c"); Path parent = grandparent.resolve("40ffacd15b0f66d5081a93407d3ff5e3c65a71"); Path other = grandparent.resolve("40ffacd15b0f66d5081a93407d3ff5e3c65a81"); Files.createDirectories(other); Path expectedContent = parent.resolve("content"); assertFalse(expectedContent + " shouldn't exist", Files.exists(expectedContent)); assertFalse(parent + " shouldn't exist", Files.exists(parent)); byte[] result; try (InputStream stream = getResourceAsStream("overlay.xhtml")) { assertThat(repository.hasContent(HashUtil.hexStringToByteArray(expResult)), is(false)); result = repository.addContent(stream); } assertThat(result, is(notNullValue())); assertThat(HashUtil.bytesToHexString(result), is(expResult)); assertThat(repository.hasContent(HashUtil.hexStringToByteArray(expResult)), is(true)); assertTrue(expectedContent + " should have been created", Files.exists(expectedContent)); assertTrue(parent + " should have been created", Files.exists(parent)); repository.removeContent(new ContentReference("overlay.xhtml", expResult)); assertFalse(repository.hasContent(HashUtil.hexStringToByteArray(expResult))); assertFalse(expectedContent + " should have been deleted", Files.exists(expectedContent)); assertFalse(parent.toAbsolutePath() + " should have been deleted", Files.exists(parent)); assertTrue(other + " should not have been deleted", Files.exists(other)); assertTrue(grandparent + " should not have been deleted", Files.exists(grandparent)); Path content = repository.getContent(result).getPhysicalFile().toPath(); assertFalse(Files.exists(content)); } /** Test that an dir not empty with no content will not be removed during cleaning. */ @Test public void testNotEmptyDir() throws Exception { Path parentDir = rootDir.toPath().resolve("ae").resolve("ffacd15b0f66d5081a93407d3ff5e3c65a71"); Path overlay = parentDir.resolve("overlay.xhtml"); Path content = parentDir.resolve("content"); Files.createDirectories(overlay.getParent()); try (InputStream stream = getResourceAsStream("overlay.xhtml")) { Files.copy(stream, overlay); Files.copy(overlay, content); assertThat(Files.exists(content), is(true)); assertThat(Files.exists(overlay), is(true)); Map<String, Set<String>> result = repository.cleanObsoleteContent(); // Mark content for deletion assertThat(result.get(ContentRepository.MARKED_CONTENT).size(), is(1)); assertThat(result.get(ContentRepository.DELETED_CONTENT).size(), is(0)); assertThat( result .get(ContentRepository.MARKED_CONTENT) .contains(parentDir.toFile().getAbsolutePath()), is(true)); Thread.sleep(10); result = repository.cleanObsoleteContent(); assertThat(Files.exists(content), is(false)); assertThat(Files.exists(overlay), is(true)); assertThat(result.get(ContentRepository.MARKED_CONTENT).size(), is(0)); assertThat(result.get(ContentRepository.DELETED_CONTENT).size(), is(1)); assertThat( result .get(ContentRepository.DELETED_CONTENT) .contains(parentDir.toFile().getAbsolutePath()), is(true)); } finally { Files.deleteIfExists(overlay); Files.deleteIfExists(overlay.getParent()); Files.deleteIfExists(overlay.getParent().getParent()); } } private InputStream getResourceAsStream(final String name) throws IOException { final InputStream result = getClass().getClassLoader().getResourceAsStream(name); // If we're on Windows we want to replace the stream with one that ignores \r if (result != null && IS_WINDOWS) { return new CarriageReturnRemovalInputStream(result); } return result; } private InputStream getFileInputStream(final File file) throws IOException { if (IS_WINDOWS) { return new CarriageReturnRemovalInputStream(new FileInputStream(file)); } return new FileInputStream(file); } private InputStream getFileInputStream(final Path path) throws IOException { if (IS_WINDOWS) { return new CarriageReturnRemovalInputStream(Files.newInputStream(path)); } return Files.newInputStream(path); } private static class CarriageReturnRemovalInputStream extends InputStream { private final InputStream delegate; private CarriageReturnRemovalInputStream(final InputStream delegate) { this.delegate = delegate; } @Override public int read() throws IOException { int result = delegate.read(); if (result == '\r') { result = delegate.read(); } return result; } @Override public int read(final byte[] b) throws IOException { Objects.nonNull(b); int result = 0; while (result > -1 && result < b.length) { int c = read(); if (c == -1) { return result == 0 ? -1 : result; } b[result++] = (byte) c; } return result; } @Override public int read(final byte[] b, final int off, final int len) throws IOException { Objects.nonNull(b); if (off < 0 || len < 0 || len > b.length - off) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } int result = 0; while (result > -1 && result < len) { int c = read(); if (c == -1) { return result == 0 ? -1 : result; } b[off + result++] = (byte) c; } return result; } @Override public long skip(final long n) throws IOException { return delegate.skip(n); } @Override public int available() throws IOException { return delegate.available(); } @Override public void close() throws IOException { delegate.close(); } @Override public void mark(final int readlimit) { delegate.mark(readlimit); } @Override public void reset() throws IOException { delegate.reset(); } @Override public boolean markSupported() { return delegate.markSupported(); } } }
/** Converts FileTime to "standard Unix time". */ public static final long fileTimeToUnixTime(FileTime ftime) { return ftime.to(TimeUnit.SECONDS); }
/** Converts Windows time (in microseconds, UTC/GMT) time to FileTime. */ public static final FileTime winTimeToFileTime(long wtime) { return FileTime.from(wtime / 10 + WINDOWS_EPOCH_IN_MICROSECONDS, TimeUnit.MICROSECONDS); }
private void setFileCreationDate(File f, long time) throws IOException { BasicFileAttributeView attributes = Files.getFileAttributeView(f.toPath(), BasicFileAttributeView.class); FileTime creationTime = FileTime.fromMillis(time); attributes.setTimes(creationTime, creationTime, creationTime); }