0001: /*
0002: * $Id: Util.java,v 1.8 2002/07/15 02:15:03 skavish Exp $
0003: *
0004: * ===========================================================================
0005: *
0006: * The JGenerator Software License, Version 1.0
0007: *
0008: * Copyright (c) 2000 Dmitry Skavish (skavish@usa.net). All rights reserved.
0009: *
0010: * Redistribution and use in source and binary forms, with or without
0011: * modification, are permitted provided that the following conditions are met:
0012: *
0013: * 1. Redistributions of source code must retain the above copyright
0014: * notice, this list of conditions and the following disclaimer.
0015: *
0016: * 2. Redistributions in binary form must reproduce the above copyright
0017: * notice, this list of conditions and the following disclaimer in
0018: * the documentation and/or other materials provided with the
0019: * distribution.
0020: *
0021: * 3. The end-user documentation included with the redistribution, if
0022: * any, must include the following acknowlegement:
0023: * "This product includes software developed by Dmitry Skavish
0024: * (skavish@usa.net, http://www.flashgap.com/)."
0025: * Alternately, this acknowlegement may appear in the software itself,
0026: * if and wherever such third-party acknowlegements normally appear.
0027: *
0028: * 4. The name "The JGenerator" must not be used to endorse or promote
0029: * products derived from this software without prior written permission.
0030: * For written permission, please contact skavish@usa.net.
0031: *
0032: * 5. Products derived from this software may not be called "The JGenerator"
0033: * nor may "The JGenerator" appear in their names without prior written
0034: * permission of Dmitry Skavish.
0035: *
0036: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0037: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0038: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0039: * DISCLAIMED. IN NO EVENT SHALL DMITRY SKAVISH OR THE OTHER
0040: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0041: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0042: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0043: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0044: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0045: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0046: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0047: * SUCH DAMAGE.
0048: *
0049: */
0050:
0051: package org.openlaszlo.iv.flash.util;
0052:
0053: import org.openlaszlo.iv.flash.api.*;
0054:
0055: import org.openlaszlo.iv.flash.cache.*;
0056: import org.openlaszlo.iv.flash.url.*;
0057: import org.openlaszlo.iv.flash.context.*;
0058:
0059: import java.awt.geom.Rectangle2D;
0060: import java.awt.geom.AffineTransform;
0061: import java.io.*;
0062: import java.net.*;
0063: import java.util.*;
0064: import java.lang.reflect.*;
0065:
0066: /**
0067: * Utility class.
0068: *
0069: * @author Dmitry Skavish
0070: */
0071: public class Util {
0072:
0073: public static String genVersion = "2.0";
0074:
0075: public static double javaVersion = 1.2;
0076: public static char fileSeparator = '/';
0077: public static char pathSeparator = ':';
0078: public static String lineSeparator = "\n";
0079:
0080: private static String installDir;
0081:
0082: /**
0083: * Initialize JGenerator
0084: * <P>
0085: * Usually you need to call this method from standalone applications only
0086: */
0087: public static void init() {
0088:
0089: // try to find jgenerator install directory
0090: String installDir = System
0091: .getProperty("org.openlaszlo.iv.flash.installDir");
0092:
0093: if (installDir == null)
0094: installDir = System.getProperty("iv.flash.installDir");
0095:
0096: // try to figure out install dir from classloader
0097: if (installDir == null) {
0098: String resource = "/"
0099: + Util.class.getName().replace('.', '/') + ".class";
0100: URL classFileURL = getResource(resource);
0101: String path = classFileURL.getPath();
0102: if (path.startsWith("file:")) {
0103: path = path.substring(5);
0104: int idx = path.lastIndexOf("/lib/");
0105: if (idx != -1) {
0106: installDir = path.substring(0, idx);
0107: }
0108: } else {
0109: int idx = path.lastIndexOf("/classes/");
0110: if (idx != -1) {
0111: installDir = path.substring(0, idx);
0112: }
0113: }
0114: }
0115:
0116: if (installDir == null)
0117: installDir = "";
0118:
0119: init(installDir);
0120: }
0121:
0122: /**
0123: * Initialize JGenerator.
0124: * <P>
0125: * Sets installation directory and reads and caches some
0126: * basic properties and iv.properties file
0127: *
0128: * @param installDir jgenerator installation directory
0129: * @param propFileName iv.properties file name
0130: */
0131: public static void init(String installDir, String propFileName) {
0132: Util.installDir = translatePath(installDir);
0133:
0134: PropertyManager.init(propFileName);
0135:
0136: try {
0137: String jVersion = System.getProperty("java.version")
0138: .substring(0, 3);
0139: javaVersion = toDouble(jVersion, 1.2);
0140: fileSeparator = System.getProperty("file.separator", "/")
0141: .charAt(0);
0142: pathSeparator = System.getProperty("path.separator", ":")
0143: .charAt(0);
0144: lineSeparator = System.getProperty("line.separator", "\n");
0145: } catch (Throwable e) {
0146: Log.error(Resource.get(Resource.CANTLOADSYSPROPS));
0147: }
0148: }
0149:
0150: /**
0151: * Initialize JGenerator.
0152: * <P>
0153: * Sets installation directory and reads and caches some
0154: * basic properties and iv.properties file
0155: *
0156: * @param installDir jgenerator installation directory
0157: */
0158: public static void init(String installDir) {
0159: init(installDir, null);
0160: }
0161:
0162: /**
0163: * Gets resource's URL
0164: *
0165: * @param resource resource name
0166: * @return resource URL
0167: */
0168: public static URL getResource(String resource) {
0169: ClassLoader classLoader = null;
0170: URL url = null;
0171:
0172: try {
0173: classLoader = Thread.currentThread()
0174: .getContextClassLoader();
0175: if (classLoader != null) {
0176: url = classLoader.getResource(resource);
0177: if (url != null) {
0178: return url;
0179: }
0180: }
0181:
0182: // We could not find resource. Ler us now try with the
0183: // classloader that loaded this class.
0184: classLoader = Util.class.getClassLoader();
0185:
0186: url = classLoader.getResource(resource);
0187: if (url != null) {
0188: return url;
0189: }
0190: } catch (Throwable t) {
0191: }
0192:
0193: // get the resource from the class path
0194: return ClassLoader.getSystemResource(resource);
0195: }
0196:
0197: /**
0198: * Returns true if the specified string is "default" in some language
0199: *
0200: * @param s string to be tested for "default"
0201: * @return true if the specified string is "default"
0202: */
0203: public static boolean isDefault(String s) {
0204: return s.equalsIgnoreCase("default")
0205: || s.equalsIgnoreCase("\u30c7\u30d5\u30a9\u30eb\u30c8")
0206: || s.equalsIgnoreCase("Standard")
0207: || s.equalsIgnoreCase("D\u00e9faut")
0208: || s.equalsIgnoreCase("Padr\u00e3o")
0209: || s.equalsIgnoreCase("Predeterminado")
0210: || s.equalsIgnoreCase("Predefinita");
0211: }
0212:
0213: /**
0214: * Converts specified string to int.
0215: *
0216: * @param v string to be converted
0217: * @param def default value to be used if there are some problems during conversion
0218: * @return int value
0219: */
0220: public static int toInt(String v, int def) {
0221: if (v == null)
0222: return def;
0223: try {
0224: return Integer.valueOf(v).intValue();
0225: } catch (NumberFormatException e) {
0226: return def;
0227: }
0228: }
0229:
0230: /**
0231: * Converts specified string to long.
0232: *
0233: * @param v string to be converted
0234: * @param def default value to be used if there are some problems during conversion
0235: * @return long value
0236: */
0237: public static long toLong(String v, long def) {
0238: if (v == null)
0239: return def;
0240: try {
0241: return Long.valueOf(v).longValue();
0242: } catch (NumberFormatException e) {
0243: return def;
0244: }
0245: }
0246:
0247: /**
0248: * Converts specified string to double.
0249: *
0250: * @param v string to be converted
0251: * @param def default value to be used if there are some problems during conversion
0252: * @return double value
0253: */
0254: public static double toDouble(String v, double def) {
0255: if (v == null)
0256: return def;
0257: try {
0258: return Double.valueOf(v).doubleValue();
0259: } catch (NumberFormatException e) {
0260: return def;
0261: }
0262: }
0263:
0264: /**
0265: * Converts specified string to boolean.
0266: *
0267: * @param v string to be converted
0268: * @param def default value to be used if there are some problems during conversion
0269: * @return boolean value
0270: */
0271: public static boolean toBool(String v, boolean def) {
0272: if (v == null)
0273: return def;
0274: return v.equalsIgnoreCase("TRUE") || v.equalsIgnoreCase("YES")
0275: || v.equalsIgnoreCase("1") || v.equalsIgnoreCase("ON");
0276: }
0277:
0278: /**
0279: * Converts specified string to color.
0280: *
0281: * @param v string to be converted
0282: * @param def default value to be used if there are some problems during conversion
0283: * @return color
0284: */
0285: public static AlphaColor toColor(String v, AlphaColor def) {
0286: if (v == null || v.length() == 0)
0287: return def;
0288: if (v.charAt(0) == '#') {
0289: try {
0290: long rgba = Long.parseLong(v.substring(1), 16);
0291: if (v.length() <= 7)
0292: rgba |= 0xff000000L; // + alpha
0293: //System.out.println( v+"->"+Util.d2h((int)rgba) );
0294: return new AlphaColor((int) rgba);
0295: } catch (NumberFormatException e) {
0296: return def;
0297: }
0298: } else {
0299: AlphaColor c = null;
0300: try {
0301: int value = (int) Double.parseDouble(v);
0302: c = new AlphaColor(value);
0303: c.setAlpha(0xFF);
0304: } catch (NumberFormatException ex) {
0305: c = AlphaColor.getColor(v);
0306: }
0307: if (c == null)
0308: return def;
0309: return c;
0310: }
0311: }
0312:
0313: /**
0314: * Processes escapes in the specified string.
0315: * <P>
0316: * Escapes to be processed:<br>
0317: * <UL>
0318: * <LI>\n - newline
0319: * <LI>\r - carriage return
0320: * <LI>\0x... - hex value
0321: * <LI>\0... - octal value
0322: * </UL>
0323: *
0324: * @param line string to be processed
0325: * @return escape-processed string
0326: */
0327: public static String processEscapes(String line) {
0328:
0329: if (line == null)
0330: return null;
0331: int cur = line.indexOf('\\');
0332: if (cur < 0)
0333: return line;
0334:
0335: int length = line.length();
0336: StringBuffer sb = new StringBuffer(line);
0337: sb.setLength(cur++);
0338:
0339: for (; cur < length;) {
0340: char ch = line.charAt(cur);
0341: switch (ch) {
0342: case 'n':
0343: sb.append('\n');
0344: break;
0345: case 'r':
0346: sb.append('\r');
0347: break;
0348: case '0':
0349: cur++;
0350: if (cur >= length)
0351: sb.append(0);
0352: else {
0353: if (line.charAt(cur) == 'x'
0354: || line.charAt(cur) == 'X') {
0355: // hex
0356: int code = 0;
0357: ;
0358: for (int l = ++cur; cur < length && cur - l < 4; cur++) {
0359: char c = line.charAt(cur);
0360: if (c >= '0' && c <= '9') {
0361: code = (code << 4) + (c - '0');
0362: } else if (c >= 'a' && c <= 'f') {
0363: code = (code << 4) + (c - 'a' + 10);
0364: } else if (c >= 'A' && c <= 'F') {
0365: code = (code << 4) + (c - 'A' + 10);
0366: } else {
0367: break;
0368: }
0369: }
0370: cur--;
0371: sb.append((char) code);
0372: } else {
0373: // oct
0374: int code = 0;
0375: ;
0376: for (int l = cur; cur < length && cur - l < 6; cur++) {
0377: char c = line.charAt(cur);
0378: if (c >= '0' && c <= '7') {
0379: code = (code << 3) + (c - '0');
0380: } else {
0381: break;
0382: }
0383: }
0384: cur--;
0385: sb.append((char) code);
0386: }
0387: }
0388: break;
0389: default:
0390: sb.append(ch);
0391: break;
0392: }
0393: cur++;
0394: int end = line.indexOf('\\', cur);
0395: if (end < 0) {
0396: sb.append(line.substring(cur, length));
0397: break;
0398: }
0399: int l = end - cur;
0400: if (l == 0) {
0401: cur++;
0402: } else {
0403: sb.append(line.substring(cur, end));
0404: cur = end + 1;
0405: }
0406: }
0407:
0408: return new String(sb);
0409: }
0410:
0411: /**
0412: * Converts byte to unsigned byte.
0413: */
0414: public static int getUByte(byte a) {
0415: return a & 0xff;
0416: }
0417:
0418: /**
0419: * Creates signed word from two bytes.
0420: *
0421: * @param a low byte
0422: * @param b high byte
0423: * @return signed word
0424: */
0425: public static int getWord(byte a, byte b) {
0426: return (a & 0xff) | (b << 8);
0427: }
0428:
0429: /**
0430: * Creates unsigned word from two bytes.
0431: *
0432: * @param a low byte
0433: * @param b high byte
0434: * @return unsigned word
0435: */
0436: public static int getUWord(byte a, byte b) {
0437: return (a & 0xff) | ((b & 0xff) << 8);
0438: }
0439:
0440: /**
0441: * Creates signed dword from four bytes.
0442: *
0443: * @param a 0 byte (low)
0444: * @param b 1 byte
0445: * @param c 2 byte
0446: * @param d 3 byte (high)
0447: * @return signed dword
0448: */
0449: public static int getDWord(byte a, byte b, byte c, byte d) {
0450: return (a & 0xff) | ((b & 0xff) << 8) | ((c & 0xff) << 16)
0451: | (d << 24);
0452: }
0453:
0454: /**
0455: * Creates unsigned dword from four bytes.
0456: *
0457: * @param a 0 byte (low)
0458: * @param b 1 byte
0459: * @param c 2 byte
0460: * @param d 3 byte (high)
0461: * @return unsigned dword
0462: */
0463: public static int getUDWord(byte a, byte b, byte c, byte d) {
0464: return (a & 0xff) | ((b & 0xff) << 8) | ((c & 0xff) << 16)
0465: | ((d & 0xff) << 24);
0466: }
0467:
0468: /**
0469: * Returns maximum element of array.
0470: *
0471: * @param arr array to be searched for maximum
0472: * @param size size of the array
0473: * @return maximim element of the array
0474: */
0475: public static int getMax(int[] arr, int size) {
0476: int max = Integer.MIN_VALUE;
0477: for (int i = 0; i < size; i++) {
0478: if (arr[i] > max)
0479: max = arr[i];
0480: }
0481: return max;
0482: }
0483:
0484: /**
0485: * Returns maximum element of array.
0486: *
0487: * @param arr array to be searched for maximum
0488: * @return maximim element of the array
0489: */
0490: public static int getMax(int[] arr) {
0491: return getMax(arr, arr.length);
0492: }
0493:
0494: /**
0495: * Returns maximum of absolute values of two numbers.
0496: *
0497: * @param a specified number
0498: * @param b specified number
0499: * @return maximum of two numbers
0500: */
0501: public static int getMax(int a, int b) {
0502: if (a < 0)
0503: a = -a;
0504: if (b < 0)
0505: b = -b;
0506: if (a >= b)
0507: return a;
0508: return b;
0509: }
0510:
0511: /**
0512: * Returns maximum of absolute values of three numbers.
0513: *
0514: * @param a specified number
0515: * @param b specified number
0516: * @param c specified number
0517: * @return maximum of three numbers
0518: */
0519: public static int getMax(int a, int b, int c) {
0520: if (a < 0)
0521: a = -a;
0522: if (b < 0)
0523: b = -b;
0524: if (c < 0)
0525: c = -c;
0526: if (a >= b && a >= c)
0527: return a;
0528: if (b >= a && b >= c)
0529: return b;
0530: return c;
0531: }
0532:
0533: /**
0534: * Returns maximum of absolute values of four numbers.
0535: *
0536: * @param a specified number
0537: * @param b specified number
0538: * @param c specified number
0539: * @param d specified number
0540: * @return maximum of four specified numbers
0541: */
0542: public static int getMax(int a, int b, int c, int d) {
0543: if (a < 0)
0544: a = -a;
0545: if (b < 0)
0546: b = -b;
0547: if (c < 0)
0548: c = -c;
0549: if (d < 0)
0550: d = -d;
0551:
0552: if (a > b) {
0553: if (a > c) {
0554: if (a > d) {
0555: return a;
0556: } else {
0557: return d;
0558: }
0559: } else {
0560: if (c > d) {
0561: return c;
0562: } else {
0563: return d;
0564: }
0565: }
0566: } else {
0567: if (b > c) {
0568: if (b > d) {
0569: return b;
0570: } else {
0571: return d;
0572: }
0573: } else {
0574: if (c > d) {
0575: return c;
0576: } else {
0577: return d;
0578: }
0579: }
0580: }
0581: }
0582:
0583: /**
0584: * Returns number of significant bits for signed integer.
0585: *
0586: * @param v signed integer
0587: * @return number of significant bits for signed integer
0588: */
0589: public static int getMinBitsS(int v) {
0590: if (v < 0)
0591: v = -v;
0592: return getMinBitsU(v) + 1;
0593: }
0594:
0595: private static final int[] BITS_LENGTH = {
0596: // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F
0597: 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 };
0598:
0599: /**
0600: * Returns number of significant bits for unsigned integer.
0601: *
0602: * @param v unsigned integer
0603: * @return number of significant bits for unsigned integer
0604: */
0605: public static int getMinBitsU(int v) {
0606: int n = 0;
0607: if ((v & ~0xffff) != 0) {
0608: n += 16;
0609: v >>>= 16;
0610: }
0611: if ((v & ~0x00ff) != 0) {
0612: n += 8;
0613: v >>>= 8;
0614: }
0615: if ((v & ~0x000f) != 0) {
0616: n += 4;
0617: v >>>= 4;
0618: }
0619: // for( ; v != 0; n++ ) v >>>= 1;
0620: n += BITS_LENGTH[v];
0621: return n;
0622: }
0623:
0624: /* --------------------------------------------------------------------------
0625: * Double, float, fixed, twips conversion helpers
0626: * -------------------------------------------------------------------------- */
0627:
0628: private static final double FRACTION_DBL = (double) 0x10000;
0629: private static final float FRACTION_FLT = (float) 0x10000;
0630:
0631: /**
0632: * Converts fixed Flash value into double
0633: *
0634: * @param value fixed Flash value
0635: * @return double value
0636: */
0637: public static double fixed2double(int value) {
0638: return (double) value / FRACTION_DBL;
0639: }
0640:
0641: /**
0642: * Converts fixed Flash value into float
0643: *
0644: * @param value fixed Flash value
0645: * @return float value
0646: */
0647: public static float fixed2float(int value) {
0648: return (float) value / FRACTION_FLT;
0649: }
0650:
0651: /**
0652: * Converts double to fixed value
0653: *
0654: * @param value double value
0655: * @return fixed value
0656: */
0657: public static int double2fixed(double value) {
0658: return (int) (value * FRACTION_DBL);
0659: }
0660:
0661: /**
0662: * Converts float to fixed value
0663: *
0664: * @param value float value
0665: * @return fixed value
0666: */
0667: public static int float2fixed(float value) {
0668: return (int) (value * FRACTION_FLT);
0669: }
0670:
0671: /**
0672: * Converts twips to double
0673: *
0674: * @param value twips value
0675: * @return double value
0676: */
0677: public static double twips2double(int value) {
0678: return (double) value / 20.0;
0679: }
0680:
0681: /**
0682: * Converts twips to float
0683: *
0684: * @param value twips value
0685: * @return float value
0686: */
0687: public static float twips2float(int value) {
0688: return (float) value / 20.0f;
0689: }
0690:
0691: /**
0692: * Converts double to twips
0693: *
0694: * @param value double value
0695: * @return twips value
0696: */
0697: public static int double2twips(double value) {
0698: return (int) (value * 20.0);
0699: }
0700:
0701: /**
0702: * Converts float to twips
0703: *
0704: * @param value float value
0705: * @return twips value
0706: */
0707: public static int float2twips(float value) {
0708: return (int) (value * 20.0f);
0709: }
0710:
0711: private static final char[] digits = { '0', '1', '2', '3', '4',
0712: '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
0713:
0714: /**
0715: * Returns hexadecimal representation of specified byte
0716: *
0717: * @param v specified byte
0718: * @return hex repsentation of specified byte
0719: */
0720: public static String b2h(int v) {
0721: char[] r = new char[2];
0722: r[0] = digits[(v & 0xf0) >> 4];
0723: r[1] = digits[(v & 0x0f)];
0724: return new String(r);
0725: }
0726:
0727: /**
0728: * Returns hexadecimal representation of specified word
0729: *
0730: * @param v specified word
0731: * @return hex repsentation of specified word
0732: */
0733: public static String w2h(int v) {
0734: char[] r = new char[4];
0735: r[0] = digits[(v & 0xf000) >> 12];
0736: r[1] = digits[(v & 0x0f00) >> 8];
0737: r[2] = digits[(v & 0x00f0) >> 4];
0738: r[3] = digits[(v & 0x000f)];
0739: return new String(r);
0740: }
0741:
0742: /**
0743: * Returns hexadecimal representation of specified dword
0744: *
0745: * @param v specified dword
0746: * @return hex repsentation of specified dword
0747: */
0748: public static String d2h(int v) {
0749: char[] r = new char[8];
0750: r[0] = digits[(v & 0xf0000000) >>> 28];
0751: r[1] = digits[(v & 0x0f000000) >> 24];
0752: r[2] = digits[(v & 0x00f00000) >> 20];
0753: r[3] = digits[(v & 0x000f0000) >> 16];
0754: r[4] = digits[(v & 0x0000f000) >> 12];
0755: r[5] = digits[(v & 0x00000f00) >> 8];
0756: r[6] = digits[(v & 0x000000f0) >> 4];
0757: r[7] = digits[(v & 0x0000000f)];
0758: return new String(r);
0759: }
0760:
0761: /**
0762: * Returns specified char if it's printable or '.'
0763: *
0764: * @param ch char to be converted to printable char
0765: * @return printable char
0766: */
0767: public static char toPrint(char ch) {
0768: if (Character.isISOControl(ch))
0769: return '.';
0770: return ch;
0771: }
0772:
0773: private static void _dump(byte[] buffer, int pos, int size,
0774: PrintStream out) {
0775: if (size == 0)
0776: return;
0777: for (int i = 0; i < 16; i++) {
0778: if (i >= size) {
0779: out.print(".. ");
0780: } else {
0781: out.print(b2h(buffer[pos + i]) + ' ');
0782: }
0783: }
0784: for (int i = 0; i < 16; i++) {
0785: if (i >= size) {
0786: out.print(" ");
0787: } else {
0788: out.print(toPrint((char) buffer[pos + i]));
0789: }
0790: }
0791: }
0792:
0793: /**
0794: * Prints hex dump of part of byte array to specified stream
0795: *
0796: * @param buffer buffer to be dumped
0797: * @param start offset in the buffer to start the dump from
0798: * @param size size of the dumped area
0799: * @param out stream to print the dump to
0800: */
0801: public static void dump(byte[] buffer, int start, int size,
0802: PrintStream out) {
0803: StringBuffer sb = new StringBuffer();
0804: int pos = 0;
0805: for (int i = 0; i < size / 16; i++) {
0806: _dump(buffer, start + pos, 16, out);
0807: pos += 16;
0808: out.println();
0809: }
0810: _dump(buffer, start + pos, size - pos, out);
0811: out.println();
0812: }
0813:
0814: /**
0815: * Returns whether specified string has generator variable or not.
0816: *
0817: * @param s string to be searched for generator variable
0818: * @return true if the specified string has generator variable
0819: */
0820: public static boolean hasVar(String s) {
0821: return s != null && s.indexOf('{') != -1;
0822: }
0823:
0824: /**
0825: * Returns concatenation of path and filename.
0826: *
0827: * @param path path
0828: * @param name filename
0829: * @return concatenation of specified path and specified filename
0830: */
0831: public static String concatFileNames(String path, String name) {
0832: if (path.length() == 0)
0833: return name;
0834: char ch = path.charAt(path.length() - 1);
0835: if (ch != '\\' && ch != '/')
0836: path += fileSeparator;
0837: if (name.charAt(0) == '/' || name.charAt(0) == '\\')
0838: return path + name.substring(1);
0839: return path + name;
0840: }
0841:
0842: /**
0843: * Returns directory where jgenerator is installed
0844: *
0845: * @return directory where jgenerator is installed
0846: */
0847: public static String getInstallDir() {
0848: if (installDir == null) {
0849: init();
0850: }
0851: return installDir;
0852: }
0853:
0854: /**
0855: * Returns jgenerator file by its name.
0856: * <P>
0857: * If name is relative returns absolute path constructing
0858: * with {@link #installDir} and the specified name
0859: *
0860: * @param name file name
0861: * @return jgenerator absolute file
0862: */
0863: public static File getSysFile(String name) {
0864: name = translatePath(name);
0865: File file = new File(name);
0866: if (file.isAbsolute())
0867: return file;
0868: return new File(installDir, name);
0869: }
0870:
0871: /**
0872: * Translates file separator in the specified string into
0873: * file separator of the system jgenerator is running on.
0874: *
0875: * @param path path to be translated
0876: * @return translated path
0877: */
0878: public static String translatePath(String path) {
0879: if (fileSeparator == '\\') {
0880: path = path.replace('/', '\\');
0881: } else if (fileSeparator == '/') {
0882: path = path.replace('\\', '/');
0883: }
0884: return path;
0885: }
0886:
0887: /**
0888: * Creates URL from specified file.
0889: *
0890: * @param file file to be used to create URL
0891: * @return created URL from File
0892: * @exception MalformedURLException
0893: */
0894: public static URL toURL(File file) throws MalformedURLException {
0895: String path = file.getAbsolutePath();
0896: if (fileSeparator != '/') {
0897: path = path.replace(fileSeparator, '/');
0898: }
0899: if (path.charAt(0) != '/') {
0900: path = '/' + path;
0901: }
0902: if (!path.endsWith("/") && file.isDirectory()) {
0903: path = path + '/';
0904: }
0905: return new URL("file", "", path);
0906: }
0907:
0908: /**
0909: * Reads data from specified url into FlashBuffer.
0910: *
0911: * @param url IVUrl to read from
0912: * @return FlashBuffer with data read
0913: * @exception IOException
0914: */
0915: public static FlashBuffer readUrl(IVUrl url) throws IOException {
0916: FlashBuffer fob = null;
0917: InputStream is = null;
0918: try {
0919: is = url.getInputStream();
0920: fob = new FlashBuffer(is);
0921: } finally {
0922: try {
0923: if (is != null)
0924: is.close();
0925: } catch (Exception e) {
0926: }
0927: }
0928:
0929: return fob;
0930: }
0931:
0932: /**
0933: * Creates new instance of an specified class
0934: *
0935: * @param className specified class name
0936: * @param parmsCls parameters types of constructor
0937: * @param parms parameters of constructor
0938: * @return new instance
0939: * @exception Exception
0940: */
0941: public static Object newInstance(String className,
0942: Class[] parmsCls, Object[] parms) throws Exception {
0943: Class clazz = Class.forName(className);
0944: if (parmsCls == null) {
0945: return clazz.newInstance();
0946: } else {
0947: Constructor constr = clazz.getConstructor(parmsCls);
0948: return constr.newInstance(parms);
0949: }
0950: }
0951:
0952: /**
0953: * Executes specified javascript text in given Context
0954: *
0955: * @param context specified context
0956: * @param js_text javascript text
0957: * @param parms parameters for javascript
0958: * @return result of "printing" in javascript
0959: */
0960: public static String executeJSString(Context context,
0961: String js_text, String[] parms) {
0962: return executeJSHelperMethod("execString", context, js_text,
0963: parms);
0964: }
0965:
0966: /**
0967: * Executes specified javascript file in given Context
0968: *
0969: * @param context specified context
0970: * @param js_text javascript text
0971: * @param parms parameters for javascript
0972: * @return result of "printing" in javascript
0973: */
0974: public static String executeJSFile(Context context,
0975: String fileName, String[] parms) {
0976: return executeJSHelperMethod("execFile", context, fileName,
0977: parms);
0978: }
0979:
0980: private static String executeJSHelperMethod(String method,
0981: Context context, String s, String[] parms) {
0982: FlashBuffer fb = new FlashBuffer(400);
0983: try {
0984: PrintStream out = new PrintStream(fb.getOutputStream());
0985: Class clazz = Class
0986: .forName("org.openlaszlo.iv.flash.js.JSHelper");
0987: Method exec = clazz.getMethod(method, new Class[] {
0988: String.class, String[].class, PrintStream.class,
0989: Context.class });
0990: exec.invoke(null, new Object[] { s, parms, out, context });
0991: out.flush();
0992: return fb.toString();
0993: } catch (Throwable e) {
0994: Log.log(e);
0995: return null;
0996: }
0997: }
0998:
0999: /**
1000: * Parses parameters of url-string begining after the specified index (usually index of '?')
1001: * <p>
1002: * Parameters are pairs: name=value, separated by ampersand
1003: *
1004: * @param s url
1005: * @param idx specified index
1006: * @return hashtable of parameter
1007: * @exception IVException
1008: */
1009: public static Hashtable parseUrlParms(String s, int idx) {
1010: s = s.substring(idx + 1);
1011: Hashtable parms = new Hashtable();
1012: StringTokenizer st = new StringTokenizer(s, "&");
1013: while (st.hasMoreTokens()) {
1014: String token = st.nextToken();
1015: idx = token.indexOf('=');
1016: if (idx == -1) {
1017: parms.put(decodeURLEncoded(token).toLowerCase(), "");
1018: } else {
1019: String name = decodeURLEncoded(token.substring(0, idx))
1020: .toLowerCase();
1021: String value = decodeURLEncoded(token
1022: .substring(idx + 1));
1023: parms.put(name, value);
1024: }
1025: }
1026: return parms;
1027: }
1028:
1029: /**
1030: * Decodes url-encoded string
1031: *
1032: * @param s url-encoded string
1033: * @return decoded string
1034: */
1035: public static String decodeURLEncoded(String s) {
1036: if (s.indexOf('+') < 0 && s.indexOf('%') < 0)
1037: return s;
1038:
1039: StringBuffer sb = new StringBuffer(s.length());
1040: for (int i = 0; i < s.length(); i++) {
1041: char ch = s.charAt(i);
1042: if (ch == '+') {
1043: sb.append(' ');
1044: } else if (ch == '%') {
1045: ch = (char) Integer.parseInt(s.substring(i + 1, i + 3),
1046: 16);
1047: sb.append(ch);
1048: i += 2;
1049: } else {
1050: sb.append(ch);
1051: }
1052: }
1053: return new String(sb);
1054: }
1055:
1056: /**
1057: * Returns Reader of specified IVUrl using encoding either
1058: * from specified IVUrl or specified FlashFile
1059: *
1060: * @param file file
1061: * @param url url
1062: * @return Reader
1063: */
1064: public static LineReader getUrlReader(FlashFile file, IVUrl url)
1065: throws IOException {
1066: String encoding;
1067:
1068: String url_encoding = url.getEncoding();
1069: if (url_encoding != null) {
1070: encoding = url_encoding;
1071: } else {
1072: encoding = file == null ? null : file.getEncoding();
1073: if (encoding == null) {
1074: encoding = PropertyManager.defaultEncoding;
1075: }
1076: }
1077:
1078: return getInputStreamReader(url.getInputStream(), encoding);
1079: }
1080:
1081: /**
1082: * Returns Reader of specified String using encoding from specified FlashFile
1083: *
1084: * @param file file
1085: * @param buf buffer
1086: * @param offset offset in the buffer
1087: * @param length buffer length
1088: * @return reader
1089: * @exception IOException
1090: */
1091: public static LineReader getArrayReader(FlashFile file, byte[] buf,
1092: int offset, int length) throws IOException {
1093:
1094: String encoding = file == null ? null : file.getEncoding();
1095: if (encoding == null) {
1096: encoding = PropertyManager.defaultEncoding;
1097: }
1098:
1099: return getInputStreamReader(new ByteArrayInputStream(buf,
1100: offset, length), encoding);
1101: }
1102:
1103: /**
1104: * Returns BufferedReader of specified InputStream and encoding
1105: *
1106: * @param is input stream
1107: * @param encoding encoding (may be null)
1108: * @return reader
1109: */
1110: public static LineReader getInputStreamReader(InputStream is,
1111: String encoding) throws IOException {
1112: Reader reader = null;
1113: if (encoding != null) {
1114: try {
1115: reader = new InputStreamReader(is, encoding);
1116: } catch (UnsupportedEncodingException e) {
1117: Log.log(e);
1118: // fall through
1119: }
1120: }
1121:
1122: if (reader == null) {
1123: reader = new InputStreamReader(is);
1124: }
1125:
1126: return new BufferedLineReader(new BufferedReader(reader));
1127: }
1128:
1129: /**
1130: * Returns version of JGenerator.
1131: *
1132: * @return version of JGenerator
1133: */
1134: public static String getVersion() {
1135: return genVersion;
1136: }
1137:
1138: }
|