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 }