pax_global_header00006660000000000000000000000064130526122670014516gustar00rootroot0000000000000052 comment=1e0125bb07c302b9b81cd2891d4d5cd88b3f2880 sejda-io-1.1.3.RELEASE/000077500000000000000000000000001305261226700142725ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/.gitignore000066400000000000000000000001641305261226700162630ustar00rootroot00000000000000*.class .classpath .project .launch .settings/ target/ .externalToolBuilders/ # Package Files # *.jar *.war *.ear sejda-io-1.1.3.RELEASE/.travis.yml000066400000000000000000000000571305261226700164050ustar00rootroot00000000000000language: java sudo: false jdk: - oraclejdk8 sejda-io-1.1.3.RELEASE/LICENSE000066400000000000000000000240411305261226700153000ustar00rootroot00000000000000Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: You must give any other recipients of the Work or Derivative Works a copy of this License; and You must cause any modified files to carry prominent notices stating that You changed the files; and You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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. sejda-io-1.1.3.RELEASE/README.md000066400000000000000000000005031305261226700155470ustar00rootroot00000000000000Sejda-io (http://www.sejda.org) ===== [![Build Status](https://travis-ci.org/torakiki/sejda-io.png)](https://travis-ci.org/torakiki/sejda-io) [![License](http://img.shields.io/badge/license-APLv2-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) A layer of Input/Output classes built on top of java io and nio. sejda-io-1.1.3.RELEASE/development/000077500000000000000000000000001305261226700166145ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/development/eclipse/000077500000000000000000000000001305261226700202405ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/development/eclipse/checkstyle plugin/000077500000000000000000000000001305261226700236555ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/development/eclipse/checkstyle plugin/checkstyle.xml000066400000000000000000000105061305261226700265370ustar00rootroot00000000000000 sejda-io-1.1.3.RELEASE/development/eclipse/checkstyle plugin/suppression.xml000066400000000000000000000003611305261226700267710ustar00rootroot00000000000000 sejda-io-1.1.3.RELEASE/development/eclipse/code_format.xml000066400000000000000000000716461305261226700232620ustar00rootroot00000000000000 sejda-io-1.1.3.RELEASE/development/eclipse/codetemplates.xml000066400000000000000000000125471305261226700236240ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/development/eclipse/eclipse_compiler_settings.epf000066400000000000000000000053451305261226700262010ustar00rootroot00000000000000#Sat Jul 23 15:11:52 CEST 2011 /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=error /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error \!/= /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.emptyStatement=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.enumIdentifier=error /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.fieldHiding=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=disabled /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.assertIdentifier=error /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=disabled /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=error /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=disabled /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.compliance=1.6 /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedImport=error /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.source=1.6 file_export_version=3.0 @org.eclipse.jdt.core=3.6.2.v_A76_R36x sejda-io-1.1.3.RELEASE/pom.xml000066400000000000000000000113771305261226700156200ustar00rootroot00000000000000 4.0.0 org.sejda sejda-io jar sejda-io 1.1.3.RELEASE An Input/Output layer built on top of Java standard io and nio packages http://www.sejda.org GitHub https://github.com/torakiki/sejda-io/ sejda http://www.sejda.org Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0 repo ASLv2 UTF-8 scm:git:git@github.com:torakiki/sejda-io.git scm:git:git@github.com:torakiki/sejda-io.git scm:git:git@github.com:torakiki/sejda-io.git v1.1.3.RELEASE torakiki Andrea Vacondio andrea.vacondio@gmail.com ediweissmann Eduard Weissmann edi.weissmann@gmail.com sonatype-nexus-snapshots https://oss.sonatype.org/content/repositories/snapshots sonatype-nexus-staging https://oss.sonatype.org/service/local/staging/deploy/maven2/ release org.apache.maven.plugins maven-javadoc-plugin 2.10.3 attach-javadocs jar org.apache.maven.plugins maven-release-plugin 2.5.2 v@{project.version} clean install org.apache.maven.plugins maven-gpg-plugin 1.6 sign-artifacts verify sign org.apache.maven.plugins maven-compiler-plugin 3.3 1.8 1.8 true lines,vars,source org.apache.maven.plugins maven-jar-plugin 2.6 org.apache.maven.plugins maven-source-plugin 2.4 attach-sources jar-no-fork org.slf4j slf4j-api 1.7.21 commons-io commons-io 2.5 ch.qos.logback logback-classic 1.1.7 test org.mockito mockito-core 1.10.19 test junit junit 4.12 test org.hamcrest hamcrest-core 1.3 test sejda-io-1.1.3.RELEASE/src/000077500000000000000000000000001305261226700150615ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/src/main/000077500000000000000000000000001305261226700160055ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/src/main/java/000077500000000000000000000000001305261226700167265ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/src/main/java/org/000077500000000000000000000000001305261226700175155ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/000077500000000000000000000000001305261226700206035ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/io/000077500000000000000000000000001305261226700212125ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/io/BaseSeekableSource.java000066400000000000000000000036161305261226700255520ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static org.sejda.util.RequireUtils.requireNotBlank; import static org.sejda.util.RequireUtils.requireState; import java.io.IOException; /** * Abstract {@link SeekableSource} that provides base functionalities common to all the {@link SeekableSource}s. * * @author Andrea Vacondio */ public abstract class BaseSeekableSource implements SeekableSource { private boolean open = true; private String id; public BaseSeekableSource(String id) { requireNotBlank(id, "SeekableSource id cannot be blank"); this.id = id; } @Override public boolean isOpen() { return open; } @Override public void close() throws IOException { this.open = false; } /** * @throws IllegalStateException * if the source is closed * @throws IOException */ protected void requireOpen() throws IOException { requireState(isOpen(), "The SeekableSource has been closed"); } /** * @return the unique id for this source */ @Override public String id() { return id; } } sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/io/BufferedCountingChannelWriter.java000066400000000000000000000077761305261226700300150ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static org.sejda.util.RequireUtils.requireNotNullArg; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.charset.StandardCharsets; import org.apache.commons.io.Charsets; import org.sejda.util.IOUtils; /** * Component providing methods to write to a {@link CountingWritableByteChannel}. This implementation is buffered and bytes are flushed to the {@link CountingWritableByteChannel} * only when the buffer is full. The buffer size is configurable using the OUTPUT_BUFFER_SIZE_PROPERTY property. * * @author Andrea Vacondio */ public class BufferedCountingChannelWriter implements Closeable { public static final String OUTPUT_BUFFER_SIZE_PROPERTY = "org.sejda.io.buffered.output.size"; private static final byte EOL = '\n'; private CountingWritableByteChannel channel; private ByteBuffer buffer = ByteBuffer.allocate(Integer.getInteger(OUTPUT_BUFFER_SIZE_PROPERTY, 4096)); private boolean onNewLine = false; public BufferedCountingChannelWriter(CountingWritableByteChannel channel) { requireNotNullArg(channel, "Cannot write to a null channell"); this.channel = channel; } @Override public void close() throws IOException { if (channel.isOpen() && buffer.position() != 0) { flush(); } IOUtils.close(channel); } public void writeEOL() throws IOException { if (!onNewLine) { write(EOL); onNewLine = true; } } /** * Writes the given string in {@link Charsets#ISO_8859_1} * * @param value * @throws IOException */ public void write(String value) throws IOException { write(value.getBytes(StandardCharsets.ISO_8859_1)); } /** * Writes the given bytes to the destination * * @param bytes * @throws IOException */ public void write(byte[] bytes) throws IOException { for (int i = 0; i < bytes.length; i++) { write(bytes[i]); } } /** * Writes the single byte to the destination * * @param myByte * @throws IOException */ public void write(byte myByte) throws IOException { onNewLine = false; buffer.put(myByte); if (!buffer.hasRemaining()) { flush(); } } /** * Writes everything that is read from the {@link InputStream} to the destination * * @param stream * @throws IOException */ public void write(InputStream stream) throws IOException { onNewLine = false; try (ReadableByteChannel readable = Channels.newChannel(stream)) { flush(); while (readable.read(buffer) != -1) { flush(); } } } /** * @return the current offset in the output */ public long offset() { return channel.count() + buffer.position(); } /** * Flush the buffer * * @throws IOException */ public void flush() throws IOException { buffer.flip(); channel.write(buffer); buffer.clear(); } } sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/io/BufferedSeekableSource.java000066400000000000000000000077311305261226700264240ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static java.util.Optional.ofNullable; import static org.sejda.util.RequireUtils.requireArg; import java.io.IOException; import java.nio.ByteBuffer; import org.sejda.util.IOUtils; /** * {@link SeekableSource} wrapping an existing one and providing buffered read. When a read method is called, a {@link SeekableSources#INPUT_BUFFER_SIZE_PROPERTY} long chunk of * bytes is read from the underlying source and stored in memory. Subsequent reads are served from the in memory buffer until they fall outside its range, at that point a new * buffer is read from the wrapped source. * * @author Andrea Vacondio */ public class BufferedSeekableSource extends BaseSeekableSource { private ByteBuffer buffer = ByteBuffer .allocate(Integer.getInteger(SeekableSources.INPUT_BUFFER_SIZE_PROPERTY, 8192)); private SeekableSource wrapped; private long position; private long size; public BufferedSeekableSource(SeekableSource wrapped) { super(ofNullable(wrapped).map(SeekableSource::id).orElseThrow(() -> { return new IllegalArgumentException("Input decorated SeekableSource cannot be null"); })); this.wrapped = wrapped; this.size = wrapped.size(); this.buffer.limit(0); } @Override public long position() { return this.position; } @Override public SeekableSource position(long newPosition) throws IOException { requireArg(newPosition >= 0, "Cannot set position to a negative value"); if (newPosition != this.position) { long newBufPosition = newPosition - position + buffer.position(); if (newBufPosition >= 0 && newBufPosition < buffer.limit()) { buffer.position((int) newBufPosition); } else { buffer.limit(0); wrapped.position(newPosition); } this.position = Math.min(newPosition, size); } return this; } @Override public long size() { return size; } @Override public void close() throws IOException { super.close(); IOUtils.close(wrapped); buffer.clear(); buffer.limit(0); } @Override public int read(ByteBuffer dst) throws IOException { requireOpen(); buffer.limit(0); wrapped.position(position); int read = wrapped.read(dst); if (read > 0) { position += read; } return read; } @Override public int read() throws IOException { requireOpen(); if (ensureBuffer() > 0) { position++; return buffer.get() & 0xff; } return -1; } private int ensureBuffer() throws IOException { if (!buffer.hasRemaining()) { buffer.clear(); wrapped.read(buffer); buffer.flip(); } return buffer.remaining(); } protected SeekableSource wrapped() { return wrapped; } @Override public SeekableSource view(long startingPosition, long length) throws IOException { requireOpen(); return new BufferedSeekableSource(wrapped.view(startingPosition, length)); } } sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/io/ByteArraySeekableSource.java000066400000000000000000000053751305261226700266060ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static java.util.Optional.ofNullable; import static org.sejda.util.RequireUtils.requireArg; import java.io.IOException; import java.nio.ByteBuffer; import java.util.UUID; /** * A byte array based {@link SeekableSource} with a max size of 2GB. * * @author Andrea Vacondio */ public class ByteArraySeekableSource extends BaseSeekableSource { private byte[] bytes; private long position; public ByteArraySeekableSource(byte[] bytes) { super(ofNullable(bytes).map(UUID::nameUUIDFromBytes).map(UUID::toString).orElseThrow(() -> { return new IllegalArgumentException("Input byte array cannot be null"); })); this.bytes = bytes; } @Override public long position() { return position; } @Override public SeekableSource position(long position) { requireArg(position >= 0, "Cannot set position to a negative value"); this.position = Math.min(position, size()); return this; } @Override public long size() { return bytes.length; } @Override public int read(ByteBuffer dst) throws IOException { requireOpen(); if (position < size()) { int toCopy = (int) Math.min(dst.remaining(), size() - position); dst.put(bytes, (int) position, toCopy); position += toCopy; return toCopy; } return -1; } @Override public int read() throws IOException { requireOpen(); if (position < size()) { return bytes[(int) position++] & 0xff; } return -1; } @Override public void close() throws IOException { super.close(); this.bytes = new byte[0]; } @Override public SeekableSource view(long startingPosition, long length) throws IOException { requireOpen(); return new SeekableSourceView(() -> new ByteArraySeekableSource(bytes), id(), startingPosition, length); } } sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/io/CountingWritableByteChannel.java000066400000000000000000000101071305261226700274510ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static org.sejda.util.RequireUtils.requireNotNullArg; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.ClosedChannelException; import java.nio.channels.WritableByteChannel; import org.sejda.util.IOUtils; /** * A {@link WritableByteChannel} that keeps track of the number of written bytes * * @author Andrea Vacondio */ public class CountingWritableByteChannel implements WritableByteChannel { private long written = 0; private WritableByteChannel wrapped; public CountingWritableByteChannel(WritableByteChannel wrapped) { requireNotNullArg(wrapped, "Cannot decorate a null instance"); this.wrapped = wrapped; } /** * @return the number of written bytes */ public long count() { return written; } @Override public int write(ByteBuffer src) throws IOException { if (!isOpen()) { throw new ClosedChannelException(); } int count = wrapped.write(src); written += count; return count; } @Override public boolean isOpen() { return wrapped.isOpen(); } @Override public void close() throws IOException { IOUtils.close(wrapped); } /** * Static factory method to create a {@link CountingWritableByteChannel} from an existing {@link WritableByteChannel}. * * @param channel * @return the newly created {@link CountingWritableByteChannel} */ public static CountingWritableByteChannel from(WritableByteChannel channel) { return new CountingWritableByteChannel(channel); } /** * Static factory method to create a {@link CountingWritableByteChannel} from an existing {@link OutputStream}. * * @param stream * @return the newly created {@link CountingWritableByteChannel} */ public static CountingWritableByteChannel from(OutputStream stream) { return new CountingWritableByteChannel(Channels.newChannel(stream)); } /** * Static factory method to create a {@link CountingWritableByteChannel} from an existing {@link File}. If the file already exists its content is purged. * * @param file * @return the newly created {@link CountingWritableByteChannel} * @throws IOException * @see RandomAccessFile#RandomAccessFile(File, String) */ public static CountingWritableByteChannel from(File file) throws IOException { RandomAccessFile raf = new RandomAccessFile(file, "rw"); raf.setLength(0); return new CountingWritableByteChannel(raf.getChannel()); } /** * Static factory method to create a {@link CountingWritableByteChannel} from an existing file path. If the file already exists its content is purged. * * @param file * @return the newly created {@link CountingWritableByteChannel} * @throws IOException * @see RandomAccessFile#RandomAccessFile(String, String) */ public static CountingWritableByteChannel from(String file) throws IOException { RandomAccessFile raf = new RandomAccessFile(file, "rw"); raf.setLength(0); return new CountingWritableByteChannel(raf.getChannel()); } } sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/io/DevNullWritableByteChannel.java000066400000000000000000000024241305261226700272370ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import java.nio.ByteBuffer; import java.nio.channels.WritableByteChannel; /** * {@link WritableByteChannel} that does nothing . * * @author Andrea Vacondio * */ public class DevNullWritableByteChannel implements WritableByteChannel { private boolean open = true; public boolean isOpen() { return open; } public void close() { this.open = false; } public int write(ByteBuffer src) { return src.remaining(); } } sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/io/FastByteArrayOutputStream.java000066400000000000000000000434741305261226700272060ustar00rootroot00000000000000/* * Copyright 2002-2016 the original author or authors. * * 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 org.sejda.io; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Iterator; import java.util.LinkedList; /** * A speedy alternative to {@link java.io.ByteArrayOutputStream}. Note that this variant does not extend {@code ByteArrayOutputStream} * *

