3131import org .slf4j .Logger ;
3232import org .slf4j .LoggerFactory ;
3333
34+ import org .apache .tika .config .ConfigDeserializer ;
3435import org .apache .tika .config .Field ;
36+ import org .apache .tika .config .JsonConfig ;
37+ import org .apache .tika .config .TikaComponent ;
3538import org .apache .tika .detect .Detector ;
3639import org .apache .tika .io .BoundedInputStream ;
3740import org .apache .tika .io .TemporaryResources ;
5053 * The default behavior is to run detection, report the results in the
5154 * metadata and then return null so that other detectors will be used.
5255 */
56+ @ TikaComponent
5357public class MagikaDetector implements Detector {
5458
5559 enum STATUS {
@@ -90,11 +94,35 @@ enum STATUS {
9094 private static ObjectMapper OBJECT_MAPPER = new ObjectMapper ();
9195 private static boolean HAS_WARNED = false ;
9296 private Boolean hasMagika = null ;
93- private String magikaPath = DEFAULT_MAGIKA_PATH ;
94- private int maxBytes = 1_000_000 ;
95- private long timeoutMs = DEFAULT_TIMEOUT_MS ;
9697
97- private boolean useMime = false ;
98+ /**
99+ * Configuration class for JSON deserialization.
100+ */
101+ public static class Config {
102+ public String magikaPath = DEFAULT_MAGIKA_PATH ;
103+ public int maxBytes = 1_000_000 ;
104+ public long timeoutMs = DEFAULT_TIMEOUT_MS ;
105+ public boolean useMime = false ;
106+ }
107+
108+ private final Config config ;
109+
110+ /**
111+ * Default constructor.
112+ */
113+ public MagikaDetector () {
114+ this .config = new Config ();
115+ }
116+
117+ /**
118+ * Constructor for JSON configuration.
119+ * Requires tika-serialization on the classpath.
120+ *
121+ * @param jsonConfig JSON configuration
122+ */
123+ public MagikaDetector (JsonConfig jsonConfig ) {
124+ this .config = ConfigDeserializer .buildConfig (jsonConfig , Config .class );
125+ }
98126
99127 public static boolean checkHasMagika (String magikaCommandPath ) {
100128 String [] commandline = new String []{magikaCommandPath , "--version" };
@@ -136,11 +164,11 @@ public static boolean checkHasMagika(String magikaCommandPath) {
136164 @ Override
137165 public MediaType detect (InputStream input , Metadata metadata ) throws IOException {
138166 if (hasMagika == null ) {
139- hasMagika = checkHasMagika (this .magikaPath );
167+ hasMagika = checkHasMagika (this .config . magikaPath );
140168 }
141169 if (!hasMagika ) {
142170 if (!HAS_WARNED ) {
143- LOGGER .warn ("'magika' command isn't working: '" + magikaPath + "'" );
171+ LOGGER .warn ("'magika' command isn't working: '" + config . magikaPath + "'" );
144172 HAS_WARNED = true ;
145173 }
146174 return MediaType .OCTET_STREAM ;
@@ -152,10 +180,10 @@ public MediaType detect(InputStream input, Metadata metadata) throws IOException
152180 return detectOnPath (tis .getPath (), metadata );
153181 }
154182
155- input .mark (maxBytes );
183+ input .mark (config . maxBytes );
156184 try (TemporaryResources tmp = new TemporaryResources ()) {
157185 Path tmpFile = tmp .createTempFile ();
158- Files .copy (new BoundedInputStream (maxBytes , input ), tmpFile , REPLACE_EXISTING );
186+ Files .copy (new BoundedInputStream (config . maxBytes , input ), tmpFile , REPLACE_EXISTING );
159187 return detectOnPath (tmpFile , metadata );
160188 } finally {
161189 input .reset ();
@@ -174,23 +202,23 @@ public MediaType detect(InputStream input, Metadata metadata) throws IOException
174202 */
175203 @ Field
176204 public void setUseMime (boolean useMime ) {
177- this .useMime = useMime ;
205+ this .config . useMime = useMime ;
178206 }
179207
180208 public boolean isUseMime () {
181- return useMime ;
209+ return config . useMime ;
182210 }
183211
184212 private MediaType detectOnPath (Path path , Metadata metadata ) throws IOException {
185213
186214 String [] args = new String []{
187- ProcessUtils .escapeCommandLine (magikaPath ),
215+ ProcessUtils .escapeCommandLine (config . magikaPath ),
188216 ProcessUtils .escapeCommandLine (path .toAbsolutePath ().toString ()),
189217 "--json"
190218 };
191219 ProcessBuilder builder = new ProcessBuilder (args );
192- FileProcessResult result = ProcessUtils .execute (builder , timeoutMs , 10000000 , 1000 );
193- return processResult (result , metadata , useMime );
220+ FileProcessResult result = ProcessUtils .execute (builder , config . timeoutMs , 10000000 , 1000 );
221+ return processResult (result , metadata , config . useMime );
194222 }
195223
196224 protected static MediaType processResult (FileProcessResult result , Metadata metadata ,
@@ -331,8 +359,8 @@ private static void addString(JsonNode node, String jsonKey, Property property,
331359 public void setMagikaPath (String fileCommandPath ) {
332360 //this opens up a potential command vulnerability.
333361 //Don't ever let an untrusted user set this.
334- this .magikaPath = fileCommandPath ;
335- checkHasMagika (this .magikaPath );
362+ this .config . magikaPath = fileCommandPath ;
363+ checkHasMagika (this .config . magikaPath );
336364 }
337365
338366 /**
@@ -344,11 +372,11 @@ public void setMagikaPath(String fileCommandPath) {
344372 */
345373 @ Field
346374 public void setMaxBytes (int maxBytes ) {
347- this .maxBytes = maxBytes ;
375+ this .config . maxBytes = maxBytes ;
348376 }
349377
350378 @ Field
351379 public void setTimeoutMs (long timeoutMs ) {
352- this .timeoutMs = timeoutMs ;
380+ this .config . timeoutMs = timeoutMs ;
353381 }
354382}
0 commit comments