001: /* Copyright (c) 1995-2000, The Hypersonic SQL Group.
002: * All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * Redistributions of source code must retain the above copyright notice, this
008: * list of conditions and the following disclaimer.
009: *
010: * Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * Neither the name of the Hypersonic SQL Group nor the names of its
015: * contributors may be used to endorse or promote products derived from this
016: * software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE HYPERSONIC SQL GROUP,
022: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
026: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: *
030: * This software consists of voluntary contributions made by many individuals
031: * on behalf of the Hypersonic SQL Group.
032: *
033: *
034: * For work added by the HSQL Development Group:
035: *
036: * Copyright (c) 2001-2005, The HSQL Development Group
037: * All rights reserved.
038: *
039: * Redistribution and use in source and binary forms, with or without
040: * modification, are permitted provided that the following conditions are met:
041: *
042: * Redistributions of source code must retain the above copyright notice, this
043: * list of conditions and the following disclaimer.
044: *
045: * Redistributions in binary form must reproduce the above copyright notice,
046: * this list of conditions and the following disclaimer in the documentation
047: * and/or other materials provided with the distribution.
048: *
049: * Neither the name of the HSQL Development Group nor the names of its
050: * contributors may be used to endorse or promote products derived from this
051: * software without specific prior written permission.
052: *
053: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
054: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
055: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
056: * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
057: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
058: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
059: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
060: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
061: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
062: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
063: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
064: */
065:
066: package org.hsqldb.util;
067:
068: import java.io.File;
069: import java.io.FileReader;
070: import java.io.FileWriter;
071: import java.io.IOException;
072: import java.io.LineNumberReader;
073: import java.util.Vector;
074:
075: // fredt@users 20020315 - patch 1.7.0 - minor fixes
076: // changed line separator to System based value
077: // moved the Profile class to org.hsqldb.test package
078: // fredt@users 20021020 - patch 1.7.1 - formatting fix
079: // avoid moving blank lines which would be interpreted as code change by CVS
080: // fredt@users 20021118 - patch 1.7.2 - no-change, no-save fix
081: // if the file contents do not change, do not save a new version of file
082: // fredt@users 20040322 - removed unused profiling code
083:
084: /**
085: * Modifies the source code to support different JDK or profile settings. <p>
086: * <pre>
087: * Usage: java CodeSwitcher [paths] [labels] [+][-]
088: * If no labels are specified then all used
089: * labels in the source code are shown.
090: * Use +MODE to switch on the things labeld MODE
091: * Use -MODE to switch off the things labeld MODE
092: * Path: Any number of path or files may be
093: * specified. Use . for the current directory
094: * (including sub-directories).
095: * Example: java CodeSwitcher +JAVA2 .
096: * This example switches on code labeled JAVA2
097: * in all *.java files in the current directory
098: * and all subdirectories.
099: * java CodeSwitcher + .
100: * Adds test code to the code.
101: * java CodeSwitcher - .
102: * Removes test code from the code
103: * </pre>
104: *
105: * @author Thomas Mueller (Hypersonic SQL Group)
106: * @version 1.7.0
107: * @since Hypersonic SQL
108: */
109: public class CodeSwitcher {
110:
111: private static final String ls = System.getProperty(
112: "line.separator", "\n");
113: private Vector vList;
114: private Vector vSwitchOn;
115: private Vector vSwitchOff;
116: private Vector vSwitches;
117: private static final int MAX_LINELENGTH = 82;
118:
119: /**
120: * Method declaration
121: *
122: *
123: * @param a
124: */
125: public static void main(String[] a) {
126:
127: CodeSwitcher s = new CodeSwitcher();
128:
129: if (a.length == 0) {
130: showUsage();
131:
132: return;
133: }
134:
135: boolean path = false;
136:
137: for (int i = 0; i < a.length; i++) {
138: String p = a[i];
139:
140: if (p.startsWith("+")) {
141: s.vSwitchOn.addElement(p.substring(1));
142: } else if (p.startsWith("-")) {
143: s.vSwitchOff.addElement(p.substring(1));
144: } else {
145: s.addDir(p);
146:
147: path = true;
148: }
149: }
150:
151: if (!path) {
152: printError("no path specified");
153: showUsage();
154: }
155:
156: s.process();
157:
158: if (s.vSwitchOff.size() == 0 && s.vSwitchOn.size() == 0) {
159: s.printSwitches();
160: }
161: }
162:
163: /**
164: * Method declaration
165: *
166: */
167: static void showUsage() {
168:
169: System.out
170: .print("Usage: java CodeSwitcher [paths] [labels] [+][-]\n"
171: + "If no labels are specified then all used\n"
172: + "labels in the source code are shown.\n"
173: + "Use +MODE to switch on the things labeld MODE\n"
174: + "Use -MODE to switch off the things labeld MODE\n"
175: + "Path: Any number of path or files may be\n"
176: + "specified. Use . for the current directory\n"
177: + "(including sub-directories).\n"
178: + "Example: java CodeSwitcher +JAVA2 .\n"
179: + "This example switches on code labeled JAVA2\n"
180: + "in all *.java files in the current directory\n"
181: + "and all subdirectories.\n");
182: }
183:
184: /**
185: * Constructor declaration
186: *
187: */
188: CodeSwitcher() {
189:
190: vList = new Vector();
191: vSwitchOn = new Vector();
192: vSwitchOff = new Vector();
193: vSwitches = new Vector();
194: }
195:
196: /**
197: * Method declaration
198: *
199: */
200: void process() {
201:
202: int len = vList.size();
203:
204: for (int i = 0; i < len; i++) {
205: System.out.print(".");
206:
207: String file = (String) vList.elementAt(i);
208:
209: if (!processFile(file)) {
210: System.out.println("in file " + file + " !");
211: }
212: }
213:
214: System.out.println("");
215: }
216:
217: /**
218: * Method declaration
219: *
220: */
221: void printSwitches() {
222:
223: System.out.println("Used labels:");
224:
225: for (int i = 0; i < vSwitches.size(); i++) {
226: System.out.println((String) (vSwitches.elementAt(i)));
227: }
228: }
229:
230: /**
231: * Method declaration
232: *
233: *
234: * @param path
235: */
236: void addDir(String path) {
237:
238: File f = new File(path);
239:
240: if (f.isFile() && path.endsWith(".java")) {
241: vList.addElement(path);
242: } else if (f.isDirectory()) {
243: String[] list = f.list();
244:
245: for (int i = 0; i < list.length; i++) {
246: addDir(path + File.separatorChar + list[i]);
247: }
248: }
249: }
250:
251: /**
252: * Method declaration
253: *
254: *
255: * @param name
256: *
257: * @return
258: */
259: boolean processFile(String name) {
260:
261: File f = new File(name);
262: File fnew = new File(name + ".new");
263: int state = 0; // 0=normal 1=inside_if 2=inside_else
264: boolean switchoff = false;
265: boolean working = false;
266:
267: try {
268: Vector v = getFileLines(f);
269: Vector v1 = new Vector(v.size());
270:
271: for (int i = 0; i < v.size(); i++) {
272: v1.addElement(v.elementAt(i));
273: }
274:
275: for (int i = 0; i < v.size(); i++) {
276: String line = (String) v.elementAt(i);
277:
278: if (line == null) {
279: break;
280: }
281:
282: if (working) {
283: if (line.equals("/*") || line.equals("*/")) {
284: v.removeElementAt(i--);
285:
286: continue;
287: }
288: }
289:
290: if (line.startsWith("//#")) {
291: if (line.startsWith("//#ifdef ")) {
292: if (state != 0) {
293: printError("'#ifdef' not allowed inside '#ifdef'");
294:
295: return false;
296: }
297:
298: state = 1;
299:
300: String s = line.substring(9);
301:
302: if (vSwitchOn.indexOf(s) != -1) {
303: working = true;
304: switchoff = false;
305: } else if (vSwitchOff.indexOf(s) != -1) {
306: working = true;
307:
308: v.insertElementAt("/*", ++i);
309:
310: switchoff = true;
311: }
312:
313: if (vSwitches.indexOf(s) == -1) {
314: vSwitches.addElement(s);
315: }
316: } else if (line.startsWith("//#else")) {
317: if (state != 1) {
318: printError("'#else' without '#ifdef'");
319:
320: return false;
321: }
322:
323: state = 2;
324:
325: if (!working) {
326: } else if (switchoff) {
327: if (v.elementAt(i - 1).equals("")) {
328: v.insertElementAt("*/", i - 1);
329:
330: i++;
331: } else {
332: v.insertElementAt("*/", i++);
333: }
334:
335: switchoff = false;
336: } else {
337: v.insertElementAt("/*", ++i);
338:
339: switchoff = true;
340: }
341: } else if (line.startsWith("//#endif")) {
342: if (state == 0) {
343: printError("'#endif' without '#ifdef'");
344:
345: return false;
346: }
347:
348: state = 0;
349:
350: if (working && switchoff) {
351: if (v.elementAt(i - 1).equals("")) {
352: v.insertElementAt("*/", i - 1);
353:
354: i++;
355: } else {
356: v.insertElementAt("*/", i++);
357: }
358: }
359:
360: working = false;
361: } else {
362: }
363: }
364: }
365:
366: if (state != 0) {
367: printError("'#endif' missing");
368:
369: return false;
370: }
371:
372: boolean filechanged = false;
373:
374: for (int i = 0; i < v.size(); i++) {
375: if (!v1.elementAt(i).equals(v.elementAt(i))) {
376: filechanged = true;
377:
378: break;
379: }
380: }
381:
382: if (!filechanged) {
383: return true;
384: }
385:
386: writeFileLines(v, fnew);
387:
388: File fbak = new File(name + ".bak");
389:
390: fbak.delete();
391: f.renameTo(fbak);
392:
393: File fcopy = new File(name);
394:
395: fnew.renameTo(fcopy);
396: fbak.delete();
397:
398: return true;
399: } catch (Exception e) {
400: printError(e.toString());
401:
402: return false;
403: }
404: }
405:
406: static Vector getFileLines(File f) throws IOException {
407:
408: LineNumberReader read = new LineNumberReader(new FileReader(f));
409: Vector v = new Vector();
410:
411: for (;;) {
412: String line = read.readLine();
413:
414: if (line == null) {
415: break;
416: }
417:
418: v.addElement(line);
419: }
420:
421: read.close();
422:
423: return v;
424: }
425:
426: static void writeFileLines(Vector v, File f) throws IOException {
427:
428: FileWriter write = new FileWriter(f);
429:
430: for (int i = 0; i < v.size(); i++) {
431: write.write((String) v.elementAt(i));
432: write.write(ls);
433: }
434:
435: write.flush();
436: write.close();
437: }
438:
439: /**
440: * Method declaration
441: *
442: *
443: * @param error
444: */
445: static void printError(String error) {
446: System.out.println("");
447: System.out.println("ERROR: " + error);
448: }
449: }
|