~ubuntu-branches/ubuntu/wily/389-ds-console/wily-proposed

« back to all changes in this revision

Viewing changes to src/com/netscape/admin/dirserv/CloneServer.java

  • Committer: Package Import Robot
  • Author(s): Timo Aaltonen
  • Date: 2012-03-15 19:58:37 UTC
  • Revision ID: package-import@ubuntu.com-20120315195837-296zyft51thld8q7
Tags: upstream-1.2.6
ImportĀ upstreamĀ versionĀ 1.2.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** BEGIN COPYRIGHT BLOCK
 
2
 * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
 
3
 * Copyright (C) 2005 Red Hat, Inc.
 
4
 * All rights reserved.
 
5
 * 
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation version 2 of the License.
 
9
 * 
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 * 
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 * END COPYRIGHT BLOCK **/
 
19
 
 
20
package com.netscape.admin.dirserv;
 
21
 
 
22
import java.util.*;
 
23
import java.net.*;
 
24
import java.awt.*;
 
25
import java.awt.event.ActionEvent;
 
26
import java.awt.event.ActionListener;
 
27
import javax.swing.*;
 
28
import com.netscape.management.client.*;
 
29
import com.netscape.management.client.console.ConsoleInfo;
 
30
import com.netscape.management.client.util.ResourceSet;
 
31
import com.netscape.management.client.util.Debug;
 
32
import com.netscape.management.client.util.RemoteImage;
 
33
import com.netscape.management.client.util.LDAPUtil;
 
34
import com.netscape.management.client.util.UtilConsoleGlobals;
 
35
import netscape.ldap.*;
 
36
import netscape.ldap.util.*;
 
37
import com.netscape.admin.dirserv.task.CGITask;
 
38
import com.netscape.admin.dirserv.task.Remove;
 
39
import com.netscape.admin.dirserv.task.Start;
 
40
 
 
41
/**
 
42
 * Handles cloning of directory servers over LDAP.  There will be a source
 
43
 * LDAP server and a destination LDAP server.  There will also be a
 
44
 * connection to the Configuration server because we will need to read
 
45
 * some entries from that server.
 
46
 *
 
47
 * @author      richm
 
48
 * @version %I%, %G%
 
49
 * @date                07/10/98
 
50
 */
 
