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 }