001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package com.sun.servicetag;
043:
044: import java.io.*;
045: import java.util.HashSet;
046: import java.util.Locale;
047: import java.util.Properties;
048: import java.util.Set;
049: import java.util.List;
050: import java.util.ArrayList;
051: import static com.sun.servicetag.Util.*;
052:
053: /**
054: * Service Tag Installer for Java SE.
055: */
056: public class Installer {
057: // System properties for testing
058: private static String SVCTAG_DIR_PATH = "servicetag.dir.path";
059: private static String SVCTAG_ENABLE_REGISTRATION = "servicetag.registration.enabled";
060: private final static String SUN_VENDOR = "Sun Microsystems";
061: private final static String REGISTRATION_XML = "registration.xml";
062: private final static String SERVICE_TAG_FILE = "servicetag";
063: private final static String REGISTRATION_HTML_NAME = "register";
064:
065: private final static Locale[] knownSupportedLocales = new Locale[] {
066: Locale.ENGLISH, Locale.JAPANESE, Locale.SIMPLIFIED_CHINESE };
067:
068: private final static String javaHome = System
069: .getProperty("java.home");
070: private static File svcTagDir;
071: private static File serviceTagFile;
072: private static File regXmlFile;
073: private static RegistrationData registration;
074: private static boolean supportRegistration;
075: private static String registerHtmlParent;
076: private static Set<Locale> supportedLocales = new HashSet<Locale>();
077: private static Properties swordfishProps = null;
078: private static String[] jreArchs = null;
079: static {
080: String dir = System.getProperty(SVCTAG_DIR_PATH);
081: if (dir == null) {
082: svcTagDir = new File(getJrePath(), "lib" + File.separator
083: + SERVICE_TAG_FILE);
084: } else {
085: svcTagDir = new File(dir);
086: }
087: serviceTagFile = new File(svcTagDir, SERVICE_TAG_FILE);
088: regXmlFile = new File(svcTagDir, REGISTRATION_XML);
089: if (System.getProperty(SVCTAG_ENABLE_REGISTRATION) == null) {
090: supportRegistration = isJdk();
091: } else {
092: supportRegistration = true;
093: }
094: }
095:
096: private Installer() {
097: }
098:
099: // Implementation of ServiceTag.getJavaServiceTag(String) method
100: static ServiceTag getJavaServiceTag(String source)
101: throws IOException {
102: if (!System.getProperty("java.vendor").startsWith(SUN_VENDOR)) {
103: // Products bundling this implementation may run on
104: // Mac OS which is not a Sun JDK
105: return null;
106: }
107: boolean cleanup = false;
108: try {
109: // Check if we have the swordfish entries for this JRE version
110: if (loadSwordfishEntries() == null) {
111: return null;
112: }
113:
114: ServiceTag st = getJavaServiceTag();
115: // Check if the service tag created by this bundle owner
116: if (st != null && st.getSource().equals(source)) {
117: // Install the system service tag if supported
118: // stclient may be installed after the service tag creation
119: if (Registry.isSupported()) {
120: installSystemServiceTag();
121: }
122: return st;
123: }
124:
125: // in case any exception thrown during the cleanup
126: cleanup = true;
127:
128: // re-create a new one for this bundle owner
129: // first delete the registration data
130: deleteRegistrationData();
131: cleanup = false;
132:
133: // create service tag and generate new register.html pages
134: return createServiceTag(source);
135: } finally {
136: if (cleanup) {
137: if (regXmlFile.exists()) {
138: regXmlFile.delete();
139: }
140: if (serviceTagFile.exists()) {
141: serviceTagFile.delete();
142: }
143: }
144: }
145: }
146:
147: /**
148: * Returns the Java SE registration data located in
149: * the <JRE>/lib/servicetag/registration.xml by default.
150: *
151: * @throws IllegalArgumentException if the registration data
152: * is of invalid format.
153: */
154: private static synchronized RegistrationData getRegistrationData()
155: throws IOException {
156: if (registration != null) {
157: return registration;
158: }
159: if (regXmlFile.exists()) {
160: BufferedInputStream in = null;
161: try {
162: in = new BufferedInputStream(new FileInputStream(
163: regXmlFile));
164: registration = RegistrationData.loadFromXML(in);
165: } catch (IllegalArgumentException ex) {
166: System.err.println("Error: Bad registration data \""
167: + regXmlFile + "\":" + ex.getMessage());
168: throw ex;
169: } finally {
170: if (in != null) {
171: in.close();
172: }
173: }
174: } else {
175: registration = new RegistrationData();
176: }
177: return registration;
178: }
179:
180: /**
181: * Write the registration data to the registration.xml file.
182: *
183: * The offline registration page has to be regenerated with
184: * the new registration data.
185: *
186: * @throws java.io.IOException
187: */
188: private static synchronized void writeRegistrationXml()
189: throws IOException {
190: if (!svcTagDir.exists()) {
191: // This check is for NetBeans or other products that
192: // bundles this com.sun.servicetag implementation for
193: // pre-6u5 release.
194: if (!svcTagDir.mkdir()) {
195: throw new IOException("Failed to create directory: "
196: + svcTagDir);
197: }
198: }
199:
200: // regenerate the new offline registration page
201: deleteRegistrationHtmlPage();
202: getRegistrationHtmlPage();
203:
204: BufferedOutputStream out = null;
205: try {
206: out = new BufferedOutputStream(new FileOutputStream(
207: regXmlFile));
208: getRegistrationData().storeToXML(out);
209: } catch (IllegalArgumentException ex) {
210: System.err.println("Error: Bad registration data \""
211: + regXmlFile + "\":" + ex.getMessage());
212: throw ex;
213: } finally {
214: if (out != null) {
215: out.close();
216: }
217: }
218: }
219:
220: /**
221: * Returns the instance urn(s) stored in the servicetag file
222: * or empty set if file not exists.
223: */
224: private static Set<String> getInstalledURNs() throws IOException {
225: Set<String> urnSet = new HashSet<String>();
226: if (serviceTagFile.exists()) {
227: BufferedReader in = null;
228: try {
229: in = new BufferedReader(new FileReader(serviceTagFile));
230: String urn;
231: while ((urn = in.readLine()) != null) {
232: urn = urn.trim();
233: if (urn.length() > 0) {
234: urnSet.add(urn);
235: }
236: }
237: } finally {
238: if (in != null) {
239: in.close();
240: }
241: }
242: }
243: return urnSet;
244: }
245:
246: /**
247: * Return the Java SE service tag(s) if it exists.
248: * Typically only one Java SE service tag but it could have two for
249: * Solaris 32-bit and 64-bit on the same install directory.
250: *
251: * @return the service tag(s) for Java SE
252: */
253: private static ServiceTag[] getJavaServiceTagArray()
254: throws IOException {
255: RegistrationData regData = getRegistrationData();
256: Set<ServiceTag> svcTags = regData.getServiceTags();
257: Set<ServiceTag> result = new HashSet<ServiceTag>();
258:
259: Properties props = loadSwordfishEntries();
260: String jdkUrn = props.getProperty("servicetag.jdk.urn");
261: String jreUrn = props.getProperty("servicetag.jre.urn");
262: for (ServiceTag st : svcTags) {
263: if (st.getProductURN().equals(jdkUrn)
264: || st.getProductURN().equals(jreUrn)) {
265: result.add(st);
266: }
267: }
268: return result.toArray(new ServiceTag[0]);
269: }
270:
271: /**
272: * Returns the Java SE service tag for this running platform;
273: * or null if not exist.
274: * This method will return the 64-bit service tag if the JDK
275: * supports both 32-bit and 64-bit if already created.
276: */
277: private static ServiceTag getJavaServiceTag() throws IOException {
278: String definedId = getProductDefinedId();
279: for (ServiceTag st : getJavaServiceTagArray()) {
280: if (st.getProductDefinedInstanceID().equals(definedId)) {
281: return st;
282: }
283: }
284: return null;
285: }
286:
287: /**
288: * Create a service tag for Java SE and install in the system
289: * service tag registry if supported.
290: *
291: * A registration data <JRE>/lib/servicetag/registration.xml
292: * will be created to storeToXML the XML entry for Java SE service tag.
293: * If the system supports service tags, this method will install
294: * the Java SE service tag in the system service tag registry and
295: * its <tt>instance_urn</tt> will be stored to <JRE>/lib/servicetag/servicetag.
296: *
297: * If <JRE>/lib/servicetag/registration.xml exists but is not installed
298: * in the system service tag registry (i.e. servicetag doesn't exist),
299: * this method will install it as described above.
300: *
301: * If the system supports service tag, stclient will be used
302: * to create the Java SE service tag.
303: *
304: * A Solaris 32-bit and 64-bit JDK will be installed in the same
305: * directory but the registration.xml will have 2 service tags.
306: * The servicetag file will also contain 2 instance_urns for that case.
307: */
308: private static ServiceTag createServiceTag(String svcTagSource)
309: throws IOException {
310: // determine if a new service tag is needed to be created
311: ServiceTag newSvcTag = null;
312: if (getJavaServiceTag() == null) {
313: newSvcTag = newServiceTag(svcTagSource);
314: }
315:
316: // Add the new service tag in the registration data
317: if (newSvcTag != null) {
318: RegistrationData regData = getRegistrationData();
319:
320: // Add the service tag to the registration data in JDK/JRE
321: newSvcTag = regData.addServiceTag(newSvcTag);
322:
323: // add if there is a service tag for the OS
324: ServiceTag osTag = SolarisServiceTag.getServiceTag();
325: if (osTag != null
326: && regData.getServiceTag(osTag.getInstanceURN()) == null) {
327: regData.addServiceTag(osTag);
328: }
329: // write to the registration.xml
330: writeRegistrationXml();
331: }
332:
333: // Install the system service tag if supported
334: if (Registry.isSupported()) {
335: installSystemServiceTag();
336: }
337: return newSvcTag;
338: }
339:
340: private static void installSystemServiceTag() throws IOException {
341: // only install the service tag in the registry if
342: // it has permission to write the servicetag file.
343: if ((!serviceTagFile.exists() && !svcTagDir.canWrite())
344: || (serviceTagFile.exists() && !serviceTagFile
345: .canWrite())) {
346: return;
347: }
348:
349: Set<String> urns = getInstalledURNs();
350: ServiceTag[] javaSvcTags = getJavaServiceTagArray();
351: if (urns.size() < javaSvcTags.length) {
352: for (ServiceTag st : javaSvcTags) {
353: // Add the service tag in the system service tag registry
354: // if not installed
355: String instanceURN = st.getInstanceURN();
356: if (!urns.contains(instanceURN)) {
357: Registry.getSystemRegistry().addServiceTag(st);
358: }
359: }
360: }
361: writeInstalledUrns();
362: }
363:
364: private static ServiceTag newServiceTag(String svcTagSource)
365: throws IOException {
366: // Load the swoRDFish information for the service tag creation
367: Properties props = loadSwordfishEntries();
368:
369: // Determine the product URN and name
370: String productURN;
371: String productName;
372:
373: if (isJdk()) {
374: // <HOME>/jre exists which implies it's a JDK
375: productURN = props.getProperty("servicetag.jdk.urn");
376: productName = props.getProperty("servicetag.jdk.name");
377: } else {
378: // Otherwise, it's a JRE
379: productURN = props.getProperty("servicetag.jre.urn");
380: productName = props.getProperty("servicetag.jre.name");
381: }
382:
383: return ServiceTag.newInstance(ServiceTag.generateInstanceURN(),
384: productName, System.getProperty("java.version"),
385: productURN,
386: props.getProperty("servicetag.parent.name"), props
387: .getProperty("servicetag.parent.urn"),
388: getProductDefinedId(), SUN_VENDOR, System
389: .getProperty("os.arch"), getZoneName(),
390: svcTagSource);
391: }
392:
393: /**
394: * Delete the registration data, the offline registration pages and
395: * the service tags in the system service tag registry if installed.
396: *
397: * The registration.xml and servicetag file will be removed.
398: */
399: private static synchronized void deleteRegistrationData()
400: throws IOException {
401: try {
402: // delete the offline registration page
403: deleteRegistrationHtmlPage();
404:
405: // Remove the service tag from the system ST registry if exists
406: Set<String> urns = getInstalledURNs();
407: if (urns.size() > 0 && Registry.isSupported()) {
408: for (String u : urns) {
409: Registry.getSystemRegistry().removeServiceTag(u);
410: }
411: }
412: registration = null;
413: } finally {
414: // Delete the registration.xml and servicetag files if exists
415: if (regXmlFile.exists()) {
416: if (!regXmlFile.delete()) {
417: throw new IOException("Failed to delete "
418: + regXmlFile);
419: }
420: }
421: if (serviceTagFile.exists()) {
422: if (!serviceTagFile.delete()) {
423: throw new IOException("Failed to delete "
424: + serviceTagFile);
425: }
426: }
427: }
428: }
429:
430: /**
431: * Updates the registration data to contain one single service tag
432: * for the running Java runtime.
433: */
434: private static synchronized void updateRegistrationData(
435: String svcTagSource) throws IOException {
436: RegistrationData regData = getRegistrationData();
437: ServiceTag curSvcTag = newServiceTag(svcTagSource);
438:
439: ServiceTag[] javaSvcTags = getJavaServiceTagArray();
440: Set<String> urns = getInstalledURNs();
441: for (ServiceTag st : javaSvcTags) {
442: if (!st.getProductDefinedInstanceID().equals(
443: curSvcTag.getProductDefinedInstanceID())) {
444: String instanceURN = st.getInstanceURN();
445: regData.removeServiceTag(instanceURN);
446:
447: // remove it from the system service tag registry if exists
448: if (urns.contains(instanceURN)
449: && Registry.isSupported()) {
450: Registry.getSystemRegistry().removeServiceTag(
451: instanceURN);
452: }
453: }
454: }
455: writeRegistrationXml();
456: writeInstalledUrns();
457: }
458:
459: private static void writeInstalledUrns() throws IOException {
460: // if the Registry is not supported,
461: // remove the servicetag file
462: if (!Registry.isSupported() && serviceTagFile.exists()) {
463: serviceTagFile.delete();
464: return;
465: }
466:
467: PrintWriter out = null;
468: try {
469: out = new PrintWriter(serviceTagFile);
470:
471: ServiceTag[] javaSvcTags = getJavaServiceTagArray();
472: for (ServiceTag st : javaSvcTags) {
473: // Write the instance_run to the servicetag file
474: String instanceURN = st.getInstanceURN();
475: out.println(instanceURN);
476: }
477: } finally {
478: if (out != null) {
479: out.close();
480: }
481: }
482: }
483:
484: /**
485: * Load the values associated with the swoRDFish metadata entries
486: * for Java SE. The swoRDFish metadata entries are different for
487: * different release.
488: *
489: * @param version Version of Java SE
490: */
491: private static synchronized Properties loadSwordfishEntries()
492: throws IOException {
493: if (swordfishProps != null) {
494: return swordfishProps;
495: }
496:
497: // The version string for Java SE 6 is 1.6.0
498: // We just need the minor number in the version string
499: int version = Util.getJdkVersion();
500:
501: String filename = "/com/sun/servicetag/resources/javase_"
502: + version + "_swordfish.properties";
503: InputStream in = Installer.class.getClass()
504: .getResourceAsStream(filename);
505: if (in == null) {
506: return null;
507: }
508: swordfishProps = new Properties();
509: try {
510: swordfishProps.load(in);
511: } finally {
512: in.close();
513: }
514: return swordfishProps;
515: }
516:
517: /**
518: * Returns the product defined instance ID for Java SE.
519: * It is a list of comma-separated name/value pairs:
520: * "id=<full-version> <arch> [<arch>]*"
521: * "dir=<java.home system property value>"
522: *
523: * where <full-version> is the full version string of the JRE,
524: * <arch> is the architecture that the runtime supports
525: * (i.e. "sparc", "sparcv9", "i386", "amd64" (ISA list))
526: *
527: * For Solaris, it can be dual mode that can support both
528: * 32-bit and 64-bit. the "id" will be set to
529: * "1.6.0_03-b02 sparc sparcv9"
530: *
531: * The "dir" property is included in the service tag to enable
532: * the Service Tag software to determine if a service tag for
533: * Java SE is invalid and perform appropriate service tag
534: * cleanup if necessary. See RFE# 6574781 Service Tags Enhancement.
535: *
536: */
537: private static String getProductDefinedId() {
538: StringBuilder definedId = new StringBuilder();
539: definedId.append("id=");
540: definedId.append(System.getProperty("java.runtime.version"));
541:
542: String[] archs = getJreArchs();
543: for (String name : archs) {
544: definedId.append(" " + name);
545: }
546:
547: String location = ",dir=" + javaHome;
548: if ((definedId.length() + location.length()) < 256) {
549: definedId.append(",dir=");
550: definedId.append(javaHome);
551: } else {
552: // if it exceeds the limit, we will not include the location
553: if (isVerbose()) {
554: System.err
555: .println("Warning: Product defined instance ID exceeds the field limit:");
556: }
557: }
558:
559: return definedId.toString();
560: }
561:
562: /**
563: * Returns the architectures that the runtime supports
564: * (i.e. "sparc", "sparcv9", "i386", "amd64" (ISA list))
565: * The directory name where libjava.so is located.
566: *
567: * On Windows, returns the "os.arch" system property value.
568: */
569: private synchronized static String[] getJreArchs() {
570: if (jreArchs != null) {
571: return jreArchs;
572: }
573:
574: Set<String> archs = new HashSet<String>();
575:
576: String os = System.getProperty("os.name");
577: if (os.equals("SunOS") || os.equals("Linux")) {
578: // Traverse the directories under <JRE>/lib.
579: // If <JRE>/lib/<arch>/libjava.so exists, add <arch>
580: // to the product defined ID
581: File dir = new File(getJrePath() + File.separator + "lib");
582: if (dir.isDirectory()) {
583: String[] children = dir.list();
584: for (String name : children) {
585: File f = new File(dir, name + File.separator
586: + "libjava.so");
587: if (f.exists()) {
588: archs.add(name);
589: }
590: }
591: }
592: } else {
593: // Windows - append the os.arch
594: archs.add(System.getProperty("os.arch"));
595: }
596: jreArchs = archs.toArray(new String[0]);
597: return jreArchs;
598: }
599:
600: /**
601: * Return the zonename if zone is supported; otherwise, return
602: * "global".
603: */
604: private static String getZoneName() throws IOException {
605: String zonename = "global";
606:
607: String command = "/usr/bin/zonename";
608: File f = new File(command);
609: // com.sun.servicetag package has to be compiled with JDK 5 as well
610: // JDK 5 doesn't support the File.canExecute() method.
611: // Risk not checking isExecute() for the zonename command is very low.
612: if (f.exists()) {
613: ProcessBuilder pb = new ProcessBuilder(command);
614: Process p = pb.start();
615: String output = commandOutput(p);
616: if (p.exitValue() == 0) {
617: zonename = output.trim();
618: }
619:
620: }
621: return zonename;
622: }
623:
624: private synchronized static String getRegisterHtmlParent()
625: throws IOException {
626: if (registerHtmlParent == null) {
627: File htmlDir; // register.html is put under the JDK directory
628: if (getJrePath().endsWith(File.separator + "jre")) {
629: htmlDir = new File(getJrePath(), "..");
630: } else {
631: // j2se non-image build
632: htmlDir = new File(getJrePath());
633: }
634:
635: // initialize the supported locales
636: initSupportedLocales(htmlDir);
637:
638: // Determine the location of the offline registration page
639: String path = System.getProperty(SVCTAG_DIR_PATH);
640: if (path == null) {
641: // Default is <JDK>/register.html
642: registerHtmlParent = htmlDir.getCanonicalPath();
643: } else {
644: File f = new File(path);
645: registerHtmlParent = f.getCanonicalPath();
646: if (!f.isDirectory()) {
647: throw new InternalError("Path " + path
648: + " set in \"" + SVCTAG_DIR_PATH
649: + "\" property is not a directory");
650: }
651: }
652: }
653: return registerHtmlParent;
654: }
655:
656: /**
657: * Returns the File object of the offline registration page localized
658: * for the default locale in the JDK directory.
659: */
660: static synchronized File getRegistrationHtmlPage()
661: throws IOException {
662: if (!supportRegistration) {
663: // No register.html page generated if JRE
664: return null;
665: }
666:
667: String parent = getRegisterHtmlParent();
668:
669: // check if the offline registration page is already generated
670: File f = new File(parent, REGISTRATION_HTML_NAME + ".html");
671: if (!f.exists()) {
672: // Generate the localized version of the offline registration Page
673: generateRegisterHtml(parent);
674: }
675:
676: String name = REGISTRATION_HTML_NAME;
677: List<Locale> candidateLocales = getCandidateLocales(Locale
678: .getDefault());
679: for (Locale l : candidateLocales) {
680: if (supportedLocales.contains(l)) {
681: name = REGISTRATION_HTML_NAME + "_" + l.toString();
682: break;
683: }
684: }
685: File htmlFile = new File(parent, name + ".html");
686: if (isVerbose()) {
687: System.out.print("Offline registration page: " + htmlFile);
688: System.out.println((htmlFile.exists() ? ""
689: : " not exist. Use register.html"));
690: }
691: if (htmlFile.exists()) {
692: return htmlFile;
693: } else {
694: return new File(parent, REGISTRATION_HTML_NAME + ".html");
695: }
696: }
697:
698: private static List<Locale> getCandidateLocales(Locale locale) {
699: String language = locale.getLanguage();
700: String country = locale.getCountry();
701: String variant = locale.getVariant();
702:
703: List<Locale> locales = new ArrayList<Locale>(3);
704: if (variant.length() > 0) {
705: locales.add(locale);
706: }
707: if (country.length() > 0) {
708: locales.add((locales.size() == 0) ? locale : new Locale(
709: language, country, ""));
710: }
711: if (language.length() > 0) {
712: locales.add((locales.size() == 0) ? locale : new Locale(
713: language, "", ""));
714: }
715: return locales;
716: }
717:
718: // Remove the offline registration pages
719: private static void deleteRegistrationHtmlPage() throws IOException {
720: String parent = getRegisterHtmlParent();
721: if (parent == null) {
722: return;
723: }
724:
725: for (Locale locale : supportedLocales) {
726: String name = REGISTRATION_HTML_NAME;
727: if (!locale.equals(Locale.ENGLISH)) {
728: name += "_" + locale.toString();
729: }
730: File f = new File(parent, name + ".html");
731: if (f.exists()) {
732: if (!f.delete()) {
733: throw new IOException("Failed to delete " + f);
734: }
735: }
736: }
737: }
738:
739: private static void initSupportedLocales(File jdkDir) {
740: if (supportedLocales.isEmpty()) {
741: // initialize with the known supported locales
742: for (Locale l : knownSupportedLocales) {
743: supportedLocales.add(l);
744: }
745: }
746:
747: // Determine unknown supported locales if any
748: // by finding the localized version of README.html
749: // This prepares if a new locale in JDK is supported in
750: // e.g. in the OpenSource world
751: FilenameFilter ff = new FilenameFilter() {
752: public boolean accept(File dir, String name) {
753: String fname = name.toLowerCase();
754: if (fname.startsWith("readme")
755: && fname.endsWith(".html")) {
756: return true;
757: }
758: return false;
759: }
760: };
761:
762: String[] readmes = jdkDir.list(ff);
763: for (String name : readmes) {
764: String basename = name.substring(0, name.length()
765: - ".html".length());
766: String[] ss = basename.split("_");
767: switch (ss.length) {
768: case 1:
769: // English version
770: break;
771: case 2:
772: supportedLocales.add(new Locale(ss[1]));
773: break;
774: case 3:
775: supportedLocales.add(new Locale(ss[1], ss[2]));
776: break;
777: default:
778: // ignore
779: break;
780: }
781: }
782: if (isVerbose()) {
783: System.out.println("Supported locales: ");
784: for (Locale l : supportedLocales) {
785: System.out.println(l);
786: }
787: }
788: }
789:
790: private static final String JDK_HEADER_PNG_KEY = "@@JDK_HEADER_PNG@@";
791: private static final String JDK_VERSION_KEY = "@@JDK_VERSION@@";
792: private static final String REGISTRATION_URL_KEY = "@@REGISTRATION_URL@@";
793: private static final String REGISTRATION_PAYLOAD_KEY = "@@REGISTRATION_PAYLOAD@@";
794:
795: @SuppressWarnings("unchecked")
796: private static void generateRegisterHtml(String parent)
797: throws IOException {
798: int version = Util.getJdkVersion();
799: int update = Util.getUpdateVersion();
800: String jdkVersion = "Version " + version;
801: if (update > 0) {
802: // product name is not translated
803: jdkVersion += " Update " + update;
804: }
805: RegistrationData regData = getRegistrationData();
806: String registerURL = SunConnection.getRegistrationURL(
807: regData.getRegistrationURN()).toString();
808: // Make sure it uses the canonical path before getting the URI.
809: File img = new File(svcTagDir.getCanonicalPath(),
810: "jdk_header.png");
811: String headerImageSrc = img.toURI().toString();
812:
813: // Format the registration data in one single line
814: StringBuilder payload = new StringBuilder();
815: String xml = regData.toString().replaceAll("\"", "%22");
816: BufferedReader reader = new BufferedReader(
817: new StringReader(xml));
818: try {
819: String line = null;
820: while ((line = reader.readLine()) != null) {
821: payload.append(line.trim());
822: }
823: } finally {
824: reader.close();
825: }
826:
827: String resourceFilename = "/com/sun/servicetag/resources/register";
828: for (Locale locale : supportedLocales) {
829: String name = REGISTRATION_HTML_NAME;
830: String resource = resourceFilename;
831: if (!locale.equals(Locale.ENGLISH)) {
832: name += "_" + locale.toString();
833: resource += "_" + locale.toString();
834: }
835: File f = new File(parent, name + ".html");
836: InputStream in = null;
837: BufferedReader br = null;
838: PrintWriter pw = null;
839: try {
840: in = Installer.class.getClass().getResourceAsStream(
841: resource + ".html");
842: if (in == null) {
843: // if the resource file is missing
844: if (isVerbose()) {
845: System.out.println("Missing resouce file: "
846: + resource + ".html");
847: }
848: continue;
849: }
850: if (isVerbose()) {
851: System.out.println("Generating " + f + " from "
852: + resource + ".html");
853: }
854:
855: br = new BufferedReader(new InputStreamReader(in,
856: "UTF-8"));
857: pw = new PrintWriter(f, "UTF-8");
858: String line = null;
859: while ((line = br.readLine()) != null) {
860: String output = line;
861: if (line.contains(JDK_VERSION_KEY)) {
862: output = line.replace(JDK_VERSION_KEY,
863: jdkVersion);
864: } else if (line.contains(JDK_HEADER_PNG_KEY)) {
865: output = line.replace(JDK_HEADER_PNG_KEY,
866: headerImageSrc);
867: } else if (line.contains(REGISTRATION_URL_KEY)) {
868: output = line.replace(REGISTRATION_URL_KEY,
869: registerURL);
870: } else if (line.contains(REGISTRATION_PAYLOAD_KEY)) {
871: output = line.replace(REGISTRATION_PAYLOAD_KEY,
872: payload.toString());
873: }
874: pw.println(output);
875: }
876: f.setReadOnly();
877: pw.flush();
878: } finally {
879: if (pw != null) {
880: pw.close();
881: }
882: if (in != null) {
883: in.close();
884: }
885: if (br != null) {
886: br.close();
887: }
888: }
889: }
890: }
891:
892: /**
893: * A utility class to create a service tag for Java SE.
894: * <p>
895: * <b>Usage:</b><br>
896: * <blockquote><tt>
897: * <JAVA_HOME>/bin/java com.sun.servicetag.Installer
898: * </tt></blockquote>
899: * <p>
900: */
901: public static void main(String[] args) {
902: String source = "Manual";
903:
904: // Parse the options (arguments starting with "-" )
905: boolean delete = false;
906: boolean update = false;
907: boolean register = false;
908: int count = 0;
909: while (count < args.length) {
910: String arg = args[count];
911: if (arg.trim().length() == 0) {
912: // skip empty arguments
913: count++;
914: continue;
915: }
916:
917: if (arg.equals("-source")) {
918: source = args[++count];
919: } else if (arg.equals("-delete")) {
920: delete = true;
921: } else if (arg.equals("-register")) {
922: register = true;
923: } else {
924: usage();
925: return;
926: }
927: count++;
928: }
929: try {
930: if (delete) {
931: deleteRegistrationData();
932: } else {
933: ServiceTag[] javaSvcTags = getJavaServiceTagArray();
934: String[] archs = getJreArchs();
935: if (javaSvcTags.length > archs.length) {
936: // 64-bit has been uninstalled
937: // so remove the service tag
938: updateRegistrationData(source);
939: } else {
940: // create the service tag
941: createServiceTag(source);
942: }
943: }
944:
945: if (register) {
946: // Registration is only supported by JDK
947: // For testing purpose, override with a "servicetag.enable.registration" property
948:
949: RegistrationData regData = getRegistrationData();
950: if (supportRegistration
951: && !regData.getServiceTags().isEmpty()) {
952: SunConnection.register(regData);
953: }
954: }
955: System.exit(0);
956: } catch (IOException e) {
957: System.err.println("I/O Error: " + e.getMessage());
958: if (isVerbose()) {
959: e.printStackTrace();
960: }
961: } catch (IllegalArgumentException ex) {
962: if (isVerbose()) {
963: ex.printStackTrace();
964: }
965: } catch (Exception e) {
966: System.err.println("Error: " + e.getMessage());
967: if (isVerbose()) {
968: e.printStackTrace();
969: }
970: }
971: System.exit(1);
972: }
973:
974: private static void usage() {
975: System.out.println("Usage:");
976: System.out.print(" " + Installer.class.getName());
977: System.out.println(" [-delete|-source <source>|-register]");
978: System.out
979: .println(" to create a service tag for the Java platform");
980: System.out.println("");
981: System.out.println("Internal Options:");
982: System.out
983: .println(" -source: to specify the source of the service tag to be created");
984: System.out.println(" -delete: to delete the service tag ");
985: System.out.println(" -register: to register the JDK");
986: System.out.println(" -help: to print this help message");
987: }
988: }
|