1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * ident        "%Z%%M% %I%     %E% SMI"
  24  *
  25  * Copyright 2001-2003 Sun Microsystems, Inc.  All rights reserved.
  26  * Use is subject to license terms.
  27  */
  28 package com.sun.dhcpmgr.common;
  29 
  30 import java.io.IOException;
  31 import java.text.MessageFormat;
  32 
  33 import com.sun.dhcpmgr.data.ExportHeader;
  34 import com.sun.dhcpmgr.data.ActionError;
  35 import com.sun.dhcpmgr.data.Network;
  36 import com.sun.dhcpmgr.server.DhcpMgr;
  37 import com.sun.dhcpmgr.bridge.BridgeException;
  38 
  39 /**
  40  * ImportController contains the logic to import data from a file to the
  41  * server's data store.  The file must have been written using the export
  42  * procedure defined by ExportController.  Users of this class must implement
  43  * the Importer interface, which allows this class to communicate with the
  44  * user.
  45  * @see Importer
  46  * @see ExportController
  47  */
  48 public class ImportController {
  49     Importer importer;
  50     DhcpMgr server;
  51     String file;
  52     Object ref = null;
  53     ExportHeader header = null;
  54     /*
  55      * The following constants are heuristics used to estimate the time
  56      * required to complete each step of the import process; they're used to
  57      * allow a GUI progress meter to pop up and behave relatively correctly.
  58      * We can't afford from a performance point of view to be precise as it
  59      * would defeat the purpose of our import architecture, so we try to
  60      * make sure the user gets at least some idea of where we are in the
  61      * process.  The *OPS constants indicate an estimate of how expensive
  62      * the various operations are relative to each other in a "typical"
  63      * import, the assumption being that there are 5 macros exported to every
  64      * option exported, and that there are around 150 clients per network.
  65      * Obviously these can vary widely, but it gets the idea across pretty well.
  66      */
  67     private static final int OPTION_OPS = 1;
  68     private static final int MACRO_OPS = 5;
  69     private static final int NET_OPS = 150;
  70 
  71     /**
  72      * Construct an ImportController with the given Importer and server
  73      * implementation to use for the import process.  Don't pass in "null"
  74      * for either argument; the implementation does not validate these inputs.
  75      * @param importer The importing object
  76      * @param server The server which will perform the work
  77      */
  78     public ImportController(Importer importer, DhcpMgr server) {
  79         this.importer = importer;
  80         this.server = server;
  81     }
  82 
  83     /**
  84      * Set the name of the file to be used for the import
  85      * @param file The name of the file.
  86      */
  87     public void setFile(String file) {
  88         // We can only have one file open at a time; close any currently open.
  89         closeFile();
  90         this.file = file;
  91     }
  92 
  93     /**
  94      * Close the file and clean up references
  95      */
  96     public void closeFile() {
  97         if (ref != null) {
  98             try {
  99                 // We *never* delete the file here
 100                 server.closeImportFile(ref, false);
 101             } catch (IOException e) {
 102                 displayError(ResourceStrings.getString("imp_err_io"),
 103                     e.getMessage());
 104             }
 105         }
 106         ref = null;
 107         header = null;
 108     }
 109     /**
 110      * Retrieve the header from the file.
 111      * @return the header record from the file
 112      */
 113     public ExportHeader getHeader()
 114             throws ClassNotFoundException, IOException {
 115         // If header not already read, then read it
 116         if (header == null) {
 117             // If file not yet open, then open it now
 118             if (ref == null) {
 119                 ref = server.openImportFile(file);
 120                 if (ref == null) {
 121                     // Import/export lock not available, display error and abort
 122                     String [] args = new String[2];
 123                     args[0] = server.getDhcpServiceMgr().getServerName();
 124                     args[1] = server.getLockPath();
 125                     MessageFormat form = new MessageFormat(
 126                         ResourceStrings.getString("lock_error"));
 127                     importer.displayError(form.format(args));
 128                     return null;
 129                 }
 130             }
 131             header = server.getExportHeader(ref);
 132         }
 133         return header;
 134     }
 135 
 136     /**
 137      * Import the data, optionally overwriting any conflicting data
 138      * @param overwrite true if conflicting objects should be overwritten.
 139      * @return true if the import completed successfully, false if not
 140      */
 141     public boolean importData(boolean overwrite) {
 142         // Default return is that import did not complete
 143         boolean retval = false;
 144         int totalOps = 0;
 145         try {
 146             // Ensure file is open and header has been read
 147             if (getHeader() == null) {
 148                 // Couldn't get header; abort
 149                 return false;
 150             }
 151 
 152             /*
 153              * Initialize progress display; recCount is number of networks + 
 154              * one for macros and one for options.
 155              */
 156             int recCount = header.getRecCount();
 157             totalOps = OPTION_OPS + MACRO_OPS + NET_OPS * (recCount - 2);
 158             importer.initializeProgress(totalOps);
 159             int progress = 0;
 160 
 161             //  Update progress, and import the options
 162             importer.updateProgress(progress,
 163                 ResourceStrings.getString("importing_options"));
 164             ActionError [] result = server.importOptions(ref, overwrite);
 165             if (result.length > 0) {
 166                 importer.displayErrors(
 167                     ResourceStrings.getString("imp_err_importing_options"),
 168                     ResourceStrings.getString("imp_option"), result);
 169             }
 170 
 171             // Update progress and import the macros
 172             progress += OPTION_OPS;
 173             importer.updateProgress(progress, 
 174                 ResourceStrings.getString("importing_macros"));
 175             result = server.importMacros(ref, overwrite);
 176             if (result.length > 0) {
 177                 importer.displayErrors(
 178                     ResourceStrings.getString("imp_err_importing_macros"),
 179                     ResourceStrings.getString("imp_macro"), result);
 180             }
 181 
 182             // Set up for network progress messages
 183             progress += MACRO_OPS;
 184             MessageFormat form = new MessageFormat(
 185                 ResourceStrings.getString("importing_network"));
 186             String [] args = new String[1];
 187 
 188             /*
 189              * Get list of networks from the header; ExportController never
 190              * writes a null reference, always a zero-length array at worst.
 191              */
 192             Network [] nets = header.getNetworks();
 193             for (int i = 0; i < nets.length; ++i) {
 194                 // For each network, update progress and import it
 195                 args[0] = nets[i].toString();
 196                 importer.updateProgress(progress, form.format(args));
 197                 result = server.importNetwork(nets[i], ref, overwrite);
 198                 if (result.length > 0) {
 199                     MessageFormat errFmt = new MessageFormat(
 200                         ResourceStrings.getString("imp_err_importing_net"));
 201                     importer.displayErrors(errFmt.format(args),
 202                         ResourceStrings.getString("imp_address"), result);
 203                 }
 204                 progress += NET_OPS;
 205             }
 206             retval = true;
 207         } catch (InterruptedException e) {
 208             // User asked us to stop; nothing to do but let it fall through
 209         } catch (ClassNotFoundException e) {
 210             // Bad version of file
 211             displayError(ResourceStrings.getString("imp_err_file_fmt"),
 212                 e.getMessage());
 213         } catch (Exception e) {
 214             // Error reading the file
 215             displayError(ResourceStrings.getString("imp_err_io"),
 216                 e.getMessage());
 217         } finally {
 218             // Finish progress
 219             try {
 220                 importer.updateProgress(totalOps,
 221                     ResourceStrings.getString("import_completed"));
 222             } catch (InterruptedException e) {
 223                 // Ignore
 224             }
 225             // Always close import file
 226             closeFile();
 227         }
 228         return retval;
 229     }
 230 
 231     private void displayError(String format, String data) {
 232         MessageFormat form = new MessageFormat(format);
 233         String [] args = new String [] { data };
 234         importer.displayError(form.format(args));
 235     }
 236 }