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      */
ImportController(Importer importer, DhcpMgr server)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      */
setFile(String file)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      */
closeFile()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      */
getHeader()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      */
importData(boolean overwrite)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 
displayError(String format, String data)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 }
237