1 /*
   2  * $Id$
   3  *
   4  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   6  *
   7  * This code is free software; you can redistribute it and/or modify it
   8  * under the terms of the GNU General Public License version 2 only, as
   9  * published by the Free Software Foundation.  Oracle designates this
  10  * particular file as subject to the "Classpath" exception as provided
  11  * by Oracle in the LICENSE file that accompanied this code.
  12  *
  13  * This code is distributed in the hope that it will be useful, but WITHOUT
  14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16  * version 2 for more details (a copy is included in the LICENSE file that
  17  * accompanied this code).
  18  *
  19  * You should have received a copy of the GNU General Public License version
  20  * 2 along with this work; if not, write to the Free Software Foundation,
  21  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  22  *
  23  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  24  * or visit www.oracle.com if you need additional information or have any
  25  * questions.
  26  */
  27 package com.sun.javatest.tool.jthelp;
  28 
  29 import com.sun.javatest.ProductInfo;
  30 import com.sun.javatest.tool.Preferences;
  31 
  32 import javax.swing.*;
  33 import java.awt.*;
  34 import java.awt.event.ActionEvent;
  35 import java.awt.event.ActionListener;
  36 import java.awt.event.KeyEvent;
  37 import java.io.*;
  38 import java.net.URL;
  39 import java.nio.charset.StandardCharsets;
  40 import java.util.Enumeration;
  41 import java.util.HashMap;
  42 import java.util.Scanner;
  43 import java.util.jar.JarEntry;
  44 import java.util.jar.JarFile;
  45 
  46 public class JTHelpBroker implements HelpBroker{
  47 
  48     private static final String HELP_DIR_NAME = "jthelp";
  49     private static final String HELP_VERSION_NAME = "version";
  50     private static final String HELP_FILE_PREFIX = "/com/sun/javatest/help/default/";
  51     private static final String HELP_FILE_NAME = "map.xml";
  52     private HashMap<String, String> helpMap;
  53 
  54     public JTHelpBroker(){
  55         this(HelpBroker.class.getResource(HELP_FILE_PREFIX+HELP_FILE_NAME));
  56     }
  57 
  58     private JTHelpBroker(URL url){
  59         helpMap = HelpSet.readHelpMap(url);
  60     }
  61 
  62     public void enableHelpKey(final Component component, String helpID){
  63         if (component instanceof JComponent) {
  64             KeyStroke keystroke = KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0, false);
  65             ((JComponent)component).registerKeyboardAction(new ActionListener() {
  66                 @Override
  67                 public void actionPerformed(ActionEvent e) {
  68                     displayCurrentID(ContextHelpManager.getHelpIDString(component));
  69                 }
  70             }, keystroke, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
  71         }
  72         ContextHelpManager.setHelpIDString(component, helpID);
  73     }
  74 
  75     private boolean isHelpUpToDate(){
  76         File helpDir = new File(Preferences.getPrefsDir(), HELP_DIR_NAME);
  77         if (!helpDir.exists()) {
  78             return false;
  79         }
  80         File helpVersion = new File(helpDir, HELP_VERSION_NAME);
  81         try {
  82             Scanner scanner = new Scanner(helpVersion, StandardCharsets.UTF_8.name());
  83             String version = scanner.nextLine();
  84             if (version == null || !version.equals(ProductInfo.getVersion()+ProductInfo.getBuildNumber())){
  85                 return false;
  86             }
  87         } catch (IOException e) {
  88             return false;
  89         }
  90 
  91 
  92         return true;
  93     }
  94 
  95     private void unpackHelpIfNeeded(){
  96 
  97         if (isHelpUpToDate()){
  98             return;
  99         }
 100 
 101         JTHelpProgressBar jtHelpProgressBar = new JTHelpProgressBar(new ProgressTask());
 102         jtHelpProgressBar.createAndShowGUI();
 103 
 104     }
 105 
 106     public void displayCurrentID(String helpID){
 107 
 108         unpackHelpIfNeeded();
 109 
 110         try {
 111             File helpDir = new File(Preferences.getPrefsDir(), HELP_DIR_NAME);
 112             String helpPage = helpMap.get(helpID) != null ? helpMap.get(helpID) : "jthelp.html";
 113             StringBuilder address = new StringBuilder();
 114             address.append("file:").append(helpDir.getAbsolutePath()).append(HELP_FILE_PREFIX).append(helpPage);
 115             URL url = new URL(address.toString());
 116             Desktop.getDesktop().browse(url.toURI());
 117         } catch (Exception e) {
 118             System.err.println("Cannot open JavaTest help file:");
 119             System.err.println(e.getMessage());
 120         }
 121     }
 122 
 123     class ProgressTask extends SwingWorker<Void, Void> {
 124         @Override
 125         public Void doInBackground() {
 126             try {
 127                 File jarFile = new File(HelpBroker.class.getProtectionDomain().getCodeSource().getLocation().toURI());
 128                 File destDir = new File(Preferences.getPrefsDir(), HELP_DIR_NAME);
 129                 File helpVersion = new File(destDir, HELP_VERSION_NAME);
 130 
 131                 JarFile jar = new JarFile(jarFile);
 132                 Enumeration enumEntries = jar.entries();
 133 
 134                 int total = 0;
 135                 while (enumEntries.hasMoreElements()) {
 136                     JarEntry file = (JarEntry) enumEntries.nextElement();
 137                     if (isHelpFile(file)) {
 138                         total++;
 139                     }
 140                 }
 141 
 142                 if (destDir.exists()){
 143                     destDir.delete();
 144                 }
 145 
 146                 destDir.mkdir();
 147 
 148                 int progress = 0;
 149                 setProgress((int) (progress * 100.0 / total));
 150                 enumEntries = jar.entries();
 151 
 152                 while (enumEntries.hasMoreElements()) {
 153                     JarEntry file = (JarEntry) enumEntries.nextElement();
 154                     File f = new java.io.File(destDir + java.io.File.separator + file.getName());
 155                     if (isHelpFile(file)) {
 156                         f.getParentFile().mkdirs();
 157                         InputStream is = jar.getInputStream(file);
 158                         FileOutputStream fos = new java.io.FileOutputStream(f);
 159                         while (is.available() > 0) {
 160                             fos.write(is.read());
 161                         }
 162                         fos.close();
 163                         is.close();
 164                         progress++;
 165                         setProgress((int) (progress * 100.0 / total));
 166                     }
 167                 }
 168 
 169                 try(PrintWriter out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(helpVersion), StandardCharsets.UTF_8))){
 170                     out.println(ProductInfo.getVersion()+ProductInfo.getBuildNumber());
 171                 }
 172 
 173             }
 174             catch (Exception e){
 175                 System.err.println("Cannot unpack JavaTest help files");
 176                 System.err.println(e.getMessage());
 177             }
 178 
 179             return null;
 180         }
 181 
 182         private boolean isHelpFile(JarEntry file) {
 183             return  (file.getName().endsWith(".html")
 184                     || file.getName().endsWith(".gif")
 185                     || file.getName().endsWith(".css"));
 186         }
 187 
 188     }
 189 
 190 }