001 package org.maltparser.core.config;
002
003 import java.io.BufferedInputStream;
004 import java.io.BufferedOutputStream;
005 import java.io.BufferedReader;
006 import java.io.BufferedWriter;
007 import java.io.File;
008 import java.io.FileInputStream;
009 import java.io.FileNotFoundException;
010 import java.io.FileOutputStream;
011 import java.io.FileReader;
012 import java.io.FileWriter;
013 import java.io.IOException;
014 import java.io.InputStream;
015 import java.io.InputStreamReader;
016 import java.io.OutputStreamWriter;
017 import java.io.UnsupportedEncodingException;
018 import java.net.MalformedURLException;
019 import java.net.URL;
020 import java.nio.ByteBuffer;
021 import java.nio.CharBuffer;
022 import java.util.Date;
023 import java.util.Enumeration;
024 import java.util.HashMap;
025 import java.util.HashSet;
026 import java.util.SortedSet;
027 import java.util.TreeSet;
028 import java.util.jar.JarEntry;
029 import java.util.jar.JarFile;
030 import java.util.jar.JarInputStream;
031 import java.util.jar.JarOutputStream;
032
033 import org.maltparser.core.config.version.Versioning;
034 import org.maltparser.core.exception.MaltChainedException;
035 import org.maltparser.core.helper.SystemInfo;
036 import org.maltparser.core.helper.SystemLogger;
037 import org.maltparser.core.helper.Util;
038 import org.maltparser.core.io.dataformat.DataFormatInstance;
039 import org.maltparser.core.io.dataformat.DataFormatManager;
040 import org.maltparser.core.options.OptionManager;
041 import org.maltparser.core.symbol.SymbolTableHandler;
042 import org.maltparser.core.symbol.trie.TrieSymbolTableHandler;
043
044
045 /**
046 * This class contains methods for handle the configuration directory.
047 *
048 * @author Johan Hall
049 */
050 public class ConfigurationDir {
051 protected static final int BUFFER = 4096;
052 protected File configDirectory;
053 protected String name;
054 protected String type;
055 protected File workingDirectory;
056 protected URL url = null;
057 protected int containerIndex;
058 protected BufferedWriter infoFile = null;
059 protected String createdByMaltParserVersion;
060
061 private SymbolTableHandler symbolTables;
062 private DataFormatManager dataFormatManager;
063 private HashMap<String,DataFormatInstance> dataFormatInstances;
064
065
066 /**
067 * Creates a configuration directory from a mco-file specified by an URL.
068 *
069 * @param url an URL to a mco-file
070 * @throws MaltChainedException
071 */
072 public ConfigurationDir(URL url) throws MaltChainedException {
073 initWorkingDirectory();
074 setUrl(url);
075 initNameNTypeFromInfoFile(url);
076 // initData();
077 }
078
079 /**
080 * Creates a new configuration directory or a configuration directory from a mco-file
081 *
082 * @param name the name of the configuration
083 * @param type the type of configuration
084 * @param containerIndex the container index
085 * @throws MaltChainedException
086 */
087 public ConfigurationDir(String name, String type, int containerIndex) throws MaltChainedException {
088 setContainerIndex(containerIndex);
089
090 initWorkingDirectory();
091 if (name != null && name.length() > 0 && type != null && type.length() > 0) {
092 setName(name);
093 setType(type);
094 } else {
095 throw new ConfigurationException("The configuration name is not specified. ");
096 }
097 setConfigDirectory(new File(workingDirectory.getPath()+File.separator+getName()));
098 }
099
100 public void initDataFormat() throws MaltChainedException {
101 String inputFormatName = OptionManager.instance().getOptionValue(containerIndex, "input", "format").toString().trim();
102 String outputFormatName = OptionManager.instance().getOptionValue(containerIndex, "output", "format").toString().trim();
103 // SystemLogger.logger().info(inputFormatName + "\n");
104 // SystemLogger.logger().info(outputFormatName + "\n");
105 if (configDirectory != null && configDirectory.exists()) {
106 if (outputFormatName.length() == 0 || inputFormatName.equals(outputFormatName)) {
107 URL inputFormatURL = Util.findURLinJars(inputFormatName);
108 if (inputFormatURL != null) {
109 outputFormatName = inputFormatName = this.copyToConfig(inputFormatURL);
110 } else {
111 outputFormatName = inputFormatName = this.copyToConfig(inputFormatName);
112 }
113 } else {
114 URL inputFormatURL = Util.findURLinJars(inputFormatName);
115 if (inputFormatURL != null) {
116 inputFormatName = this.copyToConfig(inputFormatURL);
117 } else {
118 inputFormatName = this.copyToConfig(inputFormatName);
119 }
120 URL outputFormatURL = Util.findURLinJars(outputFormatName);
121 if (inputFormatURL != null) {
122 outputFormatName = this.copyToConfig(outputFormatURL);
123 } else {
124 outputFormatName = this.copyToConfig(outputFormatName);
125 }
126 }
127 OptionManager.instance().overloadOptionValue(containerIndex, "input", "format", inputFormatName);
128 } else {
129 if (outputFormatName.length() == 0) {
130 outputFormatName = inputFormatName;
131 }
132 }
133 dataFormatInstances = new HashMap<String, DataFormatInstance>(3);
134
135 URL inURL = findURL(inputFormatName);
136 URL outURL = findURL(outputFormatName);
137 // SystemLogger.logger().info(inputFormatName + "\n");
138 // SystemLogger.logger().info(outputFormatName + "\n");
139 // SystemLogger.logger().info(inURL + "\n");
140 // SystemLogger.logger().info(outURL + "\n");
141
142 if (outURL != null) {
143 try {
144 InputStream is = outURL.openStream();
145 } catch (FileNotFoundException e) {
146 outURL = Util.findURL(outputFormatName);
147 } catch (IOException e) {
148 outURL = Util.findURL(outputFormatName);
149 }
150 } else {
151 outURL = Util.findURL(outputFormatName);
152 }
153 dataFormatManager = new DataFormatManager(inURL, outURL);
154 symbolTables = new TrieSymbolTableHandler();
155 }
156
157 private URL findURL(String specModelFileName) throws MaltChainedException {
158 URL url = null;
159 File specFile = this.getFile(specModelFileName);
160 if (specFile.exists()) {
161 try {
162 url = new URL("file:///"+specFile.getAbsolutePath());
163 } catch (MalformedURLException e) {
164 throw new MaltChainedException("Malformed URL: "+specFile, e);
165 }
166 } else {
167 url = this.getConfigFileEntryURL(specModelFileName);
168 }
169 return url;
170 }
171
172 /**
173 * Creates an output stream writer, where the corresponding file will be included in the configuration directory
174 *
175 * @param fileName a file name
176 * @param charSet a char set
177 * @return an output stream writer for writing to a file within the configuration directory
178 * @throws MaltChainedException
179 */
180 public OutputStreamWriter getOutputStreamWriter(String fileName, String charSet) throws MaltChainedException {
181 try {
182 return new OutputStreamWriter(new FileOutputStream(configDirectory.getPath()+File.separator+fileName), charSet);
183 } catch (FileNotFoundException e) {
184 throw new ConfigurationException("The file '"+fileName+"' cannot be created. ", e);
185 } catch (UnsupportedEncodingException e) {
186 throw new ConfigurationException("The char set '"+charSet+"' is not supported. ", e);
187 }
188 }
189
190 /**
191 * Creates an output stream writer, where the corresponding file will be included in the
192 * configuration directory. Uses UTF-8 for character encoding.
193 *
194 * @param fileName a file name
195 * @return an output stream writer for writing to a file within the configuration directory
196 * @throws MaltChainedException
197 */
198 public OutputStreamWriter getOutputStreamWriter(String fileName) throws MaltChainedException {
199 try {
200 return new OutputStreamWriter(new FileOutputStream(configDirectory.getPath()+File.separator+fileName, true), "UTF-8");
201 } catch (FileNotFoundException e) {
202 throw new ConfigurationException("The file '"+fileName+"' cannot be created. ", e);
203 } catch (UnsupportedEncodingException e) {
204 throw new ConfigurationException("The char set 'UTF-8' is not supported. ", e);
205 }
206 }
207 /**
208 * This method acts the same as getOutputStreamWriter with the difference that the writer append in the file
209 * if it already exists instead of deleting the previous content before starting to write.
210 *
211 * @param fileName a file name
212 * @return an output stream writer for writing to a file within the configuration directory
213 * @throws MaltChainedException
214 */
215 public OutputStreamWriter getAppendOutputStreamWriter(String fileName) throws MaltChainedException {
216 try {
217 return new OutputStreamWriter(new FileOutputStream(configDirectory.getPath()+File.separator+fileName, true), "UTF-8");
218 } catch (FileNotFoundException e) {
219 throw new ConfigurationException("The file '"+fileName+"' cannot be created. ", e);
220 } catch (UnsupportedEncodingException e) {
221 throw new ConfigurationException("The char set 'UTF-8' is not supported. ", e);
222 }
223 }
224
225 /**
226 * Creates an input stream reader for reading a file within the configuration directory
227 *
228 * @param fileName a file name
229 * @param charSet a char set
230 * @return an input stream reader for reading a file within the configuration directory
231 * @throws MaltChainedException
232 */
233 public InputStreamReader getInputStreamReader(String fileName, String charSet) throws MaltChainedException {
234 try {
235 return new InputStreamReader(new FileInputStream(configDirectory.getPath()+File.separator+fileName), charSet);
236 } catch (FileNotFoundException e) {
237 throw new ConfigurationException("The file '"+fileName+"' cannot be found. ", e);
238 } catch (UnsupportedEncodingException e) {
239 throw new ConfigurationException("The char set '"+charSet+"' is not supported. ", e);
240 }
241 }
242
243 /**
244 * Creates an input stream reader for reading a file within the configuration directory.
245 * Uses UTF-8 for character encoding.
246 *
247 * @param fileName a file name
248 * @return an input stream reader for reading a file within the configuration directory
249 * @throws MaltChainedException
250 */
251 public InputStreamReader getInputStreamReader(String fileName) throws MaltChainedException {
252 return getInputStreamReader(fileName, "UTF-8");
253 }
254
255 public JarEntry getConfigFileEntry(String fileName) throws MaltChainedException {
256 File mcoPath = new File(workingDirectory.getPath()+File.separator+getName()+".mco");
257 try {
258 JarFile mcoFile = new JarFile(mcoPath.getAbsolutePath());
259 JarEntry entry = mcoFile.getJarEntry(getName()+File.separator+fileName);
260 return entry;
261 } catch (FileNotFoundException e) {
262 throw new ConfigurationException("The file entry '"+fileName+"' in mco-file '"+mcoPath+"' cannot be found. ", e);
263 } catch (IOException e) {
264 throw new ConfigurationException("The file entry '"+fileName+"' in mco-file '"+mcoPath+"' cannot be found. ", e);
265 }
266 }
267
268 public InputStreamReader getInputStreamReaderFromConfigFileEntry(String fileName, String charSet) throws MaltChainedException {
269 File mcoPath = new File(workingDirectory.getPath()+File.separator+getName()+".mco");
270 try {
271 JarFile mcoFile = new JarFile(mcoPath.getAbsolutePath());
272 JarEntry entry = mcoFile.getJarEntry(getName()+File.separator+fileName);
273 return new InputStreamReader(mcoFile.getInputStream(entry), charSet);
274 } catch (FileNotFoundException e) {
275 throw new ConfigurationException("The file entry '"+fileName+"' in the mco file '"+mcoPath+"' cannot be found. ", e);
276 } catch (UnsupportedEncodingException e) {
277 throw new ConfigurationException("The char set '"+charSet+"' is not supported. ", e);
278 } catch (IOException e) {
279 throw new ConfigurationException("The file entry '"+fileName+"' in the mco file '"+mcoPath+"' cannot be loaded. ", e);
280 }
281 }
282
283 public InputStreamReader getInputStreamReaderFromConfigFile(String fileName) throws MaltChainedException {
284 return getInputStreamReaderFromConfigFileEntry(fileName, "UTF-8");
285 }
286
287 /**
288 * Returns a file handler object of a file within the configuration directory
289 *
290 * @param fileName a file name
291 * @return a file handler object of a file within the configuration directory
292 * @throws MaltChainedException
293 */
294 public File getFile(String fileName) throws MaltChainedException {
295 return new File(configDirectory.getPath()+File.separator+fileName);
296 }
297
298 public URL getConfigFileEntryURL(String fileName) throws MaltChainedException {
299 File mcoPath = new File(workingDirectory.getPath()+File.separator+getName()+".mco");
300 try {
301 if (!mcoPath.exists()) {
302 throw new ConfigurationException("Couldn't find mco-file '" +mcoPath.getAbsolutePath()+ "'");
303 }
304 new URL("file", null, mcoPath.getAbsolutePath());
305 return new URL("jar:"+new URL("file", null, mcoPath.getAbsolutePath())+"!/"+getName()+File.separator+fileName + "\n");
306 } catch (MalformedURLException e) {
307 throw new ConfigurationException("Couldn't find the URL '" +"jar:"+mcoPath.getAbsolutePath()+"!/"+getName()+File.separator+fileName+ "'", e);
308 }
309 }
310
311 /**
312 * Copies a file into the configuration directory.
313 *
314 * @param source a path to file
315 * @throws MaltChainedException
316 */
317 public String copyToConfig(File source) throws MaltChainedException {
318 byte[] readBuffer = new byte[BUFFER];
319 String destination = configDirectory.getPath()+File.separator+source.getName();
320 try {
321 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(source));
322 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destination), BUFFER);
323
324 int n = 0;
325 while ((n = bis.read(readBuffer, 0, BUFFER)) != -1) {
326 bos.write(readBuffer, 0, n);
327 }
328 bos.flush();
329 bos.close();
330 bis.close();
331 } catch (FileNotFoundException e) {
332 throw new ConfigurationException("The source file '"+source+"' cannot be found or the destination file '"+destination+"' cannot be created when coping the file. ", e);
333 } catch (IOException e) {
334 throw new ConfigurationException("The source file '"+source+"' cannot be copied to destination '"+destination+"'. ", e);
335 }
336 return source.getName();
337 }
338
339
340 public String copyToConfig(String fileUrl) throws MaltChainedException {
341 URL url = Util.findURL(fileUrl);
342 if (url == null) {
343 throw new ConfigurationException("The file or URL '"+fileUrl+"' could not be found. ");
344 }
345 return copyToConfig(url);
346 }
347
348 public String copyToConfig(URL url) throws MaltChainedException {
349 if (url == null) {
350 throw new ConfigurationException("URL could not be found. ");
351 }
352 byte[] readBuffer = new byte[BUFFER];
353 String destFileName = url.getPath();
354 int indexSlash = destFileName.lastIndexOf('/');
355 if (indexSlash == -1) {
356 indexSlash = destFileName.lastIndexOf('\\');
357 }
358
359 if (indexSlash != -1) {
360 destFileName = destFileName.substring(indexSlash+1);
361 }
362
363 String destination = configDirectory.getPath()+File.separator+destFileName;
364 try {
365 BufferedInputStream bis = new BufferedInputStream(url.openStream());
366 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destination), BUFFER);
367
368 int n = 0;
369 while ((n = bis.read(readBuffer, 0, BUFFER)) != -1) {
370 bos.write(readBuffer, 0, n);
371 }
372 bos.flush();
373 bos.close();
374 bis.close();
375 } catch (FileNotFoundException e) {
376 throw new ConfigurationException("The destination file '"+destination+"' cannot be created when coping the file. ", e);
377 } catch (IOException e) {
378 throw new ConfigurationException("The URL '"+url+"' cannot be copied to destination '"+destination+"'. ", e);
379 }
380 return destFileName;
381 }
382
383
384 /**
385 * Removes the configuration directory, if it exists and it contains a .info file.
386 *
387 * @throws MaltChainedException
388 */
389 public void deleteConfigDirectory() throws MaltChainedException {
390 if (!configDirectory.exists()) {
391 return;
392 }
393 File infoFile = new File(configDirectory.getPath()+File.separator+getName()+"_"+getType()+".info");
394 if (infoFile.exists()) {
395 deleteConfigDirectory(configDirectory);
396 } else {
397 throw new ConfigurationException("There exists a directory that is not a MaltParser configuration directory. ");
398 }
399 }
400
401 private void deleteConfigDirectory(File directory) throws MaltChainedException {
402 if (directory.exists()) {
403 File[] files = directory.listFiles();
404 for (int i = 0; i < files.length; i++) {
405 if (files[i].isDirectory()) {
406 deleteConfigDirectory(files[i]);
407 } else {
408 files[i].delete();
409 }
410 }
411 } else {
412 throw new ConfigurationException("The directory '"+directory.getPath()+ "' cannot be found. ");
413 }
414 directory.delete();
415 }
416
417 /**
418 * Returns a file handler object for the configuration directory
419 *
420 * @return a file handler object for the configuration directory
421 */
422 public File getConfigDirectory() {
423 return configDirectory;
424 }
425
426 protected void setConfigDirectory(File dir) {
427 this.configDirectory = dir;
428 }
429
430 /**
431 * Creates the configuration directory
432 *
433 * @throws MaltChainedException
434 */
435 public void createConfigDirectory() throws MaltChainedException {
436 checkConfigDirectory();
437 configDirectory.mkdir();
438 createInfoFile();
439 }
440
441 protected void checkConfigDirectory() throws MaltChainedException {
442 if (configDirectory.exists() && !configDirectory.isDirectory()) {
443 throw new ConfigurationException("The configuration directory name already exists and is not a directory. ");
444 }
445
446 if (configDirectory.exists()) {
447 deleteConfigDirectory();
448 }
449 }
450
451 protected void createInfoFile() throws MaltChainedException {
452 infoFile = new BufferedWriter(getOutputStreamWriter(getName()+"_"+getType()+".info"));
453 try {
454 infoFile.write("CONFIGURATION\n");
455 infoFile.write("Configuration name: "+getName()+"\n");
456 infoFile.write("Configuration type: "+getType()+"\n");
457 infoFile.write("Created: "+new Date(System.currentTimeMillis())+"\n");
458
459 infoFile.write("\nSYSTEM\n");
460 infoFile.write("Operating system architecture: "+System.getProperty("os.arch")+"\n");
461 infoFile.write("Operating system name: "+System.getProperty("os.name")+"\n");
462 infoFile.write("JRE vendor name: "+System.getProperty("java.vendor")+"\n");
463 infoFile.write("JRE version number: "+System.getProperty("java.version")+"\n");
464
465 infoFile.write("\nMALTPARSER\n");
466 infoFile.write("Version: "+SystemInfo.getVersion()+"\n");
467 infoFile.write("Build date: "+SystemInfo.getBuildDate()+"\n");
468 HashSet<String> excludeGroups = new HashSet<String>();
469 excludeGroups.add("system");
470 infoFile.write("\nSETTINGS\n");
471 infoFile.write(OptionManager.instance().toStringPrettyValues(containerIndex, excludeGroups));
472 infoFile.flush();
473 } catch (IOException e) {
474 throw new ConfigurationException("Could not create the maltparser info file. ");
475 }
476 }
477
478 /**
479 * Returns a writer to the configuration information file
480 *
481 * @return a writer to the configuration information file
482 * @throws MaltChainedException
483 */
484 public BufferedWriter getInfoFileWriter() throws MaltChainedException {
485 return infoFile;
486 }
487
488 /**
489 * Creates the malt configuration file (.mco). This file is compressed.
490 *
491 * @throws MaltChainedException
492 */
493 public void createConfigFile() throws MaltChainedException {
494 try {
495 JarOutputStream jos = new JarOutputStream(new FileOutputStream(workingDirectory.getPath()+File.separator+getName()+".mco"));
496 // configLogger.info("Creates configuration file '"+workingDirectory.getPath()+File.separator+getName()+".mco' ...\n");
497 createConfigFile(configDirectory.getPath(), jos);
498 jos.close();
499 } catch (FileNotFoundException e) {
500 throw new ConfigurationException("The maltparser configurtation file '"+workingDirectory.getPath()+File.separator+getName()+".mco"+"' cannot be found. ", e);
501 } catch (IOException e) {
502 throw new ConfigurationException("The maltparser configurtation file '"+workingDirectory.getPath()+File.separator+getName()+".mco"+"' cannot be created. ", e);
503 }
504 }
505
506 private void createConfigFile(String directory, JarOutputStream jos) throws MaltChainedException {
507 byte[] readBuffer = new byte[BUFFER];
508 try {
509 File zipDir = new File(directory);
510 String[] dirList = zipDir.list();
511
512 int bytesIn = 0;
513
514 for (int i = 0; i < dirList.length; i++) {
515 File f = new File(zipDir, dirList[i]);
516 if (f.isDirectory()) {
517 String filePath = f.getPath();
518 createConfigFile(filePath, jos);
519 continue;
520 }
521
522 FileInputStream fis = new FileInputStream(f);
523
524
525 JarEntry entry = new JarEntry(f.getPath().substring(workingDirectory.getPath().length()+1));
526 jos.putNextEntry(entry);
527
528 while ((bytesIn = fis.read(readBuffer)) != -1) {
529 jos.write(readBuffer, 0, bytesIn);
530 }
531
532 fis.close();
533 }
534 } catch (FileNotFoundException e) {
535 throw new ConfigurationException("The directory '"+directory+"' cannot be found. ", e);
536 } catch (IOException e) {
537 throw new ConfigurationException("The directory '"+directory+"' cannot be compressed into a mco file. ", e);
538 }
539 }
540
541
542 public void copyConfigFile(File in, File out, Versioning versioning) throws MaltChainedException {
543 try {
544 JarFile jar = new JarFile(in);
545 JarOutputStream tempJar = new JarOutputStream(new FileOutputStream(out));
546 byte[] buffer = new byte[BUFFER];
547 int bytesRead;
548 StringBuilder sb = new StringBuilder();
549
550 for (Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements(); ) {
551 JarEntry inEntry = (JarEntry) entries.nextElement();
552 InputStream entryStream = jar.getInputStream(inEntry);
553 JarEntry outEntry = versioning.getJarEntry(inEntry);
554
555 if (!versioning.hasChanges(inEntry, outEntry)) {
556 tempJar.putNextEntry(outEntry);
557 while ((bytesRead = entryStream.read(buffer)) != -1) {
558 tempJar.write(buffer, 0, bytesRead);
559 }
560 } else {
561 tempJar.putNextEntry(outEntry);
562 BufferedReader br = new BufferedReader(new InputStreamReader(entryStream));
563 String line = null;
564 sb.setLength(0);
565 while ((line = br.readLine()) != null) {
566 sb.append(line);
567 sb.append('\n');
568 }
569 String outString = versioning.modifyJarEntry(inEntry, outEntry, sb);
570 tempJar.write(outString.getBytes());
571 }
572 }
573 if (versioning.getFeatureModelXML() != null && versioning.getFeatureModelXML().startsWith("/appdata")) {
574 int index = versioning.getFeatureModelXML().lastIndexOf('/');
575 BufferedInputStream bis = new BufferedInputStream(Util.findURLinJars(versioning.getFeatureModelXML()).openStream());
576 tempJar.putNextEntry(new JarEntry(versioning.getNewConfigName()+"/" +versioning.getFeatureModelXML().substring(index+1)));
577 int n = 0;
578 while ((n = bis.read(buffer, 0, BUFFER)) != -1) {
579 tempJar.write(buffer, 0, n);
580 }
581 bis.close();
582 }
583 if (versioning.getInputFormatXML() != null && versioning.getInputFormatXML().startsWith("/appdata")) {
584 int index = versioning.getInputFormatXML().lastIndexOf('/');
585 BufferedInputStream bis = new BufferedInputStream(Util.findURLinJars(versioning.getInputFormatXML()).openStream());
586 tempJar.putNextEntry(new JarEntry(versioning.getNewConfigName()+"/" +versioning.getInputFormatXML().substring(index+1)));
587 int n = 0;
588 while ((n = bis.read(buffer, 0, BUFFER)) != -1) {
589 tempJar.write(buffer, 0, n);
590 }
591 bis.close();
592 }
593 tempJar.flush();
594 tempJar.close();
595 jar.close();
596 } catch (IOException e) {
597 throw new ConfigurationException("", e);
598 }
599 }
600
601 protected void initNameNTypeFromInfoFile(URL url) throws MaltChainedException {
602 if (url == null) {
603 throw new ConfigurationException("The URL cannot be found. ");
604 }
605 try {
606 JarEntry je;
607 JarInputStream jis = new JarInputStream(url.openConnection().getInputStream());
608 while ((je = jis.getNextJarEntry()) != null) {
609 String entryName = je.getName();
610 if (entryName.endsWith(".info")) {
611 int indexUnderScore = entryName.lastIndexOf('_');
612 int indexSeparator = entryName.lastIndexOf(File.separator);
613 if (indexSeparator == -1) {
614 indexSeparator = entryName.lastIndexOf('/');
615 }
616 if (indexSeparator == -1) {
617 indexSeparator = entryName.lastIndexOf('\\');
618 }
619 int indexDot = entryName.lastIndexOf('.');
620 if (indexUnderScore == -1 || indexDot == -1) {
621 throw new ConfigurationException("Could not find the configuration name and type from the URL '"+url.toString()+"'. ");
622 }
623 setName(entryName.substring(indexSeparator+1, indexUnderScore));
624 setType(entryName.substring(indexUnderScore+1, indexDot));
625 setConfigDirectory(new File(workingDirectory.getPath()+File.separator+getName()));
626 jis.close();
627 return;
628 }
629 }
630
631 } catch (IOException e) {
632 throw new ConfigurationException("Could not find the configuration name and type from the URL '"+url.toString()+"'. ", e);
633 }
634 }
635
636 /**
637 * Prints the content of the configuration information file to the system logger
638 *
639 * @throws MaltChainedException
640 */
641 public void echoInfoFile() throws MaltChainedException {
642 checkConfigDirectory();
643 JarInputStream jis;
644 try {
645 if (url == null) {
646 jis = new JarInputStream(new FileInputStream(workingDirectory.getPath()+File.separator+getName()+".mco"));
647 } else {
648 jis = new JarInputStream(url.openConnection().getInputStream());
649 }
650 JarEntry je;
651
652 while ((je = jis.getNextJarEntry()) != null) {
653 String entryName = je.getName();
654
655 if (entryName.endsWith(getName()+"_"+getType()+".info")) {
656 int c;
657 while ((c = jis.read()) != -1) {
658 SystemLogger.logger().info((char)c);
659 }
660 }
661 }
662 jis.close();
663 } catch (FileNotFoundException e) {
664 throw new ConfigurationException("Could not print configuration information file. The configuration file '"+workingDirectory.getPath()+File.separator+getName()+".mco"+"' cannot be found. ", e);
665 } catch (IOException e) {
666 throw new ConfigurationException("Could not print configuration information file. ", e);
667 }
668
669 }
670
671 /**
672 * Unpacks the malt configuration file (.mco).
673 *
674 * @throws MaltChainedException
675 */
676 public void unpackConfigFile() throws MaltChainedException {
677 checkConfigDirectory();
678 JarInputStream jis;
679 try {
680 if (url == null) {
681 jis = new JarInputStream(new FileInputStream(workingDirectory.getPath()+File.separator+getName()+".mco"));
682 } else {
683 jis = new JarInputStream(url.openConnection().getInputStream());
684 }
685 unpackConfigFile(jis);
686 jis.close();
687 } catch (FileNotFoundException e) {
688 throw new ConfigurationException("Could not unpack configuration. The configuration file '"+workingDirectory.getPath()+File.separator+getName()+".mco"+"' cannot be found. ", e);
689 } catch (IOException e) {
690 if (configDirectory.exists()) {
691 deleteConfigDirectory();
692 }
693 throw new ConfigurationException("Could not unpack configuration. ", e);
694 }
695 initCreatedByMaltParserVersionFromInfoFile();
696 }
697
698 protected void unpackConfigFile(JarInputStream jis) throws MaltChainedException {
699 try {
700 JarEntry je;
701 byte[] readBuffer = new byte[BUFFER];
702 SortedSet<String> directoryCache = new TreeSet<String>();
703 while ((je = jis.getNextJarEntry()) != null) {
704 String entryName = je.getName();
705
706 if (entryName.startsWith("/")) {
707 entryName = entryName.substring(1);
708 }
709 if (entryName.endsWith(File.separator)) {
710 return;
711 }
712 int index = -1;
713 if (File.separator.equals("\\")) {
714 entryName = entryName.replace('/', '\\');
715 index = entryName.lastIndexOf("\\");
716 } else if (File.separator.equals("/")) {
717 entryName = entryName.replace('\\', '/');
718 index = entryName.lastIndexOf("/");
719 }
720 if (index > 0) {
721 String dirName = entryName.substring(0, index);
722 if (!directoryCache.contains(dirName)) {
723 File directory = new File(workingDirectory.getPath()+File.separator+dirName);
724 if (!(directory.exists() && directory.isDirectory())) {
725 if (!directory.mkdirs()) {
726 throw new ConfigurationException("Unable to make directory '" + dirName +"'. ");
727 }
728 directoryCache.add(dirName);
729 }
730 }
731 }
732
733 if (new File(workingDirectory.getPath()+File.separator+entryName).isDirectory() && new File(workingDirectory.getPath()+File.separator+entryName).exists()) {
734 continue;
735 }
736 BufferedOutputStream bos;
737 try {
738 bos = new BufferedOutputStream(new FileOutputStream(workingDirectory.getPath()+File.separator+entryName), BUFFER);
739 } catch (FileNotFoundException e) {
740 throw new ConfigurationException("Could not unpack configuration. The file '"+workingDirectory.getPath()+File.separator+entryName+"' cannot be unpacked. ", e);
741 }
742 int n = 0;
743 while ((n = jis.read(readBuffer, 0, BUFFER)) != -1) {
744 bos.write(readBuffer, 0, n);
745 }
746 bos.flush();
747 bos.close();
748 }
749 } catch (IOException e) {
750 throw new ConfigurationException("Could not unpack configuration. ", e);
751 }
752 }
753
754 /**
755 * Returns the name of the configuration directory
756 *
757 * @return the name of the configuration directory
758 */
759 public String getName() {
760 return name;
761 }
762
763 protected void setName(String name) {
764 this.name = name;
765 }
766
767 /**
768 * Returns the type of the configuration directory
769 *
770 * @return the type of the configuration directory
771 */
772 public String getType() {
773 return type;
774 }
775
776 protected void setType(String type) {
777 this.type = type;
778 }
779
780 /**
781 * Returns a file handler object for the working directory
782 *
783 * @return a file handler object for the working directory
784 */
785 public File getWorkingDirectory() {
786 return workingDirectory;
787 }
788
789 /**
790 * Initialize the working directory
791 *
792 * @throws MaltChainedException
793 */
794 public void initWorkingDirectory() throws MaltChainedException {
795 try {
796 initWorkingDirectory(OptionManager.instance().getOptionValue(0, "config", "workingdir").toString());
797 } catch (NullPointerException e) {
798 throw new ConfigurationException("The configuration cannot be found.", e);
799 }
800 }
801
802 /**
803 * Initialize the working directory according to the path. If the path is equals to "user.dir" or current directory, then the current directory
804 * will be the working directory.
805 *
806 * @param pathPrefixString the path to the working directory
807 * @throws MaltChainedException
808 */
809 public void initWorkingDirectory(String pathPrefixString) throws MaltChainedException {
810 if (pathPrefixString == null || pathPrefixString.equalsIgnoreCase("user.dir") || pathPrefixString.equalsIgnoreCase(".")) {
811 workingDirectory = new File(System.getProperty("user.dir"));
812 } else {
813 workingDirectory = new File(pathPrefixString);
814 }
815
816 if (workingDirectory == null || !workingDirectory.isDirectory()) {
817 new ConfigurationException("The specified working directory '"+pathPrefixString+"' is not a directory. ");
818 }
819 }
820
821 /**
822 * Returns the URL to the malt configuration file (.mco)
823 *
824 * @return the URL to the malt configuration file (.mco)
825 */
826 public URL getUrl() {
827 return url;
828 }
829
830 protected void setUrl(URL url) {
831 this.url = url;
832 }
833
834 /**
835 * Returns the option container index
836 *
837 * @return the option container index
838 */
839 public int getContainerIndex() {
840 return containerIndex;
841 }
842
843 /**
844 * Sets the option container index
845 *
846 * @param containerIndex a option container index
847 */
848 public void setContainerIndex(int containerIndex) {
849 this.containerIndex = containerIndex;
850 }
851
852 /**
853 * Returns the version number of MaltParser which created the malt configuration file (.mco)
854 *
855 * @return the version number of MaltParser which created the malt configuration file (.mco)
856 */
857 public String getCreatedByMaltParserVersion() {
858 return createdByMaltParserVersion;
859 }
860
861 /**
862 * Sets the version number of MaltParser which created the malt configuration file (.mco)
863 *
864 * @param createdByMaltParserVersion a version number of MaltParser
865 */
866 public void setCreatedByMaltParserVersion(String createdByMaltParserVersion) {
867 this.createdByMaltParserVersion = createdByMaltParserVersion;
868 }
869
870 public void initCreatedByMaltParserVersionFromInfoFile() throws MaltChainedException {
871 try {
872 BufferedReader br = new BufferedReader(getInputStreamReaderFromConfigFileEntry(getName()+"_"+getType()+".info", "UTF-8"));
873 String line = null;
874 while ((line = br.readLine()) != null) {
875 if (line.startsWith("Version: ")) {
876 setCreatedByMaltParserVersion(line.substring(31));
877 break;
878 }
879 }
880 br.close();
881 } catch (FileNotFoundException e) {
882 throw new ConfigurationException("Could not retrieve the version number of the MaltParser configuration.", e);
883 } catch (IOException e) {
884 throw new ConfigurationException("Could not retrieve the version number of the MaltParser configuration.", e);
885 }
886 }
887
888 public void versioning() throws MaltChainedException {
889 initCreatedByMaltParserVersionFromInfoFile();
890 SystemLogger.logger().info("\nCurrent version : " + SystemInfo.getVersion() + "\n");
891 SystemLogger.logger().info("Parser model version : " + createdByMaltParserVersion + "\n");
892 if (SystemInfo.getVersion() == null) {
893 throw new ConfigurationException("Couln't determine the version of MaltParser");
894 } else if (createdByMaltParserVersion == null) {
895 throw new ConfigurationException("Couln't determine the version of the parser model");
896 } else if (SystemInfo.getVersion().equals(createdByMaltParserVersion)) {
897 SystemLogger.logger().info("The parser model "+getName()+".mco has already the same version as the current version of MaltParser. \n");
898 return;
899 }
900
901 File mcoPath = new File(workingDirectory.getPath()+File.separator+getName()+".mco");
902 File newMcoPath = new File(workingDirectory.getPath()+File.separator+getName()+"."+SystemInfo.getVersion().trim()+".mco");
903 Versioning versioning = new Versioning(name, type, mcoPath, createdByMaltParserVersion);
904 if (!versioning.support(createdByMaltParserVersion)) {
905 SystemLogger.logger().warn("The parser model '"+ name+ ".mco' is created by MaltParser "+getCreatedByMaltParserVersion()+", which cannot be converted to a MaltParser "+SystemInfo.getVersion()+" parser model.\n");
906 SystemLogger.logger().warn("Please retrain the parser model with MaltParser "+SystemInfo.getVersion() +" or download MaltParser "+getCreatedByMaltParserVersion()+" from http://maltparser.org/download.html\n");
907 return;
908 }
909 SystemLogger.logger().info("Converts the parser model '"+ mcoPath.getName()+ "' into '"+newMcoPath.getName()+"'....\n");
910 copyConfigFile(mcoPath, newMcoPath, versioning);
911 }
912
913 protected void checkNConvertConfigVersion() throws MaltChainedException {
914 if (createdByMaltParserVersion.startsWith("1.0")) {
915 SystemLogger.logger().info(" Converts the MaltParser configuration ");
916 SystemLogger.logger().info("1.0");
917 SystemLogger.logger().info(" to ");
918 SystemLogger.logger().info(SystemInfo.getVersion());
919 SystemLogger.logger().info("\n");
920 File[] configFiles = configDirectory.listFiles();
921 for (int i = 0, n = configFiles.length; i < n; i++) {
922 if (configFiles[i].getName().endsWith(".mod")) {
923 configFiles[i].renameTo(new File(configDirectory.getPath()+File.separator+"odm0."+configFiles[i].getName()));
924 }
925 if (configFiles[i].getName().endsWith(getName()+".dsm")) {
926 configFiles[i].renameTo(new File(configDirectory.getPath()+File.separator+"odm0.dsm"));
927 }
928 if (configFiles[i].getName().equals("savedoptions.sop")) {
929 configFiles[i].renameTo(new File(configDirectory.getPath()+File.separator+"savedoptions.sop.old"));
930 }
931 if (configFiles[i].getName().equals("symboltables.sym")) {
932 configFiles[i].renameTo(new File(configDirectory.getPath()+File.separator+"symboltables.sym.old"));
933 }
934 }
935 try {
936 BufferedReader br = new BufferedReader(new FileReader(configDirectory.getPath()+File.separator+"savedoptions.sop.old"));
937 BufferedWriter bw = new BufferedWriter(new FileWriter(configDirectory.getPath()+File.separator+"savedoptions.sop"));
938 String line;
939 while ((line = br.readLine()) != null) {
940 if (line.startsWith("0\tguide\tprediction_strategy")) {
941 bw.write("0\tguide\tdecision_settings\tT.TRANS+A.DEPREL\n");
942 } else {
943 bw.write(line);
944 bw.write('\n');
945 }
946 }
947 br.close();
948 bw.flush();
949 bw.close();
950 new File(configDirectory.getPath()+File.separator+"savedoptions.sop.old").delete();
951 } catch (FileNotFoundException e) {
952 throw new ConfigurationException("Could convert savedoptions.sop version 1.0.4 to version 1.1. ", e);
953 } catch (IOException e) {
954 throw new ConfigurationException("Could convert savedoptions.sop version 1.0.4 to version 1.1. ", e);
955 }
956 try {
957 BufferedReader br = new BufferedReader(new FileReader(configDirectory.getPath()+File.separator+"symboltables.sym.old"));
958 BufferedWriter bw = new BufferedWriter(new FileWriter(configDirectory.getPath()+File.separator+"symboltables.sym"));
959 String line;
960 while ((line = br.readLine()) != null) {
961 if (line.startsWith("AllCombinedClassTable")) {
962 bw.write("T.TRANS+A.DEPREL\n");
963 } else {
964 bw.write(line);
965 bw.write('\n');
966 }
967 }
968 br.close();
969 bw.flush();
970 bw.close();
971 new File(configDirectory.getPath()+File.separator+"symboltables.sym.old").delete();
972 } catch (FileNotFoundException e) {
973 throw new ConfigurationException("Could convert symboltables.sym version 1.0.4 to version 1.1. ", e);
974 } catch (IOException e) {
975 throw new ConfigurationException("Could convert symboltables.sym version 1.0.4 to version 1.1. ", e);
976 }
977 }
978 if (!createdByMaltParserVersion.startsWith("1.3")) {
979 SystemLogger.logger().info(" Converts the MaltParser configuration ");
980 SystemLogger.logger().info(createdByMaltParserVersion);
981 SystemLogger.logger().info(" to ");
982 SystemLogger.logger().info(SystemInfo.getVersion());
983 SystemLogger.logger().info("\n");
984
985
986 new File(configDirectory.getPath()+File.separator+"savedoptions.sop").renameTo(new File(configDirectory.getPath()+File.separator+"savedoptions.sop.old"));
987 try {
988 BufferedReader br = new BufferedReader(new FileReader(configDirectory.getPath()+File.separator+"savedoptions.sop.old"));
989 BufferedWriter bw = new BufferedWriter(new FileWriter(configDirectory.getPath()+File.separator+"savedoptions.sop"));
990 String line;
991 while ((line = br.readLine()) != null) {
992 int index = line.indexOf('\t');
993 int container = 0;
994 if (index > -1) {
995 container = Integer.parseInt(line.substring(0,index));
996 }
997
998 if (line.startsWith(container+"\tnivre\tpost_processing")) {
999 } else if (line.startsWith(container+"\tmalt0.4\tbehavior")) {
1000 if (line.endsWith("true")) {
1001 SystemLogger.logger().info("MaltParser 1.3 doesn't support MaltParser 0.4 emulation.");
1002 br.close();
1003 bw.flush();
1004 bw.close();
1005 deleteConfigDirectory();
1006 System.exit(0);
1007 }
1008 } else if (line.startsWith(container+"\tsinglemalt\tparsing_algorithm")) {
1009 bw.write(container);
1010 bw.write("\tsinglemalt\tparsing_algorithm\t");
1011 if (line.endsWith("NivreStandard")) {
1012 bw.write("class org.maltparser.parser.algorithm.nivre.NivreArcStandardFactory");
1013 } else if (line.endsWith("NivreEager")) {
1014 bw.write("class org.maltparser.parser.algorithm.nivre.NivreArcEagerFactory");
1015 } else if (line.endsWith("CovingtonNonProjective")) {
1016 bw.write("class org.maltparser.parser.algorithm.covington.CovingtonNonProjFactory");
1017 } else if (line.endsWith("CovingtonProjective")) {
1018 bw.write("class org.maltparser.parser.algorithm.covington.CovingtonProjFactory");
1019 }
1020 bw.write('\n');
1021 } else {
1022 bw.write(line);
1023 bw.write('\n');
1024 }
1025 }
1026 br.close();
1027 bw.flush();
1028 bw.close();
1029 new File(configDirectory.getPath()+File.separator+"savedoptions.sop.old").delete();
1030 } catch (FileNotFoundException e) {
1031 throw new ConfigurationException("Could convert savedoptions.sop version 1.0.4 to version 1.1. ", e);
1032 } catch (IOException e) {
1033 throw new ConfigurationException("Could convert savedoptions.sop version 1.0.4 to version 1.1. ", e);
1034 }
1035 }
1036 }
1037
1038 /**
1039 * Terminates the configuration directory
1040 *
1041 * @throws MaltChainedException
1042 */
1043 public void terminate() throws MaltChainedException {
1044 if (infoFile != null) {
1045 try {
1046 infoFile.flush();
1047 infoFile.close();
1048 } catch (IOException e) {
1049 throw new ConfigurationException("Could not close configuration information file. ", e);
1050 }
1051 }
1052 symbolTables = null;
1053 // configuration = null;
1054 }
1055
1056 /* (non-Javadoc)
1057 * @see java.lang.Object#finalize()
1058 */
1059 protected void finalize() throws Throwable {
1060 try {
1061 if (infoFile != null) {
1062 infoFile.flush();
1063 infoFile.close();
1064 }
1065 } finally {
1066 super.finalize();
1067 }
1068 }
1069
1070 public SymbolTableHandler getSymbolTables() {
1071 return symbolTables;
1072 }
1073
1074 public void setSymbolTables(SymbolTableHandler symbolTables) {
1075 this.symbolTables = symbolTables;
1076 }
1077
1078 public DataFormatManager getDataFormatManager() {
1079 return dataFormatManager;
1080 }
1081
1082 public void setDataFormatManager(DataFormatManager dataFormatManager) {
1083 this.dataFormatManager = dataFormatManager;
1084 }
1085
1086 public HashMap<String, DataFormatInstance> getDataFormatInstances() {
1087 return dataFormatInstances;
1088 }
1089 }