001: // This file is part of KeY - Integrated Deductive Software Design
002: // Copyright (C) 2001-2007 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: package de.uka.ilkd.key.util.install;
011:
012: import java.io.*;
013: import java.util.LinkedList;
014: import java.util.jar.JarEntry;
015: import java.util.jar.JarFile;
016: import java.util.Enumeration;
017:
018: /**
019: * This class is an abstract installer for the binary version of KeY. The
020: * installer UI itself is realised in subclasses in order to support
021: * a graphical and a command line interface.
022: */
023:
024: public abstract class KeYInstaller {
025:
026: private static final String binaryPath = "bin";
027: private static final String systemPath = "system";
028: private static final String configPath = "config";
029: private static final String keypatternsPath = "keypatterns";
030: private static final String keyscriptsPath = "keyscripts"
031: + File.separatorChar + "menuextension";
032: private static final String keyextjarsPath = "key-ext-jars";
033:
034: private static final String[] subdirs = { systemPath, binaryPath,
035: configPath, keypatternsPath, keyscriptsPath, keyextjarsPath };
036:
037: /** array with names of required library files */
038: private static final String[] libraries = new String[] {
039: "antlr.jar", "dresden-ocl-demo.jar", "recoder.jar",
040: "xerces.jar", "jargs.jar", "log4j.jar" };
041:
042: /** optional external binaries */
043: private static final String[] optBinaries = new String[] { "gf",
044: "Simplify" };
045:
046: /* necessary environment information */
047:
048: /** the directory where your Java interpreter is installed */
049: private String JAVA_HOME = "";
050: /** the directory where together is installed */
051: private String TOGETHER_HOME = "";
052: /** the directory where key has to be installed */
053: private String KEY_HOME = "";
054: /** the directory where the key external libraries can be found */
055: private String KEY_LIB = "";
056:
057: /**
058: * information about the supported together version
059: */
060: private String[] supportedTgVersion = new String[] { "6.2",
061: "6.0.1", "6.0" };
062:
063: private String tgVersion = supportedTgVersion[0];
064:
065: /** the underlying operation system, default linux */
066: private String[] supportedOS = { "linux", "win" };
067: private String os = "linux";
068:
069: private String keyJarPath = "";
070:
071: public KeYInstaller(String keyHome, String keyLib, String javaHome,
072: String keyJarPath, String os) {
073:
074: keyHome(keyHome);
075: keyLib(keyLib);
076: javaHome(javaHome);
077: keyJarPath(keyJarPath);
078:
079: if (os != null
080: && (os.toUpperCase().indexOf("WINDOWS") >= 0 || os
081: .toUpperCase().indexOf("WINNT") >= 0)) {
082: this .os = supportedOS[1];
083: } else {
084: this .os = supportedOS[0];
085: }
086: }
087:
088: // create strings setting the environment right
089:
090: private String replaceAll(String text, String old,
091: String replacement) {
092:
093: StringBuffer result = new StringBuffer(text);
094:
095: int idx = 0;
096:
097: while ((idx = text.indexOf(old, idx)) != -1) {
098: result.replace(idx, idx + 1, replacement);
099: }
100:
101: return result.toString();
102: }
103:
104: /**
105: * creates a comment with the given content
106: * for the installation OS
107: */
108: protected String comment(String comment) {
109: if ("linux".equals(os)) {
110: return "# " + replaceAll(comment, "\n", "\n# ") + "\n";
111: } else { // windows is assumed
112: return "rem " + replaceAll(comment, "\n", "\r\nrem ")
113: + "\r\n";
114: }
115: }
116:
117: /**
118: * sets an envrionment variable to the given value
119: * for the installation OS
120: */
121: protected String variable(String variable, String value) {
122: if ("linux".equals(os)) {
123: return variable + "=\"" + value + "\"\n";
124: } else { // windows is assumed
125: return "SET " + variable + "=" + value + "\r\n";
126: }
127: }
128:
129: /** creates preamble in script setting the environment variables */
130: protected String environment() {
131: StringBuffer environment = new StringBuffer();
132:
133: environment.append("linux".equals(os) ? "#!/bin/sh \n" : "");
134: environment.append("win".equals(os) ? "@echo off \r\n" : "");
135: environment.append(comment(" KeY-Environment Settings "));
136: environment.append(variable("TOGETHER_HOME", togetherHome()));
137: environment.append(variable("KEY_HOME", keyHome()));
138: environment.append(variable("KEY_LIB", keyLib()));
139: environment.append(variable("JAVA_HOME", javaHome()));
140:
141: return environment.toString();
142: }
143:
144: // selection of the correct shell-script
145:
146: protected String startScriptPatternName() {
147: return "startkey_" + os + "_" + tgVersion;
148: }
149:
150: protected String startScriptPatternPath() {
151: return "de.uka.ilkd.key.util.install.".replace('.',
152: File.separatorChar)
153: + startScriptPatternName();
154: }
155:
156: protected String startProverScriptPatternName() {
157: return "startProver_" + os + "_" + tgVersion;
158: }
159:
160: protected String startProverScriptPatternPath() {
161: return "de.uka.ilkd.key.util.install.".replace('.',
162: File.separatorChar)
163: + startProverScriptPatternName();
164: }
165:
166: protected String startScriptFilePath() {
167: return binaryPath() + File.separatorChar
168: + startScriptFileName();
169: }
170:
171: protected String startProverScriptFilePath() {
172: return binaryPath() + File.separatorChar
173: + startProverScriptFileName();
174: }
175:
176: protected String startScriptFileName() {
177: return "linux".equals(os) ? "startkey" : "startkey.bat";
178: }
179:
180: protected String startProverScriptFileName() {
181: return "linux".equals(os) ? "startProver" : "startProver.bat";
182: }
183:
184: protected String configPatternName() {
185: return "key.config";
186: }
187:
188: protected String configFileName() {
189: return "key.config";
190: }
191:
192: protected String configPatternPath() {
193: return "de.uka.ilkd.key.util.install.".replace('.',
194: File.separatorChar)
195: + configPatternName();
196: }
197:
198: protected String configFilePath() {
199: return configPath() + File.separatorChar + configFileName();
200: }
201:
202: // create directories
203:
204: /**
205: * creates directory structure as used by key
206: */
207:
208: public void mkdirs() {
209: for (int i = 0; i < subdirs.length; i++) {
210: File f = new File(keyHome() + File.separatorChar
211: + subdirs[i]);
212: f.mkdirs();
213: }
214: }
215:
216: public void copy(File file, String to) throws KeYInstallerException {
217:
218: File newFile = new File(to + File.separatorChar
219: + file.getName());
220: if (newFile.equals(file))
221: return;
222: if (newFile.exists())
223: newFile.delete();
224:
225: FileInputStream fis = null;
226: FileOutputStream fos = null;
227: try {
228: fis = new FileInputStream(file);
229: fos = new FileOutputStream(newFile);
230: byte[] buf = new byte[1024];
231: int i = 0;
232: while ((i = fis.read(buf)) != -1)
233: fos.write(buf, 0, i);
234: } catch (IOException ioe) {
235: throw new KeYInstallerException(
236: "Error occured while copying \n" + file
237: + "\n to \n" + newFile + " \n due to:\n"
238: + ioe);
239: } finally {
240: try {
241: if (fis != null)
242: fis.close();
243: if (fos != null)
244: fos.close();
245: } catch (IOException ioe) {
246: throw new KeYInstallerException(
247: "Error occured while closing streams :" + ioe);
248: }
249: }
250: }
251:
252: // write shellscript
253:
254: private void createStartScript(JarFile jarFile)
255: throws KeYInstallerException {
256:
257: createFile(environment(), startScriptFilePath(),
258: startScriptPatternPath(), jarFile);
259: }
260:
261: private void createStandAloneProverScript(JarFile jarFile)
262: throws KeYInstallerException {
263: createFile(environment(), startProverScriptFilePath(),
264: startProverScriptPatternPath(), jarFile);
265: }
266:
267: private void createConfigFile(JarFile jarFile)
268: throws KeYInstallerException {
269: createFile("", configFilePath(), configPatternPath(), jarFile);
270: }
271:
272: public void generateScripts(JarFile jarFile)
273: throws KeYInstallerException {
274: createStartScript(jarFile);
275: createStandAloneProverScript(jarFile);
276: createConfigFile(jarFile);
277: }
278:
279: private void createFile(String preamble, String fileNameToWrite,
280: String fileNameToReadFromJar, JarFile jarFile)
281: throws KeYInstallerException {
282:
283: // write preamble
284: FileOutputStream fw = null;
285: InputStream in = null;
286: try {
287: fw = new FileOutputStream(new File(fileNameToWrite));
288: fw.write(preamble.getBytes());
289:
290: // rest of the start script
291: JarEntry entry = (JarEntry) jarFile
292: .getEntry(fileNameToReadFromJar.replace(
293: File.separatorChar, '/'));
294:
295: if (entry == null) {
296: throw new KeYInstallerException(
297: " Could not found jar file entry : "
298: + fileNameToReadFromJar);
299: }
300: in = jarFile.getInputStream(entry);
301:
302: if (entry.getSize() > Integer.MAX_VALUE) {
303: throw new KeYInstallerException("Entry " + entry
304: + " too big. Overflow would occur.");
305: }
306:
307: byte[] scriptfileContent = new byte[(int) entry.getSize()];
308:
309: long count = 0;
310: while (count < scriptfileContent.length
311: && in.available() != 0) {
312: int bytesRead = in.read(scriptfileContent, (int) count,
313: (int) (scriptfileContent.length - count));
314: count += (bytesRead >= 0 ? bytesRead : 0);
315: }
316:
317: if (count < scriptfileContent.length) {
318: throw new KeYInstallerException("Read " + entry
319: + " only partial ");
320: }
321:
322: fw.write(scriptfileContent);
323:
324: } catch (IOException io) {
325: throw new KeYInstallerException(io.getLocalizedMessage());
326: } finally {
327: try {
328: if (in != null) {
329: in.close();
330: }
331: if (fw != null) {
332: fw.close();
333: }
334: } catch (IOException io) {
335: throw new KeYInstallerException(io
336: .getLocalizedMessage());
337: }
338: }
339: }
340:
341: protected void extractTgScripts(JarFile jarFile)
342: throws KeYInstallerException {
343: String file = "Manifest.mf";
344:
345: String keyscripts = "de.uka.ilkd.key.casetool.together.scripts";
346:
347: String fromPath = keyscripts + ".";
348:
349: String toPath = keyscriptsPath() + File.separatorChar
350: + fromPath.replace('.', File.separatorChar);
351:
352: fromPath = fromPath.replace('.', '/');
353:
354: extractFromJar(fromPath + "menuextension", toPath
355: + "menuextension", "Manifest.mf", jarFile);
356:
357: extractFromJar(fromPath + "patternupdate", toPath
358: + "patternupdate", "Manifest.mf", jarFile);
359:
360: }
361:
362: protected void extractExamples(JarFile jarFile)
363: throws KeYInstallerException {
364: try {
365: Enumeration en = jarFile.entries();
366: while (en.hasMoreElements()) {
367: JarEntry entry = ((JarEntry) en.nextElement());
368: if (!entry.getName().startsWith("examples/"))
369: continue;
370:
371: File file = new File(keyHome(), entry.getName());
372: if (entry.isDirectory()) {
373: if (!file.exists())
374: file.mkdirs();
375: } else {
376: InputStream in = jarFile.getInputStream(entry);
377: FileOutputStream out = new FileOutputStream(file);
378: byte[] buf = new byte[1024];
379: int i = 0;
380: while ((i = in.read(buf)) != -1)
381: out.write(buf, 0, i);
382: out.close();
383: in.close();
384: }
385: }
386: } catch (IOException ioe) {
387: throw new KeYInstallerException(
388: " IOException occurred when trying to extract from jar file. "
389: + jarFile, ioe);
390: }
391: }
392:
393: // jar helper methods
394:
395: /**
396: * Extracts files from the key/program jar-archive.
397: * @param entryname name of the file in the jar
398: * @param filename name to be copied to.
399: */
400: public void extractFromJar(String entrypath, String writetopath,
401: String filename, JarFile jarFile)
402: throws KeYInstallerException {
403: try {
404: //generate directories to write file:
405: boolean dirs = (new File(writetopath)).mkdirs();
406:
407: // get JarEntry
408: JarEntry entry = (JarEntry) jarFile.getEntry(entrypath
409: + '/' + filename);
410: if (entry == null) {
411: throw new KeYInstallerException(
412: " Could not find jar file entry : " + entrypath
413: + '/' + filename);
414: }
415:
416: InputStream in = jarFile.getInputStream(entry);
417: //Write to file
418: FileOutputStream out = new FileOutputStream(writetopath
419: + File.separatorChar + filename);
420: int c;
421: while ((c = in.read()) != -1) {
422: out.write(c);
423: }
424: out.close();
425: in.close();
426: } catch (IOException ioe) {
427: throw new KeYInstallerException(
428: " IOException occurred when trying to extract from jar file. "
429: + jarFile, ioe);
430: }
431: }
432:
433: /** Checks if libraries are found in the keyLib directory
434: * and returns a list of missing files
435: */
436: public String[] checkLibraries() {
437: LinkedList l = new LinkedList();
438: for (int i = 0; i < libs().length; i++) {
439: File lib = new File(keyLib() + File.separatorChar
440: + libs()[i]);
441: if (!lib.exists()) {
442: l.add(keyLib() + File.separatorChar + libs()[i]);
443: }
444: }
445: return (String[]) l.toArray(new String[l.size()]);
446: }
447:
448: // some getters
449:
450: /**
451: * returns the names of the required libraries
452: */
453: public String[] libs() {
454: return libraries;
455: }
456:
457: /**
458: * returns directory of JAVA_HOME
459: */
460: public String javaHome() {
461: return JAVA_HOME;
462: }
463:
464: /**
465: * returns directory of TOGETHER_HOME
466: */
467: public String togetherHome() {
468: return TOGETHER_HOME;
469: }
470:
471: /**
472: * returns directory of KEY_HOME
473: */
474: public String keyHome() {
475: return KEY_HOME;
476: }
477:
478: /**
479: * returns directory of KEY_LIB
480: */
481: public String keyLib() {
482: return KEY_LIB;
483: }
484:
485: /**
486: * returns directory of Together version
487: */
488: public String togetherVersion() {
489: return tgVersion;
490: }
491:
492: /**
493: * returns list of all supported together version
494: */
495: public String[] supportedTgVersion() {
496: return supportedTgVersion;
497: }
498:
499: /**
500: * returns list of all supported os
501: */
502: public String[] supportedOS() {
503: return supportedOS;
504: }
505:
506: /**
507: * returns installation os
508: */
509: public String os() {
510: return os;
511: }
512:
513: /**
514: * returns subdirectory where to put the (shell) scripts
515: */
516: public String binaryPath() {
517: return keyHome() + File.separatorChar + binaryPath;
518: }
519:
520: /**
521: * returns subdirectory where to put the patterns
522: */
523: public String keypatternsPath() {
524: return keyHome() + File.separatorChar + keypatternsPath;
525: }
526:
527: /**
528: * returns directory where to put the keyscripts
529: */
530: public String keyscriptsPath() {
531: return keyHome() + File.separatorChar + keyscriptsPath;
532: }
533:
534: /**
535: * returns directory where to put the config files
536: */
537: public String configPath() {
538: return keyHome() + File.separatorChar + configPath;
539: }
540:
541: /**
542: * returns directory where to put the system
543: * (jar file)
544: */
545: public String systemPath() {
546: return keyHome() + File.separatorChar + systemPath;
547: }
548:
549: /**
550: * returns directory where to put the system
551: * libraries ( per default )
552: */
553: public String keyextjarsPath() {
554: return keyHome() + File.separatorChar + keyextjarsPath;
555: }
556:
557: /**
558: * returns directory where to find key.jar
559: */
560: public String keyJarPath() {
561: return keyJarPath;
562: }
563:
564: /**
565: * returns file where to find key.jar
566: */
567: public String keyJarFile() {
568: return keyJarPath() + File.separatorChar + "key.jar";
569: }
570:
571: // some setters
572:
573: /**
574: * sets os; has to be one of supportedOS
575: */
576: public void os(String os) {
577: this .os = os;
578: }
579:
580: /**
581: * sets directory of JAVA_HOME
582: */
583: public void javaHome(String dir) {
584: JAVA_HOME = trail(dir);
585: }
586:
587: /**
588: * sets version of together
589: */
590: public void togetherVersion(String vers) {
591: tgVersion = vers;
592: }
593:
594: /**
595: * remove trailing file separatorchars
596: */
597: private String trail(String dir) {
598: String result = dir;
599: while (result.length() > 0
600: && result.charAt(result.length() - 1) == File.separatorChar) {
601: result = result.substring(0, result.length() - 1);
602: }
603:
604: return result;
605: }
606:
607: /**
608: * sets directory of TOGETHER_HOME
609: */
610: public void togetherHome(String dir) {
611: TOGETHER_HOME = trail(dir);
612: }
613:
614: /**
615: * sets directory of KEY_HOME
616: */
617: public void keyHome(String dir) {
618: KEY_HOME = trail(dir);
619: }
620:
621: /**
622: * sets directory of KEY_LIB
623: */
624: public void keyLib(String dir) {
625: KEY_LIB = trail(dir);
626: }
627:
628: /**
629: * sets directory where to find key.jar
630: */
631: public void keyJarPath(String dir) {
632: keyJarPath = trail(dir);
633: }
634:
635: /**
636: * entry method
637: */
638: public abstract void start();
639:
640: /*
641: Vorgehen:
642: 1. Begruessung
643: 2. Verzeichnis, in das KeY installiert werden soll angeben lassen
644: 3. Verzeichnis, in dem die KeY-Bibliotheken gesucht werden sollen
645: angeben lassen
646: 4. existiert das Verzeichnis nicht, anlegen und den
647: Benutzer auffordern die Bibliotheken dort hinein zu
648: kopieren (mgl. das zu ueberspringen
649: nur mit ausdruecklichem "I will do it later").
650: 5. Dateien kopieren
651: 6. Fertig.
652: */
653:
654: }
|