├── .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 |
--------------------------------------------------------------------------------