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 }