* Unlike {@link java.io.ByteArrayOutputStream}, this implementation is backed by a {@link java.util.LinkedList} of {@code byte[]} instead of 1 constantly resizing {@code byte[]}. * It does not copy buffers when it gets expanded. * *

* The initial buffer is only created when the stream is first written. There is also no copying of the internal buffer if its contents is extracted with the * {@link #writeTo(OutputStream)} method. * * @author Craig Andrews * @author Juergen Hoeller */ public class FastByteArrayOutputStream extends OutputStream { private static final int DEFAULT_BLOCK_SIZE = 256; // max block size is 128mb private static final int MAX_BLOCK_SIZE = 128 * 1024 * 1024; // The buffers used to store the content bytes private final LinkedList buffers = new LinkedList(); // The size, in bytes, to use when allocating the first byte[] private final int initialBlockSize; // The size, in bytes, to use when allocating the next byte[] private int nextBlockSize = 0; // The number of bytes in previous buffers. // (The number of bytes in the current buffer is in 'index'.) private int alreadyBufferedSize = 0; // The index in the byte[] found at buffers.getLast() to be written next private int index = 0; // Is the stream closed? private boolean closed = false; /** * Create a new FastByteArrayOutputStream with the default initial capacity of 256 bytes. */ public FastByteArrayOutputStream() { this(DEFAULT_BLOCK_SIZE); } /** * Create a new FastByteArrayOutputStream with the specified initial capacity. * * @param initialBlockSize * the initial buffer size in bytes */ public FastByteArrayOutputStream(int initialBlockSize) { assertIsTrue(initialBlockSize > 0, "Initial block size must be greater than 0"); this.initialBlockSize = initialBlockSize; this.nextBlockSize = initialBlockSize; } // Overridden methods @Override public void write(int datum) throws IOException { if (this.closed) { throw new IOException("Stream closed"); } else { if (this.buffers.peekLast() == null || this.buffers.getLast().length == this.index) { addBuffer(1); } // store the byte this.buffers.getLast()[this.index++] = (byte) datum; } } @Override public void write(byte[] data, int offset, int length) throws IOException { if (data == null) { throw new NullPointerException(); } else if (offset < 0 || offset + length > data.length || length < 0) { throw new IndexOutOfBoundsException(); } else if (this.closed) { throw new IOException("Stream closed"); } else { if (this.buffers.peekLast() == null || this.buffers.getLast().length == this.index) { addBuffer(length); } if (this.index + length > this.buffers.getLast().length) { int pos = offset; do { if (this.index == this.buffers.getLast().length) { addBuffer(length); } int copyLength = this.buffers.getLast().length - this.index; if (length < copyLength) { copyLength = length; } System.arraycopy(data, pos, this.buffers.getLast(), this.index, copyLength); pos += copyLength; this.index += copyLength; length -= copyLength; } while (length > 0); } else { // copy in the sub-array System.arraycopy(data, offset, this.buffers.getLast(), this.index, length); this.index += length; } } } @Override public void close() { this.closed = true; } /** * Convert the buffer's contents into a string decoding bytes using the platform's default character set. The length of the new String is a function of the character * set, and hence may not be equal to the size of the buffer. *

* This method always replaces malformed-input and unmappable-character sequences with the default replacement string for the platform's default character set. The * {@linkplain java.nio.charset.CharsetDecoder} class should be used when more control over the decoding process is required. * * @return a String decoded from the buffer's contents */ @Override public String toString() { return new String(toByteArrayUnsafe()); } // Custom methods /** * Return the number of bytes stored in this FastByteArrayOutputStream. */ public int size() { return (this.alreadyBufferedSize + this.index); } /** * Convert the stream's data to a byte array and return the byte array. *

* Also replaces the internal structures with the byte array to conserve memory: if the byte array is being made anyways, mind as well as use it. This approach also means that * if this method is called twice without any writes in between, the second call is a no-op. *

* This method is "unsafe" as it returns the internal buffer. Callers should not modify the returned buffer. * * @return the current contents of this output stream, as a byte array. * @see #size() * @see #toByteArray() */ public byte[] toByteArrayUnsafe() { int totalSize = size(); if (totalSize == 0) { return new byte[0]; } resize(totalSize); return this.buffers.getFirst(); } public byte[] toByteArray() { return toByteArrayUnsafe(); } /** * Creates a newly allocated byte array. *

* Its size is the current size of this output stream and the valid contents of the buffer have been copied into it. *

* * @return the current contents of this output stream, as a byte array. * @see #size() * @see #toByteArrayUnsafe() */ public byte[] toByteArraySafe() { byte[] bytesUnsafe = toByteArrayUnsafe(); byte[] ret = new byte[bytesUnsafe.length]; System.arraycopy(bytesUnsafe, 0, ret, 0, bytesUnsafe.length); return ret; } /** * Reset the contents of this FastByteArrayOutputStream. *

* All currently accumulated output in the output stream is discarded. The output stream can be used again. */ public void reset() { this.buffers.clear(); this.nextBlockSize = this.initialBlockSize; this.closed = false; this.index = 0; this.alreadyBufferedSize = 0; } /** * Get an {@link InputStream} to retrieve the data in this OutputStream. *

* Note that if any methods are called on the OutputStream (including, but not limited to, any of the write methods, {@link #reset()}, {@link #toByteArray()}, and * {@link #toByteArrayUnsafe()}) then the {@link java.io.InputStream} 's behavior is undefined. * * @return {@link InputStream} of the contents of this OutputStream */ public InputStream getInputStream() { return new FastByteArrayInputStream(this); } /** * Write the buffers content to the given OutputStream. * * @param out * the OutputStream to write to */ public void writeTo(OutputStream out) throws IOException { Iterator it = this.buffers.iterator(); while (it.hasNext()) { byte[] bytes = it.next(); if (it.hasNext()) { out.write(bytes, 0, bytes.length); } else { out.write(bytes, 0, this.index); } } } /** * Resize the internal buffer size to a specified capacity. * * @param targetCapacity * the desired size of the buffer * @throws IllegalArgumentException * if the given capacity is smaller than the actual size of the content stored in the buffer already * @see FastByteArrayOutputStream#size() */ public void resize(int targetCapacity) { assertIsTrue(targetCapacity >= size(), "New capacity must not be smaller than current size"); if (this.buffers.peekFirst() == null) { this.nextBlockSize = targetCapacity - size(); } else if (size() == targetCapacity && this.buffers.getFirst().length == targetCapacity) { // do nothing - already at the targetCapacity } else { int totalSize = size(); byte[] data = new byte[targetCapacity]; int pos = 0; Iterator it = this.buffers.iterator(); while (it.hasNext()) { byte[] bytes = it.next(); if (it.hasNext()) { System.arraycopy(bytes, 0, data, pos, bytes.length); pos += bytes.length; } else { System.arraycopy(bytes, 0, data, pos, this.index); } } this.buffers.clear(); this.buffers.add(data); this.index = totalSize; this.alreadyBufferedSize = 0; } } /** * Create a new buffer and store it in the LinkedList *

* Adds a new buffer that can store at least {@code minCapacity} bytes. */ private void addBuffer(int minCapacity) { if (this.buffers.peekLast() != null) { this.alreadyBufferedSize += this.index; this.index = 0; } if (this.nextBlockSize < minCapacity) { this.nextBlockSize = nextPowerOf2(minCapacity); } this.buffers.add(new byte[this.nextBlockSize]); this.nextBlockSize = Math.min(MAX_BLOCK_SIZE, this.nextBlockSize * 2); // block size doubles each time } /** * Get the next power of 2 of a number (ex, the next power of 2 of 119 is 128). */ private static int nextPowerOf2(int val) { val--; val = (val >> 1) | val; val = (val >> 2) | val; val = (val >> 4) | val; val = (val >> 8) | val; val = (val >> 16) | val; val++; return val; } /** * An implementation of {@link java.io.InputStream} that reads from a given FastByteArrayOutputStream. */ private static final class FastByteArrayInputStream extends InputStream { private final FastByteArrayOutputStream fastByteArrayOutputStream; private final Iterator buffersIterator; private byte[] currentBuffer; private int currentBufferLength = 0; private int nextIndexInCurrentBuffer = 0; private int totalBytesRead = 0; /** * Create a new FastByteArrayOutputStreamInputStream backed by the given FastByteArrayOutputStream. */ public FastByteArrayInputStream(FastByteArrayOutputStream fastByteArrayOutputStream) { this.fastByteArrayOutputStream = fastByteArrayOutputStream; this.buffersIterator = fastByteArrayOutputStream.buffers.iterator(); if (this.buffersIterator.hasNext()) { this.currentBuffer = this.buffersIterator.next(); if (this.currentBuffer == fastByteArrayOutputStream.buffers.getLast()) { this.currentBufferLength = fastByteArrayOutputStream.index; } else { this.currentBufferLength = this.currentBuffer.length; } } } @Override public int read() { if (this.currentBuffer == null) { // This stream doesn't have any data in it... return -1; } else { if (this.nextIndexInCurrentBuffer < this.currentBufferLength) { this.totalBytesRead++; return this.currentBuffer[this.nextIndexInCurrentBuffer++]; } else { if (this.buffersIterator.hasNext()) { this.currentBuffer = this.buffersIterator.next(); if (this.currentBuffer == this.fastByteArrayOutputStream.buffers.getLast()) { this.currentBufferLength = this.fastByteArrayOutputStream.index; } else { this.currentBufferLength = this.currentBuffer.length; } this.nextIndexInCurrentBuffer = 0; } else { this.currentBuffer = null; } return read(); } } } @Override public int read(byte[] b) { return read(b, 0, b.length); } @Override public int read(byte[] b, int off, int len) { if (b == null) { throw new NullPointerException(); } else if (off < 0 || len < 0 || len > b.length - off) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } else if (len < 0) { throw new IllegalArgumentException("len must be 0 or greater: " + len); } else if (off < 0) { throw new IllegalArgumentException("off must be 0 or greater: " + off); } else { if (this.currentBuffer == null) { // This stream doesn't have any data in it... return -1; } else { if (this.nextIndexInCurrentBuffer < this.currentBufferLength) { int bytesToCopy = Math.min(len, this.currentBufferLength - this.nextIndexInCurrentBuffer); System.arraycopy(this.currentBuffer, this.nextIndexInCurrentBuffer, b, off, bytesToCopy); this.totalBytesRead += bytesToCopy; this.nextIndexInCurrentBuffer += bytesToCopy; int remaining = read(b, off + bytesToCopy, len - bytesToCopy); return bytesToCopy + Math.max(remaining, 0); } else { if (this.buffersIterator.hasNext()) { this.currentBuffer = this.buffersIterator.next(); if (this.currentBuffer == this.fastByteArrayOutputStream.buffers.getLast()) { this.currentBufferLength = this.fastByteArrayOutputStream.index; } else { this.currentBufferLength = this.currentBuffer.length; } this.nextIndexInCurrentBuffer = 0; } else { this.currentBuffer = null; } return read(b, off, len); } } } } @Override public long skip(long n) throws IOException { if (n > Integer.MAX_VALUE) { throw new IllegalArgumentException("n exceeds maximum (" + Integer.MAX_VALUE + "): " + n); } else if (n == 0) { return 0; } else if (n < 0) { throw new IllegalArgumentException("n must be 0 or greater: " + n); } int len = (int) n; if (this.currentBuffer == null) { // This stream doesn't have any data in it... return 0; } else { if (this.nextIndexInCurrentBuffer < this.currentBufferLength) { int bytesToSkip = Math.min(len, this.currentBufferLength - this.nextIndexInCurrentBuffer); this.totalBytesRead += bytesToSkip; this.nextIndexInCurrentBuffer += bytesToSkip; return (bytesToSkip + skip(len - bytesToSkip)); } else { if (this.buffersIterator.hasNext()) { this.currentBuffer = this.buffersIterator.next(); if (this.currentBuffer == this.fastByteArrayOutputStream.buffers.getLast()) { this.currentBufferLength = this.fastByteArrayOutputStream.index; } else { this.currentBufferLength = this.currentBuffer.length; } this.nextIndexInCurrentBuffer = 0; } else { this.currentBuffer = null; } return skip(len); } } } @Override public int available() { return (this.fastByteArrayOutputStream.size() - this.totalBytesRead); } } private static void assertIsTrue(Boolean condition, String message) { if (!condition) throw new RuntimeException(message); } } sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/io/FileChannelSeekableSource.java000066400000000000000000000060661305261226700270520ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static java.util.Optional.ofNullable; import static org.sejda.util.RequireUtils.requireArg; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import org.sejda.util.IOUtils; /** * A {@link SeekableSource} implementation based on {@link FileChannel}. * * @author Andrea Vacondio */ public class FileChannelSeekableSource extends BaseSeekableSource { private FileChannel channel; private File file; private long size; private ThreadBoundCopiesSupplier localCopiesSupplier = new ThreadBoundCopiesSupplier<>( () -> new FileChannelSeekableSource(file)); public FileChannelSeekableSource(File file) throws IOException { super(ofNullable(file).map(File::getAbsolutePath).orElseThrow(() -> { return new IllegalArgumentException("Input file cannot be null"); })); this.channel = new RandomAccessFile(file, "r").getChannel(); this.size = channel.size(); this.file = file; } @Override public long position() throws IOException { return channel.position(); } @Override public SeekableSource position(long newPosition) throws IOException { requireArg(newPosition >= 0, "Cannot set position to a negative value"); channel.position(newPosition); return this; } @Override public long size() { return size; } @Override public void close() throws IOException { super.close(); IOUtils.close(localCopiesSupplier); IOUtils.close(channel); } @Override public int read(ByteBuffer dst) throws IOException { requireOpen(); return channel.read(dst); } @Override public int read() throws IOException { requireOpen(); ByteBuffer buffer = ByteBuffer.allocate(1); if (channel.read(buffer) > 0) { buffer.flip(); return buffer.get() & 0xff; } return -1; } @Override public SeekableSource view(long startingPosition, long length) throws IOException { requireOpen(); return new SeekableSourceView(localCopiesSupplier, id(), startingPosition, length); } } sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/io/MemoryMappedSeekableSource.java000066400000000000000000000134771305261226700273050ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static java.util.Optional.ofNullable; import static org.sejda.util.RequireUtils.requireArg; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileChannel.MapMode; import java.util.ArrayList; import java.util.List; import org.sejda.util.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A {@link SeekableSource} implementation based on MappedByteBuffer. To overcome the int limit of the MappedByteBuffer, this source implement a pagination algorithm allowing to * open files of any size. The size of the pages can be configured using the {@link SeekableSources#MEMORY_MAPPED_PAGE_SIZE_PROPERTY} system property. * * @author Andrea Vacondio * */ public class MemoryMappedSeekableSource extends BaseSeekableSource { private static final Logger LOG = LoggerFactory.getLogger(MemoryMappedSeekableSource.class); private static final long MB_256 = 1 << 28; private final long pageSize = Long.getLong(SeekableSources.MEMORY_MAPPED_PAGE_SIZE_PROPERTY, MB_256); private List pages = new ArrayList<>(); private long position; private long size; private ThreadBoundCopiesSupplier localCopiesSupplier = new ThreadBoundCopiesSupplier<>( () -> new MemoryMappedSeekableSource(this)); public MemoryMappedSeekableSource(File file) throws IOException { super(ofNullable(file).map(File::getAbsolutePath).orElseThrow(() -> { return new IllegalArgumentException("Input file cannot be null"); })); try (FileChannel channel = new RandomAccessFile(file, "r").getChannel()) { this.size = channel.size(); int zeroBasedPagesNumber = (int) (channel.size() / pageSize); for (int i = 0; i <= zeroBasedPagesNumber; i++) { if (i == zeroBasedPagesNumber) { pages.add(i, channel.map(MapMode.READ_ONLY, i * pageSize, channel.size() - (i * pageSize))); } else { pages.add(i, channel.map(MapMode.READ_ONLY, i * pageSize, pageSize)); } } LOG.debug("Created MemoryMappedSeekableSource with " + pages.size() + " pages"); } } private MemoryMappedSeekableSource(MemoryMappedSeekableSource parent) { super(parent.id()); this.size = parent.size; for (ByteBuffer page : parent.pages) { this.pages.add(page.duplicate()); } } @Override public long position() { return position; } @Override public long size() { return size; } @Override public SeekableSource position(long position) { requireArg(position >= 0, "Cannot set position to a negative value"); this.position = Math.min(position, this.size); return this; } @Override public int read(ByteBuffer dst) throws IOException { requireOpen(); int zeroBasedPagesNumber = (int) (position() / pageSize); ByteBuffer page = pages.get(zeroBasedPagesNumber); int relativePosition = (int) (position() - (zeroBasedPagesNumber * pageSize)); if (relativePosition < page.limit()) { int read = readPage(dst, zeroBasedPagesNumber, relativePosition); while (dst.hasRemaining()) { int readBytes = readPage(dst, ++zeroBasedPagesNumber, 0); if (readBytes == 0) { break; } read += readBytes; } position += read; return read; } return -1; } private int readPage(ByteBuffer dst, int pageNumber, int bufferPosition) { if (pageNumber < pages.size()) { ByteBuffer page = pages.get(pageNumber); page.position(bufferPosition); if (page.hasRemaining()) { int toRead = Math.min(dst.remaining(), page.remaining()); byte[] bufToRead = new byte[toRead]; page.get(bufToRead); dst.put(bufToRead); return toRead; } } return 0; } @Override public int read() throws IOException { requireOpen(); int zeroBasedPagesNumber = (int) (position() / pageSize); ByteBuffer page = pages.get(zeroBasedPagesNumber); int relativePosition = (int) (position() - (zeroBasedPagesNumber * pageSize)); if (relativePosition < page.limit()) { position++; return page.get(relativePosition); } return -1; } @Override public void close() throws IOException { super.close(); IOUtils.close(localCopiesSupplier); pages.stream().forEach(IOUtils::unmap); pages.clear(); } @Override public SeekableSource view(long startingPosition, long length) throws IOException { requireOpen(); return new SeekableSourceView(localCopiesSupplier, id(), startingPosition, length); } } sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/io/SeekableSource.java000066400000000000000000000117501305261226700247550ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import java.io.IOException; import java.io.InputStream; import java.nio.channels.ReadableByteChannel; /** * Readable source that provides random access capabilities. * * @author Andrea Vacondio */ public interface SeekableSource extends ReadableByteChannel { /** * @return the unique id for the source. */ String id(); /** * @return the current source position as a positive long * @throws IOException */ long position() throws IOException; /** * Sets the source position. Setting the position to a value that is greater than the source's size is legal but does not change the size of the source. A later attempt to read * bytes at such a position will immediately * * @param position * a non-negative long for the new position * @return this source * @throws IOException */ SeekableSource position(long position) throws IOException; /** * @return The source size, measured in bytes */ long size(); /** * Reads a byte of data from this source. The byte is returned as an integer in the range 0 to 255 ( {@code 0x00-0xff} ). * * @return the next byte of data, or {@code -1} if there is no more data. * @throws IOException */ int read() throws IOException; /** * @param startingPosition * @param length * @return a readable view of a portion of this {@link SeekableSource}. Reading from the view doesn't affect the {@link SeekableSource} position. Closing the * {@link SeekableSource} makes all the views unreadable but closing the view has no effect on the {@link SeekableSource}. A view may or may not work on a thread bound * copy of the {@link SeekableSource} so as a general rule it should not be created and handed to other threads.. * @throws IOException * if something goes wrong while creating the view */ SeekableSource view(long startingPosition, long length) throws IOException; /** * Skips backward the given number of bytes moving back the source position * * @param offset * the number of bytes to skip back. * @return this source * @throws IOException */ default SeekableSource back(long offset) throws IOException { long newPosition = position() - offset; if (newPosition < 0 || newPosition > size()) { throw new IllegalArgumentException( "Going back would move to " + newPosition + ", outside of source boundaries"); } position(newPosition); return this; } /** * Skips backward moving back the source position of one byte * * @return this source * @throws IOException * @see SeekableSource#back(long) */ default SeekableSource back() throws IOException { return back(1); } /** * * Skips the given number of bytes moving forward the source position * * @param offset * the number of bytes to skip . * @return this source * @throws IOException */ default SeekableSource forward(long offset) throws IOException { return back(-offset); } /** * Reads the next byte and sets the position back by one. * * @return the next byte or {@code -1} if there is no more data. * @throws IOException * @see #read() */ default int peek() throws IOException { int val = read(); if (val != -1) { back(1); } return val; } /** * Reads the previous byte and sets the position back where it was. * * @return the previous byte or {@code -1} if we are at the beginning of the source. * @throws IOException * @see #read() */ default int peekBack() throws IOException { if (position() > 0) { back(1); return read(); } return -1; } /** * Creates an {@link InputStream} from this {@link SeekableSource}. * * @return the input stream wrapping the given {@link SeekableSource} */ default InputStream asInputStream() { return new SeekableSourceInputStream(this); } } sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/io/SeekableSourceInputStream.java000066400000000000000000000050021305261226700271420ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static java.util.Objects.requireNonNull; import static org.sejda.util.RequireUtils.requireState; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; /** * Bridge between {@link SeekableSource} and {@link InputStream} * * @author Andrea Vacondio */ class SeekableSourceInputStream extends InputStream { private SeekableSource wrapped; SeekableSourceInputStream(SeekableSource wrapped) { requireNonNull(wrapped); this.wrapped = wrapped; } @Override public int read() throws IOException { return getSource().read(); } @Override public int read(byte[] b) throws IOException { if (available() > 0) { return getSource().read(ByteBuffer.wrap(b, 0, Math.min(b.length, available()))); } return -1; } @Override public int read(byte[] b, int offset, int length) throws IOException { if (available() > 0) { return getSource().read(ByteBuffer.wrap(b, Math.min(b.length, offset), Math.min(length, Math.min(b.length - offset, available())))); } return -1; } @Override public int available() throws IOException { SeekableSource source = getSource(); return (int) Math.max(0, (source.size() - source.position())); } @Override public long skip(long offset) throws IOException { SeekableSource source = getSource(); long start = source.position(); return source.forward(Math.min(offset, available())).position() - start; } private SeekableSource getSource() { requireState(wrapped.isOpen(), "The SeekableSource has been closed"); return wrapped; } } sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/io/SeekableSourceSupplier.java000066400000000000000000000015521305261226700265000ustar00rootroot00000000000000/* * Created on 17 giu 2016 * Copyright 2010 by Andrea Vacondio (andrea.vacondio@gmail.com). * * 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 org.sejda.io; import java.io.IOException; /** * @author Andrea Vacondio */ @FunctionalInterface public interface SeekableSourceSupplier { T get() throws IOException; } sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/io/SeekableSourceView.java000066400000000000000000000110341305261226700256030ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static org.sejda.util.RequireUtils.requireArg; import static org.sejda.util.RequireUtils.requireNotNullArg; import static org.sejda.util.RequireUtils.requireState; import java.io.IOException; import java.nio.ByteBuffer; /** * {@link SeekableSource} representing a view over a portion of a parent {@link SeekableSource}. A view becomes invalid if the parent {@link SeekableSource} is closed. The view * works on a thread local copy of the parent source so the parent position is not modified when a read method is called on the view. * * @author Andrea Vacondio */ class SeekableSourceView extends BaseSeekableSource { private long startingPosition; private long length; private long currentPosition; private SeekableSourceSupplier supplier; public SeekableSourceView(SeekableSourceSupplier supplier, String id, long startingPosition, long length) throws IOException { super(id); requireArg(startingPosition >= 0, "Starting position cannot be negative"); requireArg(length > 0, "View length must be positive"); requireNotNullArg(supplier, "Input decorated SeekableSource cannot be null"); this.startingPosition = startingPosition; this.currentPosition = 0; SeekableSource wrapped = supplier.get(); requireArg(startingPosition < wrapped.size(), "Starting position cannot be higher then wrapped source size"); this.length = Math.min(length, wrapped.size() - startingPosition); this.supplier = supplier; } @Override public long position() { return currentPosition; } @Override public SeekableSource position(long newPosition) throws IOException { SeekableSource wrapped = supplier.get(); requireArg(newPosition >= 0, "Cannot set position to a negative value"); this.currentPosition = Math.min(length, newPosition); wrapped.position(startingPosition + currentPosition); return this; } @Override public long size() { return length; } @Override public int read(ByteBuffer dst) throws IOException { SeekableSource wrapped = supplier.get(); requireOpen(); if (hasAvailable()) { wrapped.position(startingPosition + currentPosition); if (dst.remaining() > available()) { dst.limit(dst.position() + (int) available()); } int read = wrapped.read(dst); if (read > 0) { currentPosition += read; return read; } } return -1; } @Override public int read() throws IOException { requireOpen(); SeekableSource wrapped = supplier.get(); if (hasAvailable()) { wrapped.position(startingPosition + currentPosition); currentPosition++; return wrapped.read(); } return -1; } private boolean hasAvailable() { return available() > 0; } private long available() { return length - currentPosition; } @Override public void close() throws IOException { super.close(); this.currentPosition = 0; } @Override protected void requireOpen() throws IOException { super.requireOpen(); SeekableSource wrapped = supplier.get(); requireState(wrapped.isOpen(), "The original SeekableSource has been closed"); } /** * Cannot create a view of a view. This method throws {@link RuntimeException}. * * @throws RuntimeException */ @Override public SeekableSource view(long startingPosition, long length) { throw new RuntimeException("Cannot create a view of a view"); } } sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/io/SeekableSources.java000066400000000000000000000115031305261226700251340ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static java.util.Objects.requireNonNull; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import org.sejda.util.IOUtils; /** * This class consists of solely static methods to create the most appropriate {@link SeekableSource} based on the given input or to bridge {@link SeekableSource}s to the more * traditional {@link InputStream} or other standard I/O classes. * * @author Andrea Vacondio * */ public final class SeekableSources { /** * Threshold size in bytes where the SeekableSources method will switch to {@link MemoryMappedSeekableSource#MemoryMappedSeekableSource(File)} */ public static final String MAPPED_SIZE_THRESHOLD_PROPERTY = "org.sejda.io.mapped.size.threshold"; /** * Threshold size in bytes where the SeekableSources method will switch to {@link MemoryMappedSeekableSource#MemoryMappedSeekableSource(File)} */ public static final String DISABLE_MEMORY_MAPPED_PROPERTY = "org.sejda.io.mapped.disabled"; /** * Buffer size for {@link BufferedSeekableSource} */ public static final String INPUT_BUFFER_SIZE_PROPERTY = "org.sejda.io.buffered.input.size"; /** * Size of the pages used by {@link MemoryMappedSeekableSource} */ public static final String MEMORY_MAPPED_PAGE_SIZE_PROPERTY = "org.sejda.io.memory.mapped.page.size"; private static final long MB_16 = 1 << 24; private SeekableSources() { // utility } /** * Factory method to create a {@link SeekableSource} from a {@link File}. An attempt is made to return the best {@link SeekableSource} implementation based on the size of the * file and bitness of the JVM. * * @param file * @return a {@link SeekableSource} from the given file. * @throws IOException */ public static SeekableSource seekableSourceFrom(File file) throws IOException { requireNonNull(file); if (!"32".equals(System.getProperty("sun.arch.data.model")) && !Boolean.getBoolean(DISABLE_MEMORY_MAPPED_PROPERTY) && file.length() > Long.getLong(MAPPED_SIZE_THRESHOLD_PROPERTY, MB_16)) { return new BufferedSeekableSource(new MemoryMappedSeekableSource(file)); } return new BufferedSeekableSource(new FileChannelSeekableSource(file)); } /** * Factory method to create a {@link SeekableSource} from a {@link InputStream}. The whole stream is read an stored in a byte array with a max size of 2GB. * * @param stream * @return a {@link SeekableSource} from the given stream. * @throws IOException */ public static SeekableSource inMemorySeekableSourceFrom(InputStream stream) throws IOException { requireNonNull(stream); return new ByteArraySeekableSource(IOUtils.toByteArray(stream)); } /** * Factory method to create a {@link SeekableSource} from a byte array. * * @param bytes * @return a {@link SeekableSource} wrapping the given byte array. */ public static SeekableSource inMemorySeekableSourceFrom(byte[] bytes) { requireNonNull(bytes); return new ByteArraySeekableSource(bytes); } /** * Factory method to create a {@link SeekableSource} from a {@link InputStream}. The whole stream is copied to a temporary file. * * @param stream * @return a {@link SeekableSource} from the given stream. * @throws IOException */ public static SeekableSource onTempFileSeekableSourceFrom(InputStream stream) throws IOException { requireNonNull(stream); Path temp = Files.createTempFile("SejdaIO", null); Files.copy(stream, temp, StandardCopyOption.REPLACE_EXISTING); return new BufferedSeekableSource(new FileChannelSeekableSource(temp.toFile()) { @Override public void close() throws IOException { super.close(); Files.deleteIfExists(temp); } }); } } sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/io/ThreadBoundCopiesSupplier.java000066400000000000000000000040561305261226700271500ustar00rootroot00000000000000/* * Created on 07 gen 2016 * Copyright 2010 by Andrea Vacondio (andrea.vacondio@gmail.com). * * 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 org.sejda.io; import static java.util.Objects.isNull; import static java.util.Objects.requireNonNull; import java.io.Closeable; import java.io.IOException; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.sejda.util.IOUtils; /** * Component suppling per-thread copies of a {@link SeekableSource} using the provided supplier. When closed, all the generated copies are closed as well. * * @author Andrea Vacondio */ public class ThreadBoundCopiesSupplier implements Closeable, SeekableSourceSupplier { private ConcurrentMap copies = new ConcurrentHashMap<>(); private final SeekableSourceSupplier supplier; public ThreadBoundCopiesSupplier(SeekableSourceSupplier supplier) { requireNonNull(supplier); this.supplier = supplier; } @Override public T get() throws IOException { long id = Thread.currentThread().getId(); T copy = copies.get(id); if (isNull(copy)) { T newCopy = supplier.get(); copy = copies.putIfAbsent(id, newCopy); if (isNull(copy)) { copy = newCopy; } else { IOUtils.closeQuietly(newCopy); } } return copy; } @Override public void close() { copies.values().stream().forEach(IOUtils::closeQuietly); } } sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/util/000077500000000000000000000000001305261226700215605ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/util/IOUtils.java000066400000000000000000000206061305261226700237570ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* $Id$ */ package org.sejda.util; import static java.lang.invoke.MethodHandles.constant; import static java.lang.invoke.MethodHandles.dropArguments; import static java.lang.invoke.MethodHandles.filterReturnValue; import static java.lang.invoke.MethodHandles.guardWithTest; import static java.lang.invoke.MethodHandles.lookup; import static java.lang.invoke.MethodType.methodType; import static java.util.Objects.nonNull; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles.Lookup; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Objects; import java.util.Optional; import java.util.function.Consumer; import org.sejda.io.FastByteArrayOutputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Utility class with I/O related static methods */ public final class IOUtils { private static final Logger LOG = LoggerFactory.getLogger(IOUtils.class); private static final Optional> UNMAPPER; static { UNMAPPER = Optional .ofNullable(AccessController.doPrivileged((PrivilegedAction>) IOUtils::unmapper)); } private IOUtils() { // hide } /** * Null safe close of the given {@link Closeable}. * * @param closeable * to be closed * @throws IOException */ public static void close(Closeable closeable) throws IOException { if (closeable != null) { closeable.close(); } } /** * Null safe close of the given {@link Closeable} suppressing any exception. * * @param closeable * to be closed */ public static void closeQuietly(Closeable closeable) { try { if (closeable != null) { closeable.close(); } } catch (IOException ioe) { LOG.warn("An error occured while closing a Closeable resource", ioe); } } /** * @param input * @return the content of the input stream as a byte[] * @throws IOException */ public static byte[] toByteArray(InputStream input) throws IOException { FastByteArrayOutputStream output = new FastByteArrayOutputStream(); org.apache.commons.io.IOUtils.copy(input, output); return output.toByteArray(); } /** * Unmap memory mapped byte buffers. This is a hack waiting for a proper JVM provided solution expected in java 10 https://bugs.openjdk.java.net/browse/JDK-4724038 The issue * here is that even when closed, memory mapped byte buffers hold a lock on the underlying file until GC is executes and this in turns result in an error if the user tries to * move or delete the file. * * @param buf */ public static void unmap(ByteBuffer buf) { UNMAPPER.ifPresent(u -> { try { u.accept(buf); } catch (Exception e) { LOG.error("Unable to unmap ByteBuffer.", e); } }); } /** * This is adapted from org.apache.lucene.store.MMapDirectory * * @return */ private static Consumer unmapper() { final Lookup lookup = lookup(); try { try { // *** sun.misc.Unsafe unmapping (Java 9+) *** final Class unsafeClass = Class.forName("sun.misc.Unsafe"); // first check if Unsafe has the right method, otherwise we can give up // without doing any security critical stuff: final MethodHandle unmapper = lookup.findVirtual(unsafeClass, "invokeCleaner", methodType(void.class, ByteBuffer.class)); // fetch the unsafe instance and bind it to the virtual MH: final Field f = unsafeClass.getDeclaredField("theUnsafe"); f.setAccessible(true); final Object theUnsafe = f.get(null); return newBufferCleaner(ByteBuffer.class, unmapper.bindTo(theUnsafe)); } catch (SecurityException se) { // rethrow to report errors correctly (we need to catch it here, as we also catch RuntimeException below!): throw se; } catch (ReflectiveOperationException | RuntimeException e) { // *** sun.misc.Cleaner unmapping (Java 8) *** final Class directBufferClass = Class.forName("java.nio.DirectByteBuffer"); final Method m = directBufferClass.getMethod("cleaner"); m.setAccessible(true); final MethodHandle directBufferCleanerMethod = lookup.unreflect(m); final Class cleanerClass = directBufferCleanerMethod.type().returnType(); /* * "Compile" a MH that basically is equivalent to the following code: void unmapper(ByteBuffer byteBuffer) { sun.misc.Cleaner cleaner = ((java.nio.DirectByteBuffer) * byteBuffer).cleaner(); if (Objects.nonNull(cleaner)) { cleaner.clean(); } else { noop(cleaner); // the noop is needed because MethodHandles#guardWithTest always * needs ELSE } } */ final MethodHandle cleanMethod = lookup.findVirtual(cleanerClass, "clean", methodType(void.class)); final MethodHandle nonNullTest = lookup .findStatic(Objects.class, "nonNull", methodType(boolean.class, Object.class)) .asType(methodType(boolean.class, cleanerClass)); final MethodHandle noop = dropArguments(constant(Void.class, null).asType(methodType(void.class)), 0, cleanerClass); final MethodHandle unmapper = filterReturnValue(directBufferCleanerMethod, guardWithTest(nonNullTest, cleanMethod, noop)).asType(methodType(void.class, ByteBuffer.class)); return newBufferCleaner(directBufferClass, unmapper); } } catch (SecurityException se) { LOG.error( "Unmapping is not supported because of missing permissions. Please grant at least the following permissions: RuntimePermission(\"accessClassInPackage.sun.misc\") " + " and ReflectPermission(\"suppressAccessChecks\")", se); } catch (ReflectiveOperationException | RuntimeException e) { LOG.error("Unmapping is not supported.", e); } return null; } private static Consumer newBufferCleaner(final Class unmappableBufferClass, final MethodHandle unmapper) { assert Objects.equals(methodType(void.class, ByteBuffer.class), unmapper.type()); return (ByteBuffer buffer) -> { if (!buffer.isDirect()) { throw new IllegalArgumentException("unmapping only works with direct buffers"); } if (!unmappableBufferClass.isInstance(buffer)) { throw new IllegalArgumentException("buffer is not an instance of " + unmappableBufferClass.getName()); } final Throwable e = AccessController.doPrivileged((PrivilegedAction) () -> { try { unmapper.invokeExact(buffer); return null; } catch (Throwable t) { return t; } }); if (nonNull(e)) { LOG.error("Unable to unmap the mapped buffer", e); } }; } } sejda-io-1.1.3.RELEASE/src/main/java/org/sejda/util/RequireUtils.java000066400000000000000000000054641305261226700250710ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.util; import java.io.IOException; /** * Utility methods to check parameters and conditions validity. * * @author Andrea Vacondio * */ public final class RequireUtils { private RequireUtils() { // utility class } /** * Throws an {@link IllegalArgumentException} if the given argument is null * * @param arg * @param exceptionMessage */ public static void requireNotNullArg(Object arg, String exceptionMessage) { if (arg == null) { throw new IllegalArgumentException(exceptionMessage); } } /** * Throws an {@link IllegalArgumentException} if the given condition is not met * * @param condition * @param exceptionMessage */ public static void requireArg(boolean condition, String exceptionMessage) { if (!condition) { throw new IllegalArgumentException(exceptionMessage); } } /** * Throws an {@link IllegalArgumentException} if the given string is blank * * @param value * string * @param exceptionMessage */ public static void requireNotBlank(String value, String exceptionMessage) { requireArg(value != null && value.trim().length() > 0, exceptionMessage); } /** * Throws an {@link IOException} if the given condition is not met * * @param condition * @param exceptionMessage * @throws IOException */ public static void requireIOCondition(boolean condition, String exceptionMessage) throws IOException { if (!condition) { throw new IOException(exceptionMessage); } } /** * Throws an {@link IllegalStateException} if the given condition is not met * * @param condition * @param exceptionMessage * @throws IllegalStateException */ public static void requireState(boolean condition, String exceptionMessage) { if (!condition) { throw new IllegalStateException(exceptionMessage); } } } sejda-io-1.1.3.RELEASE/src/test/000077500000000000000000000000001305261226700160405ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/src/test/java/000077500000000000000000000000001305261226700167615ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/src/test/java/org/000077500000000000000000000000001305261226700175505ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/src/test/java/org/sejda/000077500000000000000000000000001305261226700206365ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/src/test/java/org/sejda/io/000077500000000000000000000000001305261226700212455ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/src/test/java/org/sejda/io/BaseSeekableSourceTest.java000066400000000000000000000053471305261226700264500ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.nio.ByteBuffer; import org.junit.Before; import org.junit.Test; /** * @author Andrea Vacondio * */ public class BaseSeekableSourceTest { private BaseSeekableSource victim; @Before public void setUp() { victim = new BaseSeekableSource("id") { @Override public int read(ByteBuffer dst) { return 0; } @Override public SeekableSource view(long startingPosition, long length) { return null; } @Override public long size() { return 0; } @Override public int read() { return 0; } @Override public SeekableSource position(long position) { return null; } @Override public long position() { return 0; } }; } @Test public void isOpen() throws IOException { assertTrue(victim.isOpen()); victim.close(); assertFalse(victim.isOpen()); } @Test public void requireOpen() throws IOException { assertTrue(victim.isOpen()); victim.requireOpen(); } @Test(expected = IllegalStateException.class) public void failingRequireOpen() throws IOException { assertTrue(victim.isOpen()); victim.close(); victim.requireOpen(); } @Test public void id() { assertEquals("id", victim.id()); } @Test public void inputStreamFrom() { assertNotNull(victim.asInputStream()); } } sejda-io-1.1.3.RELEASE/src/test/java/org/sejda/io/BaseTestSeekableSource.java000066400000000000000000000073661305261226700264530ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.nio.ByteBuffer; import org.junit.After; import org.junit.Test; import org.sejda.util.IOUtils; /** * @author Andrea Vacondio * */ public abstract class BaseTestSeekableSource { abstract SeekableSource victim(); @After public void tearDown() throws IOException { IOUtils.close(victim()); } @Test(expected = IllegalArgumentException.class) public void illegalPosition() throws IOException { victim().position(-10); } @Test(expected = IllegalStateException.class) public void viewClosed() throws IOException { victim().close(); victim().view(0, 2); } @Test public void view() throws IOException { assertNotNull(victim().view(0, 2)); } @Test public void close() throws IOException { victim().read(); assertTrue(victim().isOpen()); victim().close(); assertFalse(victim().isOpen()); } @Test(expected = IllegalStateException.class) public void readClosed() throws IOException { victim().close(); victim().read(); } @Test(expected = IllegalStateException.class) public void readByteBuffClosed() throws IOException { victim().close(); victim().read(ByteBuffer.allocate(5)); } @Test public void forward() throws IOException { assertEquals(0, victim().position()); assertEquals(1, victim().forward(1).position()); } @Test(expected = IllegalArgumentException.class) public void invalidForward() throws IOException { assertEquals(0, victim().position()); victim().forward(victim().size() + 1); } @Test public void back() throws IOException { assertEquals(1, victim().forward(1).position()); assertEquals(0, victim().back().position()); } @Test(expected = IllegalArgumentException.class) public void invalidBack() throws IOException { assertEquals(0, victim().position()); victim().back(); } @Test public void peek() throws IOException { assertEquals(0, victim().position()); assertNotEquals(-1, victim().peek()); assertEquals(0, victim().position()); } @Test public void peekEOF() throws IOException { victim().position(victim().size()); assertEquals(-1, victim().peek()); } @Test public void peekBack() throws IOException { victim().position(victim().size()); assertNotEquals(-1, victim().peekBack()); assertEquals(victim().size(), victim().position()); } @Test public void peekBackBeginning() throws IOException { assertEquals(0, victim().position()); assertEquals(-1, victim().peekBack()); } } sejda-io-1.1.3.RELEASE/src/test/java/org/sejda/io/BufferedCountingChannelWriterTest.java000066400000000000000000000114011305261226700306640ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Arrays; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * @author Andrea Vacondio * */ public class BufferedCountingChannelWriterTest { private ByteArrayOutputStream out; private CountingWritableByteChannel channel; private BufferedCountingChannelWriter victim; @Before public void setUp() { out = new ByteArrayOutputStream(); channel = CountingWritableByteChannel.from(out); victim = new BufferedCountingChannelWriter(channel); } @After public void after() { System.getProperties().remove(BufferedCountingChannelWriter.OUTPUT_BUFFER_SIZE_PROPERTY); } @Test(expected = IllegalArgumentException.class) public void nullConstructor() { new BufferedCountingChannelWriter(null); } @Test public void close() throws IOException { victim.close(); assertFalse(channel.isOpen()); } @Test public void flush() throws IOException { channel = mock(CountingWritableByteChannel.class); victim = new BufferedCountingChannelWriter(channel); victim.writeEOL(); verify(channel, times(0)).write(any()); victim.flush(); verify(channel).write(any()); } @Test public void closeFlushes() throws IOException { channel = mock(CountingWritableByteChannel.class); when(channel.isOpen()).thenReturn(true); victim = new BufferedCountingChannelWriter(channel); victim.writeEOL(); verify(channel, times(0)).write(any()); victim.close(); verify(channel).write(any()); } @Test public void writeEOL() throws IOException { victim.writeEOL(); victim.close(); assertTrue(Arrays.equals(new byte[] { '\n' }, out.toByteArray())); } @Test public void prettyPrintJustOneEOL() throws IOException { victim.writeEOL(); victim.writeEOL(); victim.write((byte) -1); victim.writeEOL(); victim.writeEOL(); victim.close(); assertTrue(Arrays.equals(new byte[] { '\n', -1, '\n' }, out.toByteArray())); } @Test public void multipleCloseDontThrowException() throws IOException { victim.close(); victim.writeEOL(); victim.close(); } @Test public void writeString() throws IOException { victim.write("ChuckNorris"); victim.close(); assertTrue(Arrays.equals("ChuckNorris".getBytes("ISO-8859-1"), out.toByteArray())); } @Test public void writeBytesExceedingBuffer() throws IOException { System.getProperties().setProperty(BufferedCountingChannelWriter.OUTPUT_BUFFER_SIZE_PROPERTY, "4"); victim = new BufferedCountingChannelWriter(channel); byte[] bytes = new byte[] { '1', '1', '2', '1', '1' }; victim.write(bytes); assertEquals(5, victim.offset()); victim.close(); assertTrue(Arrays.equals(bytes, out.toByteArray())); } @Test public void writeInputStream() throws IOException { byte[] bytes = new byte[] { '1', '1', '2', '1', '1' }; victim.write(bytes); byte[] streamBytes = "ChuckNorris".getBytes("ISO-8859-1"); ByteArrayInputStream is = new ByteArrayInputStream(streamBytes); victim.write(is); victim.close(); byte[] expected = Arrays.copyOf(bytes, bytes.length + streamBytes.length); System.arraycopy(streamBytes, 0, expected, bytes.length, streamBytes.length); assertTrue(Arrays.equals(expected, out.toByteArray())); } } sejda-io-1.1.3.RELEASE/src/test/java/org/sejda/io/BufferedSeekableSourceTest.java000066400000000000000000000072471305261226700273210ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.nio.ByteBuffer; import org.junit.Before; import org.junit.Test; import org.sejda.io.BufferedSeekableSource; import org.sejda.io.ByteArraySeekableSource; import org.sejda.io.SeekableSource; /** * @author Andrea Vacondio * */ public class BufferedSeekableSourceTest extends BaseTestSeekableSource { private ByteArraySeekableSource wrapped; private BufferedSeekableSource victim; @Before public void setUp() { wrapped = new ByteArraySeekableSource(new byte[] { 'a', 'b', 'c' }); victim = new BufferedSeekableSource(wrapped); } @Test(expected = IllegalArgumentException.class) public void failingConstructor() { new BufferedSeekableSource(null); } @Test public void constructor() { assertEquals(wrapped.id(), victim.id()); assertEquals(wrapped.size(), victim.size()); } @Override @Test public void close() throws IOException { victim.read(); assertTrue(victim.isOpen()); assertTrue(wrapped.isOpen()); victim.close(); assertFalse(victim.isOpen()); assertFalse(wrapped.isOpen()); } @Test public void read() throws IOException { assertEquals(97, victim.read()); assertEquals(1, victim.position()); assertEquals(98, victim.read()); assertEquals(2, victim.position()); assertEquals(99, victim.read()); assertEquals(3, victim.position()); assertEquals(-1, victim.read()); assertEquals(3, victim.position()); } @Test public void readBuff() throws IOException { victim.position(1); ByteBuffer dst = ByteBuffer.allocate(10); victim.read(dst); dst.flip(); assertEquals(2, dst.remaining()); assertEquals(98, dst.get()); assertEquals(99, dst.get()); ByteBuffer empty = ByteBuffer.allocate(10); victim.read(empty); empty.flip(); assertFalse(empty.hasRemaining()); } @Test public void position() throws IOException { assertEquals(0, victim.position()); assertEquals(97, victim.read()); victim.position(0); assertEquals(0, victim.position()); victim.position(0); assertEquals(0, victim.position()); victim.position(2); assertEquals(2, victim.position()); victim.read(); assertEquals(3, victim.position()); assertEquals(-1, victim.read()); victim.position(2); assertEquals(2, victim.position()); victim.position(20); assertEquals(3, victim.position()); assertEquals(-1, victim.read()); } @Override SeekableSource victim() { return victim; } } sejda-io-1.1.3.RELEASE/src/test/java/org/sejda/io/ByteArraySeekableSourceTest.java000066400000000000000000000057601305261226700274770ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import java.io.IOException; import java.nio.ByteBuffer; import org.junit.Before; import org.junit.Test; /** * @author Andrea Vacondio * */ public class ByteArraySeekableSourceTest extends BaseTestSeekableSource { private ByteArraySeekableSource victim; @Before public void setUp() { victim = new ByteArraySeekableSource(new byte[] { 'a', 'b', 'c' }); } @Test(expected = IllegalArgumentException.class) public void failingConstructor() { new ByteArraySeekableSource(null); } @Test public void read() throws IOException { assertEquals(97, victim.read()); assertEquals(1, victim.position()); assertEquals(98, victim.read()); assertEquals(2, victim.position()); assertEquals(99, victim.read()); assertEquals(3, victim.position()); assertEquals(-1, victim.read()); assertEquals(3, victim.position()); } @Test public void readBuff() throws IOException { victim.position(1); ByteBuffer dst = ByteBuffer.allocate(10); victim.read(dst); dst.flip(); assertEquals(2, dst.remaining()); assertEquals(98, dst.get()); assertEquals(99, dst.get()); ByteBuffer empty = ByteBuffer.allocate(10); victim.read(empty); empty.flip(); assertFalse(empty.hasRemaining()); } @Test public void position() throws IOException { assertEquals(0, victim.position()); assertEquals(97, victim.read()); victim.position(0); assertEquals(0, victim.position()); victim.position(0); assertEquals(0, victim.position()); victim.position(2); assertEquals(2, victim.position()); victim.read(); assertEquals(3, victim.position()); assertEquals(-1, victim.read()); victim.position(2); assertEquals(2, victim.position()); victim.position(20); assertEquals(3, victim.position()); assertEquals(-1, victim.read()); } @Override SeekableSource victim() { return victim; } } sejda-io-1.1.3.RELEASE/src/test/java/org/sejda/io/CountingWritableByteChannelTest.java000066400000000000000000000101601305261226700303430ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.ClosedChannelException; import java.nio.channels.WritableByteChannel; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import org.junit.Before; import org.junit.Test; public class CountingWritableByteChannelTest { private ByteArrayOutputStream out; private CountingWritableByteChannel victim; private WritableByteChannel wrapped; private ByteBuffer src = ByteBuffer.wrap(new byte[] { '1', '1', '2', '1', '1' }); @Before public void setUp() { out = new ByteArrayOutputStream(); wrapped = Channels.newChannel(out); victim = new CountingWritableByteChannel(wrapped); } @Test(expected = IllegalArgumentException.class) public void nullConstructor() { new CountingWritableByteChannel(null); } @Test public void count() throws Exception { assertEquals(0, victim.count()); victim.write(src); assertEquals(5, victim.count()); } @Test(expected = ClosedChannelException.class) public void closedWrite() throws Exception { victim.close(); victim.write(src); } @Test public void write() throws Exception { victim.write(src); assertTrue(Arrays.equals(out.toByteArray(), src.array())); } @Test public void isOpen() { assertTrue(victim.isOpen()); assertTrue(wrapped.isOpen()); } @Test public void close() throws Exception { assertTrue(victim.isOpen()); assertTrue(wrapped.isOpen()); victim.close(); assertFalse(victim.isOpen()); assertFalse(wrapped.isOpen()); } @Test public void testFromWritableByteChannel() throws Exception { victim = CountingWritableByteChannel.from(Channels.newChannel(out)); victim.write(src); assertTrue(Arrays.equals(out.toByteArray(), src.array())); } @Test public void fromOutputStream() throws Exception { victim = CountingWritableByteChannel.from(out); victim.write(src); assertTrue(Arrays.equals(out.toByteArray(), src.array())); } @Test public void fromFile() throws Exception { Path tempFile = Files.createTempFile("SAMBox", null); try { assertEquals(0, Files.size(tempFile)); victim = CountingWritableByteChannel.from(tempFile.toFile()); victim.write(src); assertTrue(Arrays.equals(Files.readAllBytes(tempFile), src.array())); } finally { Files.deleteIfExists(tempFile); } } @Test public void fromString() throws Exception { Path tempFile = Files.createTempFile("SAMBox", null); try { assertEquals(0, Files.size(tempFile)); victim = CountingWritableByteChannel.from(tempFile.toAbsolutePath().toString()); victim.write(src); assertTrue(Arrays.equals(Files.readAllBytes(tempFile), src.array())); } finally { Files.deleteIfExists(tempFile); } } } sejda-io-1.1.3.RELEASE/src/test/java/org/sejda/io/DevNullWritableByteChannelTest.java000066400000000000000000000026431305261226700301350ustar00rootroot00000000000000/* * Created on 14/ago/2015 * Copyright 2010 by Andrea Vacondio (andrea.vacondio@gmail.com). * * 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 org.sejda.io; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.nio.ByteBuffer; import org.junit.Before; import org.junit.Test; /** * @author Andrea Vacondio * */ public class DevNullWritableByteChannelTest { private DevNullWritableByteChannel victim; private ByteBuffer src = ByteBuffer.wrap(new byte[] { '1', '1', '2', '1', '1' }); @Before public void setUp() { victim = new DevNullWritableByteChannel(); } @Test public void write() { assertEquals(5, victim.write(src)); } @Test public void close() { assertTrue(victim.isOpen()); victim.close(); assertFalse(victim.isOpen()); } } sejda-io-1.1.3.RELEASE/src/test/java/org/sejda/io/FileChannelSeekableSourceTest.java000066400000000000000000000055101305261226700277360ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.sejda.io.FileChannelSeekableSource; import org.sejda.io.SeekableSource; /** * @author Andrea Vacondio */ public class FileChannelSeekableSourceTest extends BaseTestSeekableSource { private FileChannelSeekableSource victim; private Path tempFile; @Before public void setUp() throws Exception { tempFile = Files.createTempFile("SejdaIO", null); Files.copy(getClass().getResourceAsStream("/pdf/simple_test.pdf"), tempFile, StandardCopyOption.REPLACE_EXISTING); victim = new FileChannelSeekableSource(tempFile.toFile()); } @After public void after() throws IOException { Files.deleteIfExists(tempFile); } @Test(expected = IllegalArgumentException.class) public void failingConstructor() throws IOException { new FileChannelSeekableSource(null); } @Test public void read() throws IOException { assertEquals(0, victim.position()); assertNotNull(victim.read()); assertNotNull(victim.read()); assertEquals(2, victim.position()); victim.position(victim.size()); assertEquals(-1, victim.read()); } @Test public void readBuff() throws IOException { ByteBuffer dst = ByteBuffer.allocate(20); victim.read(dst); dst.flip(); assertEquals(20, dst.remaining()); assertEquals(20, victim.position()); victim.position(victim.size()); ByteBuffer empty = ByteBuffer.allocate(10); victim.read(empty); empty.flip(); assertFalse(empty.hasRemaining()); } @Override SeekableSource victim() { return victim; } } sejda-io-1.1.3.RELEASE/src/test/java/org/sejda/io/MemoryMappedSeekableSourceTest.java000066400000000000000000000112671305261226700301730ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import org.junit.After; import org.junit.Before; import org.junit.Test; public class MemoryMappedSeekableSourceTest extends BaseTestSeekableSource { private MemoryMappedSeekableSource victim; private Path tempFile; @Before public void setUp() throws Exception { tempFile = Files.createTempFile("SejdaIO", null); Files.copy(getClass().getResourceAsStream("/pdf/simple_test.pdf"), tempFile, StandardCopyOption.REPLACE_EXISTING); victim = new MemoryMappedSeekableSource(tempFile.toFile()); } @After public void after() throws IOException { System.getProperties().remove(SeekableSources.MEMORY_MAPPED_PAGE_SIZE_PROPERTY); Files.deleteIfExists(tempFile); } @Test(expected = IllegalArgumentException.class) public void failingConstructor() throws IOException { new MemoryMappedSeekableSource(null); } @Test public void read() throws IOException { assertEquals(0, victim.position()); assertNotNull(victim.read()); assertNotNull(victim.read()); assertEquals(2, victim.position()); victim.position(victim.size()); assertEquals(-1, victim.read()); } @Test public void pagedRead() throws IOException { System.setProperty(SeekableSources.MEMORY_MAPPED_PAGE_SIZE_PROPERTY, "50"); Path tempFile = Files.createTempFile("SejdaIO", null); try { Files.copy(getClass().getResourceAsStream("/pdf/simple_test.pdf"), tempFile, StandardCopyOption.REPLACE_EXISTING); victim = new MemoryMappedSeekableSource(tempFile.toFile()); victim.position(49); assertNotNull(victim.read()); assertNotNull(victim.read()); assertNotNull(victim.read()); assertEquals(52, victim.position()); } finally { Files.deleteIfExists(tempFile); } } @Test public void readBuff() throws IOException { ByteBuffer dst = ByteBuffer.allocate(20); victim.read(dst); dst.flip(); assertEquals(20, dst.remaining()); assertEquals(20, victim.position()); victim.position(victim.size()); ByteBuffer empty = ByteBuffer.allocate(10); victim.read(empty); empty.flip(); assertFalse(empty.hasRemaining()); } @Test public void pagedReadBuff() throws IOException { System.setProperty(SeekableSources.MEMORY_MAPPED_PAGE_SIZE_PROPERTY, "50"); Path tempFile = Files.createTempFile("SejdaIO", null); try { Files.copy(getClass().getResourceAsStream("/pdf/simple_test.pdf"), tempFile, StandardCopyOption.REPLACE_EXISTING); victim = new MemoryMappedSeekableSource(tempFile.toFile()); ByteBuffer dst = ByteBuffer.allocate(70); victim.read(dst); dst.flip(); assertEquals(70, dst.remaining()); assertEquals(70, victim.position()); victim.position(victim.size() - 70); ByteBuffer dst2 = ByteBuffer.allocate(120); victim.read(dst2); dst2.flip(); assertEquals(70, dst2.remaining()); victim.position(victim.size()); ByteBuffer empty = ByteBuffer.allocate(10); victim.read(empty); empty.flip(); assertFalse(empty.hasRemaining()); } finally { Files.deleteIfExists(tempFile); } } @Override SeekableSource victim() { return victim; } } sejda-io-1.1.3.RELEASE/src/test/java/org/sejda/io/SeekableSourceInputStreamTest.java000066400000000000000000000121241305261226700300400ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.IOException; import java.nio.ByteBuffer; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; /** * @author Andrea Vacondio * */ public class SeekableSourceInputStreamTest { private SeekableSource source; private SeekableSourceInputStream victim; @Before public void setUp() { source = mock(SeekableSource.class); when(source.isOpen()).thenReturn(true); victim = new SeekableSourceInputStream(source); } @Test(expected = NullPointerException.class) public void nullSource() { new SeekableSourceInputStream(null); } @Test public void read() throws IOException { victim.read(); verify(source).read(); } @Test(expected = IllegalStateException.class) public void readClosed() throws IOException { when(source.isOpen()).thenReturn(false); victim.read(); } @Test public void readByteArray() throws IOException { ArgumentCaptor captor = ArgumentCaptor.forClass(ByteBuffer.class); byte[] b = new byte[10]; when(source.size()).thenReturn(20L); when(source.position()).thenReturn(0L); victim.read(b); verify(source).read(captor.capture()); ByteBuffer captured = captor.getValue(); assertEquals(10, captured.capacity()); assertEquals(0, captured.position()); assertTrue(captured.hasArray()); } @Test(expected = IllegalStateException.class) public void readByteArrayClosed() throws IOException { when(source.isOpen()).thenReturn(false); victim.read(new byte[10]); } @Test public void readByteArrayWithPos() throws IOException { ArgumentCaptor captor = ArgumentCaptor.forClass(ByteBuffer.class); byte[] b = new byte[10]; when(source.size()).thenReturn(20L); when(source.position()).thenReturn(0L); victim.read(b, 5, 2); verify(source).read(captor.capture()); ByteBuffer captured = captor.getValue(); assertEquals(10, captured.capacity()); assertEquals(5, captured.position()); assertEquals(7, captured.limit()); assertTrue(captured.hasArray()); } @Test(expected = IllegalStateException.class) public void readByteArrayWithPosClosed() throws IOException { when(source.isOpen()).thenReturn(false); victim.read(new byte[10], 5, 2); } @Test public void readByteArrayWhenEndOfStream() throws IOException { ByteArraySeekableSource source = new ByteArraySeekableSource(new byte[] { -1, 1, 0, 1 }); SeekableSourceInputStream victim = new SeekableSourceInputStream(source); source.position(4); assertEquals(-1, source.read()); byte[] b = new byte[10]; assertEquals(-1, victim.read(b, 5, 2)); } @Test public void available() throws IOException { when(source.size()).thenReturn(20L); when(source.position()).thenReturn(3L); assertEquals(17, victim.available()); } @Test public void availableNotNegative() throws IOException { ByteArraySeekableSource source = new ByteArraySeekableSource(new byte[] { -1, 1, 0, 1 }); SeekableSourceInputStream victim = new SeekableSourceInputStream(source); source.position(10); assertEquals(0, victim.available()); } @Test public void close() throws IOException { victim.close(); verify(source, never()).close(); } @Test public void skip() throws IOException { ByteArraySeekableSource source = new ByteArraySeekableSource(new byte[] { -1, 1, 0, 1 }); SeekableSourceInputStream victim = new SeekableSourceInputStream(source); assertEquals(0, source.position()); victim.skip(2); assertEquals(2, source.position()); assertEquals(2, victim.skip(1000)); } @Test(expected = IllegalStateException.class) public void skipClosed() throws IOException { when(source.isOpen()).thenReturn(false); victim.skip(5); } } sejda-io-1.1.3.RELEASE/src/test/java/org/sejda/io/SeekableSourceViewTest.java000066400000000000000000000115571305261226700265100ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * @author Andrea Vacondio * */ public class SeekableSourceViewTest extends BaseTestSeekableSource { private SeekableSourceView victim; private Path tempFile; @Before public void setUp() throws Exception { tempFile = Files.createTempFile("SejdaIO", null); Files.copy(getClass().getResourceAsStream("/pdf/simple_test.pdf"), tempFile, StandardCopyOption.REPLACE_EXISTING); victim = new SeekableSourceView(() -> new FileChannelSeekableSource(tempFile.toFile()), "id", 50, 100); } @After public void after() throws IOException { Files.deleteIfExists(tempFile); } @Test(expected = IllegalArgumentException.class) public void nullSourceConstructor() throws IOException { new SeekableSourceView(null, "id", 50, 100); } @Test(expected = IllegalArgumentException.class) public void negativeStartPositionConstructor() throws IOException { new SeekableSourceView(() -> new ByteArraySeekableSource(new byte[] { -1 }), "id", -10, 100); } @Test(expected = IllegalArgumentException.class) public void outOfBoundsStartPositionConstructor() throws IOException { new SeekableSourceView(() -> new ByteArraySeekableSource(new byte[] { -1, 2 }), "id", 3, 100); } @Test(expected = IllegalArgumentException.class) public void nullNonPositiveLengthConstructor() throws IOException { new SeekableSourceView(() -> new ByteArraySeekableSource(new byte[] { -1 }), "id", 0, 0); } @Test public void size() { assertEquals(100, victim.size()); } @Test public void sizeTrimmed() throws IOException { assertEquals(2, new SeekableSourceView(() -> new ByteArraySeekableSource(new byte[] { -1, 2 }), "id", 0, 100).size()); } @Override @Test(expected = RuntimeException.class) public void view() throws IOException { victim().view(0, 2); } @Override @Test(expected = RuntimeException.class) public void viewClosed() throws IOException { victim().close(); victim().view(0, 2); } @Test(expected = IllegalStateException.class) public void parentClosed() throws IOException { ByteArraySeekableSource wrapped = new ByteArraySeekableSource(new byte[] { -1 }); victim = new SeekableSourceView(() -> wrapped, "id", 0, 1); wrapped.close(); assertTrue(victim.isOpen()); victim.read(); } @Test public void closeDoesntCloseParent() throws IOException { ByteArraySeekableSource wrapped = new ByteArraySeekableSource(new byte[] { -1 }); victim = new SeekableSourceView(() -> wrapped, "id", 0, 1); victim.close(); assertTrue(wrapped.isOpen()); } @Override SeekableSource victim() { return victim; } @Test public void read() throws IOException { assertEquals(0, victim.position()); assertNotNull(victim.read()); assertNotNull(victim.read()); assertEquals(2, victim.position()); victim.position(victim.size()); assertEquals(-1, victim.read()); } @Test public void readBuff() throws IOException { victim.position(1); ByteBuffer dst = ByteBuffer.allocate(10); victim.read(dst); dst.flip(); assertEquals(10, dst.remaining()); victim.position(victim.size()); ByteBuffer empty = ByteBuffer.allocate(10); victim.read(empty); empty.flip(); assertFalse(empty.hasRemaining()); } @Test public void readBigBuff() throws IOException { ByteBuffer dst = ByteBuffer.allocate(8000); assertEquals(100, victim.read(dst)); } } sejda-io-1.1.3.RELEASE/src/test/java/org/sejda/io/SeekableSourcesTest.java000066400000000000000000000134721305261226700260360ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.io; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; /** * @author Andrea Vacondio * */ public class SeekableSourcesTest { private static String BITNESS; @BeforeClass public static void before() { BITNESS = System.getProperty("sun.arch.data.model"); System.setProperty("sun.arch.data.model", "64"); } @AfterClass public static void after() { System.setProperty("sun.arch.data.model", BITNESS); } @Rule public TemporaryFolder temp = new TemporaryFolder(); @Test(expected = NullPointerException.class) public void nullSeekableSourceFrom() throws IOException { SeekableSources.seekableSourceFrom(null); } @Test(expected = NullPointerException.class) public void nullInMemorySeekableSourceFromBytes() { SeekableSources.inMemorySeekableSourceFrom((byte[]) null); } @Test(expected = NullPointerException.class) public void nullInMemorySeekableSourceFromStream() throws IOException { SeekableSources.inMemorySeekableSourceFrom((InputStream) null); } @Test(expected = NullPointerException.class) public void nullOnTempFileSeekableSourceFrom() throws IOException { SeekableSources.onTempFileSeekableSourceFrom(null); } @Test public void seekableSourceFrom() throws IOException { assertNotNull(SeekableSources.seekableSourceFrom(temp.newFile())); } @Test public void aboveThresholdSeekableSourceFrom() throws IOException { try { System.setProperty(SeekableSources.MAPPED_SIZE_THRESHOLD_PROPERTY, "10"); Path tempFile = Files.createTempFile("SejdaIO", null); Files.copy(getClass().getResourceAsStream("/pdf/simple_test.pdf"), tempFile, StandardCopyOption.REPLACE_EXISTING); SeekableSource source = SeekableSources.seekableSourceFrom(tempFile.toFile()); assertNotNull(source); assertTrue(source instanceof BufferedSeekableSource); assertTrue(((BufferedSeekableSource) source).wrapped() instanceof MemoryMappedSeekableSource); } finally { System.getProperties().remove(SeekableSources.MAPPED_SIZE_THRESHOLD_PROPERTY); } } @Test public void disableMemoryMapped() throws IOException { try { System.setProperty(SeekableSources.MAPPED_SIZE_THRESHOLD_PROPERTY, "10"); System.setProperty(SeekableSources.DISABLE_MEMORY_MAPPED_PROPERTY, "true"); Path tempFile = Files.createTempFile("SejdaIO", null); Files.copy(getClass().getResourceAsStream("/pdf/simple_test.pdf"), tempFile, StandardCopyOption.REPLACE_EXISTING); SeekableSource source = SeekableSources.seekableSourceFrom(tempFile.toFile()); assertNotNull(source); assertTrue(source instanceof BufferedSeekableSource); assertTrue(((BufferedSeekableSource) source).wrapped() instanceof FileChannelSeekableSource); } finally { System.getProperties().remove(SeekableSources.MAPPED_SIZE_THRESHOLD_PROPERTY); System.getProperties().remove(SeekableSources.DISABLE_MEMORY_MAPPED_PROPERTY); } } @Test public void nonMappedMemoryFor32bits() throws IOException { try { System.setProperty(SeekableSources.MAPPED_SIZE_THRESHOLD_PROPERTY, "10"); System.setProperty("sun.arch.data.model", "32"); Path tempFile = Files.createTempFile("SejdaIO", null); Files.copy(getClass().getResourceAsStream("/pdf/simple_test.pdf"), tempFile, StandardCopyOption.REPLACE_EXISTING); SeekableSource source = SeekableSources.seekableSourceFrom(tempFile.toFile()); assertNotNull(source); assertTrue(source instanceof BufferedSeekableSource); assertTrue(((BufferedSeekableSource) source).wrapped() instanceof FileChannelSeekableSource); } finally { System.getProperties().remove(SeekableSources.MAPPED_SIZE_THRESHOLD_PROPERTY); System.setProperty("sun.arch.data.model", BITNESS); } } @Test public void inMemorySeekableSourceFromBytes() { assertNotNull(SeekableSources.inMemorySeekableSourceFrom(new byte[] { -1 })); } @Test public void inMemorySeekableSourceFromStream() throws IOException { assertNotNull( SeekableSources.inMemorySeekableSourceFrom(getClass().getResourceAsStream("/pdf/simple_test.pdf"))); } @Test public void onTempFileSeekableSourceFrom() throws IOException { assertNotNull(SeekableSources.onTempFileSeekableSourceFrom(new ByteArrayInputStream(new byte[] { -1 }))); } } sejda-io-1.1.3.RELEASE/src/test/java/org/sejda/io/ThreadBoundCopiesSupplierTest.java000066400000000000000000000071501305261226700300410ustar00rootroot00000000000000/* * Created on 07 gen 2016 * Copyright 2010 by Andrea Vacondio (andrea.vacondio@gmail.com). * * 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 org.sejda.io; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import java.io.IOException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.function.Supplier; import org.junit.Test; /** * @author Andrea Vacondio * */ public class ThreadBoundCopiesSupplierTest { @Test public void closeCopies() throws IOException { SeekableSource copy = mock(SeekableSource.class); ThreadBoundCopiesSupplier victim = new ThreadBoundCopiesSupplier<>(() -> copy); assertEquals(copy, victim.get()); victim.close(); verify(copy).close(); } @Test public void differentCopyPerThread() throws IOException, InterruptedException, ExecutionException { SeekableSourceSupplier supplier = spy( new SeekableSourceSupplier() { public ByteArraySeekableSource get() { return new ByteArraySeekableSource(new byte[0]); } }); ThreadBoundCopiesSupplier victim = new ThreadBoundCopiesSupplier<>(supplier); ByteArraySeekableSource first = victim.get(); assertNotNull(first); ByteArraySeekableSource second = CompletableFuture.supplyAsync(() -> { try { return victim.get(); } catch (Exception e) { return null; } }).get(); assertNotNull(second); assertNotEquals(first, second); } @Test public void sameThreadSameCopy() throws IOException, InterruptedException, ExecutionException { SeekableSourceSupplier supplier = spy( new SeekableSourceSupplier() { public ByteArraySeekableSource get() { return new ByteArraySeekableSource(new byte[0]); } }); ThreadBoundCopiesSupplier victim = new ThreadBoundCopiesSupplier<>(supplier); assertEquals(victim.get(), victim.get()); Executor executor = Executors.newSingleThreadExecutor(); Supplier completableSupplier = () -> { try { return victim.get(); } catch (Exception e) { return null; } }; ByteArraySeekableSource first = CompletableFuture.supplyAsync(completableSupplier, executor).get(); ByteArraySeekableSource second = CompletableFuture.supplyAsync(completableSupplier, executor).get(); assertEquals(first, second); } } sejda-io-1.1.3.RELEASE/src/test/java/org/sejda/util/000077500000000000000000000000001305261226700216135ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/src/test/java/org/sejda/util/RequireUtilsTest.java000066400000000000000000000046771305261226700257710ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sejda.util; import static org.sejda.util.RequireUtils.requireArg; import static org.sejda.util.RequireUtils.requireIOCondition; import static org.sejda.util.RequireUtils.requireNotBlank; import static org.sejda.util.RequireUtils.requireNotNullArg; import static org.sejda.util.RequireUtils.requireState; import java.io.IOException; import org.junit.Test; /** * @author Andrea Vacondio * */ public class RequireUtilsTest { @Test(expected = IllegalArgumentException.class) public void nullArg() { requireNotNullArg(null, "message"); } @Test(expected = IllegalArgumentException.class) public void falseConditionArg() { requireArg(false, "message"); } @Test(expected = IllegalArgumentException.class) public void nullArgNotBlank() { requireNotBlank(null, "message"); } @Test(expected = IllegalArgumentException.class) public void emptyArgNotBlank() { requireNotBlank("", "message"); } @Test(expected = IllegalArgumentException.class) public void blankArgNotBlank() { requireNotBlank(" ", "message"); } @Test(expected = IOException.class) public void faseConditionIO() throws IOException { requireIOCondition(false, "message"); } @Test(expected = IllegalStateException.class) public void falseState() { requireState(false, "message"); } @Test public void positiveArg() throws IOException { requireArg(true, "message"); requireNotNullArg(new Object(), "message"); requireNotBlank("ChuckNorris", "message"); requireIOCondition(true, "message"); requireState(true, "message"); } } sejda-io-1.1.3.RELEASE/src/test/resources/000077500000000000000000000000001305261226700200525ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/src/test/resources/pdf/000077500000000000000000000000001305261226700206235ustar00rootroot00000000000000sejda-io-1.1.3.RELEASE/src/test/resources/pdf/simple_test.pdf000066400000000000000000000014621305261226700236510ustar00rootroot00000000000000%PDF-1.4 %öäüß 1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj 2 0 obj << /Type /Pages /Kids [3 0 R] /Count 1 >> endobj 3 0 obj << /Type /Page /Parent 2 0 R /Resources 4 0 R /MediaBox [0 0 500 800] /Contents 5 0 R /Annots [6 0 R] >> endobj 4 0 obj << /Font << /F1 7 0 R >> >> endobj 5 0 obj << /Length 44 >> stream BT /F1 24 Tf 175 720 Td (Hello World!)Tj ET endstream endobj 6 0 obj << /Type /Annot /Subtype /Text /Rect [175 720 175 720] /Contents (Hello Annotation!) /Open true >> endobj 7 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica >> endobj 8 0 obj << /Root 1 0 R /ID [ ] /Type /XRef /Size 9 /Filter /FlateDecode /Index [1 7] /W [1 2 0] /Length 29 >> stream xœcdàgdp`d¨ddøÈÈ(ÃÈXÃÈøÆJ endstream endobj startxref 564 %%EOF