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