51
 
 
52
public class CloneServer {
 
53
 
 
54
        /**
 
55
         * The configDS is the connection to the Configuration directory where
 
56
         * the topology and SIE information is stored.  The sourceDN is the SIE
 
57
         * of the source DS, and the destDN is the SIE of the destination DS.
 
58
         */
 
59
        public static boolean cloneServer(LDAPConnection configDS, String sourceDN,
 
60
                                                                          String destDN, JFrame frame) {
 
61
                Debug.println("CloneServer.cloneServer: begin: configDS=" +
 
62
                                          DSUtil.format(configDS) + " sourceDN=" + sourceDN +
 
63
                                          " destDN=" + destDN);
 
64
                // sourceValues will contain the attribute/value pairs from the DN
 
65
                Hashtable sourceValues = new Hashtable();
 
66
                LDAPConnection source = getConnection(configDS, sourceDN, sourceValues,
 
67
                                                                                          frame);
 
68
                if (source == null)
 
69
                        return false;
 
70
 
 
71
                // destValues will contain the attribute/value pairs from the DN
 
72
                Hashtable destValues = new Hashtable();
 
73
                LDAPConnection dest = getConnection(configDS, destDN, destValues,
 
74
                                                                                        frame);
 
75
                if (dest == null) {
 
76
                        try {
 
77
                                source.disconnect();
 
78
                        } catch (Exception e) {
 
79
                        }
 
80
                        return false;
 
81
                }
 
82
 
 
83
                // now we have ldap connections to the source and destination for the
 
84
                // clone; we want to read the configuration entries in the source and
 
85
                // write the values to the corresponding entries on the destination
 
86
                DN[] entryList = getEntriesToClone(source, frame);
 
87
                if (entryList == null) {
 
88
                        DSUtil.showErrorDialog(frame, "clonesourceempty", "cn=config");
 
89
                        try {
 
90
                                source.disconnect();
 
91
                        } catch (Exception e) {
 
92
                        }
 
93
                        try {
 
94
                                dest.disconnect();
 
95
                        } catch (Exception e) {
 
96
                        }
 
97
                        return false;
 
98
                }
 
99
 
 
100
                for (int ii = 0; ii < entryList.length; ++ii) {
 
101
                        Debug.println("entryList[" + ii + "]=" + entryList[ii]);
 
102
                }
 
103
 
 
104
                String oldDir = replace(sourceValues.get("serverroot").toString() +
 
105
                                                                "/" +
 
106
                                                                sourceValues.get("nsserverid").toString(),
 
107
                                                                "\\", "/");
 
108
 
 
109
                String newDir = replace(destValues.get("serverroot").toString() +
 
110
                                                                "/" +
 
111
                                                                destValues.get("nsserverid").toString(),
 
112
                                                                "\\", "/");
 
113
 
 
114
                // some attributes can only be cloned if the servers are not
 
115
                // running on the same host, so we need to determine if the
 
116
                // source and destination hosts are the same
 
117
                String sourceHost = (String)sourceValues.get("serverhostname");
 
118
                try {
 
119
                        sourceHost = DSUtil.canonicalHost(sourceHost);
 
120
                } catch (UnknownHostException e) {
 
121
                }
 
122
                if (sourceHost == null || sourceHost.equals(""))
 
123
                        sourceHost = (String)sourceValues.get("serverhostname");
 
124
 
 
125
                String destHost = (String)destValues.get("serverhostname");
 
126
                try {
 
127
                        destHost = DSUtil.canonicalHost(destHost);
 
128
                } catch (UnknownHostException e) {
 
129
                }
 
130
                if (destHost == null || destHost.equals(""))
 
131
                        destHost = (String)destValues.get("serverhostname");
 
132
 
 
133
                boolean hostsAreSame = sourceHost.equalsIgnoreCase(destHost);
 
134
 
 
135
                // for each entry, read it from the source, delete those attributes
 
136
                // we don't want to copy, and write the entry to the destination
 
137
                String err = null; // which error dialog
 
138
                String[] args = null; // arguments for dialog
 
139
                boolean cloneWasSuccessful = true;
 
140
                for (int index = 0;
 
141
                         cloneWasSuccessful && index < entryList.length; ++index) {
 
142
                        LDAPEntry entry = null;
 
143
                        Debug.println("CloneServer.cloneServer: reading entry DN=" +
 
144
                                                  entryList[index].toString());
 
145
                        boolean done = false;
 
146
                        while (!done) {
 
147
                                try {
 
148
                                        entry = source.read(entryList[index].toString());
 
149
                                        // if the entry is null or contains no elements, this
 
150
                                        // usually means that we didn't have permission to read
 
151
                                        // that particular entry, so we need to reauthenticate
 
152
                                        // as a more priviledged user
 
153
                                        if (entry == null) {
 
154
                                                throw new LDAPException("no elements",
 
155
                                                        LDAPException.INSUFFICIENT_ACCESS_RIGHTS);
 
156
                                        }
 
157
                                        done = true;
 
158
                                } catch (LDAPException lde) {
 
159
                                        done = reauthenticate(source, lde,
 
160
                                                                                  entryList[index].toString(),
 
161
                                                                                  frame, "clonesourceread");
 
162
                                        if (done) // unhandled error or cancel
 
163
                                                cloneWasSuccessful = false;
 
164
                                }
 
165
                        }
 
166
 
 
167
                        if (entry != null) {
 
168
                                Debug.println("CloneServer.cloneServer: modifying DN=" +
 
169
                                                          entry.getDN());
 
170
                                LDAPModificationSet ldapmodset = getMods(entry, dest, frame,
 
171
                                                                                                                 hostsAreSame, oldDir,
 
172
                                                                                                                 newDir);
 
173
 
 
174
                                done = false;
 
175
                                if (ldapmodset == null || ldapmodset.size() == 0) {
 
176
                                        done = true; // nothing to be done
 
177
                                } else {
 
178
                                        Debug.println("CloneServer.cloneServer: DN=" +
 
179
                                                                  entry.getDN() + " num attrs to modify=" +
 
180
                                                                  ldapmodset.size());
 
181
                                }
 
182
                                while (!done) {
 
183
                                        try {
 
184
                                                dest.modify(entryList[index].toString(), ldapmodset);
 
185
                                                done = true;
 
186
                                        } catch (LDAPException lde) {
 
187
                                                done = reauthenticate(dest, lde,
 
188
                                                                                          entryList[index].toString(),
 
189
                                                                                          frame, "clonedestwrite");
 
190
                                                if (done) // unhandled error or cancel
 
191
                                                        cloneWasSuccessful = false;
 
192
                                        }
 
193
                                }
 
194
                        } else { // entry is null
 
195
                                Debug.println("DSAdmin.cloneFrom(): could not read entry " +
 
196
                                                          "from source " + DSUtil.format(source));
 
197
                                err = "clonesourceempty";
 
198
                                args = new String[1];
 
199
                                args[0] = entryList[index].toString();
 
200
                        }
 
201
 
 
202
                        if (err != null) {
 
203
                                DSUtil.showErrorDialog(frame, err, args);
 
204
                                cloneWasSuccessful = false;
 
205
                        }
 
206
                        err = null; // reset for next entry
 
207
                        args = null; // reset for next entry
 
208
                }
 
209
 
 
210
                if (cloneWasSuccessful)
 
211
                        cloneWasSuccessful = cloneSchema(source, dest, frame);
 
212
 
 
213
                try {
 
214
                        source.disconnect();
 
215
                } catch (Exception e) {
 
216
                }
 
217
                try {
 
218
                        dest.disconnect();
 
219
                } catch (Exception e) {
 
220
                }
 
221
 
 
222
                if (cloneWasSuccessful) {
 
223
                        DSUtil.showInformationDialog(frame, "clonesuccess",
 
224
                                                                                 (String)null);
 
225
                } else {
 
226
                        DSUtil.showErrorDialog(frame, "clonefailed", (String)null);
 
227
                }
 
228
 
 
229
                return cloneWasSuccessful;
 
230
        }
 
231
 
 
232
        private static LDAPConnection getConnection(LDAPConnection configDS,
 
233
                                                                                                String sieDN, Hashtable values,
 
234
                                                                                                JFrame frame) {
 
235
                values.put("nsbinddn", "");
 
236
                values.put("cn", "");
 
237
                values.put("serverroot", "");
 
238
                values.put("nsserverid", "");
 
239
 
 
240
                LDAPConnection ldc = null;
 
241
                try {
 
242
                        ldc = DSAdmin.getLDAPConnection(configDS, sieDN,
 
243
                                                                                        "serverhostname",
 
244
                                                                                        "nsserverport",
 
245
                                                                                        values);
 
246
                } catch (LDAPException lde) {
 
247
                        String host = (String)values.get("serverhostname");
 
248
                        String port = (String)values.get("nsserverport");
 
249
                        Debug.println("CloneServer.cloneServer(): could not read DN = " +
 
250
                                                  sieDN + " or connect to " + host + ":" + port +
 
251
                                                  " LDAP exception = " + lde);
 
252
                } catch (Exception other) {
 
253
                        String host = (String)values.get("serverhostname");
 
254
                        String port = (String)values.get("nsserverport");
 
255
                        Debug.println("CloneServer.cloneServer(): could not read DN = " +
 
256
                                                  sieDN + " or connect to " + host + ":" + port +
 
257
                                                  " exception = " + other);
 
258
                }
 
259
 
 
260
                if (ldc == null || !ldc.isConnected()) {
 
261
                        String name = (String)values.get("cn");
 
262
                        String host = (String)values.get("serverhostname");
 
263
                        String port = (String)values.get("nsserverport");
 
264
                        DSUtil.showErrorDialog(frame, "120", name + " " +
 
265
                                                                   host + ":" + port);
 
266
                        return null;
 
267
                }
 
268
 
 
269
                return ldc;
 
270
        }
 
271
 
 
272
        /*
 
273
         * The entries to clone from the source can be found by enumerating the
 
274
         * nsslapd-privatenamespaces attributes in the entry cn=config and by
 
275
         * getting these entries and their corresponding ldbm-config children.
 
276
         * Also, by looking at cn=features, cn=config and its children.
 
277
         */
 
278
        static private DN[] getEntriesToClone(LDAPConnection ldc, JFrame frame) {
 
279
                Vector entryList = null;
 
280
                String configDN = "cn=config";
 
281
                // list of DNs to ignore
 
282
                String[] ignoreList = { "cn=monitor", "cn=schema", "cn=encryption",
 
283
                                                                "cn=features" };
 
284
                String feConfigAttr = "nsslapd-privatenamespaces";
 
285
                LDAPEntry configEntry = null;
 
286
                String[] attrs = { feConfigAttr };
 
287
                boolean done = false;
 
288
 
 
289
                while (!done) {
 
290
                        try {
 
291
                                configEntry = ldc.read(configDN, attrs);
 
292
                                // if the entry is null or contains no elements, this
 
293
                                // usually means that we didn't have permission to read
 
294
                                // that particular entry, so we need to reauthenticate
 
295
                                // as a more priviledged user
 
296
                                if (configEntry == null) {
 
297
                                        throw new LDAPException("no elements",
 
298
                                                                LDAPException.INSUFFICIENT_ACCESS_RIGHTS);
 
299
                                }
 
300
                                done = true;
 
301
                        } catch (LDAPException lde) {
 
302
                                done = reauthenticate(ldc, lde, configDN, frame,
 
303
                                                                          "clonesourcread");
 
304
                        }
 
305
                }
 
306
 
 
307
                if (configEntry == null)
 
308
                        return null;
 
309
 
 
310
                entryList = new Vector();
 
311
                for (int ii = 0; ii < attrs.length; ++ii) {
 
312
                        Enumeration en = configEntry.getAttribute(attrs[ii]).
 
313
                                getStringValues();
 
314
                        while (en.hasMoreElements()) {
 
315
                                String dn = (String)en.nextElement();
 
316
 
 
317
                                if (dn.equals(""))
 
318
                                        continue; // ignore root DSE
 
319
 
 
320
                                for (int jj = 0; jj < ignoreList.length; ++jj) {
 
321
                                        if (dn.indexOf(ignoreList[jj]) != -1) {
 
322
                                                dn = null;
 
323
                                                break;
 
324
                                        }
 
325
                                }
 
326
 
 
327
                                if (dn == null)
 
328
                                        continue;
 
329
 
 
330
                                // for the config entries, we need to do a subtree
 
331
                                // search to get all of their entries as well
 
332
                                LDAPSearchResults result = null;
 
333
                                String filter = "(objectclass=*)";
 
334
                                        
 
335
                                try {
 
336
                                        result = ldc.search(dn, LDAPConnection.SCOPE_SUB,
 
337
                                                                                filter, null, false);
 
338
                                } catch (LDAPException e) {
 
339
                                        Debug.println("error CloneServer.getEntriesToClone: LDAP" +
 
340
                                                                  " search failed: " + filter);
 
341
                                        Debug.println("error CloneServer.getEntriesToClone: " +
 
342
                                                                  "could not find any servers under " +
 
343
                                                                  dn + " error: " + e);
 
344
                                }
 
345
 
 
346
                                while (result != null && result.hasMoreElements()) {
 
347
                                        LDAPEntry lde = (LDAPEntry)result.nextElement();
 
348
                                        for (int jj = 0; jj < ignoreList.length; ++jj) {
 
349
                                                if (lde.getDN().indexOf(ignoreList[jj]) != -1) {
 
350
                                                        lde = null;
 
351
                                                        break;
 
352
                                                }
 
353
                                        }
 
354
                                        if (lde != null)
 
355
                                                entryList.addElement(new DN(lde.getDN()));
 
356
                                }
 
357
                        }
 
358
                }
 
359
 
 
360
                DN[] retval = null;
 
361
                if (entryList != null && entryList.size() > 0) {
 
362
                        retval = new DN[entryList.size()];
 
363
                        entryList.copyInto(retval);
 
364
                }
 
365
 
 
366
                return retval;
 
367
        }
 
368
 
 
369
        static private boolean reauthenticate(
 
370
                LDAPConnection ldc, LDAPException lde, String dn, JFrame frame,
 
371
                String err
 
372
        ) {
 
373
                boolean done = false;
 
374
                Debug.println("CloneServer.reauthenticate(): LDAP error code=" +
 
375
                                          lde.getLDAPResultCode() + " error=" +
 
376
                                          lde);
 
377
                Debug.println("CloneServer.reauthenticate(): could not read DN = " +
 
378
                                          dn + " from source ldap = " +
 
379
                                          DSUtil.format(ldc));
 
380
                // if the read failed due to permissions, notify the user
 
381
                // via a dialog and ask the user to authenticate using a
 
382
                // different user id/password.  If the user selects OK,
 
383
                // popup the password dialog asking for another user id and
 
384
                // password.  If the user hits OK, update the userid and
 
385
                // password in the _ldc object and retry the modify.  Keep
 
386
                // looping until: 1. The modify succeeds 2. The user hits
 
387
                // Cancel in either the confirm dialog or the password
 
388
                // dialog 3. we get some other type of LDAP error
 
389
                if (lde.getLDAPResultCode() ==
 
390
                        LDAPException.INSUFFICIENT_ACCESS_RIGHTS) {
 
391
                        // display a message
 
392
                        DSUtil.showPermissionDialog(frame, ldc);
 
393
                        // hack; for some reason, reauthenticate does not
 
394
                        // rebind to the server; so, I disconnect in order to
 
395
                        // force a re-connection
 
396
                        try {
 
397
                                ldc.disconnect();
 
398
                        } catch (Exception e) {
 
399
                        }
 
400
                        done = !DSUtil.reauthenticate(ldc, frame, null,
 
401
                                                                                  ldc.getAuthenticationDN(),
 
402
                                                                                  null);
 
403
                } else {
 
404
                        Debug.println("CloneServer.reauthenticate(): could not " +
 
405
                                                  "handle " +
 
406
                                                  "the exception, entry will not be " +
 
407
                                                  "read from source " + DSUtil.format(ldc));
 
408
                        if (err != null) {
 
409
                                String[] args = { dn, lde.toString() };
 
410
                                DSUtil.showErrorDialog(frame, err, args);
 
411
                        }
 
412
                                
 
413
                        done = true; // could not read entry ...
 
414
                }
 
415
 
 
416
                return done;
 
417
        }
 
418
 
 
419
        static private boolean cloneSchema(LDAPConnection source,
 
420
                                                                           LDAPConnection dest,
 
421
                                                                           JFrame frame) {
 
422
                String schemaDN = "cn=schema";
 
423
 
 
424
                LDAPEntry sourceSchema = null;
 
425
                try {
 
426
                        sourceSchema = source.read(schemaDN);
 
427
                } catch (LDAPException e) {
 
428
                        sourceSchema = null;
 
429
                        String[] args = { schemaDN, e.toString() };
 
430
                        DSUtil.showErrorDialog(frame, "clonesourceread", args);
 
431
                }
 
432
 
 
433
                if (sourceSchema == null)
 
434
                        return false;
 
435
 
 
436
                Debug.println("CloneServer.cloneSchema(): read source schema");
 
437
                LDAPEntry destSchema = null;
 
438
                try {
 
439
                        destSchema = dest.read(schemaDN);
 
440
                } catch (LDAPException e) {
 
441
                        destSchema = null;
 
442
                        String[] args = { schemaDN, e.toString() };
 
443
                        DSUtil.showErrorDialog(frame, "clonedestwrite", args);
 
444
                }
 
445
 
 
446
                if (destSchema == null)
 
447
                        return false;
 
448
 
 
449
                Debug.println("CloneServer.cloneSchema(): read dest schema");
 
450
                // read the dest schema values into a hashtable
 
451
                Hashtable dhash = new Hashtable();
 
452
                LDAPAttributeSet las = destSchema.getAttributeSet();
 
453
                for (Enumeration attrs = las.getAttributes();
 
454
                         attrs.hasMoreElements();) {
 
455
                        LDAPAttribute la = (LDAPAttribute)attrs.nextElement();
 
456
                        for (Enumeration vals = la.getStringValues();
 
457
                                 vals.hasMoreElements();) {
 
458
                                String val = (String)vals.nextElement();
 
459
                                if (val == null)
 
460
                                        continue;
 
461
                                dhash.put(val, la.getName());
 
462
                        }
 
463
                }
 
464
 
 
465
                Debug.println("CloneServer.cloneSchema(): dest schema size=" +
 
466
                                          dhash.size());
 
467
                // loop through the source looking for values which are not
 
468
                // present in the dest
 
469
                Vector ocList = null; // for objectclass mods
 
470
                LDAPModificationSet lms = null; // for attribute mods
 
471
                int op = LDAPModification.ADD;
 
472
                las = sourceSchema.getAttributeSet();
 
473
                for (Enumeration attrs = las.getAttributes();
 
474
                         attrs.hasMoreElements();) {
 
475
                        LDAPAttribute la = (LDAPAttribute)attrs.nextElement();
 
476
                        LDAPAttribute newla = null;
 
477
                        for (Enumeration vals = la.getStringValues();
 
478
                                 vals.hasMoreElements();) {
 
479
                                String val = (String)vals.nextElement();
 
480
                                if (val == null)
 
481
                                        continue;
 
482
                                if (!dhash.containsKey(val)) {
 
483
                                        /*
 
484
                                          Objectclasses should be added via the
 
485
                                          LDAPSchemaElement.add interface rather than by
 
486
                                          the modify() interface
 
487
                                        */
 
488
                                        if (isObjectClass(la)) {
 
489
                                                if (ocList == null)
 
490
                                                        ocList = new Vector();
 
491
                                                ocList.addElement(new LDAPObjectClassSchema(val));
 
492
                                        } else {
 
493
                                                if (newla == null)
 
494
                                                        newla = new LDAPAttribute(la.getName());
 
495
                                                newla.addValue(val);
 
496
                                        }
 
497
                                        Debug.println(9, "CloneServer.cloneSchema(): found " +
 
498
                                                                  "attribute value not present on dest=" +
 
499
                                                                  newla);
 
500
                                }
 
501
                        }
 
502
                        // now newla contains only those values not present on the dest
 
503
                        if (newla != null) {
 
504
                                if (lms == null)
 
505
                                        lms = new LDAPModificationSet();
 
506
                                lms.add(op, newla);
 
507
                        }
 
508
                }
 
509
 
 
510
                if ((lms == null || lms.size() == 0) &&
 
511
                        ((ocList == null) || (ocList.size() == 0))) {
 
512
                        Debug.println("CloneServer.cloneSchema(): source and dest are" +
 
513
                                                  " identical, nothing to modify");
 
514
                        return true;
 
515
                }
 
516
 
 
517
                Debug.println("CloneServer.cloneSchema(): modifying " +
 
518
                                          lms.size() + " schema elements");
 
519
                try {
 
520
                        dest.modify(schemaDN, lms);
 
521
                        for (int ii = 0; ocList != null && ii < ocList.size(); ++ii) {
 
522
                                LDAPObjectClassSchema locs =
 
523
                                        (LDAPObjectClassSchema)ocList.elementAt(ii);
 
524
                                locs.add(dest);
 
525
                        }
 
526
                } catch (LDAPException e) {
 
527
                        destSchema = null;
 
528
                        String[] args = { schemaDN, e.toString() };
 
529
                        DSUtil.showErrorDialog(frame, "clonedestwrite", args);
 
530
                        return false;
 
531
                }
 
532
 
 
533
                Debug.println("CloneServer.cloneSchema(): success");
 
534
                return true;
 
535
        }
 
536
 
 
537
        static private LDAPAttribute convertValue(LDAPAttribute la, int factor) {
 
538
                Vector newVals = new Vector();
 
539
                for (Enumeration e = la.getStringValues(); e.hasMoreElements();) {
 
540
                        String sval = (String)e.nextElement();
 
541
                        int ival = -1;
 
542
                        try {
 
543
                                Debug.println("Converting value=" + sval + " using" +
 
544
                                        " factor=" + factor);
 
545
                                ival = Integer.parseInt(sval);
 
546
                                if (factor != 0) {
 
547
                                        ival /= factor;
 
548
                                        sval = Integer.toString(ival);
 
549
                                        Debug.println("Converting new value=" + sval);
 
550
                                }
 
551
                        } catch (Exception ex) {
 
552
                        } finally {
 
553
                                newVals.addElement(sval);
 
554
                        }
 
555
                }
 
556
 
 
557
                String[] nv = new String[newVals.size()];
 
558
                newVals.copyInto(nv);
 
559
                return new LDAPAttribute(la.getName(), nv);
 
560
        }
 
561
 
 
562
        static private String replace(String src, String old, String news) {
 
563
                int index = src.indexOf(old);
 
564
                if (index == -1)
 
565
                        return src;
 
566
 
 
567
                StringBuffer sb = new StringBuffer();
 
568
                int start = 0;
 
569
                while (index != -1) {
 
570
                        // copy the src into the buffer
 
571
                        sb.append(src.substring(start, index));
 
572
                        // copy the new string instead of the old one
 
573
                        sb.append(news);
 
574
                        // start the next copy after this one
 
575
                        start = index + old.length();
 
576
                        // find the next occurance of the old string
 
577
                        index = src.indexOf(old, start);
 
578
                }
 
579
                // copy remainder of string
 
580
                if (start < src.length())
 
581
                        sb.append(src.substring(start));
 
582
 
 
583
                return sb.toString();
 
584
        }
 
585
 
 
586
        static private LDAPAttribute replaceValue(LDAPAttribute la, String oldStr,
 
587
                                                                                          String newStr) {
 
588
                Vector newVals = new Vector();
 
589
                for (Enumeration e = la.getStringValues(); e.hasMoreElements();) {
 
590
                        String sval = (String)e.nextElement();
 
591
                        newVals.addElement(replace(sval, oldStr, newStr));
 
592
                }
 
593
 
 
594
                String[] nv = new String[newVals.size()];
 
595
                newVals.copyInto(nv);
 
596
                return new LDAPAttribute(la.getName(), nv);
 
597
        }
 
598
 
 
599
        static private LDAPModificationSet getMods(LDAPEntry sourceEntry,
 
600
                                                                                           LDAPConnection dest,
 
601
                                                                                           JFrame frame,
 
602
                                                                                           boolean hostsAreSame,
 
603
                                                                                           String oldDir, String newDir) {
 
604
                
 
605
                LDAPEntry destEntry = null;
 
606
                boolean done = false;
 
607
                Debug.println("CloneServer.getMods(): getting attributes to modify" +
 
608
                                          " for DN=" + sourceEntry.getDN());
 
609
                boolean noEntry = false;
 
610
                while (!done) {
 
611
                        try {
 
612
                                destEntry = dest.read(sourceEntry.getDN());
 
613
                                // if the entry is null or contains no elements, this
 
614
                                // usually means that we didn't have permission to read
 
615
                                // that particular entry, so we need to reauthenticate
 
616
                                // as a more privileged user
 
617
                                if (destEntry == null) {
 
618
                                        throw new LDAPException("no elements",
 
619
                                                                LDAPException.INSUFFICIENT_ACCESS_RIGHTS);
 
620
                                }
 
621
                                done = true;
 
622
                        } catch (LDAPException lde) {
 
623
                                if (lde.getLDAPResultCode() == LDAPException.NO_SUCH_OBJECT) {
 
624
                                        noEntry = true;
 
625
                                        done = true;
 
626
                                        // its ok if the dest entry does not exist because we will
 
627
                                        // create it
 
628
                                } else {
 
629
                                        done = reauthenticate(dest, lde,
 
630
                                                                                  sourceEntry.getDN(),
 
631
                                                                                  frame, "clonedestread");
 
632
                                }
 
633
                        }
 
634
                }
 
635
 
 
636
                if (destEntry == null && !noEntry)
 
637
                        return null;
 
638
 
 
639
                Debug.println("CloneServer.getMods(): got dest entry DN=" +
 
640
                                          sourceEntry.getDN());
 
641
                LDAPAttributeSet ldas = sourceEntry.getAttributeSet();
 
642
 
 
643
                LDAPModificationSet ldapmodset = new LDAPModificationSet();
 
644
                // loop through sourceEntry attributes; if the attribute exists on the
 
645
                // source entry but not on the dest entry, the op is add otherwise
 
646
                // it's replace
 
647
                for (Enumeration e = ldas.getAttributes();
 
648
                         e.hasMoreElements();) {
 
649
                        LDAPAttribute lda = (LDAPAttribute)e.nextElement();
 
650
                        Enumeration e2 = lda.getStringValues();
 
651
                        // Make sure the attribute has a value.  Only attributes
 
652
                        // which have a value will be ADDed or REPLACEd.  Attributes
 
653
                        // which do not have a value will be handled by the delete
 
654
                        // loop below
 
655
                        if (!hasAValue(lda))
 
656
                                continue;
 
657
 
 
658
                        int op = LDAPModification.REPLACE;
 
659
                        if ((destEntry == null) ||
 
660
                                !hasAValue(destEntry.getAttribute(lda.getName())))
 
661
                                op = LDAPModification.ADD;
 
662
                        else if (noCopyAttrs.containsKey(lda.getName()))
 
663
                                continue; // we cannot replace noCopyAttrs, but we
 
664
                                                  // can add them
 
665
 
 
666
                        // see if we need to do some conversion of the value before
 
667
                        // we write it to the dest
 
668
                        if (convertAttrs.containsKey(lda.getName())) {
 
669
                                Debug.println("converting attribute " +
 
670
                                                          lda.getName());
 
671
                                Integer factor =
 
672
                                        (Integer)convertAttrs.get(lda.getName());
 
673
                                lda = convertValue(lda, factor.intValue());
 
674
                        } else if (replacePathAttrs.containsKey(lda.getName())) {
 
675
                                lda = replaceValue(lda, oldDir, newDir);
 
676
                        } else if (hostsAreSame &&
 
677
                                           differentHostsAttrs.containsKey(lda.getName())) {
 
678
                                continue; // do not add this attribute to the
 
679
                                // list to copy
 
680
                        }
 
681
 
 
682
                        ldapmodset.add(op, lda);
 
683
                }
 
684
 
 
685
                // loop through destEntry attributes; if the attribute exists on
 
686
                // the dest entry but not the source, or if the attribute value
 
687
                // is a special delete or remove value, it should be deleted from
 
688
                // the dest
 
689
                if (destEntry != null) {
 
690
                        ldas = destEntry.getAttributeSet();
 
691
                        for (Enumeration e = ldas.getAttributes();
 
692
                                 e.hasMoreElements();) {
 
693
                                LDAPAttribute lda = (LDAPAttribute)e.nextElement();
 
694
                                if (!hasAValue(lda))
 
695
                                        continue; // attribute does not exist on dest
 
696
 
 
697
                                if (hasAValue(sourceEntry.getAttribute(lda.getName())))
 
698
                                        continue; // attribute exists on source
 
699
 
 
700
                                int op = LDAPModification.DELETE;
 
701
                                // check for attributes which are not removed the conventional
 
702
                                // way . . .
 
703
                                if (specialRemoveAttrs.containsKey(lda.getName())) {
 
704
                                        lda.addValue(specialRemoveAttrs.get(lda.getName()).toString());
 
705
                                        op = LDAPModification.REPLACE;
 
706
                                }
 
707
 
 
708
                                ldapmodset.add(op, lda);
 
709
                        }
 
710
                }
 
711
 
 
712
                return ldapmodset;
 
713
        }
 
714
 
 
715
        /**
 
716
         * An attribute has a value if its non null, if its size != 0, if
 
717
         * it has a list of values, and if the values do not contain the
 
718
         * special null or delete value
 
719
         */
 
720
        static private boolean hasAValue(LDAPAttribute lda) {
 
721
                if (lda == null) {
 
722
                        Debug.println("CloneServer.hasAValue(): attr is null");
 
723
                        return false;
 
724
                }
 
725
 
 
726
                if (lda.size() == 0) {
 
727
                        Debug.println("CloneServer.hasAValue(): attr=" + lda.getName() +
 
728
                                                  " is empty");
 
729
                        return false;
 
730
                }
 
731
 
 
732
                Enumeration e = lda.getStringValues();
 
733
                if ((e == null) || !e.hasMoreElements()) {
 
734
                        Debug.println("CloneServer.hasAValue(): attr=" + lda.getName() +
 
735
                                                  " has no values");
 
736
                        return false;
 
737
                }
 
738
 
 
739
                boolean hasAVal = false;
 
740
                if (specialDeleteAttrs.containsKey(lda.getName())) {
 
741
                        Debug.println("checking for deletion of attr=" + lda.getName() +
 
742
                                                  " value=" + lda.toString());
 
743
                        for (; !hasAVal && e.hasMoreElements(); ) {
 
744
                                String val = (String)e.nextElement();
 
745
                                String delval =
 
746
                                        (String)specialDeleteAttrs.get(lda.getName());
 
747
                                hasAVal = (val != null) && !val.equals(delval);
 
748
                        }
 
749
                }
 
750
                else {
 
751
                        hasAVal = true;
 
752
                }
 
753
 
 
754
                if (!hasAVal) {
 
755
                        Debug.println("CloneServer.hasAValue(): attr=" + lda.getName() +
 
756
                                                  " has all null values");
 
757
                } else {
 
758
                        Debug.println(9, "CloneServer.hasAValue(): attr=" + lda.getName() +
 
759
                                                  " has value=" + lda.toString());
 
760
                }
 
761
                return hasAVal;
 
762
        }
 
763
 
 
764
        /**
 
765
         * Returns true if the attribute is the raw objectclass representation
 
766
         * from the attribute value in the schema entry
 
767
         */
 
768
        static private boolean isObjectClass(LDAPAttribute la) {
 
769
                return la.getName().equalsIgnoreCase("objectclasses");
 
770
        }
 
771
 
 
772
        /**
 
773
         * noCopyAttrs is a look up table of attributes which should not be
 
774
         * copied from the source to the dest.  Most of these are pretty
 
775
         * obvious.
 
776
         */
 
777
        static private Hashtable noCopyAttrs = new Hashtable();
 
778
        static {
 
779
                noCopyAttrs.put("cn", "");
 
780
                noCopyAttrs.put("objectclass", "");
 
781
                noCopyAttrs.put("oid", "");
 
782
                noCopyAttrs.put("nsslapd-config", "");
 
783
                noCopyAttrs.put("nsslapd-betype", "");
 
784
                noCopyAttrs.put("nsslapd-privatenamespaces", "");
 
785
                noCopyAttrs.put("nsslapd-rootdn", "");
 
786
                noCopyAttrs.put("nsslapd-rootpw", "");
 
787
                noCopyAttrs.put("nsslapd-instancedir", "");
 
788
                noCopyAttrs.put("nsslapd-useroc", "");
 
789
                noCopyAttrs.put("nsslapd-userat", "");
 
790
                noCopyAttrs.put("nsslapd-localhost", "");
 
791
                noCopyAttrs.put("nsslapd-security", "");
 
792
                noCopyAttrs.put("nsslapd-plugin", "");
 
793
                noCopyAttrs.put("nsslapd-include", "");
 
794
                noCopyAttrs.put("nsslapd-backendconfig", "");
 
795
                noCopyAttrs.put("nsslapd-accesslog", "");
 
796
                noCopyAttrs.put("nsslapd-accesslog-list", "");
 
797
                noCopyAttrs.put("nsslapd-errorlog", "");
 
798
                noCopyAttrs.put("nsslapd-errorlog-list", "");
 
799
                noCopyAttrs.put("nsslapd-auditlog", "");
 
800
                noCopyAttrs.put("nsslapd-auditlog-list", "");
 
801
                noCopyAttrs.put("nsslapd-requiresrestart", "");
 
802
                noCopyAttrs.put("nsslapd-database", "");
 
803
                noCopyAttrs.put("nsslapd-directory", "");
 
804
                noCopyAttrs.put("nsslapd-idlistscanlimit", ""); // why?
 
805
                noCopyAttrs.put("nsslapd-parentcheck", ""); // why?
 
806
                noCopyAttrs.put("nsslapd-mode", ""); // why?
 
807
                noCopyAttrs.put("nsslapd-groupevalnestlevel", ""); // why?
 
808
                // only the nsslapd-pluginenabled attribute should be copied
 
809
                noCopyAttrs.put("nsslapd-pluginpath", "");
 
810
                noCopyAttrs.put("nsslapd-plugininitfunc", "");
 
811
                noCopyAttrs.put("nsslapd-plugintype", "");
 
812
                noCopyAttrs.put("nsslapd-pluginid", "");
 
813
                noCopyAttrs.put("nsslapd-pluginversion", "");
 
814
                noCopyAttrs.put("nsslapd-pluginvendor", "");
 
815
                noCopyAttrs.put("nsslapd-plugindescription", "");
 
816
                noCopyAttrs.put("nsslapd-backend", "");
 
817
                noCopyAttrs.put("nsslapd-referralmode", "");
 
818
        }
 
819
 
 
820
        /**
 
821
         * This is a table of attributes which have a special value
 
822
         * which indicates that the destination should be deleted
 
823
         * usually, if the source attribute is empty or has a null value,
 
824
         * it means the destination attribute should be deleted.  There
 
825
         * are also special attributes which can have a special value
 
826
         * which means the destination should be deleted
 
827
         * the key is the attribute name and the value is the special
 
828
         * value which means deletion
 
829
         */
 
830
        static private Hashtable specialDeleteAttrs = new Hashtable();
 
831
        static {
 
832
                specialDeleteAttrs.put("nsslapd-changelogmaxentries", "0");
 
833
                specialDeleteAttrs.put("nsslapd-changelogmaxage", "0");
 
834
                specialDeleteAttrs.put("nsslapd-accesslog-logmaxdiskspace", "0");
 
835
                specialDeleteAttrs.put("nsslapd-errorlog-logmaxdiskspace", "0");
 
836
                specialDeleteAttrs.put("nsslapd-auditlog-logmaxdiskspace", "0");
 
837
                specialDeleteAttrs.put("nsslapd-accesslog-maxlogsize", "0");
 
838
                specialDeleteAttrs.put("nsslapd-errorlog-maxlogsize", "0");
 
839
                specialDeleteAttrs.put("nsslapd-auditlog-maxlogsize", "0");
 
840
        }
 
841
 
 
842
        /**
 
843
         * this is a table of attributes whose values must be converted
 
844
         * by dividing by an integral before writing to the destination
 
845
         */
 
846
        static private Hashtable convertAttrs = new Hashtable();
 
847
        static {
 
848
//              convertAttrs.put("passwordmaxage", new Integer(86400));
 
849
//              convertAttrs.put("passwordwarning", new Integer(86400));
 
850
        }
 
851
 
 
852
        /**
 
853
         * this is a table of attributes whose values must undergo
 
854
         * a string replacement of the path
 
855
         */
 
856
        static private Hashtable replacePathAttrs = new Hashtable();
 
857
        static {
 
858
                replacePathAttrs.put("nsslapd-changelogdir", "");
 
859
        }
 
860
 
 
861
        /**
 
862
         * this is a table of attributes that we only want to clone
 
863
         * if the source and the destination are on different hosts
 
864
         */
 
865
        static private Hashtable differentHostsAttrs = new Hashtable();
 
866
        static {
 
867
                differentHostsAttrs.put("nsslapd-port", "");
 
868
                differentHostsAttrs.put("nsslapd-secureport", "");
 
869
                differentHostsAttrs.put("nsslapd-ntsynch-port", "");
 
870
        }
 
871
 
 
872
        /**
 
873
         * this is a table of attributes which have a special remove
 
874
         * value e.g. we don't do an LDAP REMOVE, we just set the
 
875
         * value of the attribute to this special value
 
876
         */
 
877
        static private Hashtable specialRemoveAttrs = new Hashtable();
 
878
        static {
 
879
                specialRemoveAttrs.put("nsslapd-referral", "remove");
 
880
        }
 
881
}
 
882