1 /*
   2  * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.servicetag;
  27 
  28 import java.io.*;
  29 import java.net.URISyntaxException;
  30 import java.net.URL;
  31 import java.net.HttpURLConnection;
  32 import java.net.MalformedURLException;
  33 import java.io.OutputStreamWriter;
  34 import java.util.Locale;
  35 import javax.net.ssl.HttpsURLConnection;
  36 
  37 /**
  38  * Sun Connection Class for Product Registration.
  39  *
  40  * Registration Web Application Interface
  41  * 1) POST the product registry to the output stream of the registration
  42  *    relay service.
  43  * 2) Open the webapp URL from a browser with the following parameters:
  44  *    registry-urn
  45  *    product=jdk
  46  *    locale=<default-locale>
  47  *    version=<version>
  48  *
  49  * @see https://sn-tools.central.sun.com/twiki/pub/ServiceTags/RegistrationRelayService/
  50  *
  51  */
  52 class SunConnection {
  53 
  54     private static String JDK_REGISTRATION_URL = "https://hs-ws1.oracle.com/";
  55     private static String SANDBOX_TESTING_URL = "https://hs-ws1-tst.oracle.com/";
  56     private static String REGISTRATION_WEB_PATH = "RegistrationWeb/register";
  57 
  58     // System properties for testing
  59     private static String SVCTAG_REGISTER_TESTING = "servicetag.register.testing";
  60     private static String SVCTAG_REGISTRATION_URL = "servicetag.registration.url";
  61     private static String SVCTAG_CONNECTION_TIMEOUT = "servicetag.connection.timeout";
  62 
  63     private SunConnection() {
  64     }
  65 
  66     /**
  67      * Returns a URL for JDK registration interfacing with the Sun Connection
  68      * registration relay service in this form:
  69      *   <registration-url>/<registry_urn>?product=jdk&locale=<locale>
  70      *
  71      * The <registration-url> can be overridden by an environment
  72      * variable or a system property.
  73      *
  74      * 1) "servicetag.register.testing" system property to switch to the
  75      *    Sun Connection registration sandbox testing.
  76      * 2) "servicetag.registration.url" system property to override
  77      *    the URL
  78      * 3) Default production URL
  79      *
  80      */
  81     static URL getRegistrationURL(String registrationURN, Locale locale, String version) {
  82         String url = System.getProperty(SVCTAG_REGISTRATION_URL);
  83         if (url == null) {
  84             if (System.getProperty(SVCTAG_REGISTER_TESTING) != null) {
  85                 url = SANDBOX_TESTING_URL;
  86             } else {
  87                 url = JDK_REGISTRATION_URL;
  88             }
  89         }
  90         url += REGISTRATION_WEB_PATH;
  91 
  92         // trim whitespaces
  93         url = url.trim();
  94         if (url.length() == 0) {
  95             throw new InternalError("Empty registration url set");
  96         }
  97 
  98         // Add the registry_urn in the URL's query
  99         String registerURL = rewriteURL(url, registrationURN, locale, version);
 100         try {
 101             return new URL(registerURL);
 102         } catch (MalformedURLException ex) {
 103             // should never reach here
 104             throw new InternalError(ex.getMessage(), ex);
 105         }
 106     }
 107 
 108     private static String rewriteURL(String url, String registryURN, Locale locale, String version) {
 109         StringBuilder sb = new StringBuilder(url.trim());
 110         int len = sb.length();
 111         if (sb.charAt(len-1) != '/') {
 112             sb.append('/');
 113         }
 114         sb.append(registryURN);
 115         sb.append("?");
 116         sb.append("product=jdk");
 117         sb.append("&");
 118         sb.append("locale=").append(locale.toString());
 119         sb.append("&");
 120         sb.append("version=").append(version);
 121         return sb.toString();
 122     }
 123 
 124     /**
 125      * Registers all products in the given product registry.  If it fails
 126      * to post the service tag registry, open the browser with the offline
 127      * registration page.
 128      *
 129      * @param regData registration data to be posted to the Sun Connection
 130      *             for registration.
 131      * @param locale Locale
 132      * @param version JDK version
 133      *
 134      * @throws IOException if I/O error occurs in this operation
 135      */
 136     public static void register(RegistrationData regData,
 137                                 Locale locale,
 138                                 String version) throws IOException {
 139         // Gets the URL for SunConnection registration relay service
 140         URL url = getRegistrationURL(regData.getRegistrationURN(),
 141                                      locale,
 142                                      version);
 143 
 144         // Post the Product Registry to Sun Connection
 145         boolean succeed = postRegistrationData(url, regData);
 146         if (succeed) {
 147             // service tags posted successfully
 148             // now prompt for registration
 149             openBrowser(url);
 150         } else {
 151             // open browser with the offline registration page
 152             openOfflineRegisterPage();
 153         }
 154     }
 155 
 156     /**
 157      * Opens a browser for JDK product registration.
 158      * @param url Registration Webapp URL
 159      */
 160     private static void openBrowser(URL url) throws IOException {
 161         if (!BrowserSupport.isSupported()) {
 162             if (Util.isVerbose()) {
 163                 System.out.println("Browser is not supported");
 164             }
 165             return;
 166         }
 167 
 168         try {
 169             BrowserSupport.browse(url.toURI());
 170         } catch (URISyntaxException ex) {
 171             throw new InternalError("Error in registering: " + ex.getMessage(), ex);
 172         } catch (IllegalArgumentException ex) {
 173             if (Util.isVerbose()) {
 174                 ex.printStackTrace();
 175             }
 176         } catch (UnsupportedOperationException ex) {
 177             // ignore if not supported
 178             if (Util.isVerbose()) {
 179                 ex.printStackTrace();
 180             }
 181         }
 182     }
 183 
 184     /**
 185      * POST service tag registry to Sun Connection
 186      * @param loc the URL of the webapp to handle the POST request
 187      * @param streg the Service Tag registry
 188      * @return true if posting succeeds; otherwise, false.
 189      */
 190     private static boolean postRegistrationData(URL url,
 191                                                 RegistrationData registration) {
 192         try {
 193             HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
 194             con.setDoInput(true);
 195             con.setDoOutput(true);
 196             con.setUseCaches(false);
 197             con.setAllowUserInteraction(false);
 198 
 199             // default 10 seconds timeout
 200             String timeout = System.getProperty(SVCTAG_CONNECTION_TIMEOUT, "10");
 201             con.setConnectTimeout(Util.getIntValue(timeout) * 1000);
 202 
 203             if (Util.isVerbose()) {
 204                 System.out.println("Connecting to post registration data at " + url);
 205             }
 206 
 207             con.setRequestMethod("POST");
 208             con.setRequestProperty("Content-Type", "text/xml;charset=\"utf-8\"");
 209             con.connect();
 210 
 211             OutputStream out = null;
 212             try {
 213                 out = con.getOutputStream();
 214                 registration.storeToXML(out);
 215                 out.flush();
 216             } finally {
 217                 if (out != null) {
 218                     out.close();
 219                 }
 220             }
 221 
 222             int returnCode = con.getResponseCode();
 223             if (Util.isVerbose()) {
 224                 System.out.println("POST return status = " + returnCode);
 225                 printReturnData(con, returnCode);
 226             }
 227             return (returnCode == HttpURLConnection.HTTP_OK);
 228         } catch (MalformedURLException me) {
 229             // should never reach here
 230             throw new InternalError("Error in registering: " + me.getMessage(), me);
 231         } catch (Exception ioe) {
 232             // SocketTimeoutException, IOException or UnknownHostException
 233             if (Util.isVerbose()) {
 234                 ioe.printStackTrace();
 235             }
 236             return false;
 237         }
 238     }
 239 
 240     /**
 241      * Opens the offline registratioin page in the browser.
 242      *
 243      */
 244     private static void openOfflineRegisterPage()
 245             throws IOException {
 246         if (!BrowserSupport.isSupported()) {
 247             if (Util.isVerbose()) {
 248                 System.out.println("Browser is not supported");
 249             }
 250             return;
 251         }
 252 
 253         File registerPage = Installer.getRegistrationHtmlPage();
 254         try {
 255             BrowserSupport.browse(registerPage.toURI());
 256         } catch (FileNotFoundException ex) {
 257             // should never reach here
 258             throw new InternalError(
 259                     "Error in launching " + registerPage + ": " + ex.getMessage()
 260                     , ex);
 261         } catch (IllegalArgumentException ex) {
 262             if (Util.isVerbose()) {
 263                 ex.printStackTrace();
 264             }
 265         } catch (UnsupportedOperationException ex) {
 266             // ignore if not supported
 267             if (Util.isVerbose()) {
 268                 ex.printStackTrace();
 269             }
 270         }
 271     }
 272 
 273     private static void printReturnData(HttpURLConnection con, int returnCode)
 274             throws IOException {
 275         BufferedReader reader = null;
 276         try {
 277             if (returnCode < 400) {
 278                 reader = new BufferedReader(
 279                              new InputStreamReader(con.getInputStream()));
 280             } else {
 281                 reader = new BufferedReader(
 282                              new InputStreamReader(con.getErrorStream()));
 283             }
 284             StringBuilder sb = new StringBuilder();
 285             String line;
 286             while ((line = reader.readLine()) != null) {
 287                 sb.append(line).append("\n");
 288             }
 289             System.out.println("Response is : ");
 290             System.out.println(sb.toString());
 291         } finally {
 292             if (reader != null) {
 293                 reader.close();
 294             }
 295         }
 296     }
 297 }