0001: /*
0002:
0003: Derby - Class org.apache.derby.impl.tools.sysinfo.Main
0004:
0005: Licensed to the Apache Software Foundation (ASF) under one or more
0006: contributor license agreements. See the NOTICE file distributed with
0007: this work for additional information regarding copyright ownership.
0008: The ASF licenses this file to you under the Apache License, Version 2.0
0009: (the "License"); you may not use this file except in compliance with
0010: the License. You may obtain a copy of the License at
0011:
0012: http://www.apache.org/licenses/LICENSE-2.0
0013:
0014: Unless required by applicable law or agreed to in writing, software
0015: distributed under the License is distributed on an "AS IS" BASIS,
0016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017: See the License for the specific language governing permissions and
0018: limitations under the License.
0019:
0020: */
0021:
0022: package org.apache.derby.impl.tools.sysinfo;
0023:
0024: import java.security.AccessController;
0025: import java.security.PrivilegedAction;
0026: import java.util.Locale;
0027: import java.io.IOException;
0028: import java.io.UnsupportedEncodingException;
0029: import java.io.InputStream;
0030: import java.util.Properties;
0031: import java.io.BufferedReader;
0032: import java.io.InputStreamReader;
0033: import java.util.Locale;
0034: import java.util.MissingResourceException;
0035: import java.util.ResourceBundle;
0036: import java.util.StringTokenizer;
0037: import java.io.File;
0038: import java.util.zip.ZipFile;
0039: import java.io.IOException;
0040: import java.util.zip.ZipEntry;
0041: import java.io.FileInputStream;
0042: import java.util.Vector;
0043: import java.io.InputStream;
0044: import java.lang.reflect.Method;
0045: import java.net.URL;
0046: import java.net.URLDecoder;
0047: import java.security.ProtectionDomain;
0048: import java.security.CodeSource;
0049: import java.security.AccessController;
0050:
0051: import org.apache.derby.iapi.services.info.PropertyNames;
0052: import org.apache.derby.iapi.services.info.ProductVersionHolder;
0053: import org.apache.derby.iapi.services.info.ProductGenusNames;
0054: import org.apache.derby.iapi.error.StandardException;
0055:
0056: import org.apache.derby.iapi.tools.i18n.*;
0057:
0058: /**
0059: <P>
0060: Sysinfo reports values relevant to the current Derby configuration.
0061:
0062: <P>
0063: Sysinfo looks for properties files in org.apache.derby.info named after
0064: the genus names in org.apache.derby.tools.sysinfo, and gets their location
0065: using getResource. It also searches the classpath and attempts to load
0066: the info properties files from the directory or jar locations on the
0067: classpath, and eliminates any duplicated information. If no files
0068: are found, or some other exception occurs, the
0069: value returned will be that set for the key
0070: SysInfo.failureTag, or be the value "<info unavailable>".
0071:
0072: <P>
0073: This class can be used to print out system information at the
0074: command line by issuing the command:
0075: <PRE>
0076: java org.apache.derby.tools.sysinfo
0077: </PRE>
0078: Alternatively, you can use SysInfo within your program to display
0079: Cloudscape information; a Cloudscape version string is returned by this Java code:
0080: <PRE>
0081: new Main().toString();
0082: </PRE>
0083:
0084: */
0085:
0086: public final class Main {
0087:
0088: /**
0089: Application entry point for SysInfo. This will print out
0090: the Cloudscape product information as well as a snapshot of
0091: the System properties.
0092: */
0093: public static void main(String args[]) {
0094: // adjust the application in accordance with derby.ui.locale and derby.ui.codeset
0095: LocalizedResource.getInstance();
0096:
0097: LocalizedOutput out;
0098:
0099: //using AppStreamReader(extends InputStreamReader) for conversion into specific codeset
0100:
0101: out = LocalizedResource.OutputWriter();
0102:
0103: // because we're in a static method, we need to
0104: // get our own instance variable
0105: parseArgs(args);
0106:
0107: if (cptester == true)
0108: getClasspathInfo(args, out);
0109: else
0110: getMainInfo(out, setPause);
0111:
0112: } // end of main (String args[])
0113:
0114: public static void getMainInfo(java.io.PrintWriter aw, boolean pause) {
0115:
0116: aw.println(javaSep);
0117: reportJavaInfo(aw);
0118: aw.println(jbmsSep);
0119: reportDerby(aw);
0120:
0121: aw.println(sep);
0122:
0123: // Locales info
0124: try {
0125: reportLocales(aw);
0126: } catch (Exception e) {
0127:
0128: aw.println(Main.getTextMessage("SIF01.Q"));
0129: aw.println(Main.getTextMessage("SIF01.B"));
0130: }
0131:
0132: if (pause) {
0133: pause();
0134: }
0135:
0136: } // end of getMainInfo (AppStreamWriter aw, boolean printLicense, boolean pause)
0137:
0138: private static boolean setPause = false;
0139:
0140: private static boolean setLicense = false;
0141:
0142: private static boolean cptester = false;
0143:
0144: private static void parseArgs(String args[]) {
0145:
0146: if (args == null) {
0147:
0148: return;
0149: }
0150:
0151: for (int i = 0; i < args.length; i++) {
0152:
0153: if (args[i].equals("-pause")) {
0154:
0155: setPause = true;
0156: }
0157:
0158: if (args[i].equals("-cp")) {
0159:
0160: cptester = true;
0161: }
0162:
0163: } // end for
0164:
0165: } // end of parseArgs (String args[])
0166:
0167: /**
0168: For the benefit of DOS box users, this method waits for input
0169: before returning
0170: */
0171: private static void pause() {
0172:
0173: try {
0174:
0175: System.out.print(Main.getTextMessage("SIF01.C"));
0176: BufferedReader br = new BufferedReader(
0177: new InputStreamReader(System.in));
0178: br.readLine();
0179: } catch (IOException ioe) {
0180:
0181: //just return
0182: }
0183:
0184: } // end of pause ()
0185:
0186: /**
0187: prints out the jbms info to the specified AppStreamWriter.
0188: @param localAW the AppStreamWriter to use. If null, System.out is
0189: used
0190: */
0191:
0192: private static void reportDerby(java.io.PrintWriter localAW) {
0193:
0194: localAW.println("JRE - JDBC: "
0195: + org.apache.derby.iapi.services.info.JVMInfo
0196: .derbyVMLevel());
0197:
0198: String classpath;
0199:
0200: try {
0201: classpath = System.getProperty("java.class.path");
0202: } catch (SecurityException se) {
0203: localAW.println(Main.getTextMessage("SIF01.U", se
0204: .getMessage()));
0205: classpath = null;
0206: }
0207:
0208: ZipInfoProperties zip[] = Main.getAllInfo(classpath);
0209:
0210: if (zip != null) {
0211:
0212: for (int i = 0; i < zip.length; i++) {
0213:
0214: String this Info = "[" + zip[i].getLocation() + "] "
0215: + zip[i].getVersionBuildInfo();
0216:
0217: localAW.println(this Info);
0218: }
0219: }
0220:
0221: else {
0222:
0223: localAW.println(Main.getTextMessage("SIF01.D"));
0224: }
0225:
0226: } // end of reportDerby
0227:
0228: /**
0229: Writes out the relevant info about the Java environment to
0230: the specified AppStreamWriter.
0231:
0232: @param localAW The AppStreamWriter to write info out to. If this is
0233: null, the info is written to System.out
0234: */
0235:
0236: private static void reportJavaInfo(java.io.PrintWriter localAW) {
0237:
0238: localAW.println(Main.getTextMessage("SIF02.A",
0239: getJavaProperty("java.version")));
0240:
0241: localAW.println(Main.getTextMessage("SIF02.B",
0242: getJavaProperty("java.vendor")));
0243:
0244: localAW.println(Main.getTextMessage("SIF02.C",
0245: getJavaProperty("java.home")));
0246:
0247: localAW.println(Main.getTextMessage("SIF02.D",
0248: getJavaProperty("java.class.path")));
0249:
0250: localAW.println(Main.getTextMessage("SIF02.E",
0251: getJavaProperty("os.name")));
0252:
0253: localAW.println(Main.getTextMessage("SIF02.F",
0254: getJavaProperty("os.arch")));
0255:
0256: localAW.println(Main.getTextMessage("SIF02.G",
0257: getJavaProperty("os.version")));
0258:
0259: localAW.println(Main.getTextMessage("SIF02.H",
0260: getJavaProperty("user.name")));
0261:
0262: localAW.println(Main.getTextMessage("SIF02.I",
0263: getJavaProperty("user.home")));
0264:
0265: localAW.println(Main.getTextMessage("SIF02.J",
0266: getJavaProperty("user.dir")));
0267:
0268: localAW.println("java.specification.name: "
0269: + getJavaProperty("java.specification.name"));
0270: localAW.println("java.specification.version: "
0271: + getJavaProperty("java.specification.version"));
0272:
0273: } // end of reportJavaInfo
0274:
0275: /**
0276: Return Java properties from java.lang.System. Will catch
0277: SecurityExceptions and note them for displaying information.
0278:
0279: @return the Java property value or a string capturing a
0280: security exception.
0281: */
0282:
0283: private static String getJavaProperty(String whichProperty) {
0284:
0285: String property;
0286: String unavailable = Main.getTextMessage("SIF01.H");
0287:
0288: try {
0289:
0290: property = System.getProperty(whichProperty, unavailable);
0291: return property;
0292: } catch (SecurityException se) {
0293:
0294: return Main.getTextMessage("SIF01.I", se);
0295: }
0296:
0297: } // end of getJavaProperty (String whichProperty)
0298:
0299: /**
0300: for use by the main () method
0301: */
0302:
0303: private final static String sep = "------------------------------------------------------";
0304: private final static String javaSep = Main
0305: .getTextMessage("SIF01.L");
0306:
0307: private final static String jbmsSep = Main
0308: .getTextMessage("SIF01.M");
0309:
0310: private final static String licSep = Main.getTextMessage("SIF01.N");
0311:
0312: private final static String locSep = Main.getTextMessage("SIF01.P");
0313:
0314: private final static String curLoc = Main.getTextMessage("SIF01.T");
0315:
0316: /**
0317: The name of the failure tag in the information file.
0318: The failure tag's value provides a default value if
0319: any other properties are missing.
0320: */
0321: private final static String failureTag = Main
0322: .getTextMessage("SIF01.J");
0323:
0324: private static void getClasspathInfo(String args[],
0325: java.io.PrintWriter aw) {
0326:
0327: Main.useMe(args, aw);
0328: }
0329:
0330: /**
0331: Writes out information about the locales with the
0332: product.
0333:
0334: @param localAW the AppStreamWriter to which the info is written. If this
0335: value is null, the info is written to System.out
0336:
0337: */
0338: private static void reportLocales(java.io.PrintWriter localAW) { // throws StandardException {
0339:
0340: boolean cur_loc = true;
0341:
0342: localAW.println(locSep);
0343:
0344: // Read all the possible locales, and test for each one, if it loads.
0345: // If so, then read the properties, and print them out.
0346:
0347: Locale[] supportedLocales = Locale.getAvailableLocales();
0348: String[] stringLocales = new String[supportedLocales.length];
0349: for (int i = 0; i < supportedLocales.length; i++) {
0350: stringLocales[i] = supportedLocales[i].toString();
0351: }
0352: java.util.Arrays.sort(stringLocales);
0353:
0354: Properties p = new Properties();
0355: for (int i = 0; i < stringLocales.length; i++) {
0356:
0357: String localeResource = "/org/apache/derby/info/locale_"
0358: + stringLocales[i] + ".properties";
0359:
0360: final Properties finalp = p;
0361: final String finalLocaleResource = localeResource;
0362:
0363: try {
0364: InputStream is = (InputStream) AccessController
0365: .doPrivileged(new PrivilegedAction() {
0366: public Object run() {
0367: InputStream locis = finalp.getClass()
0368: .getResourceAsStream(
0369: finalLocaleResource);
0370: return locis;
0371: }
0372: });
0373:
0374: if (is == null) {
0375: // localAW.println("resource is null: " + localeResource);
0376: } else {
0377:
0378: try {
0379: p.clear();
0380: p.load(is);
0381: //Displaying Current Locale
0382: if (cur_loc) {
0383: Locale loc = null;
0384: loc = Locale.getDefault();
0385: localAW.println(Main
0386: .getTextMessage("SIF01.T")
0387: + " ["
0388: + loc.getDisplayLanguage()
0389: + "/"
0390: + loc.getDisplayCountry()
0391: + " [" + loc + "]]");
0392: cur_loc = false;
0393: }
0394:
0395: //Beetle 5079: do not print unlocalized locale names to console, only print locale code.
0396: String localeName = p
0397: .getProperty("derby.locale.external.name");
0398: localeName = localeName.substring(localeName
0399: .indexOf("[") + 1);
0400: localeName = localeName.substring(0, localeName
0401: .indexOf("]"));
0402:
0403: localAW.println(Main.getTextMessage("SIF01.R",
0404: localeName));
0405:
0406: int major = Integer
0407: .valueOf(
0408: p
0409: .getProperty("derby.locale.version.major"))
0410: .intValue();
0411: int minor = Integer
0412: .valueOf(
0413: p
0414: .getProperty("derby.locale.version.minor"))
0415: .intValue();
0416: int maint = Integer
0417: .valueOf(
0418: p
0419: .getProperty("derby.locale.version.maint"))
0420: .intValue();
0421: String build = p
0422: .getProperty("derby.locale.build.number");
0423:
0424: String lv = ProductVersionHolder
0425: .fullVersionString(major, minor, maint,
0426: false, build);
0427:
0428: localAW.println(Main.getTextMessage("SIF01.S",
0429: lv));
0430:
0431: } catch (IOException ioe) {
0432:
0433: //This case is a bit ugly. If we get an IOException, we return
0434: //null. Though this correctly reflects that the product is not
0435: //available for use, it may be confusing to users that we swallow
0436: //the IO error here.
0437:
0438: localAW
0439: .println("Could not get locale properties from : "
0440: + is);
0441: }
0442: }
0443:
0444: } catch (Throwable t) {
0445: localAW.println("Could not load resource: "
0446: + localeResource);
0447: localAW.println("Exception: " + t);
0448: }
0449:
0450: }
0451:
0452: localAW.println(sep);
0453:
0454: } // end of reportLocales
0455:
0456: /* for arguments, choose from one of:*/
0457: private static final String EMBEDDED = "embedded";
0458:
0459: /* you can add this if you like*/
0460: private static final String TOOLS = "tools";
0461:
0462: private static final String NET = "server";
0463: private static final String CLIENT = "client";
0464: private static final String DB2DRIVER = "db2driver";
0465:
0466: /* you can add this if you like */
0467:
0468: private static final String MAINUSAGESTRING = "java org.apache.derby.tools.sysinfo -cp";
0469:
0470: private static final String USAGESTRINGPARTA = MAINUSAGESTRING
0471: + " [ [ " + EMBEDDED + " ][ " + NET + " ][ " + CLIENT
0472: + "] [ " + DB2DRIVER + " ] [ " + TOOLS + " ] [ ";
0473: private static final String USAGESTRINGPARTB = ".class ] ]";
0474:
0475: static void useMe(String[] args, java.io.PrintWriter pw) {
0476: java.io.PrintWriter localPW = pw;
0477:
0478: if (localPW == null) {
0479: localPW = new java.io.PrintWriter(System.out);
0480: }
0481:
0482: int length = args.length;
0483: if (length == 1) {
0484:
0485: try {
0486: tryAllClasspaths(localPW);
0487:
0488: }
0489:
0490: catch (Throwable t) {
0491:
0492: }
0493: } else {
0494: try {
0495: trySomeClasspaths(args, localPW);
0496: }
0497:
0498: catch (Throwable t) {
0499:
0500: }
0501: }
0502:
0503: }
0504:
0505: private static void tryAllClasspaths(java.io.PrintWriter localPW)
0506: throws Throwable {
0507: localPW.println(Main.getTextMessage("SIF08.B"));
0508: localPW.println(Main.getTextMessage("SIF08.C", MAINUSAGESTRING
0509: + " args"));
0510: StringBuffer successes = new StringBuffer(Main
0511: .getTextMessage("SIF08.D")
0512: + crLf());
0513: StringBuffer failures = new StringBuffer(crLf()
0514: + Main.getTextMessage("SIF08.E") + crLf());
0515: tryCoreClasspath(successes, failures);
0516: tryNetClasspath(successes, failures);
0517: tryClientClasspath(successes, failures);
0518: tryDB2DriverClasspath(successes, failures);
0519: tryUtilsClasspath(successes, failures);
0520: localPW.println(successes.toString());
0521: if (!failures.toString().equals(
0522: crLf() + Main.getTextMessage("SIF08.E") + crLf())) {
0523: localPW.println(failures.toString());
0524: } else {
0525:
0526: localPW.println(Main.getTextMessage("SIF08.F"));
0527: }
0528: localPW.flush();
0529: }
0530:
0531: private static void trySomeClasspaths(String[] args,
0532: java.io.PrintWriter localPW) throws Throwable {
0533:
0534: boolean seenArg = false;
0535: StringBuffer successes = new StringBuffer(Main
0536: .getTextMessage("SIF08.D")
0537: + crLf());
0538: StringBuffer failures = new StringBuffer(crLf()
0539: + Main.getTextMessage("SIF08.E") + crLf());
0540:
0541: if (argumentsContain(args, EMBEDDED)) {
0542:
0543: tryCoreClasspath(successes, failures);
0544: seenArg = true;
0545:
0546: }
0547: if (argumentsContain(args, NET)) {
0548: tryNetClasspath(successes, failures);
0549: seenArg = true;
0550:
0551: }
0552: if (argumentsContain(args, CLIENT)) {
0553: tryClientClasspath(successes, failures);
0554: seenArg = true;
0555:
0556: }
0557: if (argumentsContain(args, DB2DRIVER)) {
0558: tryDB2DriverClasspath(successes, failures);
0559: seenArg = true;
0560: }
0561:
0562: if (argumentsContain(args, TOOLS)
0563: || argumentsContain(args, "utils")) {
0564: tryUtilsClasspath(successes, failures);
0565: seenArg = true;
0566:
0567: }
0568:
0569: String userclass = argumentMatches(args, ".class");
0570: if (!userclass.equals("")) {
0571: tryMyClasspath(argumentMatches(args, ".class"), Main
0572: .getTextMessage("SIF08.H", userclass), successes,
0573: failures);
0574: seenArg = true;
0575: }
0576:
0577: if (seenArg) {
0578:
0579: localPW.println(successes.toString());
0580: if (!failures.toString().equals(
0581: crLf() + Main.getTextMessage("SIF08.E") + crLf())) {
0582: localPW.println(failures.toString());
0583: } else {
0584:
0585: localPW.println(Main.getTextMessage("SIF08.F"));
0586: }
0587: } else {
0588: localPW.println(Main.getTextMessage("SIF08.A",
0589: USAGESTRINGPARTA, USAGESTRINGPARTB));
0590: }
0591: localPW.flush();
0592:
0593: }
0594:
0595: private static void tryCoreClasspath(StringBuffer successes,
0596: StringBuffer failures) {
0597: tryMyClasspath("org.apache.derby.database.Database", Main
0598: .getTextMessage("SIF08.J", "derby.jar"), successes,
0599: failures);
0600: }
0601:
0602: private static void tryNetClasspath(StringBuffer successes,
0603: StringBuffer failures) {
0604: tryMyClasspath("org.apache.derby.database.Database", Main
0605: .getTextMessage("SIF08.J", "derby.jar"), successes,
0606: failures);
0607: tryMyClasspath("org.apache.derby.drda.NetworkServerControl",
0608: Main.getTextMessage("SIF08.I", "derbynet.jar"),
0609: successes, failures);
0610: }
0611:
0612: private static void tryClientClasspath(StringBuffer successes,
0613: StringBuffer failures) {
0614: tryMyClasspath("org.apache.derby.jdbc.ClientDriver", Main
0615: .getTextMessage("SIF08.L", "derbyclient.jar"),
0616: successes, failures);
0617: }
0618:
0619: private static void tryDB2DriverClasspath(StringBuffer successes,
0620: StringBuffer failures) {
0621: tryMyClasspath("com.ibm.db2.jcc.DB2Driver", Main
0622: .getTextMessage("SIF08.L", "db2jcc.jar"), successes,
0623: failures);
0624: }
0625:
0626: private static void tryUtilsClasspath(StringBuffer successes,
0627: StringBuffer failures) {
0628: tryMyClasspath("org.apache.derby.tools.ij", Main
0629: .getTextMessage("SIF08.Q", "derbytools.jar"),
0630: successes, failures);
0631: }
0632:
0633: private static void tryMyClasspath(String cn, String library,
0634: StringBuffer successes, StringBuffer failures) {
0635:
0636: try {
0637: Class c = Class.forName(cn);
0638: String loc = getFileWhichLoadedClass(c);
0639: successes.append(found(cn, library, loc));
0640: }
0641:
0642: catch (Throwable t) {
0643:
0644: failures.append(notFound(cn, library));
0645:
0646: }
0647:
0648: }
0649:
0650: private static void tryAsResource(String cn, String library,
0651: StringBuffer successes, StringBuffer failures) {
0652:
0653: try {
0654: java.io.InputStream in = cn.getClass().getResourceAsStream(
0655: cn);
0656: in.close();
0657: String loc = getFileWhichLoadedClass(cn.getClass());
0658: successes.append(found(cn, library, loc));
0659: }
0660:
0661: catch (Throwable t) {
0662: failures.append(notFound(cn, library));
0663:
0664: }
0665:
0666: }
0667:
0668: private static String found(String cn, String library, String loc) {
0669: StringBuffer temp = new StringBuffer(crLf());
0670: temp.append(" " + library);
0671: temp.append(crLf());
0672: if (loc != null)
0673: temp.append(" ").append(loc).append(crLf());
0674: temp.append(crLf());
0675: return temp.toString();
0676: }
0677:
0678: private static String notFound(String cn, String library) {
0679:
0680: StringBuffer temp = new StringBuffer(crLf());
0681: temp.append(" " + library);
0682: temp.append(crLf());
0683: temp.append(" " + Main.getTextMessage("SIF08.U", cn));
0684: temp.append(crLf());
0685: temp.append(crLf());
0686: return temp.toString();
0687: }
0688:
0689: private static String crLf() {
0690: return System.getProperty("line.separator");
0691: }
0692:
0693: private static String lookForMainArg(String[] args,
0694: java.io.PrintWriter localPW) {
0695: int length = args.length;
0696: String[] legalargs = new String[1];
0697: legalargs[0] = EMBEDDED;
0698:
0699: int argsfound = 0;
0700: String whichargument = "";
0701:
0702: for (int i = 0; i < length; i++) {
0703:
0704: for (int j = 0; j < legalargs.length; j++) {
0705: if (args[i]
0706: .toUpperCase(java.util.Locale.ENGLISH)
0707: .equals(
0708: legalargs[j]
0709: .toUpperCase(java.util.Locale.ENGLISH))) {
0710: argsfound++;
0711: whichargument = legalargs[j];
0712: }
0713: }
0714: }
0715: if (argsfound > 1 || argsfound < 1) {
0716: localPW.println(Main.getTextMessage("SIF08.A",
0717: USAGESTRINGPARTA, USAGESTRINGPARTB));
0718: return "";
0719: }
0720: return whichargument;
0721: }
0722:
0723: private static boolean argumentsContain(String[] args, String s) {
0724: for (int i = 0; i < args.length; i++) {
0725: if (args[i].equalsIgnoreCase(s))
0726: return true;
0727: }
0728: return false;
0729:
0730: }
0731:
0732: private static String argumentMatches(String[] args, String ss) {
0733: String userclass = "";
0734: int length = args.length;
0735: for (int i = 0; i < length; i++) {
0736: if (args[i].endsWith(ss)) {
0737: userclass = args[i].substring(0, args[i].length() - 6);
0738:
0739: }
0740:
0741: }
0742: return userclass;
0743: }
0744:
0745: /*
0746: ** Code related to loading info fromjar files.
0747: */
0748:
0749: private static final String infoNames[] = {
0750:
0751: "org/apache/derby/info/"
0752: + org.apache.derby.iapi.services.info.ProductGenusNames.DBMS
0753: + ".properties",
0754:
0755: "org/apache/derby/info/"
0756: + org.apache.derby.iapi.services.info.ProductGenusNames.TOOLS
0757: + ".properties",
0758:
0759: "org/apache/derby/info/"
0760: + org.apache.derby.iapi.services.info.ProductGenusNames.NET
0761: + ".properties",
0762:
0763: "org/apache/derby/info/"
0764: + org.apache.derby.iapi.services.info.ProductGenusNames.DNC
0765: + ".properties" };
0766:
0767: /**
0768: * Get all the info we can obtain from the local execution context
0769: * as to the availability of the Derby classes by attempting to load
0770: * the info files with loadZipFromResource() and checking classpath
0771: * locations with checkForInfo if the classpath is accessible.
0772: *
0773: * @param classpath the classpath, or null if not accessible
0774: * @return an array of ZipInfoProperties with the locations of the located
0775: * resources
0776: * @see #loadZipFromResource()
0777: * @see #checkForInfo(String)
0778: */
0779: public static ZipInfoProperties[] getAllInfo(String classpath) {
0780: ZipInfoProperties zips[] = loadZipFromResource();
0781:
0782: // No info properties files found, but here we are in sysinfo.
0783: // Avoid an NPE in mergeZips by creating a ZipInfoProperties array
0784: // with the location of the sysinfo that is currently executing.
0785: if (zips == null) {
0786: zips = new ZipInfoProperties[1];
0787: ZipInfoProperties zip = new ZipInfoProperties(
0788: ProductVersionHolder
0789: .getProductVersionHolderFromMyEnv(org.apache.derby.tools.sysinfo.TOOLS));
0790: zip.setLocation(getFileWhichLoadedClass(new Main()
0791: .getClass()));
0792: zips[0] = zip;
0793: }
0794:
0795: try {
0796: if (classpath != null) {
0797: String cp[] = parseClasspath(classpath);
0798: Vector v = new Vector();
0799: for (int i = 0; i < cp.length; i++) {
0800: ZipInfoProperties zip = null;
0801: try {
0802: zip = checkForInfo(cp[i]);
0803: } catch (SecurityException se) {
0804: zip = new ZipInfoProperties(null);
0805: zip.setLocation(Main.getTextMessage("SIF03.C",
0806: se.getMessage()));
0807: }
0808: if (zip != null) {
0809: v.addElement(zip);
0810: }
0811: }
0812: if (v.size() > 0) {
0813: ZipInfoProperties cpzips[] = new ZipInfoProperties[v
0814: .size()];
0815: v.copyInto(cpzips);
0816: return mergeZips(zips, cpzips);
0817: }
0818: }
0819: return mergeZips(zips, null);
0820:
0821: } catch (SecurityException se) {
0822: ZipInfoProperties zip[] = new ZipInfoProperties[1];
0823: zip[0] = new ZipInfoProperties(null);
0824: zip[0].setLocation(Main.getTextMessage("SIF03.C", se
0825: .getMessage()));
0826: return zip;
0827: }
0828: }
0829:
0830: /**
0831: * Attempt to load the info properties files specified in infoNames[i]
0832: * using getResourceAsStream(). If none are able to be loaded, return
0833: * a null array.
0834: *
0835: * @return An array of ZipInfoProperties with the locations from which
0836: * the info properties files were loaded.
0837: * @see #infoNames
0838: */
0839: private static ZipInfoProperties[] loadZipFromResource() {
0840: java.util.ArrayList al = new java.util.ArrayList();
0841:
0842: for (int i = 0; i < infoNames.length; i++) {
0843: final String resource = "/".concat(infoNames[i]);
0844:
0845: InputStream is = (InputStream) AccessController
0846: .doPrivileged(new PrivilegedAction() {
0847: public Object run() {
0848: InputStream locis = new Main().getClass()
0849: .getResourceAsStream(resource);
0850: return locis;
0851: }
0852: });
0853:
0854: if (is == null)
0855: continue;
0856:
0857: ZipInfoProperties ze = new ZipInfoProperties(
0858: ProductVersionHolder
0859: .getProductVersionHolderFromMyEnv(is));
0860:
0861: // get the real location of the info file
0862: URL locUrl = (URL) AccessController
0863: .doPrivileged(new PrivilegedAction() {
0864: public Object run() {
0865: URL realUrl = new Main().getClass()
0866: .getResource(resource);
0867: return realUrl;
0868: }
0869: });
0870:
0871: ze.setLocation(formatURL(locUrl));
0872:
0873: al.add(ze);
0874: }
0875:
0876: if (al.size() == 0) {
0877: return null;
0878: }
0879:
0880: ZipInfoProperties[] zip = new ZipInfoProperties[al.size()];
0881:
0882: al.toArray(zip);
0883:
0884: return zip;
0885: }
0886:
0887: /**
0888: * Split the classpath into separate elements.
0889: *
0890: * @param cp the classpath, if accessible.
0891: * @return a String array with the individual classpath elements.
0892: */
0893: private static String[] parseClasspath(String cp) {
0894: StringTokenizer st = new StringTokenizer(cp, File.pathSeparator);
0895: int count = st.countTokens();
0896: if (count == 0) {
0897: return null;
0898: }
0899:
0900: String vals[] = new String[count];
0901: for (int i = 0; i < count; i++) {
0902: vals[i] = st.nextToken();
0903: }
0904: return vals;
0905: }
0906:
0907: /**
0908: * Given an individual element of the element of the classpath, call
0909: * checkDirectory() if the element is a directory or checkFile()
0910: * if the element is a file.
0911: *
0912: * @param cpEntry the classpath element
0913: * @return a ZipInfoProperties if an info properties file is found.
0914: */
0915: private static ZipInfoProperties checkForInfo(String cpEntry) {
0916: File f = new File(cpEntry);
0917: if (!f.exists()) {
0918: return null;
0919: }
0920:
0921: if (f.isDirectory()) {
0922: ZipInfoProperties zip = checkDirectory(cpEntry);
0923: return zip;
0924: }
0925:
0926: if (f.isFile()) {
0927: ZipInfoProperties zip = checkFile(cpEntry);
0928: return zip;
0929: }
0930: return null;
0931: }
0932:
0933: /**
0934: * Check a given directory for the presence of an info properties file in
0935: * org/apache/derby/info inside the directory.
0936: *
0937: * @param dirname the directory to check as a String
0938: * @return a ZipInfoProperties if a file is found, otherwise null.
0939: */
0940: private static ZipInfoProperties checkDirectory(String dirname) {
0941: boolean foundOne = false;
0942: File f = null;
0943: for (int i = 0; i < infoNames.length; i++) {
0944: String localSysinfo = infoNames[i].replace('/',
0945: File.separatorChar);
0946: f = new File(dirname, localSysinfo);
0947: if (f.exists()) {
0948: foundOne = true;
0949: break;
0950: }
0951: }
0952:
0953: if (!foundOne || (f == null)) {
0954: return null;
0955: }
0956:
0957: try {
0958: InputStream bis = new FileInputStream(f);
0959:
0960: ZipInfoProperties zip = new ZipInfoProperties(
0961: ProductVersionHolder
0962: .getProductVersionHolderFromMyEnv(bis));
0963: zip.setLocation(new File(dirname).getCanonicalPath()
0964: .replace('/', File.separatorChar));
0965: return zip;
0966: } catch (IOException ioe) {
0967: return null;
0968: }
0969:
0970: }
0971:
0972: /**
0973: * Check inside a jar file for the presence of a Derby info properties
0974: * file. There is a special case for db2jcc, which does not have a Derby
0975: * info propeties file. If db2jcc is in the filename, acquire DB2Driver
0976: * via reflection and get the version number from it.
0977: *
0978: * @param filename the jar file to check
0979: * @return ZipInfoProperties with the jar file set as the location
0980: * or null if not found.
0981: */
0982: private static ZipInfoProperties checkFile(String filename) {
0983: // try to create a ZipFile from it
0984:
0985: // Check to see if it's a version of db2jcc.jar and if so, report the version number.
0986: if (filename.indexOf("db2jcc") >= 0) {
0987: Class c = null;
0988: Method m = null;
0989: Object o = null;
0990: Integer build = null;
0991: Integer major = null;
0992: Integer minor = null;
0993: try {
0994: try {
0995: c = Class.forName("com.ibm.db2.jcc.DB2Driver");
0996: m = c.getMethod("getJCCBuildNumber", null);
0997: o = c.newInstance();
0998: build = (Integer) m.invoke(o, null);
0999: } catch (ClassNotFoundException cnfe) {
1000: c = Class.forName("com.ibm.db2.jcc.DB2Version");
1001: m = c.getMethod("getBuildNumber", null);
1002: o = c.newInstance();
1003: build = (Integer) m.invoke(o, null);
1004: }
1005: m = c.getMethod("getMajorVersion", null);
1006: major = (Integer) m.invoke(o, null);
1007: m = c.getMethod("getMinorVersion", null);
1008: minor = (Integer) m.invoke(o, null);
1009:
1010: ProductVersionHolder jccVersion = ProductVersionHolder
1011: .getProductVersionHolder("IBM Corp.",
1012: "DB2 Java Common Client", "DRDA:jcc",
1013: major.intValue(), minor.intValue(), 0,
1014: 0, build.toString(), Boolean.FALSE);
1015:
1016: ZipInfoProperties zip = new ZipInfoProperties(
1017: jccVersion);
1018:
1019: String loc = getFileWhichLoadedClass(c);
1020: // For db2jcc.jar, report the actual file from which DB2Driver
1021: // was loaded, if we can determine it. For db2jcc_license_c,
1022: // report the filename from the classpath, and the version
1023: // info from the DB2Driver that we loaded. This is slightly
1024: // misleading, since db2jcc_license_c.jar doesn't really have
1025: // a "version", but the two jars are usually linked.
1026: if (loc != null && filename.indexOf("license_c") < 0)
1027: zip.setLocation(loc);
1028: else
1029: zip.setLocation(new File(filename)
1030: .getCanonicalPath().replace('/',
1031: File.separatorChar));
1032: return zip;
1033: } catch (Exception e) {
1034: return null;
1035: }
1036: }
1037:
1038: try {
1039: ZipFile zf = new ZipFile(filename);
1040: // try to get a ZipEntry from the ZipFile
1041:
1042: ZipEntry this Entry = null;
1043:
1044: for (int i = 0; i < infoNames.length; i++) {
1045: this Entry = zf.getEntry(infoNames[i]);
1046: if (this Entry != null) {
1047: break;
1048: }
1049: }
1050:
1051: if (this Entry == null) {
1052: return null;
1053: }
1054:
1055: InputStream bis = zf.getInputStream(this Entry);
1056: if (bis == null) {
1057: return null;
1058: }
1059:
1060: ZipInfoProperties zip = new ZipInfoProperties(
1061: ProductVersionHolder
1062: .getProductVersionHolderFromMyEnv(bis));
1063: zip.setLocation(new File(filename).getCanonicalPath()
1064: .replace('/', File.separatorChar));
1065: return zip;
1066:
1067: } catch (IOException ioe) {
1068: //guess not
1069: return null;
1070: }
1071:
1072: }
1073:
1074: /*
1075: ** Message handling
1076: */
1077: private static ResourceBundle getBundle() {
1078: try {
1079: return ResourceBundle
1080: .getBundle("org.apache.derby.loc.sysinfoMessages");
1081: } catch (MissingResourceException mre) {
1082: }
1083: return null;
1084: }
1085:
1086: public static String getTextMessage(String msgId) {
1087: return getCompleteMessage(msgId, (Object[]) null);
1088: }
1089:
1090: public static String getTextMessage(String msgId, Object a1) {
1091:
1092: return getCompleteMessage(msgId, new Object[] { a1 });
1093: }
1094:
1095: public static String getTextMessage(String msgId, Object a1,
1096: Object a2) {
1097: return getCompleteMessage(msgId, new Object[] { a1, a2 });
1098: }
1099:
1100: public static String getTextMessage(String msgId, Object a1,
1101: Object a2, Object a3) {
1102: return getCompleteMessage(msgId, new Object[] { a1, a2, a3 });
1103: }
1104:
1105: public static String getTextMessage(String msgId, Object a1,
1106: Object a2, Object a3, Object a4) {
1107: return getCompleteMessage(msgId,
1108: new Object[] { a1, a2, a3, a4 });
1109: }
1110:
1111: /**
1112: */
1113: public static String getCompleteMessage(String msgId,
1114: Object[] arguments) {
1115:
1116: // we have a base file (sysinfoMessages.properties) so don't give us a last chance.
1117: return org.apache.derby.iapi.services.i18n.MessageService
1118: .formatMessage(getBundle(), msgId, arguments, false);
1119: }
1120:
1121: /**
1122: * Given a loaded class, this
1123: * routine asks the class's class loader for information about where the
1124: * class was loaded from. Typically, this is a file, which might be
1125: * either a class file or a jar file. The routine figures that out, and
1126: * returns the name of the file. If it can't figure it out, it returns null
1127: */
1128: private static String getFileWhichLoadedClass(final Class cls) {
1129: return (String) AccessController
1130: .doPrivileged(new PrivilegedAction() {
1131: public Object run() {
1132: CodeSource cs = null;
1133: try {
1134: cs = cls.getProtectionDomain()
1135: .getCodeSource();
1136: } catch (SecurityException se) {
1137: return Main.getTextMessage("SIF01.V", cls,
1138: se.getMessage());
1139: }
1140:
1141: if (cs == null)
1142: return null;
1143:
1144: URL result = cs.getLocation();
1145:
1146: return formatURL(result);
1147: }
1148: });
1149: }
1150:
1151: /**
1152: * <P>
1153: * Merge and flatten two arrays of ZipInfoProperties, removing any
1154: * duplicates. There may be duplicates in the arrays because
1155: * loadZipFromResource may find all the properties files in the same
1156: * location, such as when loading from compiled source instead of
1157: * packaged jars. Also, a poorly constructed classpath may contain
1158: * duplicate entries that each contain the Derby classes, and we
1159: * need only report the first of each such instances found.
1160: * <P>
1161: * The second array may be null if the classpath was empty, in which
1162: * case we still remove the duplicates from the first array and return
1163: * the shortened array.
1164: *
1165: * @param zip1 the first array from loadZipWithResource
1166: * @param zip2 the second array from analyzing the classpath
1167: * @return the merged array
1168: */
1169: private static ZipInfoProperties[] mergeZips(
1170: ZipInfoProperties[] zip1, ZipInfoProperties[] zip2) {
1171: Vector v = new Vector();
1172: boolean foundDup = false;
1173:
1174: // remove duplicates from first array
1175: for (int i = 0; i < zip1.length; i++) {
1176: if (zip1[i] != null && zip1.length > 1) {
1177: for (int j = i + 1; j < zip1.length; j++) {
1178: if (zip1[i].getLocation().equals(
1179: zip1[j].getLocation()))
1180: zip1[j] = null;
1181: }
1182: }
1183: if (zip1[i] != null)
1184: v.addElement(zip1[i]);
1185: }
1186:
1187: // if provided a second array, remove any locations in second array
1188: // still in first array.
1189: if (zip2 != null) {
1190: for (int j = 0; j < zip2.length; j++) {
1191: for (int k = 0; k < v.size(); k++) {
1192: ZipInfoProperties z = (ZipInfoProperties) v.get(k);
1193: if (zip2[j].getLocation().equals(z.getLocation()))
1194: foundDup = true;
1195: }
1196: if (!foundDup) {
1197: v.addElement(zip2[j]);
1198: }
1199: foundDup = false;
1200: }
1201: }
1202:
1203: ZipInfoProperties[] merged = new ZipInfoProperties[v.size()];
1204: v.copyInto(merged);
1205: return merged;
1206: }
1207:
1208: /**
1209: * Strip a given URL down to the filename. The URL will be a jarfile or
1210: * directory containing a Derby info properties file. Return the canonical
1211: * path for the filename, with the path separators normalized.
1212: */
1213: private static String formatURL(URL loc) {
1214: String filename = URLDecoder.decode(loc.toString());
1215:
1216: if (filename.startsWith("jar:")) {
1217: filename = filename.substring(4);
1218: }
1219: if (filename.startsWith("file:")) {
1220: filename = filename.substring(5);
1221: }
1222: if (filename.indexOf("!") > -1) {
1223: filename = filename.substring(0, filename.indexOf("!"));
1224: }
1225: if (filename.indexOf("/org/apache/derby") > -1) {
1226: filename = filename.substring(0, filename
1227: .indexOf("/org/apache/derby"));
1228: }
1229: if (filename.charAt(0) == '/'
1230: && Character.isLetter(filename.charAt(1))
1231: && filename.charAt(2) == ':'
1232: && filename.charAt(2) == '/') {
1233: filename = filename.substring(1);
1234: }
1235:
1236: String result = "";
1237: try {
1238: result = new File(filename).getCanonicalPath().replace('/',
1239: File.separatorChar);
1240: } catch (IOException e) {
1241: result = "IOException";
1242: }
1243: return result;
1244: }
1245:
1246: } // end of class Main
|