├── .gitignore ├── src ├── test │ ├── resources │ │ └── checkme.txt │ └── java │ │ └── nl │ │ └── kb │ │ └── magicfiletest │ │ └── MagicFileTest.java ├── main │ └── java │ │ └── nl.kb.magicfile │ │ ├── Check.java │ │ └── MagicFile.java └── csource │ ├── nl_kb_magicfile_MagicFile.h │ └── nl_kb_magicfile_MagicFile.cc ├── Makefile ├── pom.xml └── README.rst /.gitignore: -------------------------------------------------------------------------------- 1 | *.so 2 | *.iml 3 | target 4 | .idea -------------------------------------------------------------------------------- /src/test/resources/checkme.txt: -------------------------------------------------------------------------------- 1 | hello world 2 | im us-ascii, not bytes -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: package 2 | 3 | clean: 4 | rm -f src/main/resources/libmagicjbind.so 5 | mvn clean 6 | 7 | compile: 8 | mkdir -p src/main/resources 9 | g++ -shared -o src/main/resources/libmagicjbind.so -I$(JAVA_HOME)/include/ -I$(JAVA_HOME)/include/linux/ -lmagic src/csource/nl_kb_magicfile_MagicFile.cc 10 | 11 | test: compile 12 | mvn test; 13 | 14 | package: compile 15 | mvn package 16 | 17 | standalone: package 18 | mvn assembly:single 19 | 20 | testrun: package 21 | mvn exec:java -Dexec.mainClass="nl.kb.magicfile.MagicFile" -Dexec.args="libmagicjbind.so" 22 | 23 | install: package 24 | mvn install 25 | 26 | -------------------------------------------------------------------------------- /src/main/java/nl.kb.magicfile/Check.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | package nl.kb.magicfile; 15 | 16 | public enum Check { 17 | TEXT, MIMETYPE, ENCODING; 18 | } 19 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | nl.kb 8 | magicfile 9 | 0.1.0 10 | jar 11 | 12 | 13 | 14 | 15 | commons-io 16 | commons-io 17 | 2.3 18 | 19 | 20 | junit 21 | junit 22 | 4.8.2 23 | test 24 | 25 | 26 | 27 | 28 | 29 | 30 | maven-assembly-plugin 31 | 32 | 33 | 34 | nl.kb.magicfile.MagicFile 35 | 36 | 37 | 38 | jar-with-dependencies 39 | 40 | 41 | 42 | 43 | org.apache.maven.plugins 44 | maven-compiler-plugin 45 | 2.5.1 46 | 47 | true 48 | true 49 | 1.6 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/csource/nl_kb_magicfile_MagicFile.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | /* DO NOT EDIT THIS FILE - it is machine generated */ 16 | #include 17 | /* Header for class nl_kb_magicfile_MagicFile */ 18 | 19 | #ifndef _Included_nl_kb_magicfile_MagicFile 20 | #define _Included_nl_kb_magicfile_MagicFile 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | /* 25 | * Class: nl_kb_magicfile_MagicFile 26 | * Method: checkText 27 | * Signature: (Ljava/lang/String;)Ljava/lang/String; 28 | */ 29 | JNIEXPORT jstring JNICALL Java_nl_kb_magicfile_MagicFile_checkText 30 | (JNIEnv *, jclass, jstring); 31 | 32 | /* 33 | * Class: nl_kb_magicfile_MagicFile 34 | * Method: checkMime 35 | * Signature: (Ljava/lang/String;)Ljava/lang/String; 36 | */ 37 | JNIEXPORT jstring JNICALL Java_nl_kb_magicfile_MagicFile_checkMime 38 | (JNIEnv *, jclass, jstring); 39 | 40 | /* 41 | * Class: nl_kb_magicfile_MagicFile 42 | * Method: checkEncoding 43 | * Signature: (Ljava/lang/String;)Ljava/lang/String; 44 | */ 45 | JNIEXPORT jstring JNICALL Java_nl_kb_magicfile_MagicFile_checkEncoding 46 | (JNIEnv *, jclass, jstring); 47 | 48 | /* 49 | * Class: nl_kb_magicfile_MagicFile 50 | * Method: checkTextStream 51 | * Signature: ([B)Ljava/lang/String; 52 | */ 53 | JNIEXPORT jstring JNICALL Java_nl_kb_magicfile_MagicFile_checkTextStream 54 | (JNIEnv *, jclass, jbyteArray); 55 | 56 | /* 57 | * Class: nl_kb_magicfile_MagicFile 58 | * Method: checkMimeStream 59 | * Signature: ([B)Ljava/lang/String; 60 | */ 61 | JNIEXPORT jstring JNICALL Java_nl_kb_magicfile_MagicFile_checkMimeStream 62 | (JNIEnv *, jclass, jbyteArray); 63 | 64 | /* 65 | * Class: nl_kb_magicfile_MagicFile 66 | * Method: checkEncodingStream 67 | * Signature: ([B)Ljava/lang/String; 68 | */ 69 | JNIEXPORT jstring JNICALL Java_nl_kb_magicfile_MagicFile_checkEncodingStream 70 | (JNIEnv *, jclass, jbyteArray); 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | #endif 76 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Experimental Java binding for `libmagic `_ `file `_ characterisation 2 | ====================== 3 | 4 | This is an experimental package. Sources for the binding were tested by compiling them on Ubuntu 10.04 LTS against headers from the libmagic-dev package version 5.03. 5 | 6 | Compiled bindings proved to run without error on both `libmagic `_ v5.03 and v5.11, using: 7 | 8 | - sun jdk 1.6.0.26 9 | 10 | - openjdk 1.6.0_20 11 | 12 | - jdk1.7.0 -b147 13 | 14 | Compiling and Packaging 15 | ------- 16 | A Makefile is included which also makes use of maven lifecycle goals to test the binding. The quickest way to compile and install the sources is by running the commands below. 17 | 18 | - Install the libmagic-dev package (these sources were tested against the 5.03 version):: 19 | 20 | $ sudo apt-get install libmagic-dev 21 | 22 | - Make sure your java home is set to the correct VM, if not, something like:: 23 | 24 | $ export JAVA_HOME=/usr/lib/jvm/java-6-sun-1.6.0.26/ 25 | $ export JAVA_HOME=/usr/lib/jvm/java-1.6.0-openjdk/ 26 | $ export JAVA_HOME=/usr/lib/jvm/jdk1.7.0/ 27 | 28 | - Run make (this will execute the 'package' goal of maven as well):: 29 | 30 | $ make 31 | 32 | - If at this stage no errors have occured, the binding was succesfully compiled and the junit tests will have succeeded as well, so now you can call:: 33 | 34 | $ make install 35 | 36 | - Or: 37 | 38 | $ mvn install 39 | 40 | 41 | Completing the above steps succesfully means you can now include the jar in any java project running on the system, provided that the file libmagicjbind.so can be found in one of the paths specified in the jvm's java.library.path system property (keeping it in /usr/lib/ will probably ensure this):: 42 | 43 | 44 | nl.kb 45 | magicfile 46 | 0.1.0 47 | 48 | 49 | 50 | You could also package a 'standalone' jar (which has the commons-io jar included) by running:: 51 | 52 | $ make standalone 53 | $ java -jar target/magicfile-0.1.0-jar-with-dependencies.jar /path/to/file 54 | 55 | 56 | 57 | Available make targets 58 | ------------ 59 | 60 | - 'all': defaults to the 'package' target 61 | 62 | - 'clean': removes the .so file and calls 'mvn clean' 63 | 64 | - 'compile': compiles the sources against libmagic. Note that compilation expects the 'include' and 'include/linux' directories to exist in your jvm's root. 65 | 66 | - 'test': runs 'compile' and mvn test 67 | 68 | - 'package': runs 'compile' and mvn package 69 | 70 | - 'standalone': builds a jar with the commons-io dependency included 71 | 72 | - 'testrun': runs 'package' and then tries to run the packaged jar 73 | 74 | - 'install': run mvn install 75 | 76 | 77 | Prerequisites 78 | ------- 79 | The complete list of preconditions: 80 | 81 | - Up to date gnu compiler 82 | 83 | - Ubuntu 10.04 LTS 84 | 85 | - libmagic-dev >= 5.03 86 | 87 | - libmagic >= 5.03 88 | 89 | - jdk, tested versions: 90 | 91 | - Java 6 Sun jdk version 1.6.0.26 92 | 93 | - Java 6 OpenJDK 1.6.0_20 94 | 95 | - Java 7 jdk1.7.0-b147 96 | 97 | - make 98 | 99 | - Maven >= 2.x 100 | 101 | -------------------------------------------------------------------------------- /src/csource/nl_kb_magicfile_MagicFile.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | #include "nl_kb_magicfile_MagicFile.h" 16 | #include 17 | #include 18 | #include 19 | 20 | #define MAX_DETECT_SIZE 4096 21 | 22 | 23 | using namespace std; 24 | 25 | 26 | magic_t initMagic(int flags) { 27 | magic_t checker = magic_open(flags); 28 | magic_load(checker, NULL); 29 | return checker; 30 | } 31 | 32 | char* checkFile(int flags, const char *path) { 33 | magic_t checker = initMagic(flags); 34 | static char ret[1024]; 35 | strcpy(ret, magic_file(checker, path)); 36 | magic_close(checker); 37 | return ret; 38 | } 39 | 40 | char* checkStream(int flags, void *bytes, size_t len) { 41 | magic_t checker = initMagic(flags); 42 | static char ret[1024]; 43 | strcpy(ret, magic_buffer(checker, bytes, len)); 44 | magic_close(checker); 45 | free(bytes); 46 | return ret; 47 | } 48 | 49 | size_t castBytes(JNIEnv *env, jbyteArray bytes, void* &pointer) { 50 | if(bytes == NULL) 51 | return -1; 52 | jint len = env->GetArrayLength(bytes); 53 | if(len < MAX_DETECT_SIZE) { 54 | pointer = (void*)malloc(len+1); 55 | env->GetByteArrayRegion(bytes, 0, len, (jbyte*)pointer); 56 | } else { 57 | len = MAX_DETECT_SIZE; 58 | pointer = (void*)malloc(MAX_DETECT_SIZE); 59 | env->GetByteArrayRegion(bytes, 0, len, (jbyte*)pointer); 60 | } 61 | return (size_t)len; 62 | } 63 | 64 | /* 65 | * Class: MagicFile 66 | * Method: checkText 67 | * Signature: (Ljava/lang/String;)Ljava/lang/String; 68 | */ 69 | JNIEXPORT jstring JNICALL Java_nl_kb_magicfile_MagicFile_checkText(JNIEnv *env, jclass cl, jstring path) { 70 | return env->NewStringUTF(checkFile(MAGIC_NONE, env->GetStringUTFChars(path, 0))); 71 | } 72 | 73 | /* 74 | * Class: MagicFile 75 | * Method: checkMime 76 | * Signature: (Ljava/lang/String;)Ljava/lang/String; 77 | */ 78 | JNIEXPORT jstring JNICALL Java_nl_kb_magicfile_MagicFile_checkMime(JNIEnv *env, jclass cl, jstring path) { 79 | return env->NewStringUTF(checkFile(MAGIC_MIME_TYPE, env->GetStringUTFChars(path, 0))); 80 | } 81 | 82 | /* 83 | * Class: MagicFile 84 | * Method: checkEncoding 85 | * Signature: (Ljava/lang/String;)Ljava/lang/String; 86 | */ 87 | JNIEXPORT jstring JNICALL Java_nl_kb_magicfile_MagicFile_checkEncoding(JNIEnv *env, jclass cl, jstring path) { 88 | return env->NewStringUTF(checkFile(MAGIC_MIME_ENCODING, env->GetStringUTFChars(path, 0))); 89 | } 90 | 91 | /* 92 | * Class: MagicFile 93 | * Method: checkTextStream 94 | * Signature: ([B)Ljava/lang/String; 95 | */ 96 | JNIEXPORT jstring JNICALL Java_nl_kb_magicfile_MagicFile_checkTextStream(JNIEnv *env, jclass cl, jbyteArray bytes) { 97 | void* pointer = NULL; 98 | size_t len = castBytes(env, bytes, pointer); 99 | if(len < 1) { 100 | env->ThrowNew(env->FindClass("java/io/IOException"), "Byte stream is empty"); 101 | } else 102 | return env->NewStringUTF(checkStream(MAGIC_NONE, pointer, len)); 103 | } 104 | 105 | /* 106 | * Class: MagicFile 107 | * Method: checkMimeStream 108 | * Signature: ([B)Ljava/lang/String; 109 | */ 110 | JNIEXPORT jstring JNICALL Java_nl_kb_magicfile_MagicFile_checkMimeStream(JNIEnv *env, jclass cl, jbyteArray bytes) { 111 | void* pointer = NULL; 112 | size_t len = castBytes(env, bytes, pointer); 113 | if(len < 1) { 114 | env->ThrowNew(env->FindClass("java/io/IOException"), "Byte stream is empty"); 115 | } else 116 | return env->NewStringUTF(checkStream(MAGIC_MIME_TYPE, pointer, len)); 117 | } 118 | 119 | /* 120 | * Class: MagicFile 121 | * Method: checkEncodingStream 122 | * Signature: ([B)Ljava/lang/String; 123 | */ 124 | JNIEXPORT jstring JNICALL Java_nl_kb_magicfile_MagicFile_checkEncodingStream(JNIEnv *env, jclass cl, jbyteArray bytes) { 125 | void* pointer = NULL; 126 | size_t len = castBytes(env, bytes, pointer); 127 | if(len < 1) { 128 | env->ThrowNew(env->FindClass("java/io/IOException"), "Byte stream is empty"); 129 | } else 130 | return env->NewStringUTF(checkStream(MAGIC_MIME_ENCODING, pointer, len)); 131 | } 132 | 133 | 134 | int main() { } 135 | -------------------------------------------------------------------------------- /src/test/java/nl/kb/magicfiletest/MagicFileTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | package nl.kb.magicfiletest; 15 | 16 | import nl.kb.magicfile.Check; 17 | import nl.kb.magicfile.MagicFile; 18 | import junit.framework.TestCase; 19 | import java.io.IOException; 20 | import java.io.File; 21 | import java.io.FileNotFoundException; 22 | import java.io.FileInputStream; 23 | import java.io.InputStream; 24 | import java.util.Arrays; 25 | import java.util.Map; 26 | 27 | public class MagicFileTest extends TestCase { 28 | private static String testFilePath; 29 | private static final String BOGUS_FILE_PATH = "thisFileProbablyDoesNot.exist"; 30 | 31 | public void setUp() { 32 | testFilePath = this.getClass().getResource("/checkme.txt").getPath(); 33 | } 34 | 35 | public void testFileText() throws Exception { 36 | System.out.print("Asserting that file " + testFilePath + " is characterised as ASCII text "); 37 | String result = MagicFile.checkText(new File(testFilePath)); 38 | assertTrue(result.contains("ASCII text")); 39 | System.out.println("-- result: '" + result + "'-- OK"); 40 | } 41 | 42 | public void testFileNotFoundException() throws Exception { 43 | System.out.print("Asserting that file " + BOGUS_FILE_PATH + " throws a FileNotFoundException "); 44 | boolean thrown = false; 45 | try { 46 | MagicFile.checkText(new File(BOGUS_FILE_PATH)); 47 | } catch(FileNotFoundException e) { 48 | thrown = true; 49 | } 50 | assertTrue(thrown); 51 | System.out.println("-- OK"); 52 | } 53 | 54 | public void testFileMime() throws Exception { 55 | System.out.print("Asserting that file " + testFilePath + " is characterised with MIME type text/plain "); 56 | String result = MagicFile.checkMime(new File(testFilePath)); 57 | assertTrue(result.contains("text/plain")); 58 | System.out.println(" result: '" + result + "' -- OK"); 59 | } 60 | 61 | public void testFileEncoding() throws Exception { 62 | System.out.print("Asserting that file " + testFilePath + " is characterised with correct encoding "); 63 | String result = MagicFile.checkEncoding(new File(testFilePath)); 64 | assertTrue(result.contains("ascii")); 65 | System.out.println("-- result: '" + result + "' -- OK"); 66 | } 67 | 68 | public void testFileNameInInstance() throws Exception { 69 | MagicFile m = new MagicFile(testFilePath); 70 | System.out.println("Asserting that an instance will work with an existing filename"); 71 | System.out.println("Result A: " + m.checkText()); 72 | System.out.println("Result B: " + m.checkMime()); 73 | System.out.println("Result C: " + m.checkEncoding()); 74 | System.out.println("OK"); 75 | } 76 | 77 | public void testFileInInstance() throws Exception { 78 | MagicFile m = new MagicFile(new File(testFilePath)); 79 | System.out.println("Asserting that an instance will work with existing file"); 80 | System.out.println("Result A: " + m.checkText()); 81 | System.out.println("Result B: " + m.checkMime()); 82 | System.out.println("Result C: " + m.checkEncoding()); 83 | System.out.println("OK"); 84 | } 85 | 86 | 87 | public void testBytesInInstance() throws Exception { 88 | MagicFile m = new MagicFile(new FileInputStream(testFilePath)); 89 | System.out.println("Asserting stream gets loaded correctly in buffer for multiple checks "); 90 | System.out.println("Result A: " + m.checkText()); 91 | System.out.println("Result B: " + m.checkMime()); 92 | System.out.println("Result C: " + m.checkEncoding()); 93 | System.out.println("OK"); 94 | } 95 | 96 | public void testBytes() throws Exception { 97 | System.out.println("Asserting that a stream can be characterised directly once"); 98 | InputStream is = new FileInputStream(testFilePath); 99 | System.out.println("Result: " + MagicFile.checkText(is)); 100 | System.out.println("OK"); 101 | System.out.println("Asserting that an IOException gets thrown when trying to access the same stream twice"); 102 | int thrown = 0; 103 | try { 104 | System.out.println("Should fail: " + MagicFile.checkEncoding(is)); 105 | } catch(IOException e) { 106 | thrown++; 107 | } 108 | try { 109 | System.out.println("Should fail: " + MagicFile.checkMime(is)); 110 | } catch(IOException e) { 111 | thrown++; 112 | } 113 | assertEquals(thrown, 2); 114 | System.out.println("OK"); 115 | } 116 | 117 | public void testComprehensive() throws Exception { 118 | System.out.print("Asserting that we can characterize all at once by file"); 119 | Map results = MagicFile.characterize(Arrays.asList(new Check[]{Check.ENCODING, Check.MIMETYPE, Check.TEXT}), new File(testFilePath)); 120 | assertTrue(results.get(Check.ENCODING).contains("ascii")); 121 | assertTrue(results.get(Check.MIMETYPE).contains("text/plain")); 122 | assertTrue(results.get(Check.TEXT).contains("ASCII text")); 123 | System.out.println(" -- OK"); 124 | } 125 | 126 | public void testComprehensiveStream() throws Exception { 127 | System.out.print("Asserting that we can characterize all at once by stream"); 128 | Map results = MagicFile.characterize(Arrays.asList(new Check[]{Check.ENCODING, Check.MIMETYPE, Check.TEXT}), new FileInputStream(testFilePath)); 129 | assertTrue(results.get(Check.MIMETYPE).contains("text/plain")); 130 | assertTrue(results.get(Check.TEXT).contains("ASCII text")); 131 | System.out.println(" -- OK"); 132 | } 133 | 134 | public void testComprehensiveInstance() throws Exception { 135 | System.out.print("Asserting that we can characterize all at once by stream in an instance"); 136 | MagicFile m = new MagicFile(new FileInputStream(testFilePath)); 137 | Map results = m.characterize(Arrays.asList(new Check[]{Check.ENCODING, Check.MIMETYPE, Check.TEXT})); 138 | assertTrue(results.get(Check.MIMETYPE).contains("text/plain")); 139 | assertTrue(results.get(Check.TEXT).contains("ASCII text")); 140 | System.out.println(" -- OK"); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/nl.kb.magicfile/MagicFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | package nl.kb.magicfile; 15 | 16 | import org.apache.commons.io.IOUtils; 17 | 18 | import java.io.IOException; 19 | import java.io.FileNotFoundException; 20 | import java.io.File; 21 | import java.io.InputStream; 22 | import java.io.FileOutputStream; 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | 27 | public final class MagicFile { 28 | private static final String LIBRARY_NAME = "libmagicjbind.so"; 29 | private static final int MAX_CHECK_SIZE = 4096; 30 | 31 | private byte[] currentBytes = new byte[MAX_CHECK_SIZE]; 32 | private boolean byteBufferFilled = false; 33 | private File currentFile = null; 34 | 35 | static { 36 | InputStream is = MagicFile.class.getResourceAsStream("/" + LIBRARY_NAME); 37 | try { 38 | File temp = File.createTempFile(LIBRARY_NAME, ""); 39 | FileOutputStream fos = new FileOutputStream(temp); 40 | fos.write(IOUtils.toByteArray(is)); 41 | fos.close(); 42 | is.close(); 43 | System.load(temp.getAbsolutePath()); 44 | } catch(IOException e) { 45 | throw new RuntimeException(e); 46 | } 47 | } 48 | 49 | 50 | private synchronized static native String checkText(String path); 51 | private synchronized static native String checkMime(String path); 52 | private synchronized static native String checkEncoding(String path); 53 | private synchronized static native String checkTextStream(byte[] buffer) throws IOException; 54 | private synchronized static native String checkMimeStream(byte[] buffer) throws IOException; 55 | private synchronized static native String checkEncodingStream(byte[] buffer) throws IOException; 56 | 57 | private static byte[] readBytes(InputStream is) throws IOException { 58 | byte[] bytes = new byte[MAX_CHECK_SIZE]; 59 | IOUtils.read(is, bytes); 60 | is.close(); 61 | return bytes; 62 | } 63 | 64 | private static String characterize(Check check, byte[] bytes) throws IOException { 65 | switch(check) { 66 | case TEXT: return checkTextStream(bytes); 67 | case MIMETYPE: return checkMimeStream(bytes); 68 | default: return checkEncodingStream(bytes); 69 | } 70 | } 71 | 72 | public static String characterize(Check check, File file) throws FileNotFoundException { 73 | if(file == null) { 74 | throw new NullPointerException("No file specified"); 75 | } else if(!file.exists() || !file.canRead()) { 76 | throw new FileNotFoundException("File cannot be read: " + file.getAbsolutePath()); 77 | } 78 | switch(check) { 79 | case ENCODING: 80 | return checkEncoding(file.getAbsolutePath()); 81 | case MIMETYPE: 82 | return checkMime(file.getAbsolutePath()); 83 | default: 84 | return checkText(file.getAbsolutePath()); 85 | } 86 | } 87 | 88 | public static Map characterize(Iterable checks, File file) throws FileNotFoundException { 89 | Map results = new HashMap(); 90 | for(Check check : checks) { results.put(check, characterize(check,file)); } 91 | return results; 92 | } 93 | 94 | public static Map characterize(Iterable checks, InputStream is) throws IOException { 95 | Map results = new HashMap(); 96 | byte[] bytes = readBytes(is); 97 | for(Check check : checks) { results.put(check, characterize(check, bytes)); } 98 | return results; 99 | } 100 | 101 | public static String checkText(File file) throws FileNotFoundException { return characterize(Check.TEXT, file); } 102 | public static String checkMime(File file) throws FileNotFoundException { return characterize(Check.MIMETYPE, file); } 103 | public static String checkEncoding(File file) throws FileNotFoundException { return characterize(Check.ENCODING, file); } 104 | 105 | 106 | public static String characterize(Check check, InputStream is) throws IOException { 107 | if(is == null || is.available() <= 0) { 108 | throw new IOException("At end of stream or stream is closed"); 109 | } 110 | return characterize(check, readBytes(is)); 111 | } 112 | 113 | public static String checkText(InputStream is) throws IOException { return characterize(Check.TEXT, is); } 114 | public static String checkMime(InputStream is) throws IOException { return characterize(Check.MIMETYPE, is); } 115 | public static String checkEncoding(InputStream is) throws IOException { return characterize(Check.ENCODING, is); } 116 | 117 | private void setInput(File f) throws FileNotFoundException { 118 | if(f.exists() && f.canRead()) { 119 | currentFile = f; 120 | } else { 121 | throw new FileNotFoundException("Unable to read file: " + f.getAbsolutePath()); 122 | } 123 | } 124 | 125 | private void setInput(InputStream is) throws IOException { 126 | currentBytes = readBytes(is); 127 | byteBufferFilled = true; 128 | currentFile = null; 129 | } 130 | 131 | public MagicFile(InputStream is) throws IOException { setInput(is); } 132 | public MagicFile(File f) throws FileNotFoundException { setInput(f); } 133 | public MagicFile(String filename) throws FileNotFoundException { setInput(new File(filename)); } 134 | 135 | public String characterize(Check check) throws IOException { 136 | if(currentFile != null) { return characterize(check, currentFile); } 137 | else if(byteBufferFilled) { return characterize(check, currentBytes); } 138 | else { throw new IOException("No input-stream or file set"); } 139 | } 140 | 141 | public Map characterize(Iterable checks) throws IOException { 142 | Map results = new HashMap(); 143 | for(Check check : checks) { results.put(check, characterize(check)); } 144 | return results; 145 | } 146 | 147 | public String checkText() throws IOException { return characterize(Check.TEXT); } 148 | public String checkMime() throws IOException { return characterize(Check.MIMETYPE); } 149 | public String checkEncoding() throws IOException { return characterize(Check.ENCODING); } 150 | 151 | public static void main(String args[]) { 152 | System.out.println("MagicFile binding for libmagic..."); 153 | if(args.length > 0 && new File(args[0]).exists() && new File(args[0]).canRead()) { 154 | try { 155 | System.out.println("Characteristics for: " + args[0]); 156 | System.out.println("Textual representation: " + checkText(new File(args[0]))); 157 | System.out.println("Magic mime type: " + checkMime(new File(args[0]))); 158 | System.out.println("Encoding: " + checkEncoding(new File(args[0]))); 159 | } catch(FileNotFoundException e) { 160 | e.printStackTrace(); 161 | } catch(IOException e) { 162 | e.printStackTrace(); 163 | } 164 | } else { 165 | System.out.println("First argument should be the path to an existing filename."); 166 | } 167 | } 168 | } 169 | --------------------------------------------------------------------------------