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 }