Coverage Report - org.mule.modules.boot.LicenseHandler
 
Classes in this File Line Coverage Branch Coverage Complexity
LicenseHandler
0%
0/136
0%
0/27
9.333
 
 1  
 /*
 2  
  * $Id $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
 5  
  *
 6  
  * The software in this package is published under the terms of the CPAL v1.0
 7  
  * license, a copy of which has been included with this distribution in the
 8  
  * LICENSE.txt file.
 9  
  */
 10  
 
 11  
 package org.mule.modules.boot;
 12  
 
 13  
 import java.io.BufferedReader;
 14  
 import java.io.File;
 15  
 import java.io.FileInputStream;
 16  
 import java.io.FileOutputStream;
 17  
 import java.io.FileReader;
 18  
 import java.io.IOException;
 19  
 import java.io.InputStreamReader;
 20  
 import java.nio.channels.FileChannel;
 21  
 import java.util.jar.JarEntry;
 22  
 import java.util.jar.JarFile;
 23  
 import java.util.jar.JarOutputStream;
 24  
 import java.util.zip.ZipEntry;
 25  
 
 26  
 /**
 27  
  * This class has methods for displaying the EULA and saving the license acceptance
 28  
  * acknowledgment.
 29  
  */
 30  
 public class LicenseHandler
 31  
 {
 32  
     private File muleHome;
 33  
     private File muleBase;
 34  0
     private static int maxRowsToDisplay = 80;
 35  
 
 36  0
     public static String defaultLicenseType = "MuleSource Public License";
 37  0
     public static String defaultLicenseVersion = "UNKNOWN";
 38  0
     public static String ackJarName = "mule-local-install.jar";
 39  0
     public static String ackLicenseName = "META-INF/mule/LICENSE.txt";
 40  0
     public static String ackFileName = "META-INF/mule/license.props";
 41  0
     public static String licenseFileName = "LICENSE.txt";
 42  
 
 43  
     /**
 44  
      * Constructor for when we only know MULE_HOME This is the constructor that the
 45  
      * GUI installer should use.
 46  
      * 
 47  
      * @param muleHome File pointing to MULE_HOME
 48  
      */
 49  
     public LicenseHandler(File muleHome)
 50  0
     {
 51  0
         this.muleHome = muleHome;
 52  0
         this.muleBase = muleHome;
 53  0
     }
 54  
 
 55  
     /**
 56  
      * Constructor for when we know both MULE_HOME and MULE_BASE This is the
 57  
      * constructor used by MuleBootstrap
 58  
      * 
 59  
      * @param muleHome File pointing to MULE_HOME
 60  
      * @param muleBase File pointing to MULE_BASE
 61  
      */
 62  
     public LicenseHandler(File muleHome, File muleBase)
 63  0
     {
 64  0
         this.muleHome = muleHome;
 65  0
         this.muleBase = muleBase;
 66  0
     }
 67  
 
 68  
     /**
 69  
      * Display the EULA and get the user's acceptance. Note that only a missing
 70  
      * license file or a non-yes answer will cause this to return false. If the user
 71  
      * accepts, but we can't write the license ack file for some reason, we'll still
 72  
      * return true.
 73  
      * 
 74  
      * @return boolean whether the license was accepted or not
 75  
      */
 76  
     public boolean getAcceptance()
 77  
     {
 78  0
         String licenseType = "";
 79  0
         String licenseVersion = "";
 80  
 
 81  
         try
 82  
         {
 83  0
             File licenseFile = new File(muleHome, licenseFileName);
 84  0
             File muleLib = new File(muleHome, "lib/mule");
 85  
 
 86  
             // Make sure the license file exists
 87  
             // Also make sure that MULE_HOME/lib/mule exists - it
 88  
             // should, of course, but it doesn't hurt to check since
 89  
             // we'll need that directory later
 90  
 
 91  0
             if (!licenseFile.exists() || !muleLib.exists())
 92  
             {
 93  0
                 System.out
 94  
                     .println("\nYour Mule installation seems to be incomplete. Please try downloading it again from http://mule.mulesource.org/display/MULE/Download and start again.");
 95  0
                 return false;
 96  
             }
 97  
 
 98  0
             System.out.println("\n\nPlease read over the following license agreement carefully:\n\n");
 99  
 
 100  0
             int row = 1;
 101  0
             String input = "";
 102  
 
 103  0
             BufferedReader is = new BufferedReader(new InputStreamReader(System.in));
 104  0
             BufferedReader br = new BufferedReader(new FileReader(licenseFile));
 105  
 
 106  0
             while (br.ready())
 107  
             {
 108  0
                 String line = br.readLine();
 109  
 
 110  0
                 if (row == 1) licenseType = line;
 111  0
                 if (row == 2 && line.startsWith("Version ")) licenseVersion = line.substring(8);
 112  
 
 113  0
                 if ((row % maxRowsToDisplay) == 0)
 114  
                 {
 115  0
                     System.out.print("\nHit return to continue ... ");
 116  0
                     input = is.readLine();
 117  
                 }
 118  
 
 119  0
                 System.out.println(line);
 120  0
                 row++;
 121  
             }
 122  
 
 123  0
             System.out.print("\n\nDo you accept the terms and conditions of this license agreement [y/n]?");
 124  0
             input = is.readLine();
 125  
 
 126  0
             if (!input.toLowerCase().startsWith("y"))
 127  
             {
 128  0
                 System.out
 129  
                     .println("\nSorry, until you accept the terms and conditions of this EULA, you won't be able to start Mule");
 130  0
                 return false;
 131  
             }
 132  
         }
 133  0
         catch (Exception e)
 134  
         {
 135  0
             System.out
 136  
                 .println("\nSorry, we encountered an error in processing your license agreement - please try again");
 137  0
             return false;
 138  0
         }
 139  
 
 140  0
         if (licenseType.equals("")) licenseType = defaultLicenseType;
 141  0
         if (licenseVersion.equals("")) licenseVersion = defaultLicenseVersion;
 142  
 
 143  
         try
 144  
         {
 145  0
             saveLicenseAck(licenseType, licenseVersion);
 146  
         }
 147  0
         catch (Exception e)
 148  
         {
 149  0
             System.out.println(e);
 150  0
             e.printStackTrace();
 151  0
         }
 152  
 
 153  0
         return true;
 154  
     }
 155  
 
 156  
     /**
 157  
      * Saves the license acceptance acknowledgement file. This method should be used
 158  
      * by the GUI installer.
 159  
      * <p>
 160  
      * For now, the acknowlegment file is license.props and contains:
 161  
      * <ul>
 162  
      * <li>LicenseVersion:
 163  
      * <li>LicenseAcceptanceDate:
 164  
      * <li>LicenseType:
 165  
      * </ul>
 166  
      * We are also making a copy of the license file into the jar as well. The logic
 167  
      * here is:
 168  
      * <ol>
 169  
      * <li> Normally, save the license ack in a jar in MULE_HOME/lib/mule called
 170  
      * "mule-local-install.jar"
 171  
      * <li> If MULE_HOME/lib/mule is not writable AND MULE_BASE != MULE_HOME, try to
 172  
      * save in MULE_BASE/lib/user
 173  
      * <li> If MULE_BASE/lib/user is not writable, something is probably strange and
 174  
      * we need a third option ... which is ... well, I'm sure there is one ...
 175  
      * </ol>
 176  
      * 
 177  
      * @param licenseType type of license - for now, should be just MuleSource Public
 178  
      *            License
 179  
      * @param licenseVersion version of license - for now, should be 1.1.3
 180  
      * @throws Exception if there is nowhere to write the file or somehow the jar
 181  
      *             creation fails (disk full, etc.)
 182  
      */
 183  
     public void saveLicenseAck(String licenseType, String licenseVersion) throws Exception
 184  
     {
 185  0
         File muleLib = new File(muleHome, "lib/mule");
 186  0
         File tempJar = createAckJarFile(licenseType, licenseVersion);
 187  
 
 188  
         // First check if the file exists. We do this in case the license.props
 189  
         // has not yet been loaded into the classpath - which might be the case
 190  
         // with the GUI installer.
 191  0
         if (licenseJarExists())
 192  
         {
 193  0
             return;
 194  
         }
 195  
 
 196  0
         if (!muleLib.canWrite())
 197  
         {
 198  
             // If we can't write to MULE_HOME/lib/mule, try MULE_BASE/lib/user
 199  0
             if (!muleHome.getCanonicalFile().equals(muleBase.getCanonicalFile()))
 200  
             {
 201  0
                 muleLib = new File(muleBase, "lib/user");
 202  
 
 203  0
                 if (!muleLib.canWrite())
 204  0
                     throw new Exception("No write permissions for " + ackJarName
 205  
                                     + " in either MULE_HOME or MULE_BASE");
 206  
 
 207  
             }
 208  
             else
 209  
             {
 210  0
                 throw new Exception("No write permission for " + ackJarName);
 211  
             }
 212  
         }
 213  
 
 214  
         // Now we have a directory to create the jar to, so let's rename
 215  
         // the temporary one
 216  0
         File newJarFile = new File(muleLib, ackJarName);
 217  
 
 218  0
         if (newJarFile.exists())
 219  0
             throw new Exception("Unable to rename temporary jar to " + newJarFile.getAbsolutePath()
 220  
                             + " a file with this name already exists!");
 221  
 
 222  0
         if (!tempJar.renameTo(newJarFile))
 223  
         {
 224  
             // Make sure the file is still there - sometimes renaming
 225  
             // claims to have faild when it actually works
 226  
 
 227  0
             if (!tempJar.exists()) return;
 228  
 
 229  0
             FileChannel srcChannel = null;
 230  0
             FileChannel destChannel = null;
 231  
 
 232  
             try
 233  
             {
 234  0
                 srcChannel = new FileInputStream(tempJar.getAbsolutePath()).getChannel();
 235  0
                 destChannel = new FileOutputStream(newJarFile).getChannel();
 236  0
                 destChannel.transferFrom(srcChannel, 0, srcChannel.size());
 237  0
             }
 238  0
             catch (Exception e)
 239  
             {
 240  0
                 throw new Exception("Unable to rename temporary jar to " + newJarFile.getAbsolutePath(), e);
 241  
             }
 242  
             finally
 243  
             {
 244  0
                 try { if (srcChannel != null) srcChannel.close(); } catch (Exception e1) { }
 245  0
                 try { if (destChannel != null) destChannel.close(); } catch (Exception e2) { }
 246  0
                 try { tempJar.delete(); } catch (Exception e3) { }
 247  0
             }
 248  
         }
 249  
 
 250  0
         if (!newJarFile.exists())
 251  0
             throw new Exception("Unable to rename temporary jar to " + newJarFile.getAbsolutePath());
 252  0
     }
 253  
 
 254  
     /**
 255  
      * This method checks to see if there is a license jar file already. It checks
 256  
      * both MULE_HOME/lib/mule and, if relevant, MULE_BASE/lib/user.
 257  
      */
 258  
 
 259  
     public boolean licenseJarExists()
 260  
     {
 261  
         try
 262  
         {
 263  0
             File muleLib = new File(muleHome, "lib/mule");
 264  0
             File testJarFile = new File(muleLib, ackJarName);
 265  0
             JarFile jar = null;
 266  
 
 267  0
             if (testJarFile.exists())
 268  
             {
 269  0
                 jar = new JarFile(testJarFile);
 270  
             }
 271  
             else
 272  
             {
 273  
                 // Not in MULE_HOME/lib/mule, if MULE_BASE is defined
 274  
                 // (and therefore != MULE_HOME), check in MULE_BASE/lib/user
 275  0
                 if (!muleHome.getCanonicalFile().equals(muleBase.getCanonicalFile()))
 276  
                 {
 277  0
                     muleLib = new File(muleBase, "lib/user");
 278  0
                     testJarFile = new File(muleLib, ackJarName);
 279  
 
 280  0
                     if (testJarFile.exists())
 281  
                     {
 282  0
                         jar = new JarFile(testJarFile);
 283  
                     }
 284  
                 }
 285  
             }
 286  
 
 287  0
             if (jar != null)
 288  
             {
 289  0
                 ZipEntry entry = jar.getEntry(ackFileName);
 290  
 
 291  
                 // The only way this method will return true is if we
 292  
                 // find the license.props file in the jar
 293  0
                 if (entry != null)
 294  
                 {
 295  0
                     return true;
 296  
                 }
 297  
             }
 298  
         }
 299  0
         catch (Exception e)
 300  
         {
 301  0
             System.out.println("Unknown error checking for license jar: " + e.toString());
 302  0
         }
 303  
 
 304  0
         return false;
 305  
     }
 306  
 
 307  
     /**
 308  
      * This method will create a temporary jar file with the license ack file. It
 309  
      * will either return the File or throw an Exception
 310  
      * 
 311  
      * @throws Exception
 312  
      */
 313  
     private File createAckJarFile(String licenseType, String licenseVersion) throws Exception
 314  
     {
 315  0
         File tempJar = File.createTempFile(ackJarName, null);
 316  0
         File licenseFile = new File(muleHome, licenseFileName);
 317  
         JarOutputStream newJar;
 318  
         FileOutputStream fos;
 319  
 
 320  0
         String ackData = "LicenseType=" + licenseType + "\n";
 321  0
         ackData += "LicenseVersion=" + licenseVersion + "\n";
 322  0
         ackData += "LicenseDate=" + (new java.util.Date()).toString() + "\n";
 323  
 
 324  
         try
 325  
         {
 326  0
             fos = new FileOutputStream(tempJar);
 327  0
             newJar = new JarOutputStream(fos);
 328  
         }
 329  0
         catch (IOException ioe)
 330  
         {
 331  0
             throw new Exception("Unable to create temporary jar file");
 332  0
         }
 333  
 
 334  0
         byte buffer[] = new byte[1024];
 335  
         int bytesRead;
 336  0
         FileInputStream fis = null;
 337  
 
 338  
         try
 339  
         {
 340  0
             fis = new FileInputStream(licenseFile);
 341  
 
 342  0
             JarEntry entry = new JarEntry(ackFileName);
 343  0
             newJar.putNextEntry(entry);
 344  0
             newJar.write(ackData.getBytes(), 0, ackData.getBytes().length);
 345  
 
 346  0
             entry = new JarEntry(ackLicenseName);
 347  0
             newJar.putNextEntry(entry);
 348  
 
 349  0
             while ((bytesRead = fis.read(buffer)) != -1)
 350  
             {
 351  0
                 newJar.write(buffer, 0, bytesRead);
 352  
             }
 353  
 
 354  
             // wait till the physical file is written and released by the OS
 355  0
             newJar.flush();
 356  0
             fos.getFD().sync();
 357  0
         }
 358  0
         catch (IOException ioe)
 359  
         {
 360  0
             throw new Exception("Unable to write " + ackFileName + " to temporary jar file");
 361  
         }
 362  
         finally
 363  
         {
 364  0
             if (fis != null)
 365  
             {
 366  
                 try
 367  
                 {
 368  0
                     fis.close();
 369  
                 }
 370  0
                 catch (Exception e)
 371  
                 {
 372  
                     // ignored
 373  0
                 }
 374  
             }
 375  0
         }
 376  
 
 377  
         try
 378  
         {
 379  0
             newJar.close();
 380  
         }
 381  0
         catch (IOException ioe)
 382  
         {
 383  0
             throw new Exception("Unable to close temporary jar file");
 384  0
         }
 385  
 
 386  0
         return tempJar;
 387  
     }
 388  
 
 389  
 }