001: // This file is part of KeY - Integrated Deductive Software Design
002: // Copyright (C) 2001-2005 Universitaet Karlsruhe, Germany
003: // Universitaet Koblenz-Landau, Germany
004: // Chalmers University of Technology, Sweden
005: //
006: // The KeY system is protected by the GNU General Public License.
007: // See LICENSE.TXT for details.
008: //
009: //
010: //
011: //
012:
013: package de.uka.ilkd.key.ocl.gf;
014:
015: import java.io.*;
016: import java.net.URL;
017: import java.nio.channels.Channels;
018: import java.nio.channels.FileChannel;
019: import java.nio.channels.ReadableByteChannel;
020: import java.util.logging.Level;
021: import java.util.logging.Logger;
022:
023: import de.uka.ilkd.key.util.KeYResourceManager;
024:
025: /** @author Kristofer Johannisson and Hans-Joachim Daniels
026: * handles the copying of GF OCL grammars from the resource directory
027: * to a temporary directory (so that GF can access them)
028: */
029: class TempGrammarFiles {
030:
031: private final static Logger logger = Logger
032: .getLogger(TempGrammarFiles.class.getName());
033: final static String grammars2 = "grammars2";
034: /**
035: * for debugging, one might want to keep the generated grammar files
036: */
037: static boolean deleteOnExit = true;
038: File oclgf2Dir = null;
039: /**
040: * a directory in the tmp directory with a unique name
041: */
042: File tempG2ParentDir = null;
043: /**
044: * a directory in grammars2TempDir with name grammars2
045: */
046: File tempGrammars2Dir = null;
047: final static String grammarFileListName = "grammars2list.txt";
048:
049: /**
050: * copy GF OCL grammars from internal resource directory to
051: * a temporary directory, where GF can access them
052: */
053: public TempGrammarFiles() throws IOException {
054: // attention: together with the KeYResourceHandler use "/" not
055: // File.separator
056: final URL grammarFileList = KeYResourceManager.getManager()
057: .getResourceFile(TempGrammarFiles.class,
058: grammars2 + "/" + grammarFileListName);
059:
060: final BufferedReader listReader = new BufferedReader(
061: new InputStreamReader(grammarFileList.openStream()));
062:
063: //This is not really safe, so. could do sth. between delete and mkdir.
064: tempG2ParentDir = File.createTempFile("grammars2_", null);
065: tempG2ParentDir.delete();
066: tempG2ParentDir.mkdir();
067: tempGrammars2Dir = new File(tempG2ParentDir.getPath()
068: + File.separator + grammars2);
069: tempGrammars2Dir.mkdirs();
070:
071: int timer = 0;
072: for (String filename = listReader.readLine(); filename != null; filename = listReader
073: .readLine()) {
074:
075: if (filename.startsWith(".")) {
076: filename = filename.substring(2, filename.length());
077: }
078:
079: URL oldFileURL = KeYResourceManager.getManager()
080: .getResourceFile(TempGrammarFiles.class,
081: grammars2 + "/" + filename);
082: if (oldFileURL == null) {
083: throw new FileNotFoundException(
084: "GF cannot be started due to a missing file ("
085: + grammars2
086: + "/"
087: + filename
088: + "). "
089: + "Please ask the KeY team support@key-project.org for assistance.");
090: }
091:
092: File newFile = new File(tempGrammars2Dir.getAbsolutePath()
093: + File.separator
094: + filename.replaceAll("/", File.separator));
095:
096: if (logger.isLoggable(Level.FINER)) {
097: logger.finer("Copy: " + oldFileURL.getPath() + " --> "
098: + newFile.getAbsolutePath());
099: }
100: if (!newFile.getParentFile().exists()) {
101: newFile.getParentFile().mkdirs();
102: }
103: newFile.createNewFile();
104: copyFile(new BufferedInputStream(oldFileURL.openStream()),
105: newFile);
106: }
107: listReader.close();
108: }
109:
110: /**
111: * returns the location of the OCL-GF2 grammar files in the temp directory.
112: * @return the location of the OCL-GF2 grammar files in the temp directory.
113: */
114: public String path2grammars2() {
115: return tempGrammars2Dir.getAbsolutePath();
116: }
117:
118: /**
119: * creates a file with the given ocl constraint as the content and returns the handle.
120: * Every call generates a new File.
121: * @param ocl the constraint to be written
122: * @return a File object representing the temporary file
123: * @throws IOException
124: */
125: public static File createOCLtmp(String ocl) throws IOException {
126: File result = File.createTempFile("ocl_", null);
127:
128: PrintWriter toW = new PrintWriter(new BufferedWriter(
129: new FileWriter(result)));
130: toW.println(ocl);
131: toW.close();
132: perhapsDeleteOnExit(result);
133: return result;
134: }
135:
136: /**
137: * If the flag deleteOnExit is set, the same named function will
138: * be called on candidate
139: * @param candidate the File that gets deleted on exit if set so
140: */
141: private static void perhapsDeleteOnExit(File candidate) {
142: if (deleteOnExit) {
143: try {
144: candidate.deleteOnExit();
145: } catch (SecurityException e) {
146: logger.warning(e.getLocalizedMessage());
147: e.printStackTrace();
148: }
149: }
150: }
151:
152: /**
153: * copies the content of src into dest
154: * @param src the InputStream from where to read from
155: * @param dest The destination File. Should dest already exist, it will get deleted first.
156: * For that, it must not be a non-empty directory.
157: * @throws IOException
158: */
159: private static void copyFile(InputStream src, File dest)
160: throws IOException {
161: final int BLOCK_LENGTH = 50000;
162: final ReadableByteChannel inChannel = Channels
163: .newChannel(new BufferedInputStream(src, BLOCK_LENGTH));
164:
165: if (dest.exists()) {
166: dest.delete();
167: }
168:
169: final RandomAccessFile raf = new RandomAccessFile(dest, "rw");
170: final FileChannel outChannel = raf.getChannel();
171:
172: long writtenBytes = -1;
173: long position = 0;
174: do {
175: writtenBytes = outChannel.transferFrom(inChannel, position,
176: BLOCK_LENGTH);
177: if (writtenBytes > 0
178: && position > Long.MAX_VALUE - writtenBytes) {
179: throw new RuntimeException(
180: "Cannot handle files greater than "
181: + Long.MAX_VALUE + " bytes.");
182: }
183: position += writtenBytes;
184: } while (writtenBytes >= BLOCK_LENGTH);
185: inChannel.close();
186: outChannel.close();
187: raf.close();
188: }
189: }
|