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