Compare commits
12 Commits
NETSCAPE_7
...
LDAPJavaSD
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a126fe6fc | ||
|
|
bf76134755 | ||
|
|
677ac0508a | ||
|
|
948f53fd8c | ||
|
|
d643bfb551 | ||
|
|
31c81ab0b0 | ||
|
|
84b616c6f4 | ||
|
|
25df3ce15f | ||
|
|
aa4f4a38ba | ||
|
|
c98fd85075 | ||
|
|
9ac2abf404 | ||
|
|
35717268e5 |
@@ -1,80 +0,0 @@
|
||||
#!perl
|
||||
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Simon Fraser <sfraser@netscape.com>
|
||||
#
|
||||
|
||||
require 5.004;
|
||||
|
||||
use strict;
|
||||
|
||||
use Cwd;
|
||||
use Moz::BuildUtils;
|
||||
use Moz::BuildCore;
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# Where have the build options gone?
|
||||
#
|
||||
# The various build flags have been centralized into one place.
|
||||
# The master list of options is in MozBuildFlags.txt. However,
|
||||
# you should never need to edit that file, or this one.
|
||||
#
|
||||
# To customize what gets built, or where to start the build,
|
||||
# edit the $prefs_file_name file in
|
||||
# System Folder:Preferences:Mozilla build prefs:
|
||||
# Documentation is provided in that file.
|
||||
#-------------------------------------------------------------
|
||||
|
||||
my($prefs_file_name) = "Mozilla opt build prefs";
|
||||
my($config_header_file_name) = ":mozilla:config:mac:DefinesOptions.h";
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# hashes to hold build options
|
||||
#-------------------------------------------------------------
|
||||
my(%build);
|
||||
my(%options);
|
||||
my(%filepaths);
|
||||
my(%optiondefines);
|
||||
|
||||
# Hash of input files for this build. Eventually, there will be
|
||||
# input files for manifests, and projects too.
|
||||
my(%inputfiles) = (
|
||||
"buildflags", "MozillaBuildFlags.txt",
|
||||
"checkoutdata", "MozillaCheckoutList.txt",
|
||||
"buildprogress", "¥ Mozilla opt progress",
|
||||
"buildmodule", "MozillaBuildList.pm",
|
||||
"checkouttime", "Mozilla last checkout"
|
||||
);
|
||||
#-------------------------------------------------------------
|
||||
# end build hashes
|
||||
#-------------------------------------------------------------
|
||||
|
||||
# set the build root directory, which is the the dir above mozilla
|
||||
SetupBuildRootDir(":mozilla:build:mac:build_scripts");
|
||||
|
||||
# Set up all the flags on $main::, like DEBUG, CARBON etc.
|
||||
# Override the defaults using the preferences files.
|
||||
SetupDefaultBuildOptions(0, ":mozilla:dist:viewer:", $config_header_file_name);
|
||||
|
||||
my($do_checkout) = 0;
|
||||
my($do_build) = 1;
|
||||
|
||||
RunBuild($do_checkout, $do_build, \%inputfiles, $prefs_file_name);
|
||||
@@ -1,80 +0,0 @@
|
||||
#!perl
|
||||
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Simon Fraser <sfraser@netscape.com>
|
||||
#
|
||||
|
||||
require 5.004;
|
||||
|
||||
use strict;
|
||||
|
||||
use Cwd;
|
||||
use Moz::BuildUtils;
|
||||
use Moz::BuildCore;
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# Where have the build options gone?
|
||||
#
|
||||
# The various build flags have been centralized into one place.
|
||||
# The master list of options is in MozBuildFlags.txt. However,
|
||||
# you should never need to edit that file, or this one.
|
||||
#
|
||||
# To customize what gets built, or where to start the build,
|
||||
# edit the $prefs_file_name file in
|
||||
# System Folder:Preferences:Mozilla build prefs:
|
||||
# Documentation is provided in that file.
|
||||
#-------------------------------------------------------------
|
||||
|
||||
my($prefs_file_name) = "Mozilla debug build prefs";
|
||||
my($config_header_file_name) = ":mozilla:config:mac:DefinesOptionsDebug.h";
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# hashes to hold build options
|
||||
#-------------------------------------------------------------
|
||||
my(%build);
|
||||
my(%options);
|
||||
my(%filepaths);
|
||||
my(%optiondefines);
|
||||
|
||||
# Hash of input files for this build. Eventually, there will be
|
||||
# input files for manifests, and projects too.
|
||||
my(%inputfiles) = (
|
||||
"buildflags", "MozillaBuildFlags.txt",
|
||||
"checkoutdata", "MozillaCheckoutList.txt",
|
||||
"buildprogress", "¥ Mozilla debug progress",
|
||||
"buildmodule", "MozillaBuildList.pm",
|
||||
"checkouttime", "Mozilla last checkout"
|
||||
);
|
||||
#-------------------------------------------------------------
|
||||
# end build hashes
|
||||
#-------------------------------------------------------------
|
||||
|
||||
# set the build root directory, which is the the dir above mozilla
|
||||
SetupBuildRootDir(":mozilla:build:mac:build_scripts");
|
||||
|
||||
# Set up all the flags on $main::, like DEBUG, CARBON etc.
|
||||
# Override the defaults using the preferences files.
|
||||
SetupDefaultBuildOptions(1, ":mozilla:dist:viewer_debug:", $config_header_file_name);
|
||||
|
||||
my($do_pull) = 0; # overridden by flags and prefs
|
||||
my($do_build) = 1;
|
||||
|
||||
RunBuild($do_pull, $do_build, \%inputfiles, $prefs_file_name);
|
||||
@@ -1,595 +0,0 @@
|
||||
#!perl -w
|
||||
package Moz::BuildCore;
|
||||
|
||||
require 5.004;
|
||||
require Exporter;
|
||||
|
||||
use strict;
|
||||
use vars qw( @ISA @EXPORT );
|
||||
|
||||
# perl includes
|
||||
use Cwd;
|
||||
use POSIX;
|
||||
use Time::Local;
|
||||
use File::Basename;
|
||||
use LWP::Simple;
|
||||
|
||||
# homegrown
|
||||
use Moz::Moz;
|
||||
use Moz::Jar;
|
||||
use Moz::BuildFlags;
|
||||
use Moz::BuildUtils;
|
||||
use Moz::CodeWarriorLib;
|
||||
|
||||
# use MozillaBuildList; # eventually, this should go away, and be replaced by data input
|
||||
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT = qw(
|
||||
RunBuild
|
||||
);
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// DoPrebuildCheck
|
||||
#//
|
||||
#// Check the build tools etc before running the build.
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub DoPrebuildCheck()
|
||||
{
|
||||
SanityCheckBuildOptions();
|
||||
|
||||
# launch codewarrior and persist its location. Have to call this before first
|
||||
# call to getCodeWarriorPath().
|
||||
my($ide_path_file) = $main::filepaths{"idepath"};
|
||||
$ide_path_file = full_path_to($ide_path_file);
|
||||
LaunchCodeWarrior($ide_path_file);
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// SanityCheckBuildOptions
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub SanityCheckBuildOptions()
|
||||
{
|
||||
my($bad_options) = 0;
|
||||
|
||||
# Jar options
|
||||
if (!$main::options{chrome_jars} && !$main::options{chrome_files})
|
||||
{
|
||||
print "Warning: Both \$options{chrome_jars} and \$options{chrome_files} are off. You won't get any chrome.\n";
|
||||
$bad_options = 1;
|
||||
}
|
||||
|
||||
if (!$main::options{chrome_jars} && $main::options{use_jars})
|
||||
{
|
||||
print "Warning: \$options{chrome_jars} is off but \$options{use_jars} is on. Your build won't run (expects jars, got files).\n";
|
||||
$bad_options = 1;
|
||||
}
|
||||
|
||||
if (!$main::options{chrome_files} && !$main::options{use_jars})
|
||||
{
|
||||
print "Warning: \$options{chrome_jars} is off but \$options{chrome_files} is on. Your build won't run (expects files, got jars).\n";
|
||||
$bad_options = 1;
|
||||
}
|
||||
|
||||
if ($main::options{ldap_experimental} && !$main::options{ldap})
|
||||
{
|
||||
print "Warning: \$options{ldap_experimental} is on but \$options{ldap} is off. LDAP experimental features will not be built.\n";
|
||||
$bad_options = 1;
|
||||
}
|
||||
|
||||
if ($main::options{wsp} && !$main::options{xmlextras})
|
||||
{
|
||||
print "Warning: \$options{wsp} is on but \$options{xmlextras} is off. wsp will not be built.\n";
|
||||
$bad_options = 1;
|
||||
}
|
||||
|
||||
if ($bad_options) {
|
||||
print "Build will start in 5 seconds. Press command-. to stop\n";
|
||||
|
||||
DelayFor(5);
|
||||
}
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// GenBuildSystemInfo
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub GenBuildSystemInfo()
|
||||
{
|
||||
# always rebuild the configuration program.
|
||||
BuildProjectClean(":mozilla:build:mac:tools:BuildSystemInfo:BuildSystemInfo.mcp", "BuildSystemInfo");
|
||||
|
||||
# delete the configuration file.
|
||||
unlink(":mozilla:build:mac:BuildSystemInfo.pm");
|
||||
|
||||
# run the program.
|
||||
system(":mozilla:build:mac:BuildSystemInfo");
|
||||
|
||||
# wait for the file to be created.
|
||||
while (!(-e ":mozilla:build:mac:BuildSystemInfo.pm")) { WaitNextEvent(); }
|
||||
|
||||
# wait for BuildSystemInfo to finish, so that we see correct results.
|
||||
while (IsProcessRunning("BuildSystemInfo")) { WaitNextEvent(); }
|
||||
|
||||
# now, evaluate the contents of the file.
|
||||
open(F, ":mozilla:build:mac:BuildSystemInfo.pm");
|
||||
while (<F>) { eval; }
|
||||
close(F);
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// Make library aliases
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub MakeLibAliases()
|
||||
{
|
||||
my($dist_dir) = GetBinDirectory();
|
||||
|
||||
#// ProfilerLib
|
||||
if ($main::PROFILE)
|
||||
{
|
||||
my($profilerlibpath) = Moz::CodeWarriorLib::getCodeWarriorPath("MacOS Support:Profiler:Profiler Common:ProfilerLib");
|
||||
MakeAlias("$profilerlibpath", "$dist_dir"."Essential Files:");
|
||||
}
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// ConfigureBuildSystem
|
||||
#//
|
||||
#// defines some build-system configuration variables.
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub ConfigureBuildSystem()
|
||||
{
|
||||
#// In the future, we may want to do configurations based on the actual build system itself.
|
||||
#// GenBuildSystemInfo();
|
||||
|
||||
#// For now, if we discover a newer header file than existed in Universal Interfaces 3.2,
|
||||
#// we'll assume that 3.3 or later is in use.
|
||||
my($universal_interfaces) = Moz::CodeWarriorLib::getCodeWarriorPath("MacOS Support:Universal:Interfaces:CIncludes:");
|
||||
if (-e ($universal_interfaces . "ControlDefinitions.h")) {
|
||||
$main::UNIVERSAL_INTERFACES_VERSION = 0x0330;
|
||||
}
|
||||
|
||||
#// Rename IC SDK folder in the Mac OS Support folder
|
||||
my($ic_sdk_folder) = Moz::CodeWarriorLib::getCodeWarriorPath("MacOS Support:ICProgKit2.0.2");
|
||||
if( -e $ic_sdk_folder)
|
||||
{
|
||||
my($new_ic_folder_name) = Moz::CodeWarriorLib::getCodeWarriorPath("MacOS Support:(ICProgKit2.0.2)");
|
||||
rename ($ic_sdk_folder, $new_ic_folder_name);
|
||||
# note that CodeWarrior doesn't descend into folders with () the name
|
||||
print "Mozilla no longer needs the Internet Config SDK to build:\n Renaming the 'ICProgKit2.0.2' folder to '(ICProgKit2.0.2)'\n";
|
||||
}
|
||||
|
||||
printf("UNIVERSAL_INTERFACES_VERSION = 0x%04X\n", $main::UNIVERSAL_INTERFACES_VERSION);
|
||||
|
||||
# alias required CodeWarrior libs into the Essential Files folder (only the Profiler lib now)
|
||||
MakeLibAliases();
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// CheckOutModule. Takes variable number of args; first two are required
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub CheckOutModule($$$$)
|
||||
{
|
||||
my($session, $module, $revision, $date) = @_;
|
||||
|
||||
my($result) = $session->checkout($module, $revision, $date);
|
||||
|
||||
# result of 1 is success
|
||||
if ($result) { return; }
|
||||
|
||||
my($checkout_err) = $session->getLastError();
|
||||
if ($checkout_err == 708) {
|
||||
die "Error: Checkout was cancelled.\n";
|
||||
} elsif ($checkout_err == 911) {
|
||||
die "Error: CVS session settings are incorrect. Check your password, and the CVS root settings.\n";
|
||||
} elsif ($checkout_err == 703) {
|
||||
die "Error: CVS checkout failed. Unknown module, unknown tag, bad username, or other CVS error.\n";
|
||||
} elsif ($checkout_err == 711) {
|
||||
print "Checkout of '$module' failed.\n";
|
||||
}
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getScriptFolder
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub getScriptFolder()
|
||||
{
|
||||
return dirname($0);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getScriptFolder
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub get_url_contents($)
|
||||
{
|
||||
my($url) = @_;
|
||||
|
||||
my($url_contents) = LWP::Simple::get($url);
|
||||
$url_contents =~ s/\r\n/\n/g; # normalize linebreaks
|
||||
$url_contents =~ s/\r/\n/g; # normalize linebreaks
|
||||
return $url_contents;
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// get_files_from_content
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub uniq
|
||||
{
|
||||
my $lastval;
|
||||
grep(($_ ne $lastval, $lastval = $_)[$[], @_);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// get_files_from_content
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub get_files_from_content($)
|
||||
{
|
||||
my($content) = @_;
|
||||
|
||||
my(@jscalls) = grep (/return js_file_menu[^{]*/, split(/\n/, $content));
|
||||
my $i;
|
||||
|
||||
for ($i = 0; $i < @jscalls ; $i++)
|
||||
{
|
||||
$jscalls[$i] =~ s/.*\(|\).*//g;
|
||||
my(@callparams) = split(/,/, $jscalls[$i]);
|
||||
my ($repos, $dir, $file, $rev) = grep(s/['\s]//g, @callparams);
|
||||
$jscalls[$i] = "$dir/$file";
|
||||
}
|
||||
|
||||
&uniq(sort(@jscalls));
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getLastUpdateTime
|
||||
#//
|
||||
#// Get the last time we updated. Return 0 on failure
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub getLastUpdateTime($)
|
||||
{
|
||||
my($timestamp_file) = @_;
|
||||
|
||||
my($time_string);
|
||||
|
||||
local(*TIMESTAMP_FILE);
|
||||
unless (open(TIMESTAMP_FILE, "< $timestamp_file")) { return 0; }
|
||||
|
||||
while (<TIMESTAMP_FILE>)
|
||||
{
|
||||
my($line) = $_;
|
||||
chomp($line);
|
||||
|
||||
# ignore comments and empty lines
|
||||
if ($line =~ /^\#/ || $line =~ /^\s*$/) {
|
||||
next;
|
||||
}
|
||||
|
||||
$time_string = $line;
|
||||
}
|
||||
|
||||
# get the epoch seconds
|
||||
my($last_update_secs) = $time_string;
|
||||
$last_update_secs =~ s/\s#.+$//;
|
||||
|
||||
print "FAST_UPDATE found that you last updated at ".localtime($last_update_secs)."\n";
|
||||
|
||||
# how long ago was this, in hours?
|
||||
my($gm_now) = time();
|
||||
my($update_hours) = 1 + ceil(($gm_now - $last_update_secs) / (60 * 60));
|
||||
|
||||
return $update_hours;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// saveCheckoutTimestamp
|
||||
#//
|
||||
#// Create a file on disk containing the current time. Param is time(), which is an Epoch seconds
|
||||
#// (and therefore in GMT).
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub saveCheckoutTimestamp($$)
|
||||
{
|
||||
my($gm_secs, $timestamp_file) = @_;
|
||||
|
||||
local(*TIMESTAMP_FILE);
|
||||
open(TIMESTAMP_FILE, ">$timestamp_file") || die "Failed to open $timestamp_file\n";
|
||||
print(TIMESTAMP_FILE "# time of last checkout or update, in GMT. Used by FAST_UPDATE\n");
|
||||
print(TIMESTAMP_FILE "$gm_secs \# around ".localtime()." local time\n");
|
||||
close(TIMESTAMP_FILE);
|
||||
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// FastUpdate
|
||||
#//
|
||||
#// Use Bonsai url data to update only those dirs which have new files
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub FastUpdate($$)
|
||||
{
|
||||
my($modules, $timestamp_file) = @_; # list of modules to check out
|
||||
|
||||
my($num_hours) = getLastUpdateTime($timestamp_file);
|
||||
if ($num_hours == 0 || $num_hours > 170) {
|
||||
print "Can't fast_update; last update was too long ago, or never. Doing normal checkout.\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
print "Doing fast update, pulling files changed in the last $num_hours hours\n";
|
||||
|
||||
my($cvsfile) = AskAndPersistFile($main::filepaths{"sessionpath"});
|
||||
my($session) = Moz::MacCVS->new( $cvsfile );
|
||||
unless (defined($session)) { die "Error: Checkout aborted. Cannot create session file: $session" }
|
||||
|
||||
# activate MacCVS
|
||||
ActivateApplication('Mcvs');
|
||||
|
||||
my($checkout_start_time) = time();
|
||||
|
||||
#print "Time now is $checkout_start_time ($checkout_start_time + 0)\n";
|
||||
|
||||
my($this_co);
|
||||
foreach $this_co (@$modules)
|
||||
{
|
||||
my($module, $revision, $date) = ($this_co->[0], $this_co->[1], $this_co->[2]);
|
||||
|
||||
# assume that things pulled by date wont change
|
||||
if ($date ne "") {
|
||||
print "$module is pulled by date, so ignoring in FastUpdate.\n";
|
||||
next;
|
||||
}
|
||||
|
||||
my($search_type) = "hours";
|
||||
my($min_date) = "";
|
||||
my($max_date) = "";
|
||||
my($url) = "http://bonsai.mozilla.org/cvsquery.cgi?treeid=default&module=${module}&branch=${revision}&branchtype=match&dir=&file=&filetype=match&who=&whotype=match&sortby=Date&hours=${num_hours}&date=${search_type}&mindate=${min_date}&maxdate=${max_date}&cvsroot=%2Fcvsroot";
|
||||
|
||||
if ($revision eq "") {
|
||||
print "Getting list of checkins to $module from Bonsai...\n";
|
||||
} else {
|
||||
print "Getting list of checkins to $module on branch $revision from Bonsai...\n";
|
||||
}
|
||||
my(@files) = &get_files_from_content(&get_url_contents($url));
|
||||
|
||||
if ($#files > 0)
|
||||
{
|
||||
my(@cvs_co_list);
|
||||
|
||||
my($co_file);
|
||||
foreach $co_file (@files)
|
||||
{
|
||||
print "Updating $co_file\n";
|
||||
push(@cvs_co_list, $co_file);
|
||||
}
|
||||
|
||||
my($result) = $session->update($revision, \@cvs_co_list);
|
||||
# result of 1 is success
|
||||
if (!$result) { die "Error: Fast update failed\n"; }
|
||||
} else {
|
||||
print "No files in this module changed\n";
|
||||
}
|
||||
}
|
||||
|
||||
saveCheckoutTimestamp($checkout_start_time, $timestamp_file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// Checkout
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub CheckoutModules($$$)
|
||||
{
|
||||
my($modules, $pull_date, $timestamp_file) = @_; # list of modules to check out
|
||||
|
||||
my($start_time) = TimeStart();
|
||||
|
||||
# assertRightDirectory();
|
||||
my($cvsfile) = AskAndPersistFile($main::filepaths{"sessionpath"});
|
||||
my($session) = Moz::MacCVS->new( $cvsfile );
|
||||
unless (defined($session)) { die "Error: Checkout aborted. Cannot create session file: $session" }
|
||||
|
||||
my($checkout_start_time) = time();
|
||||
|
||||
# activate MacCVS
|
||||
ActivateApplication('Mcvs');
|
||||
|
||||
my($this_co);
|
||||
foreach $this_co (@$modules)
|
||||
{
|
||||
my($module, $revision, $date) = ($this_co->[0], $this_co->[1], $this_co->[2]);
|
||||
if ($date eq "") {
|
||||
$date = $pull_date;
|
||||
}
|
||||
CheckOutModule($session, $module, $revision, $date);
|
||||
# print "Checking out $module with ref $revision, date $date\n";
|
||||
}
|
||||
|
||||
saveCheckoutTimestamp($checkout_start_time, $timestamp_file);
|
||||
TimeEnd($start_time, "Checkout");
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// ReadCheckoutModulesFile
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub ReadCheckoutModulesFile($$)
|
||||
{
|
||||
my($modules_file, $co_list) = @_;
|
||||
|
||||
my($checkout_file) = getScriptFolder().":".$modules_file;
|
||||
local(*CHECKOUT_FILE);
|
||||
open(CHECKOUT_FILE, "< $checkout_file") || die "Error: failed to open checkout list $checkout_file\n";
|
||||
while (<CHECKOUT_FILE>)
|
||||
{
|
||||
my($line) = $_;
|
||||
chomp($line);
|
||||
|
||||
# ignore comments and empty lines
|
||||
if ($line =~ /^\#/ || $line =~ /^\s*$/) {
|
||||
next;
|
||||
}
|
||||
|
||||
my(@cvs_co) = ["", "", ""];
|
||||
|
||||
my($module, $revision, $date) = (0, 1, 2);
|
||||
|
||||
if ($line =~ /\s*([^#,\s]+)\s*\,\s*([^#,\s]+)\s*\,\s*([^#]+)/)
|
||||
{
|
||||
@cvs_co[$module] = $1;
|
||||
@cvs_co[$revision] = $2;
|
||||
@cvs_co[$date] = $3;
|
||||
}
|
||||
elsif ($line =~ /\s*([^#,\s]+)\s*\,\s*([^#,\s]+)\s*(#.+)?/)
|
||||
{
|
||||
@cvs_co[$module] = $1;
|
||||
@cvs_co[$revision] = $2;
|
||||
}
|
||||
elsif ($line =~ /\s*([^#,\s]+)\s*\,\s*,\s*([^#,]+)/)
|
||||
{
|
||||
@cvs_co[$module] = $1;
|
||||
@cvs_co[$date] = $2;
|
||||
}
|
||||
elsif ($line =~ /\s*([^#,\s]+)/)
|
||||
{
|
||||
@cvs_co[$module] = $1;
|
||||
}
|
||||
else
|
||||
{
|
||||
die "Error: unrecognized line '$line' in $modules_file\n";
|
||||
}
|
||||
|
||||
# strip surrounding space from date
|
||||
@cvs_co[$date] =~ s/^\s*|\s*$//g;
|
||||
|
||||
# print "Going to check out '@cvs_co[$module]', '@cvs_co[$revision]', '@cvs_co[$date]'\n";
|
||||
push(@$co_list, \@cvs_co);
|
||||
}
|
||||
|
||||
close(CHECKOUT_FILE);
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// PullFromCVS
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub PullFromCVS($$)
|
||||
{
|
||||
unless ( $main::build{pull} ) { return; }
|
||||
|
||||
my($modules_file, $timestamp_file) = @_;
|
||||
|
||||
StartBuildModule("pull");
|
||||
|
||||
my(@cvs_co_list);
|
||||
ReadCheckoutModulesFile($modules_file, \@cvs_co_list);
|
||||
|
||||
if ($main::FAST_UPDATE && $main::options{pull_by_date})
|
||||
{
|
||||
die "Error: you can't use FAST_UPDATE if you are pulling by date.\n";
|
||||
}
|
||||
|
||||
my($did_fast_update) = $main::FAST_UPDATE && FastUpdate(\@cvs_co_list, $timestamp_file);
|
||||
if (!$did_fast_update)
|
||||
{
|
||||
my($pull_date) = "";
|
||||
if ($main::options{pull_by_date})
|
||||
{
|
||||
# acceptable CVS date formats are (in local time):
|
||||
# ISO8601 (e.g. "1972-09-24 20:05") and Internet (e.g. "24 Sep 1972 20:05").
|
||||
# Perl's localtime() string format also seems to work.
|
||||
$pull_date = localtime().""; # force string interp.
|
||||
print "Pulling by date $pull_date\n";
|
||||
}
|
||||
|
||||
CheckoutModules(\@cvs_co_list, $pull_date, $timestamp_file);
|
||||
}
|
||||
|
||||
EndBuildModule("pull");
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// RunBuild
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub RunBuild($$$$)
|
||||
{
|
||||
my($do_pull, $do_build, $input_files, $build_prefs) = @_;
|
||||
|
||||
InitBuildProgress($input_files->{"buildprogress"});
|
||||
|
||||
# if we are pulling, we probably want to do a full build, so clear the build progress
|
||||
if ($do_pull) {
|
||||
ClearBuildProgress();
|
||||
}
|
||||
|
||||
# read local prefs, and the build progress file, and set flags to say what to build
|
||||
SetupBuildParams(\%main::build,
|
||||
\%main::options,
|
||||
\%main::optiondefines,
|
||||
\%main::filepaths,
|
||||
$input_files->{"buildflags"},
|
||||
$build_prefs);
|
||||
|
||||
# If we were told to pull, make sure we do, overriding prefs etc.
|
||||
if ($do_pull)
|
||||
{
|
||||
$main::build{"pull"} = 1;
|
||||
}
|
||||
|
||||
# transfer this flag
|
||||
$CodeWarriorLib::CLOSE_PROJECTS_FIRST = $main::CLOSE_PROJECTS_FIRST;
|
||||
|
||||
# setup the build log
|
||||
SetupBuildLog($main::filepaths{"buildlogfilepath"}, $main::USE_TIMESTAMPED_LOGS);
|
||||
StopForErrors();
|
||||
|
||||
if ($main::LOG_TO_FILE) {
|
||||
RedirectOutputToFile($main::filepaths{"scriptlogfilepath"});
|
||||
}
|
||||
|
||||
# run a pre-build check to see that the tools etc are in order
|
||||
DoPrebuildCheck();
|
||||
|
||||
# do the pull
|
||||
PullFromCVS($input_files->{"checkoutdata"}, $input_files->{"checkouttime"});
|
||||
|
||||
unless ($do_build) { return; }
|
||||
|
||||
my($build_start) = TimeStart();
|
||||
|
||||
# check the build environment
|
||||
ConfigureBuildSystem();
|
||||
|
||||
# here we load and call methods in the build module indirectly.
|
||||
# we have to use indirection because the build module can be named
|
||||
# differently for different builds.
|
||||
chdir(dirname($0)); # change to the script dir
|
||||
my($build_module) = $input_files->{"buildmodule"};
|
||||
# load the build module
|
||||
require $build_module;
|
||||
{ # scope for no strict 'refs'
|
||||
no strict 'refs';
|
||||
|
||||
my($package_name) = $build_module;
|
||||
$package_name =~ s/\.pm$//;
|
||||
|
||||
chdir($main::MOZ_SRC);
|
||||
&{$package_name."::BuildDist"}();
|
||||
|
||||
chdir($main::MOZ_SRC);
|
||||
&{$package_name."::BuildProjects"}();
|
||||
}
|
||||
|
||||
# the build finished, so clear the build progress state
|
||||
ClearBuildProgress();
|
||||
|
||||
TimeEnd($build_start, "Build");
|
||||
print "Build complete\n";
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -1,425 +0,0 @@
|
||||
#!perl -w
|
||||
package Moz::BuildFlags;
|
||||
|
||||
require 5.004;
|
||||
require Exporter;
|
||||
|
||||
# Package that attempts to read a file from the Preferences folder,
|
||||
# and get build settings out of it
|
||||
|
||||
use strict;
|
||||
use Exporter;
|
||||
|
||||
use Cwd;
|
||||
use File::Basename;
|
||||
|
||||
use Moz::Moz;
|
||||
use Moz::Prefs;
|
||||
|
||||
use vars qw(@ISA @EXPORT);
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT = qw(
|
||||
SetupBuildParams
|
||||
InitBuildProgress
|
||||
WriteBuildProgress
|
||||
ClearBuildProgress
|
||||
ReadBuildProgress
|
||||
);
|
||||
|
||||
|
||||
my(@build_flags);
|
||||
my(@options_flags);
|
||||
my(@filepath_flags);
|
||||
|
||||
my(%arrays_list) = (
|
||||
"build_flags", \@build_flags,
|
||||
"options_flags", \@options_flags,
|
||||
"filepath_flags", \@filepath_flags
|
||||
);
|
||||
|
||||
my($progress_file) = "¥ÊBuild progress";
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# appendArrayFlag
|
||||
#
|
||||
# Set a flag in the array
|
||||
#-------------------------------------------------------------------------------
|
||||
sub appendArrayFlag(@)
|
||||
{
|
||||
my($array_name) = shift;
|
||||
my($setting) = shift;
|
||||
my($value) = shift;
|
||||
|
||||
my(@optional_values);
|
||||
foreach (@_) {
|
||||
push(@optional_values, $_);
|
||||
}
|
||||
|
||||
my(@this_flag) = [$setting, $value, @optional_values];
|
||||
my($flags_array) = $arrays_list{$array_name};
|
||||
if ($flags_array)
|
||||
{
|
||||
push(@{$flags_array}, @this_flag) || die "Failed to append\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
die "Error: unknown build flags array $array_name\n";
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# readFlagsFile
|
||||
#
|
||||
# Read the file of build flags from disk. File path is relative to the
|
||||
# script directory.
|
||||
#-------------------------------------------------------------------------------
|
||||
sub readFlagsFile($)
|
||||
{
|
||||
my($flags_file) = @_;
|
||||
|
||||
my($file_path) = $0;
|
||||
$file_path =~ s/[^:]+$/$flags_file/;
|
||||
|
||||
print "Reading build flags from '$file_path'\n";
|
||||
|
||||
local(*FLAGS_FILE);
|
||||
open(FLAGS_FILE, "< $file_path") || die "Error: failed to open flags file $file_path\n";
|
||||
|
||||
my($cur_array) = "";
|
||||
|
||||
while(<FLAGS_FILE>)
|
||||
{
|
||||
my($line) = $_;
|
||||
chomp($line);
|
||||
|
||||
# ignore comments and empty lines
|
||||
if ($line =~ /^\#/ || $line =~ /^\s*$/) {
|
||||
next;
|
||||
}
|
||||
|
||||
# 1-word line, probably array name
|
||||
if ($line =~ /^([^#\s]+)\s*$/)
|
||||
{
|
||||
$cur_array = $1;
|
||||
next;
|
||||
}
|
||||
elsif ($line =~ /^([^#\s]+)\s+\"(.+)\"(\s+#.+)?$/) # quoted option, possible comment
|
||||
{
|
||||
my($flag) = $1;
|
||||
my($setting) = $2;
|
||||
|
||||
appendArrayFlag($cur_array, $flag, $setting);
|
||||
}
|
||||
elsif ($line =~ /^([^#\s]+)((\s+[^#\s]+)+)(\s+#.+)?$/) # multiple word line, possible comment
|
||||
{
|
||||
my($flag) = $1;
|
||||
|
||||
appendArrayFlag($cur_array, $flag, split(' ', $2));
|
||||
}
|
||||
else
|
||||
{
|
||||
die "Error: unknown build flag at '$line'\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
close(FLAGS_FILE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# flagsArrayToHash
|
||||
#
|
||||
# Utility routine to migrate flag from a 2D array to a hash, where
|
||||
# item[n][0] is the hash entry name, and item[n][1] is the hash entry value.
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub flagsArrayToHash($$)
|
||||
{
|
||||
my($src_array, $dest_hash) = @_;
|
||||
|
||||
my($item);
|
||||
foreach $item (@$src_array)
|
||||
{
|
||||
$dest_hash->{$item->[0]} = $item->[1];
|
||||
}
|
||||
}
|
||||
|
||||
#-----------------------------------------------
|
||||
# printHash
|
||||
#
|
||||
# Utility routine to print a hash
|
||||
#-----------------------------------------------
|
||||
sub printHash($)
|
||||
{
|
||||
my($hash_ref) = @_;
|
||||
|
||||
print "Printing hash:\n";
|
||||
|
||||
my($key, $value);
|
||||
|
||||
while (($key, $value) = each (%$hash_ref))
|
||||
{
|
||||
print " $key $value\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-----------------------------------------------
|
||||
# printBuildArray
|
||||
#
|
||||
# Utility routine to print a 2D array
|
||||
#-----------------------------------------------
|
||||
sub printBuildArray($)
|
||||
{
|
||||
my($build_array) = @_;
|
||||
|
||||
my($entry);
|
||||
foreach $entry (@$build_array)
|
||||
{
|
||||
print "$entry->[0] = $entry->[1]\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# SetBuildFlags
|
||||
#-------------------------------------------------------------------------------
|
||||
sub SetBuildFlags($)
|
||||
{
|
||||
my($build) = @_;
|
||||
|
||||
flagsArrayToHash(\@build_flags, $build);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# SetBuildOptions
|
||||
#-------------------------------------------------------------------------------
|
||||
sub SetBuildOptions($)
|
||||
{
|
||||
my($options) = @_;
|
||||
|
||||
flagsArrayToHash(\@options_flags, $options);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# SetFilepathFlags
|
||||
#-------------------------------------------------------------------------------
|
||||
sub SetFilepathFlags($)
|
||||
{
|
||||
my($filepath) = @_;
|
||||
|
||||
flagsArrayToHash(\@filepath_flags, $filepath);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# SetOptionDefines
|
||||
#-------------------------------------------------------------------------------
|
||||
sub SetOptionDefines($)
|
||||
{
|
||||
my($optiondefines) = @_;
|
||||
|
||||
foreach my $entry (@options_flags)
|
||||
{
|
||||
if (defined($entry->[2])) {
|
||||
$optiondefines->{$entry->[0]}{$entry->[2]} = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# PropagateAllFlags
|
||||
#-------------------------------------------------------------------------------
|
||||
sub PropagateAllFlags($)
|
||||
{
|
||||
my($build_array) = @_;
|
||||
|
||||
# if "all" is set, set all the flags to 1
|
||||
unless ($build_array->[0][0] eq "all") { die "Error: 'all' must come first in the flags array\n"; }
|
||||
|
||||
if ($build_array->[0][1] == 1)
|
||||
{
|
||||
my($index);
|
||||
foreach $index (@$build_array)
|
||||
{
|
||||
$index->[1] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// _getBuildProgressFile
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub _getBuildProgressFile()
|
||||
{
|
||||
return $progress_file;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// setBuildProgressStart
|
||||
#//
|
||||
#// This automagically sets $build{"all"} to 0
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub setBuildProgressStart($$)
|
||||
{
|
||||
my($build_array, $name) = @_;
|
||||
|
||||
my($index);
|
||||
foreach $index (@$build_array)
|
||||
{
|
||||
$index->[1] = 0;
|
||||
if ($index->[0] eq $name) {
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
print "Building from module after $name, as specified by build progress\n";
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// InitBuildProgress
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub InitBuildProgress($)
|
||||
{
|
||||
my($prog_file) = @_;
|
||||
if ($prog_file ne "") {
|
||||
$progress_file = full_path_to($prog_file);
|
||||
print "Writing build progress to $progress_file\n";
|
||||
}
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// WriteBuildProgress
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub WriteBuildProgress($)
|
||||
{
|
||||
my($module_built) = @_;
|
||||
|
||||
my($progress_file) = _getBuildProgressFile();
|
||||
|
||||
if ($progress_file ne "")
|
||||
{
|
||||
open(PROGRESS_FILE, ">>$progress_file") || die "Failed to open $progress_file\n";
|
||||
print(PROGRESS_FILE "$module_built\n");
|
||||
close(PROGRESS_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// ClearBuildProgress
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub ClearBuildProgress()
|
||||
{
|
||||
my($progress_file) = _getBuildProgressFile();
|
||||
if ($progress_file ne "") {
|
||||
unlink $progress_file;
|
||||
}
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// WipeBuildProgress
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub WipeBuildProgress()
|
||||
{
|
||||
print "Ignoring build progress\n";
|
||||
ClearBuildProgress();
|
||||
$progress_file = "";
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// ReadBuildProgress
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub ReadBuildProgress($)
|
||||
{
|
||||
my($build_array) = @_;
|
||||
my($progress_file) = _getBuildProgressFile();
|
||||
|
||||
my($last_module);
|
||||
|
||||
if (open(PROGRESS_FILE, "< $progress_file"))
|
||||
{
|
||||
print "Getting build progress from $progress_file\n";
|
||||
|
||||
while (<PROGRESS_FILE>)
|
||||
{
|
||||
my($line) = $_;
|
||||
chomp($line);
|
||||
$last_module = $line;
|
||||
}
|
||||
|
||||
close(PROGRESS_FILE);
|
||||
}
|
||||
|
||||
if ($last_module)
|
||||
{
|
||||
setBuildProgressStart($build_array, $last_module);
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# clearOldBuildSettings
|
||||
#-------------------------------------------------------------------------------
|
||||
sub clearOldBuildSettings($$$$)
|
||||
{
|
||||
my($build, $options, $optiondefines, $filepaths) = @_;
|
||||
|
||||
# empty the arrays in case we're being called twice
|
||||
@build_flags = ();
|
||||
@options_flags = ();
|
||||
@filepath_flags = ();
|
||||
|
||||
# and empty the hashes
|
||||
%$build = ();
|
||||
%$options = ();
|
||||
%$optiondefines = ();
|
||||
%$filepaths = ();
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# SetupBuildParams
|
||||
#-------------------------------------------------------------------------------
|
||||
sub SetupBuildParams($$$$$$)
|
||||
{
|
||||
my($build, $options, $optiondefines, $filepaths, $flags_file, $prefs_file) = @_;
|
||||
|
||||
# Empty the hashes and arrays, to wipe out any stale data.
|
||||
# Needed because these structures persist across two build scripts
|
||||
# called using 'do' from a parent script.
|
||||
clearOldBuildSettings($build, $options, $optiondefines, $filepaths);
|
||||
|
||||
# Read from the flags file, which sets up the various arrays
|
||||
readFlagsFile($flags_file);
|
||||
|
||||
# If 'all' is set in the build array, propagate that to all entries
|
||||
PropagateAllFlags(\@build_flags);
|
||||
|
||||
# read the user pref file, that can change values in the array
|
||||
ReadMozUserPrefs($prefs_file, \@build_flags, \@options_flags, \@filepath_flags);
|
||||
|
||||
# If build progress exists, this clears flags in the array up to a certain point
|
||||
if ($main::USE_BUILD_PROGRESS) {
|
||||
ReadBuildProgress(\@build_flags);
|
||||
} else {
|
||||
WipeBuildProgress();
|
||||
}
|
||||
|
||||
# printBuildArray(\@build_flags);
|
||||
# printBuildArray(\@options_flags);
|
||||
|
||||
SetBuildFlags($build);
|
||||
SetBuildOptions($options);
|
||||
SetOptionDefines($optiondefines);
|
||||
SetFilepathFlags($filepaths);
|
||||
|
||||
# printHash($build);
|
||||
# printHash($options);
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
@@ -1,786 +0,0 @@
|
||||
|
||||
package Moz::BuildUtils;
|
||||
|
||||
require 5.004;
|
||||
require Exporter;
|
||||
|
||||
# Package that contains build util functions specific to the Mozilla build
|
||||
# process.
|
||||
|
||||
use strict;
|
||||
use Exporter;
|
||||
|
||||
use Cwd;
|
||||
use File::Path;
|
||||
use File::Basename;
|
||||
|
||||
use Mac::Events;
|
||||
use Mac::StandardFile;
|
||||
|
||||
use Moz::Moz;
|
||||
use Moz::BuildFlags;
|
||||
use Moz::MacCVS;
|
||||
#use Moz::ProjectXML; #optional; required for static build only
|
||||
|
||||
use vars qw(@ISA @EXPORT);
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT = qw(
|
||||
SetupDefaultBuildOptions
|
||||
SetupBuildRootDir
|
||||
StartBuildModule
|
||||
EndBuildModule
|
||||
GetBinDirectory
|
||||
BuildOneProjectWithOutput
|
||||
BuildOneProject
|
||||
BuildProject
|
||||
BuildProjectClean
|
||||
BuildIDLProject
|
||||
BuildFolderResourceAliases
|
||||
AskAndPersistFile
|
||||
DelayFor
|
||||
TimeStart
|
||||
TimeEnd
|
||||
EmptyTree
|
||||
SetupBuildLog
|
||||
SetBuildNumber
|
||||
SetTimeBomb
|
||||
UpdateConfigHeader
|
||||
);
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// SetupDefaultBuildOptions
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub SetupDefaultBuildOptions($$$)
|
||||
{
|
||||
my($debug, $bin_dir, $config_header_file_name) = @_;
|
||||
|
||||
# Here we set up defaults for the various build flags.
|
||||
# If you want to override any of these, it's best to do
|
||||
# so via the relevant preferences file, which lives in
|
||||
# System Folder:Preferences:Mozilla build prefs:{build prefs file}.
|
||||
# For the name of the prefs file, see the .pl script that you
|
||||
# run to start this build. The prefs files are created when
|
||||
# you run the build, and contain some documentation.
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# configuration variables that globally affect what is built
|
||||
#-------------------------------------------------------------
|
||||
$main::DEBUG = $debug;
|
||||
$main::PROFILE = 0;
|
||||
$main::RUNTIME = 0; # turn on to just build runtime support and NSPR projects
|
||||
$main::GC_LEAK_DETECTOR = 0; # turn on to use GC leak detection
|
||||
$main::MOZILLA_OFFICIAL = 0; # generate build number
|
||||
$main::LOG_TO_FILE = 0; # write perl output to a file
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# configuration variables that affect the manner of building,
|
||||
# but possibly affecting the outcome.
|
||||
#-------------------------------------------------------------
|
||||
$main::ALIAS_SYM_FILES = $main::DEBUG;
|
||||
$main::CLOBBER_LIBS = 1; # turn on to clobber existing libs and .xSYM files before
|
||||
# building each project
|
||||
# The following two options will delete all dist files (if you have $main::build{dist} turned on),
|
||||
# but leave the directory structure intact.
|
||||
$main::CLOBBER_DIST_ALL = 1; # turn on to clobber all aliases/files inside dist (headers/xsym/libs)
|
||||
$main::CLOBBER_DIST_LIBS = 0; # turn on to clobber only aliases/files for libraries/sym files in dist
|
||||
$main::CLOBBER_IDL_PROJECTS = 0; # turn on to clobber all IDL projects.
|
||||
$main::CLOBBER_PROJECTS = 0; # turn on to remove object code from each project before building it
|
||||
|
||||
$main::UNIVERSAL_INTERFACES_VERSION = 0x0320;
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# configuration variables that are preferences for the build,
|
||||
# style and do not affect what is built.
|
||||
#-------------------------------------------------------------
|
||||
$main::CLOSE_PROJECTS_FIRST = 0;
|
||||
# 1 = close then make (for development),
|
||||
# 0 = make then close (for tinderbox).
|
||||
$main::USE_TIMESTAMPED_LOGS = 0;
|
||||
$main::USE_BUILD_PROGRESS = 1; # track build progress for restartable builds
|
||||
#-------------------------------------------------------------
|
||||
# END OF CONFIG SWITCHES
|
||||
#-------------------------------------------------------------
|
||||
|
||||
$main::BIN_DIRECTORY = $bin_dir;
|
||||
$main::DEFINESOPTIONS_FILE = $config_header_file_name;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// SetupBuildRootDir
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub SetupBuildRootDir($)
|
||||
{
|
||||
my($rel_path_to_script) = @_;
|
||||
|
||||
my($cur_dir) = cwd();
|
||||
$cur_dir =~ s/$rel_path_to_script$//;
|
||||
chdir($cur_dir) || die "Error: failed to set build root directory to '$cur_dir'.\nYou probably need to put 'mozilla' one level down (in a folder).\n";
|
||||
$main::MOZ_SRC = cwd();
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// StartBuildModule
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub StartBuildModule($)
|
||||
{
|
||||
my($module) = @_;
|
||||
|
||||
print("---- Start of $module ----\n");
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// EndBuildModule
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub EndBuildModule($)
|
||||
{
|
||||
my($module) = @_;
|
||||
WriteBuildProgress($module);
|
||||
print("---- End of $module ----\n");
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
# GetBinDirectory
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
sub GetBinDirectory()
|
||||
{
|
||||
if ($main::BIN_DIRECTORY eq "") { die "Dist directory not set\n"; }
|
||||
return $main::BIN_DIRECTORY;
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
# AskAndPersistFile stores the information about the user pick inside
|
||||
# the file $session_storage
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
sub AskAndPersistFile($)
|
||||
{
|
||||
my ($sessionStorage) = @_;
|
||||
my $cvsfile;
|
||||
|
||||
if (( -e $sessionStorage) &&
|
||||
open( SESSIONFILE, $sessionStorage ))
|
||||
{
|
||||
# Read in the path if available
|
||||
$cvsfile = <SESSIONFILE>;
|
||||
chomp $cvsfile;
|
||||
close SESSIONFILE;
|
||||
if ( ! -e $cvsfile )
|
||||
{
|
||||
print STDERR "$cvsfile has disappeared\n";
|
||||
undef $cvsfile;
|
||||
}
|
||||
}
|
||||
unless (defined ($cvsfile))
|
||||
{
|
||||
# make sure that MacPerl is a front process
|
||||
ActivateApplication('McPL');
|
||||
MacPerl::Answer("Could not find your MacCVS session file. Please choose one", "OK");
|
||||
|
||||
# prompt user for the file name, and store it
|
||||
my $macFile = StandardGetFile( 0, "McvD");
|
||||
if ( $macFile->sfGood() )
|
||||
{
|
||||
$cvsfile = $macFile->sfFile();
|
||||
# save the choice if we can
|
||||
if ( open (SESSIONFILE, ">" . $sessionStorage))
|
||||
{
|
||||
printf SESSIONFILE $cvsfile, "\n";
|
||||
close SESSIONFILE;
|
||||
}
|
||||
else
|
||||
{
|
||||
print STDERR "Could not open storage file $sessionStorage for saving $cvsfile\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
return $cvsfile;
|
||||
}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
# BuildIDLProject
|
||||
#
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub BuildIDLProject($$)
|
||||
{
|
||||
my ($project_path, $module_name) = @_;
|
||||
|
||||
if ($main::CLOBBER_IDL_PROJECTS)
|
||||
{
|
||||
my (@suffix_list) = (".mcp", ".xml");
|
||||
my ($project_name, $project_dir, $suffix) = fileparse($project_path, @suffix_list);
|
||||
if ($suffix eq "") { die "Error: Project, $project_path must end in .xml or .mcp\n"; }
|
||||
|
||||
my($datafolder_path);
|
||||
if ($suffix eq ".xml")
|
||||
{
|
||||
$datafolder_path = $project_dir . "_" . $project_name . " Data:";
|
||||
}
|
||||
else {
|
||||
$datafolder_path = $project_dir . $project_name . " Data:";
|
||||
}
|
||||
|
||||
print STDERR "Deleting IDL data folder: $datafolder_path\n";
|
||||
EmptyTree($datafolder_path);
|
||||
}
|
||||
|
||||
BuildOneProject($project_path, "headers", 0, 0, 0);
|
||||
BuildOneProject($project_path, $module_name.".xpt", 1, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
# CreateStaticLibTargets
|
||||
#
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
sub CreateXMLStaticLibTargets($)
|
||||
{
|
||||
my($xml_path) = @_;
|
||||
|
||||
my (@suffix_list) = (".xml");
|
||||
my ($project_name, $project_dir, $suffix) = fileparse($xml_path, @suffix_list);
|
||||
if ($suffix eq "") { die "XML munging: $xml_path must end in .xml\n"; }
|
||||
|
||||
#sniff the file to see if we need to fix up broken Pro5-exported XML
|
||||
print "Parsing $xml_path\n";
|
||||
|
||||
my $ide_version = Moz::ProjectXML::SniffProjectXMLIDEVersion($xml_path);
|
||||
if ($ide_version eq "4.0")
|
||||
{
|
||||
my $new_file = $project_dir.$project_name."2.xml";
|
||||
|
||||
print "Cleaning up Pro 5 xml to $new_file\n";
|
||||
|
||||
Moz::ProjectXML::CleanupPro5XML($xml_path, $new_file);
|
||||
|
||||
unlink $xml_path;
|
||||
rename ($new_file, $xml_path);
|
||||
}
|
||||
|
||||
my $doc = Moz::ProjectXML::ParseXMLDocument($xml_path);
|
||||
my @target_list = Moz::ProjectXML::GetTargetsList($doc);
|
||||
my $target;
|
||||
|
||||
my %target_hash; # for easy lookups below
|
||||
foreach $target (@target_list) { $target_hash{$target} = 1; }
|
||||
|
||||
foreach $target (@target_list)
|
||||
{
|
||||
if ($target =~ /(.+).shlb$/) # if this is a shared lib target
|
||||
{
|
||||
my $target_base = $1;
|
||||
my $static_target = $target_base.".o";
|
||||
|
||||
# ensure that this does not exist already
|
||||
if ($target_hash{$static_target}) {
|
||||
print "Static target $static_target already exists in project. Not making\n";
|
||||
next;
|
||||
}
|
||||
|
||||
print "Making static target '$static_target' from target '$target'\n";
|
||||
|
||||
Moz::ProjectXML::CloneTarget($doc, $target, $static_target);
|
||||
Moz::ProjectXML::SetAsStaticLibraryTarget($doc, $static_target, $static_target);
|
||||
}
|
||||
}
|
||||
|
||||
print "Writing XML file to $xml_path\n";
|
||||
my $temp_path = $project_dir."_".$project_name.".xml";
|
||||
Moz::ProjectXML::WriteXMLDocument($doc, $temp_path, $ide_version);
|
||||
Moz::ProjectXML::DisposeXMLDocument($doc);
|
||||
|
||||
if (-e $temp_path)
|
||||
{
|
||||
unlink $xml_path;
|
||||
rename ($temp_path, $xml_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
die "Error: Failed to add new targets to XML project\n";
|
||||
}
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// ProcessProjectXML
|
||||
#//
|
||||
#// Helper routine to allow for XML pre-processing. This should read in the XML, process it,
|
||||
#// and replace the original file with the processed version.
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub ProcessProjectXML($)
|
||||
{
|
||||
my($xml_path) = @_;
|
||||
|
||||
# we need to manually load Moz::ProjectXML, becaues not everyone will have the
|
||||
# required perl modules in their distro.
|
||||
my($cur_dir) = cwd();
|
||||
|
||||
chdir(dirname($0)); # change to the script dir
|
||||
eval "require Moz::ProjectXML";
|
||||
if ($@) { die "Error: could not do Project XML munging because you do not have the correct XML modules installed. Error is:\n################\n $@################"; }
|
||||
|
||||
chdir($cur_dir);
|
||||
|
||||
CreateXMLStaticLibTargets($xml_path);
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// Build one project, and make the alias. Parameters are project path, target name, shared library
|
||||
#// name, make shlb alias (boolean), make xSYM alias (boolean), and is component (boolean).
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub BuildOneProjectWithOutput($$$$$$)
|
||||
{
|
||||
my ($project_path, $target_name, $output_name, $alias_lib, $alias_xSYM, $component) = @_;
|
||||
|
||||
unless ($project_path =~ m/^$main::BUILD_ROOT.+/) { return; }
|
||||
|
||||
my (@suffix_list) = (".mcp", ".xml");
|
||||
my ($project_name, $project_dir, $suffix) = fileparse($project_path, @suffix_list);
|
||||
if ($suffix eq "") { die "Error: Project, $project_path must end in .xml or .mcp\n"; }
|
||||
|
||||
my($dist_dir) = GetBinDirectory();
|
||||
|
||||
# Put libraries in "Essential Files" folder, Components in "Components" folder
|
||||
my($output_dir) = $component ? "Components:" : "Essential Files:";
|
||||
my($output_path) = $dist_dir.$output_dir;
|
||||
|
||||
if ($main::options{static_build})
|
||||
{
|
||||
if ($output_name =~ /\.o$/ || $output_name =~ /\.[Ll]ib$/)
|
||||
{
|
||||
$alias_xSYM = 0;
|
||||
$alias_lib = 1;
|
||||
$output_path = $main::DEBUG ? ":mozilla:dist:static_libs_debug:" : ":mozilla:dist:static_libs:";
|
||||
}
|
||||
}
|
||||
|
||||
# if the flag is on to export projects to XML, export and munge them
|
||||
if ($main::EXPORT_PROJECTS && !($project_path =~ /IDL\.mcp$/))
|
||||
{
|
||||
my $xml_out_path = $project_path;
|
||||
|
||||
$xml_out_path =~ s/\.mcp$/\.xml/;
|
||||
|
||||
# only do this if project is newer?
|
||||
if (! -e $xml_out_path)
|
||||
{
|
||||
ExportProjectToXML(full_path_to($project_path), full_path_to($xml_out_path));
|
||||
ProcessProjectXML($xml_out_path);
|
||||
}
|
||||
}
|
||||
|
||||
# if the flag is set to use XML projects, default to XML if the file
|
||||
# is present.
|
||||
if ($main::USE_XML_PROJECTS && !($project_path =~ /IDL\.mcp$/))
|
||||
{
|
||||
my $xml_project_path = $project_dir.$project_name.".xml";
|
||||
if (-e $xml_project_path)
|
||||
{
|
||||
$project_path = $xml_project_path;
|
||||
$suffix = ".xml";
|
||||
}
|
||||
}
|
||||
|
||||
if ($suffix eq ".xml")
|
||||
{
|
||||
my($xml_path) = $project_path;
|
||||
# Prepend an "_" onto the name of the generated project file so it doesn't conflict
|
||||
$project_path = $project_dir . "_" . $project_name . ".mcp";
|
||||
my($project_modtime) = (-e $project_path ? GetFileModDate($project_path) : 0);
|
||||
my($xml_modtime) = (-e $xml_path ? GetFileModDate($xml_path) : 0);
|
||||
|
||||
if ($xml_modtime > $project_modtime)
|
||||
{
|
||||
print("Importing $project_path from $project_name.xml.\n");
|
||||
unlink($project_path);
|
||||
# Might want to delete the "xxx.mcp Data" dir ???
|
||||
ImportXMLProject(full_path_to($xml_path), full_path_to($project_path));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($main::CLOBBER_LIBS)
|
||||
{
|
||||
unlink "$project_dir$output_name"; # it's OK if these fail
|
||||
unlink "$project_dir$output_name.xSYM";
|
||||
}
|
||||
|
||||
DoBuildProject($project_path, $target_name, $main::CLOBBER_PROJECTS);
|
||||
|
||||
$alias_lib ? MakeAlias("$project_dir$output_name", "$output_path") : 0;
|
||||
$alias_xSYM ? MakeAlias("$project_dir$output_name.xSYM", "$output_path") : 0;
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// For compatiblity with existing scripts, BuildOneProject now just calls
|
||||
#// BuildOneProjectWithOutput, with the output name and target name identical.
|
||||
#// Note that this routine assumes that the target name and the shared libary name
|
||||
#// are the same.
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub BuildOneProject($$$$$)
|
||||
{
|
||||
my ($project_path, $target_name, $alias_lib, $alias_xSYM, $component) = @_;
|
||||
|
||||
BuildOneProjectWithOutput($project_path, $target_name, $target_name,
|
||||
$alias_lib, $alias_xSYM, $component);
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// For compatiblity with existing scripts, BuildProject now just calls
|
||||
#// BuildOneProjectWithOutput, with the output name and target name identical.
|
||||
#// Note that this routine assumes that the target name and the shared libary name
|
||||
#// are the same. No aliases of the output are made.
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub BuildProject($$)
|
||||
{
|
||||
my ($project_path, $target_name) = @_;
|
||||
|
||||
BuildOneProjectWithOutput($project_path, $target_name, $target_name, 0, 0, 0);
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// Identical to BuildProject but clobbers the project before building it.
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub BuildProjectClean($$)
|
||||
{
|
||||
my ($project_path, $target_name) = @_;
|
||||
my ($save_clobber_flag) = $main::CLOBBER_PROJECTS;
|
||||
$main::CLOBBER_PROJECTS = 1;
|
||||
BuildOneProjectWithOutput($project_path, $target_name, $target_name, 0, 0, 0);
|
||||
$main::CLOBBER_PROJECTS = $save_clobber_flag;
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// Make resource aliases for one directory
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub BuildFolderResourceAliases($$)
|
||||
{
|
||||
my($src_dir, $dest_dir) = @_;
|
||||
|
||||
# get a list of all the resource files
|
||||
opendir(SRCDIR, $src_dir) || die("can't open $src_dir");
|
||||
my(@resource_files) = readdir(SRCDIR);
|
||||
closedir(SRCDIR);
|
||||
|
||||
# make aliases for each one into the dest directory
|
||||
print("Placing aliases to all files from $src_dir in $dest_dir\n");
|
||||
for ( @resource_files )
|
||||
{
|
||||
next if $_ eq "CVS";
|
||||
#print(" Doing $_\n");
|
||||
if (-l $src_dir.$_)
|
||||
{
|
||||
print(" $_ is an alias\n");
|
||||
next;
|
||||
}
|
||||
my($file_name) = $src_dir . $_;
|
||||
MakeAlias($file_name, $dest_dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// DelayFor
|
||||
#//
|
||||
#// Delay for the given number of seconds, allowing the script to be cancelled
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub DelayFor($)
|
||||
{
|
||||
my($delay_secs) = @_;
|
||||
|
||||
STDOUT->autoflush(1);
|
||||
|
||||
my($end_time) = time() + $delay_secs;
|
||||
|
||||
my($last_time) = 0;
|
||||
my($cur_time) = time();
|
||||
|
||||
while ($cur_time < $end_time)
|
||||
{
|
||||
$cur_time = time();
|
||||
if ($cur_time > $last_time)
|
||||
{
|
||||
print ".";
|
||||
$last_time = $cur_time;
|
||||
}
|
||||
|
||||
WaitNextEvent();
|
||||
}
|
||||
|
||||
print "\n";
|
||||
STDOUT->autoflush(0);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// TimeStart
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub TimeStart()
|
||||
{
|
||||
return time();
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// TimeEnd
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub TimeEnd($$)
|
||||
{
|
||||
use integer;
|
||||
|
||||
my($start_time, $operation_name) = @_;
|
||||
my($end_time) = time();
|
||||
|
||||
my($tot_sec) = $end_time - $start_time;
|
||||
|
||||
my($seconds) = $tot_sec;
|
||||
|
||||
my($hours) = $seconds / (60 * 60);
|
||||
$seconds -= $hours * (60 * 60);
|
||||
|
||||
my($minutes) = $seconds / 60;
|
||||
$seconds -= $minutes * 60;
|
||||
|
||||
print "$operation_name took $hours hours $minutes minutes and $seconds seconds\n";
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// Remove all files from a tree, leaving directories intact (except "CVS").
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub EmptyTree($)
|
||||
{
|
||||
my ($root) = @_;
|
||||
#print "EmptyTree($root)\n";
|
||||
opendir(DIR, $root);
|
||||
my $sub;
|
||||
foreach $sub (readdir(DIR))
|
||||
{
|
||||
my $fullpathname = $root.$sub; # -f, -d only work on full paths
|
||||
|
||||
# Don't call empty tree for the alias of a directory.
|
||||
# -d returns true for the alias of a directory, false for a broken alias)
|
||||
|
||||
if (-d $fullpathname)
|
||||
{
|
||||
if (-l $fullpathname) # delete aliases
|
||||
{
|
||||
unlink $fullpathname;
|
||||
next;
|
||||
}
|
||||
EmptyTree($fullpathname.":");
|
||||
if ($sub eq "CVS")
|
||||
{
|
||||
#print "rmdir $fullpathname\n";
|
||||
rmdir $fullpathname;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unless (unlink $fullpathname) { die "Failed to delete $fullpathname\n"; }
|
||||
}
|
||||
}
|
||||
closedir(DIR);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// Recurse through a directory hierarchy, looking for MANIFEST files.
|
||||
#// Currently unused.
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub ScanForManifestFiles($$$$)
|
||||
{
|
||||
my($dir, $theme_root, $theme_name, $dist_dir) = @_;
|
||||
|
||||
opendir(DIR, $dir) or die "Cannot open dir $dir\n";
|
||||
my @files = readdir(DIR);
|
||||
closedir DIR;
|
||||
|
||||
my $file;
|
||||
|
||||
foreach $file (@files)
|
||||
{
|
||||
my $filepath = $dir.":".$file;
|
||||
|
||||
if (-d $filepath)
|
||||
{
|
||||
# print "Looking for MANIFEST files in $filepath\n";
|
||||
ScanForManifestFiles($filepath, $theme_root, $theme_name, $dist_dir);
|
||||
}
|
||||
elsif ($file eq "MANIFEST")
|
||||
{
|
||||
# print "Doing manifest file $filepath\n";
|
||||
|
||||
# Get the dest path from the first line of the file
|
||||
|
||||
open(MANIFEST, $filepath) || die "Could not open file $file";
|
||||
# Read in the path if available
|
||||
my($dest_line) = <MANIFEST>;
|
||||
chomp $dest_line;
|
||||
close MANIFEST;
|
||||
|
||||
$dest_line =~ s|^#!dest[\t ]+|| || die "No destination line found in $filepath\n";
|
||||
|
||||
my($dest_path) = $dist_dir."chrome:skins:$theme_name:$dest_line";
|
||||
# print " Destination is $dest_path\n";
|
||||
|
||||
InstallResources($filepath, "$dest_path", 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-----------------------------------------------
|
||||
# SetupBuildLog
|
||||
#-----------------------------------------------
|
||||
sub SetupBuildLog($$)
|
||||
{
|
||||
my($logfile_path, $timestamped_log) = @_;
|
||||
|
||||
my($logdir) = "";
|
||||
my($logfile) = $logfile_path;
|
||||
|
||||
if ($logfile_path =~ /(.+?:)([^:]+)$/) # ? for non-greedy match
|
||||
{
|
||||
$logdir = $1;
|
||||
$logfile = $2;
|
||||
|
||||
mkpath($logdir);
|
||||
}
|
||||
|
||||
if ($timestamped_log)
|
||||
{
|
||||
#Use time-stamped names so that you don't clobber your previous log file!
|
||||
my $now = localtime();
|
||||
while ($now =~ s@:@.@) {} # replace all colons by periods
|
||||
OpenErrorLog("${logdir}${now}");
|
||||
}
|
||||
else
|
||||
{
|
||||
OpenErrorLog("${logdir}${logfile}");
|
||||
}
|
||||
}
|
||||
|
||||
#-----------------------------------------------
|
||||
# SetBuildNumber
|
||||
#-----------------------------------------------
|
||||
sub SetBuildNumber($$)
|
||||
{
|
||||
my($build_num_file, $files_to_touch) = @_;
|
||||
|
||||
# Make sure we add the config dir to search, to pick up mozBDate.pm
|
||||
# Need to do this dynamically, because this module can be used before
|
||||
# mozilla/config has been checked out.
|
||||
|
||||
my ($inc_path) = $0; # $0 is the path to the parent script
|
||||
$inc_path =~ s/:build:mac:build_scripts:.+$/:config/;
|
||||
push(@INC, $inc_path);
|
||||
|
||||
require mozBDate;
|
||||
|
||||
mozBDate::UpdateBuildNumber($build_num_file, $main::MOZILLA_OFFICIAL);
|
||||
|
||||
my($file);
|
||||
foreach $file (@$files_to_touch)
|
||||
{
|
||||
print "Writing build number to $file from ${file}.in\n";
|
||||
mozBDate::SubstituteBuildNumber($file, $build_num_file, "${file}.in");
|
||||
}
|
||||
}
|
||||
|
||||
#-----------------------------------------------
|
||||
# SetTimeBomb
|
||||
#-----------------------------------------------
|
||||
sub SetTimeBomb($$)
|
||||
{
|
||||
my ($warn_days, $bomb_days) = @_;
|
||||
|
||||
system("perl :mozilla:config:mac-set-timebomb.pl $warn_days $bomb_days");
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// Regenerate a configuration header file if necessary
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub UpdateConfigHeader($)
|
||||
{
|
||||
my($config_path) = @_;
|
||||
|
||||
my($config, $oldconfig) = ("", "");
|
||||
my($define, $definevalue, $defines);
|
||||
my($k, $l,);
|
||||
|
||||
foreach $k (keys(%main::options))
|
||||
{
|
||||
if ($main::options{$k})
|
||||
{
|
||||
foreach $l (keys(%{$main::optiondefines{$k}}))
|
||||
{
|
||||
$my::defines{$l} = $main::optiondefines{$k}{$l};
|
||||
print "Setting up my::defines{$l}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $config_headerfile = current_directory().$config_path;
|
||||
if (-e $config_headerfile)
|
||||
{
|
||||
open(CONFIG_HEADER, "< $config_headerfile") || die "$config_headerfile: $!\n";
|
||||
my($line);
|
||||
while ($line = <CONFIG_HEADER>)
|
||||
{
|
||||
if ($line =~ m/#define\s+([^\s]*)\s+([^\s]*)\s*\n/)
|
||||
{
|
||||
$define = $1;
|
||||
$definevalue = $2;
|
||||
|
||||
#canonicalize so that whitespace changes are not significant
|
||||
my $canon_value = "#define " . $define . " " . $definevalue . "\n";
|
||||
$oldconfig .= $canon_value;
|
||||
|
||||
if (exists ($my::defines{$define}) and ($my::defines{$define} == $definevalue))
|
||||
{
|
||||
delete $my::defines{$define};
|
||||
$config .= $canon_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
close(CONFIG_HEADER);
|
||||
}
|
||||
|
||||
if (%my::defines)
|
||||
{
|
||||
foreach $k (keys(%my::defines))
|
||||
{
|
||||
$config .= "#define " . $k . " " . $my::defines{$k} . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
my $file_name = basename($config_headerfile);
|
||||
if (($config ne $oldconfig) || (!-e $config_headerfile))
|
||||
{
|
||||
printf("Writing new configuration header $file_name\n");
|
||||
open(CONFIG_HEADER, "> $config_headerfile") || die "$config_headerfile: $!\n";
|
||||
print(CONFIG_HEADER "/* This file is auto-generated based on build options. Do not edit. */\n");
|
||||
print CONFIG_HEADER ($config);
|
||||
close(CONFIG_HEADER);
|
||||
|
||||
MacPerl::SetFileInfo("CWIE", "TEXT", $config_headerfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Configuration header $file_name is up-to-date\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
@@ -1,660 +0,0 @@
|
||||
#!perl
|
||||
package Moz::CodeWarriorLib;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
CodeWarriorLib - supply interface to CodeWarrior
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
#!perl
|
||||
use CodeWarriorLib;
|
||||
CodeWarriorLib::activate();
|
||||
$had_errors = CodeWarriorLib::build_project(
|
||||
$project_path, $target_name, $recent_errors_file, $clean_build
|
||||
);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Replaces the AppleScript library I<CodeWarriorLib>.
|
||||
|
||||
=over 4
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
|
||||
use Cwd;
|
||||
use File::Basename;
|
||||
|
||||
use Mac::Types;
|
||||
use Mac::Events;
|
||||
use Mac::AppleEvents;
|
||||
use Mac::AppleEvents::Simple;
|
||||
use Mac::Processes;
|
||||
use Mac::MoreFiles;
|
||||
use Mac::StandardFile;
|
||||
|
||||
|
||||
use vars qw($VERSION);
|
||||
$VERSION = '1.02';
|
||||
|
||||
my($app) = 'CWIE';
|
||||
my($scriptDir) = cwd(); # could use $0 for this
|
||||
my($ide_loc_file) = "";
|
||||
|
||||
# 0 == don't switch CWIE to front app in do_event(), 1 == do switch
|
||||
# note: activate() still switches when called
|
||||
$Mac::AppleEvents::Simple::SWITCH = 0;
|
||||
# $Mac::AppleEvents::Simple::WARN = 1;
|
||||
|
||||
# supply your own path to the source here
|
||||
#_test('PowerPudgeIV:mozilla:mozilla:');
|
||||
|
||||
# If you want to understand the gobbldeygook that's used to build Apple Events,
|
||||
# you should start by reading the AEGizmos documentation.
|
||||
|
||||
=pod
|
||||
|
||||
=item _get_project($full_path)
|
||||
|
||||
A private routine returning a reference to the open project with the given name,
|
||||
or else the empty string (when that project is not open)
|
||||
|
||||
full_path is a string identifying the project to be built and is of the form,
|
||||
e.g., "HD:ProjectFolder:MyProject.mcp". It must be supplied.
|
||||
|
||||
=cut
|
||||
|
||||
sub _get_project ($) {
|
||||
my(
|
||||
$full_path, $candidate_projects
|
||||
) = @_;
|
||||
$candidate_projects = _doc_named(basename($full_path, '*'));
|
||||
if ($candidate_projects) {
|
||||
my($cps) = _get_dobj($candidate_projects);
|
||||
my($num) = AECountItems($cps);
|
||||
if ($num) { # is a list
|
||||
foreach (1 .. AECountItems($cps)) {
|
||||
my($cp) = AEGetNthDesc($cps, $_);
|
||||
if (lc $full_path eq lc _full_path($cp)) {
|
||||
return($cp);
|
||||
}
|
||||
}
|
||||
} else { # is only one, not a list
|
||||
if (lc $full_path eq lc _full_path($cps)) {
|
||||
return($cps);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=item build_project
|
||||
|
||||
Build a selected target of a project, saving any errors to a file, if supplied.
|
||||
|
||||
full_path is a string identifying the project to be built and is of the form,
|
||||
e.g., "HD:ProjectFolder:MyProject.mcp". It must be supplied.
|
||||
|
||||
If target_name is the empty string, the current target of the selected project
|
||||
will be built, else, target_name should be a string matching a target name in
|
||||
the selected project.
|
||||
|
||||
If error_path is the empty string, errors will not be saved to a file,
|
||||
else, error_path should be the full path of a file to save error messages into.
|
||||
|
||||
=cut
|
||||
|
||||
$CodeWarriorLib::CLOSE_PROJECTS_FIRST = 0; # If true we close then make. If false, make then close.
|
||||
my $last_project_built = "";
|
||||
my $last_project_was_closed = 0;
|
||||
|
||||
sub build_project ($;$$$) {
|
||||
my(
|
||||
$full_path, $target_name, $error_path,
|
||||
$remove_object, $p, $project_was_closed, $had_errors
|
||||
) = @_;
|
||||
_close_errors_window();
|
||||
|
||||
if ($CodeWarriorLib::CLOSE_PROJECTS_FIRST && ($last_project_built ne $full_path))
|
||||
{
|
||||
# If we're in "close first" mode, we don't close if the current project
|
||||
# is the same as the previous one.
|
||||
if ($last_project_was_closed) {
|
||||
$p = _get_project($last_project_built);
|
||||
_close($p);
|
||||
}
|
||||
$last_project_built = $full_path;
|
||||
$last_project_was_closed = 0; # now refers to the new project
|
||||
}
|
||||
$project_was_closed = 0;
|
||||
while (1) {
|
||||
$p = _get_project($full_path);
|
||||
if (!$p) {
|
||||
if ($project_was_closed) {
|
||||
print "### Error - request for project document failed after opening\n";
|
||||
die "### possibly CW Pro 4 bug: be sure to close your Find window\n";
|
||||
}
|
||||
$project_was_closed = 1;
|
||||
$last_project_was_closed = 1;
|
||||
_open_file($full_path);
|
||||
} else {
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
$had_errors = 0;
|
||||
if ($target_name eq '') {
|
||||
if ($remove_object) {_remove_object($p)}
|
||||
_build($p);
|
||||
} else {
|
||||
if ($remove_object) {_remove_object($p, $target_name)}
|
||||
_build($p, $target_name);
|
||||
}
|
||||
|
||||
if ($error_path ne '') {
|
||||
_save_errors_window($error_path);
|
||||
}
|
||||
$had_errors = _close_errors_window();
|
||||
|
||||
if (!$CodeWarriorLib::CLOSE_PROJECTS_FIRST)
|
||||
{
|
||||
if ($project_was_closed) {
|
||||
$p = _get_project($full_path);
|
||||
_close($p);
|
||||
}
|
||||
}
|
||||
|
||||
return($had_errors);
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=item appIsRunning()
|
||||
|
||||
=cut
|
||||
sub _appIsRunning($)
|
||||
{
|
||||
my ($appSignature) = @_;
|
||||
my ($psi);
|
||||
my ($found) = 0;
|
||||
my ($appPSN);
|
||||
|
||||
foreach $psi (values(%Process))
|
||||
{
|
||||
if ($psi->processSignature() eq $appSignature)
|
||||
{
|
||||
$appPSN = $psi->processNumber();
|
||||
$found = 1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
return $found;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=item appIsFrontmost()
|
||||
|
||||
=cut
|
||||
sub _appIsFrontmost($)
|
||||
{
|
||||
my ($appSignature) = @_;
|
||||
my ($psi);
|
||||
my ($found) = 0;
|
||||
my ($appPSN);
|
||||
|
||||
foreach $psi (values(%Process))
|
||||
{
|
||||
if ($psi->processSignature() eq $appSignature)
|
||||
{
|
||||
$appPSN = $psi->processNumber();
|
||||
$found = 1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
return (GetFrontProcess() == $appPSN);
|
||||
}
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
=item activate()
|
||||
|
||||
Launches CodeWarrior and brings it to the front.
|
||||
|
||||
Once found, path will be saved in $idepath_file for future reference.
|
||||
Edit or delete this file to change the location of the IDE. If app is
|
||||
moved, C<activate()> will prompt for a new location.
|
||||
|
||||
First looks for an open CodeWarrior app. Second, tries to open previously
|
||||
saved location in ':idepath.txt'. Third, tries to find it and allow user
|
||||
to choose it with Navigation Services (if present). Fourth, uses good old
|
||||
GUSI routines built-in to MacPerl for a Choose Directory dialog box.
|
||||
|
||||
=cut
|
||||
|
||||
sub activate ($) {
|
||||
|
||||
$ide_loc_file = $_[0]; # save in global
|
||||
|
||||
my($filepath, $appath, $psi) = ($ide_loc_file);
|
||||
|
||||
foreach $psi (values(%Process)) {
|
||||
if ($psi->processSignature() eq $app) {
|
||||
$appath = $psi->processAppSpec();
|
||||
_save_appath($filepath, $appath);
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$appath || !-x $appath) {
|
||||
$appath = _read_appath($filepath);
|
||||
}
|
||||
|
||||
if (!$appath || ! -x $appath)
|
||||
{
|
||||
# make sure that MacPerl is a front process
|
||||
#ActivateApplication('McPL');
|
||||
MacPerl::Answer("Please locate the CodeWarrior application.", "OK");
|
||||
|
||||
# prompt user for the file name, and store it
|
||||
my $macFile = StandardGetFile( 0, "APPL");
|
||||
if ( $macFile->sfGood() )
|
||||
{
|
||||
$appath = $macFile->sfFile();
|
||||
}
|
||||
else
|
||||
{
|
||||
die "Operation canceled\n";
|
||||
}
|
||||
|
||||
# if (eval {require Mac::Navigation}) {
|
||||
# my($options, $nav);
|
||||
# Mac::Navigation->import();
|
||||
# $options = NavGetDefaultDialogOptions();
|
||||
# $options->message('Where is CodeWarrior IDE?');
|
||||
# $options->windowTitle('Find CodeWarrior IDE');
|
||||
# $nav = NavChooseObject($Application{$app}, $options);
|
||||
# die "CodeWarrior IDE not found.\n" if (!$nav || !$nav->file(1));
|
||||
# $appath = $nav->file(1);
|
||||
# } else {
|
||||
# local(*D);
|
||||
# my $cwd = `pwd`;
|
||||
# $appath = _get_folder(
|
||||
# 'Where is the CW IDE folder?',
|
||||
# dirname($Application{$app})
|
||||
# );
|
||||
# die "CodeWarrior IDE not found.\n" if !$appath;
|
||||
# opendir(D, $appath) or die $!;
|
||||
# chdir($appath);
|
||||
# foreach my $file (sort readdir (D)) {
|
||||
# my(@app) = MacPerl::GetFileInfo($file);
|
||||
# if ($app[0] && $app[1] &&
|
||||
# $app[1] eq 'APPL' && $app[0] eq $app
|
||||
# ) {
|
||||
# $appath .= $file;
|
||||
# last;
|
||||
# }
|
||||
# }
|
||||
# chomp($cwd);
|
||||
# chdir($cwd);
|
||||
# }
|
||||
_save_appath($filepath, $appath);
|
||||
}
|
||||
|
||||
my($lp) = LaunchParam->new(
|
||||
launchAppSpec => $appath,
|
||||
launchControlFlags => launchContinue() + launchNoFileFlags()
|
||||
);
|
||||
|
||||
unless (LaunchApplication($lp)) {
|
||||
unlink($filepath);
|
||||
die $^E;
|
||||
}
|
||||
|
||||
# wait for CodeWarrior to show up in the list of processes
|
||||
while (!_appIsRunning('CWIE'))
|
||||
{
|
||||
WaitNextEvent();
|
||||
}
|
||||
|
||||
# wait for CodeWarrior to come to the front
|
||||
while (!_appIsFrontmost('CWIE'))
|
||||
{
|
||||
WaitNextEvent();
|
||||
}
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=item getCodeWarriorPath()
|
||||
|
||||
Returns a file path relative to the CodeWarrior folder
|
||||
|
||||
=cut
|
||||
|
||||
sub getCodeWarriorPath($)
|
||||
{
|
||||
my($subfolder)=@_;
|
||||
|
||||
my($app_path) = _read_appath($ide_loc_file);
|
||||
if ($app_path eq "") { die "Error: Failed to get CodeWarrior IDE path\n"; }
|
||||
|
||||
my($codewarrior_root) = $app_path;
|
||||
$codewarrior_root =~ s/[^:]*$//;
|
||||
return ($codewarrior_root . $subfolder);
|
||||
}
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
=item getCodeWarriorIDEName()
|
||||
|
||||
Returns the name of the CodeWarrior application
|
||||
|
||||
=cut
|
||||
|
||||
sub getCodeWarriorIDEName()
|
||||
{
|
||||
my($subfolder)=@_;
|
||||
|
||||
my($app_path) = _read_appath($ide_loc_file);
|
||||
if ($app_path eq "") { die "Error: Failed to get CodeWarrior IDE path\n"; }
|
||||
|
||||
my(@codewarrior_path) = split(/:/, $app_path);
|
||||
return pop(@codewarrior_path);
|
||||
}
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
=item quit()
|
||||
|
||||
Quits CodeWarrior.
|
||||
|
||||
=cut
|
||||
|
||||
sub quit() {
|
||||
|
||||
$last_project_built = "";
|
||||
$last_project_was_closed = 0;
|
||||
|
||||
my($evt) = do_event(qw/aevt quit/, $app);
|
||||
}
|
||||
|
||||
|
||||
sub _build ($;$) {
|
||||
my($evt);
|
||||
if ($_[1]) {
|
||||
my($prm) =
|
||||
q"'----':obj {form:name, want:type(TRGT), seld:TEXT(@), from:" .
|
||||
AEPrint($_[0]) . '}';
|
||||
$evt = do_event(qw/CWIE MAKE/, $app, $prm, $_[1]);
|
||||
} else {
|
||||
my($prm) = q"'----':" . AEPrint($_[0]);
|
||||
$evt = do_event(qw/CWIE MAKE/, $app, $prm);
|
||||
}
|
||||
}
|
||||
|
||||
sub _remove_object ($;$) {
|
||||
my($evt);
|
||||
if ($_[1]) {
|
||||
my($prm) =
|
||||
q"'----':obj {form:name, want:type(TRGT), seld:TEXT(@), from:" .
|
||||
AEPrint($_[0]) . '}';
|
||||
$evt = do_event(qw/CWIE RMOB/, $app, $prm, $_[1]);
|
||||
} else {
|
||||
my($prm) = q"'----':" . AEPrint($_[0]);
|
||||
$evt = do_event(qw/CWIE RMOB/, $app, $prm);
|
||||
}
|
||||
}
|
||||
|
||||
sub _open_file ($) {
|
||||
my($prm) =
|
||||
q"'----':obj {form:name, want:type(alis), " .
|
||||
q"seld:TEXT(@), from:'null'()}";
|
||||
|
||||
do_event(qw/aevt odoc/, $app, $prm, $_[0]);
|
||||
}
|
||||
|
||||
sub import_project ($$) {
|
||||
my($xml_file, $project_path) = @_;
|
||||
|
||||
my($prm) = "kocl:type(PRJD), rtyp:TEXT(@), data:TEXT(@), &subj:'null'()";
|
||||
|
||||
my($evt) = do_event(qw/core crel/, $app, $prm, $project_path, $xml_file);
|
||||
my($result) = _get_event_result($evt);
|
||||
|
||||
if ($result eq "") {
|
||||
_close(_get_project($project_path));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
sub export_project ($$) {
|
||||
my($project_path, $xml_out_path) = @_;
|
||||
my($p, $project_was_closed);
|
||||
|
||||
$project_was_closed = 0;
|
||||
while (1) {
|
||||
$p = _get_project($project_path);
|
||||
if (!$p) {
|
||||
if ($project_was_closed) {
|
||||
print "### Error - request for project document failed after opening\n";
|
||||
die "### possibly CW bug: be sure to close your Find window\n";
|
||||
}
|
||||
$project_was_closed = 1;
|
||||
_open_file($project_path);
|
||||
} else {
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# avoid problems with the Project Messages window
|
||||
_close_named_window("Project Messages");
|
||||
|
||||
my($prm) =
|
||||
q"'----':obj {form:indx, want:type(PRJD), " .
|
||||
q"seld:1, from:'null'()}, kfil:TEXT(@)";
|
||||
|
||||
my($evt) = do_event(qw/CWIE EXPT/, $app, $prm, $xml_out_path);
|
||||
|
||||
if ($project_was_closed) {
|
||||
$p = _get_project($project_path);
|
||||
_close($p);
|
||||
}
|
||||
|
||||
return _get_event_result($evt);
|
||||
}
|
||||
|
||||
sub _doc_named ($) {
|
||||
my($prm) =
|
||||
q"'----':obj {form:test, want:type(docu), from:'null'(), " .
|
||||
q"seld:cmpd{relo:'= ', 'obj1':obj {form:prop, want:type" .
|
||||
q"(prop), seld:type(pnam), from:'exmn'()}, 'obj2':TEXT(@)}}";
|
||||
|
||||
my($evt) = do_event(qw/core getd/, $app, $prm, $_[0]);
|
||||
return($evt->{REPLY} eq 'aevt\ansr{}' ? undef : $evt);
|
||||
}
|
||||
|
||||
sub _full_path ($) {
|
||||
my($obj) = $_[0];
|
||||
my($prm) =
|
||||
q"'----':obj {form:prop, want:type(prop), seld:type(FILE), " .
|
||||
q"from:" . AEPrint($_[0]) . q"}, rtyp:type(TEXT)";
|
||||
my($evt) = do_event(qw/core getd/, $app, $prm);
|
||||
|
||||
return MacPerl::MakePath(
|
||||
MacUnpack('fss ', (
|
||||
AEGetParamDesc($evt->{REP}, keyDirectObject()))->data()->get()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
sub _save_errors_window ($) {
|
||||
my($prm) =
|
||||
q"'----':obj {form:name, want:type(alis), seld:TEXT(@), from:'null'()}";
|
||||
do_event(qw/MMPR SvMs/, $app, $prm, $_[0]);
|
||||
}
|
||||
|
||||
|
||||
sub _close_errors_window () {
|
||||
return _close_named_window('Errors & Warnings');
|
||||
}
|
||||
|
||||
|
||||
sub _close_named_window ($) {
|
||||
my($window_name) = @_;
|
||||
|
||||
my($prm) =
|
||||
q"'----':obj {form:name, want:type(cwin), " .
|
||||
q"seld:TEXT(@), from:'null'()}";
|
||||
|
||||
my($evt) = do_event(qw/core clos/, $app, $prm, $window_name);
|
||||
return($evt->{REPLY} eq 'aevt\ansr{}' ? 1 : 0);
|
||||
}
|
||||
|
||||
sub _close () {
|
||||
my($prm) = q"'----':" . AEPrint($_[0]);
|
||||
do_event(qw/core clos/, $app, $prm);
|
||||
}
|
||||
|
||||
sub _get_dobj ($) {
|
||||
return(AEGetParamDesc($_[0]->{REP}, keyDirectObject()));
|
||||
}
|
||||
|
||||
sub _get_folder ($$) {
|
||||
require 'GUSI.ph';
|
||||
my($prompt, $default) = @_;
|
||||
MacPerl::Choose(
|
||||
GUSI::AF_FILE(), 0, $prompt, '',
|
||||
GUSI::CHOOSE_DIR() + ($default ? &GUSI::CHOOSE_DEFAULT : 0),
|
||||
$default
|
||||
);
|
||||
}
|
||||
|
||||
sub _get_event_result ($)
|
||||
{
|
||||
my($evt) = @_;
|
||||
|
||||
my($result) = $evt->{ERROR};
|
||||
|
||||
if ( $result eq "" && $evt->{ERRNO} != 0 )
|
||||
{
|
||||
$result = "unknown error (".$evt->{ERRNO}.")";
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
sub _save_appath ($$) {
|
||||
|
||||
my($cwd) = cwd(); # remember the current working dir
|
||||
chdir($scriptDir); # change dir to the script dir
|
||||
|
||||
local(*F);
|
||||
open(F, '>' . $_[0]) or die $!;
|
||||
print F $_[1];
|
||||
close(F);
|
||||
|
||||
chdir($cwd); # restore the cwd
|
||||
}
|
||||
|
||||
sub _read_appath ($) {
|
||||
|
||||
my($filepath) = @_;
|
||||
|
||||
my($cwd) = cwd(); # remember the current working dir
|
||||
chdir($scriptDir); # change dir to the script dir
|
||||
|
||||
if (! -e $filepath) {
|
||||
return "";
|
||||
}
|
||||
|
||||
local(*F);
|
||||
open(F, $filepath);
|
||||
my($appath) = <F>;
|
||||
close(F);
|
||||
|
||||
chdir($cwd); # restore the cwd
|
||||
return($appath);
|
||||
}
|
||||
|
||||
|
||||
sub _test ($) {
|
||||
activate($ide_loc_file);
|
||||
my($path) = $_[0];
|
||||
build_project(
|
||||
"${path}modules:xml:macbuild:XML.mcp", '',
|
||||
"${path}build:mac:Mozilla.BuildLog.part"
|
||||
);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=back
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
=over 4
|
||||
|
||||
=item v1.02, September 23, 1998
|
||||
|
||||
Made fixes in finding and saving location of CodeWarrior IDE.
|
||||
|
||||
=item v1.01, June 1, 1998
|
||||
|
||||
Made fixes to C<chdir()> in C<activate()>, made C<activate()> more robust
|
||||
in finding CodeWarrior IDE, added global variable to NOT switch to IDE
|
||||
for each sent event, a few other fixes.
|
||||
|
||||
=item v1.00, May 30, 1998
|
||||
|
||||
First shot
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Chris Nandor F<E<lt>pudge@pobox.comE<gt>>, and the author of the
|
||||
original I<CodeWarriorLib>, Scott Collins F<E<lt>scc@netscape.comE<gt>>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
BuildProject L<Moz>.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
The contents of this file are subject to the Netscape Public
|
||||
License Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License. You may obtain a copy of
|
||||
the License at http://www.mozilla.org/NPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS
|
||||
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
rights and limitations under the License.
|
||||
|
||||
The Original Code is Mozilla Communicator client code, released
|
||||
March 31, 1998.
|
||||
|
||||
The Initial Developer of the Original Code is Netscape
|
||||
Communications Corporation. Portions created by Netscape are
|
||||
Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
=cut
|
||||
@@ -1,573 +0,0 @@
|
||||
#!perl -w
|
||||
package Moz::Jar;
|
||||
|
||||
#
|
||||
# Module for creating jar files, either using a jar manifest, or
|
||||
# simply jarring up folders on disk.
|
||||
#
|
||||
|
||||
require 5.004;
|
||||
require Exporter;
|
||||
|
||||
use strict;
|
||||
use Archive::Zip;
|
||||
use File::Path;
|
||||
|
||||
use Mac::Files;
|
||||
|
||||
use Moz::Moz;
|
||||
|
||||
use vars qw( @ISA @EXPORT );
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT = qw(
|
||||
CreateJarFileFromDirectory
|
||||
CreateJarFromManifest
|
||||
WriteOutJarFiles
|
||||
SanityCheckJarOptions
|
||||
);
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Add the contents of a directory to the zip file
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
sub _addDirToJar($$$$)
|
||||
{
|
||||
my($dir, $jar_root, $zip, $compress) = @_;
|
||||
|
||||
opendir(DIR, $dir) or die "Error: Cannot open dir $dir\n";
|
||||
my @files = readdir(DIR);
|
||||
closedir DIR;
|
||||
|
||||
my $unix_jar_root = $jar_root;
|
||||
$unix_jar_root =~ s|:|/|g; # colon to slash conversion
|
||||
|
||||
my $file;
|
||||
|
||||
foreach $file (@files)
|
||||
{
|
||||
my $filepath = $dir.":".$file;
|
||||
|
||||
if (-d $filepath)
|
||||
{
|
||||
print "Adding files to jar from $filepath\n";
|
||||
_addDirToJar($filepath, $jar_root, $zip, $compress);
|
||||
}
|
||||
else
|
||||
{
|
||||
my $member = Archive::Zip::Member->newFromFile($filepath);
|
||||
die "Error: Failed to create zip file member $filepath\n" unless $member;
|
||||
|
||||
my $unixName = $filepath;
|
||||
$unixName =~ s|:|/|g; # colon to slash conversion
|
||||
$unixName =~ s|^$unix_jar_root||; # relativise
|
||||
|
||||
$member->fileName($unixName);
|
||||
|
||||
# print "Adding $file as $unixName\n";
|
||||
|
||||
if ($compress) {
|
||||
$member->desiredCompressionMethod(Archive::Zip::COMPRESSION_DEFLATED);
|
||||
} else {
|
||||
$member->desiredCompressionMethod(Archive::Zip::COMPRESSION_STORED);
|
||||
}
|
||||
|
||||
$zip->addMember($member);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Add the contents of a directory to the zip file
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub CreateJarFileFromDirectory($$$)
|
||||
{
|
||||
my($srcdir, $jarpath, $compress) = @_;
|
||||
|
||||
my $zip = Archive::Zip->new();
|
||||
|
||||
_addDirToJar($srcdir, $srcdir, $zip, $compress);
|
||||
|
||||
print "Saving zip file...\n";
|
||||
my $status = $zip->writeToFileNamed($jarpath);
|
||||
if ($status == 0) {
|
||||
print "Zipping completed successfully\n";
|
||||
} else {
|
||||
print "Error saving zip file\n";
|
||||
}
|
||||
|
||||
# set the file type/creator to something reasonable
|
||||
MacPerl::SetFileInfo("ZIP ", "ZIP ", $jarpath);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# printZipContents
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
sub printZipContents($)
|
||||
{
|
||||
my($zip) = @_;
|
||||
|
||||
my(@members) = $zip->memberNames();
|
||||
|
||||
print "Zip contains:\n";
|
||||
|
||||
my($member);
|
||||
foreach $member (@members)
|
||||
{
|
||||
print " $member\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# safeSaveJarFile
|
||||
#
|
||||
# Archive::Zip has a problem where you cannot save a zip file on top of
|
||||
# an existing zip file that it has open, because it holds references
|
||||
# into that zip. So we have to save to a temp file, then do a swap.
|
||||
#
|
||||
# Note that the zip will become invalid after this operation.
|
||||
# If you want to do further operations on it, you'll have to reread it.
|
||||
#-------------------------------------------------------------------------------
|
||||
sub safeSaveJarFile($$)
|
||||
{
|
||||
my($zip, $full_dest_path) = @_;
|
||||
|
||||
my($temp_file_name) = $full_dest_path."_temp";
|
||||
|
||||
($zip->writeToFileNamed($temp_file_name) == Archive::Zip::AZ_OK) || die "Error: died writing jar to temp file $temp_file_name\n";
|
||||
|
||||
unlink $full_dest_path;
|
||||
|
||||
(rename $temp_file_name, $full_dest_path) || die "Error: Failed to rename $temp_file_name\n";
|
||||
|
||||
MacPerl::SetFileInfo("ZIP ", "ZIP ", $full_dest_path);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# addToJarFile
|
||||
#
|
||||
# Add a file to a jar file
|
||||
#
|
||||
# Parameters:
|
||||
# 1. Jar ID. Unix path of jar file inside chrome.
|
||||
# 2. Abs path to jar.mn file (i.e. source) (mac breaks)
|
||||
# 3. File source, relative to jar.mn path (mac breaks)
|
||||
# 4. Abs path to the resulting .jar file (mac breaks)
|
||||
# 5. Relative file path within the jar (unix breaks)
|
||||
# 6. Reference to hash of jar files
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub addToJarFile($$$$$$$)
|
||||
{
|
||||
my($jar_id, $jar_man_dir, $file_src, $jar_path, $file_jar_path, $override, $jars) = @_;
|
||||
|
||||
# print "addToJarFile with:\n $jar_man_dir\n $file_src\n $jar_path\n $file_jar_path\n";
|
||||
|
||||
unless ($jar_path =~ m/(.+:)([^:]+)$/) { die "Error: Bad jar path $jar_path\n"; }
|
||||
|
||||
my($target_dir) = $1;
|
||||
my($jar_name) = $2;
|
||||
|
||||
$target_dir =~ s/[^:]+$//;
|
||||
|
||||
# print "¥ $target_dir $jar_name\n";
|
||||
|
||||
# find the source file
|
||||
my($src) = $jar_man_dir.":".$file_src;
|
||||
if ((!-e $src) && ($file_src =~ m/.+:([^:]+)$/)) # src does not exist. Fall back to looking for src in jar.mn dir
|
||||
{
|
||||
$file_src = $1;
|
||||
$src = $jar_man_dir.":".$file_src;
|
||||
|
||||
if (!-e $src) {
|
||||
die "Error: Can't find chrome file $src\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($main::options{chrome_jars})
|
||||
{
|
||||
my($zip) = $jars->{$jar_id};
|
||||
unless ($zip) { die "Error: Can't find Zip entry for $jar_id\n"; }
|
||||
|
||||
# print "Adding $file_src to jar file $jar_path at $file_jar_path\n";
|
||||
my($member) = Archive::Zip::Member->newFromFile($src);
|
||||
unless ($member) { die "Error: Failed to create zip file member $src\n"; }
|
||||
|
||||
$member->fileName($file_jar_path);
|
||||
|
||||
my($compress) = 1;
|
||||
if ($compress) {
|
||||
$member->desiredCompressionMethod(Archive::Zip::COMPRESSION_DEFLATED);
|
||||
$member->desiredCompressionLevel(Archive::Zip::COMPRESSION_LEVEL_DEFAULT); # defaults to 6
|
||||
} else {
|
||||
$member->desiredCompressionMethod(Archive::Zip::COMPRESSION_STORED);
|
||||
}
|
||||
|
||||
my($old_member) = $zip->memberNamed($file_jar_path);
|
||||
|
||||
if ($override)
|
||||
{
|
||||
if ($old_member)
|
||||
{
|
||||
# print "Overriding $file_jar_path in jar file $jar_id\n";
|
||||
# need to compare mod dates or use the + here
|
||||
$zip->removeMember($old_member);
|
||||
}
|
||||
|
||||
$zip->addMember($member);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($old_member)
|
||||
{
|
||||
#compare dates here
|
||||
my($member_moddate) = $old_member->lastModTime();
|
||||
my($file_moddate) = GetFileModDate($src);
|
||||
|
||||
if ($file_moddate > $member_moddate)
|
||||
{
|
||||
print "Updating older file $file_jar_path in $jar_id\n";
|
||||
$zip->removeMember($old_member);
|
||||
$zip->addMember($member);
|
||||
}
|
||||
else
|
||||
{
|
||||
print "File $file_jar_path in $jar_id is more recent. Not updating.\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$zip->addMember($member);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($main::options{chrome_files}) # we install raw files too
|
||||
{
|
||||
my($rel_path) = $file_jar_path;
|
||||
$rel_path =~ s|/|:|g; # slash to colons
|
||||
|
||||
my($dir_name) = $jar_name;
|
||||
$dir_name =~ s/\.jar$//;
|
||||
|
||||
my($dst) = $target_dir.$dir_name.":".$rel_path;
|
||||
|
||||
# print "Aliassing $src\n to\n$dst\n";
|
||||
if ($override)
|
||||
{
|
||||
unlink $dst;
|
||||
MakeAlias($src, $dst); # don't check errors, otherwise we fail on replacement
|
||||
}
|
||||
else
|
||||
{
|
||||
if (-e $dst)
|
||||
{
|
||||
#compare dates here
|
||||
my($dst_moddate) = GetFileModDate($dst);
|
||||
my($file_moddate) = GetFileModDate($src);
|
||||
|
||||
if ($file_moddate > $dst_moddate)
|
||||
{
|
||||
print "Updating older file $rel_path in $dir_name\n";
|
||||
unlink $dst;
|
||||
MakeAlias($src, $dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
print "File $file_jar_path in $jar_id is more recent. Not updating.\n";
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
MakeAlias($src, $dst);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# setupJarFile
|
||||
#
|
||||
# setup a zip for writing
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub setupJarFile($$$)
|
||||
{
|
||||
my($jar_id, $dest_path, $jar_hash) = @_;
|
||||
|
||||
# print "Creating jar file $jar_id at $jar_path\n";
|
||||
|
||||
my($jar_file) = $jar_id;
|
||||
$jar_file =~ s|/|:|g; # slash to colons
|
||||
my($full_jar_path) = full_path_to($dest_path.":".$jar_file);
|
||||
|
||||
if ($main::options{chrome_jars})
|
||||
{
|
||||
my($zip) = $jar_hash->{$jar_id};
|
||||
if (!$zip) # if we haven't made it already, do so
|
||||
{
|
||||
my($zip) = Archive::Zip->new();
|
||||
$jar_hash->{$jar_id} = $zip;
|
||||
|
||||
# does the jar file exist already? If so, read it in
|
||||
if (-e $full_jar_path)
|
||||
{
|
||||
print "Reading in jar file $jar_id\n";
|
||||
if ($zip->read($full_jar_path) != Archive::Zip::AZ_OK) { die "Error: Failed to re-read $full_jar_path\n"; }
|
||||
|
||||
# printZipContents($zip);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
# installing files.
|
||||
# nothing to do. MakeAlias creates dirs as needed.
|
||||
|
||||
# add this jar to the list
|
||||
$jar_hash->{$jar_id} = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# closeJarFile
|
||||
#
|
||||
# We're done with this jar file _for this jar.mn_. We may add more entries
|
||||
# to it later, so keep it open in the hash.
|
||||
#-------------------------------------------------------------------------------
|
||||
sub closeJarFile($$)
|
||||
{
|
||||
my($jar_path, $jar_hash) = @_;
|
||||
|
||||
# print "Closing jar file $jar_path\n";
|
||||
|
||||
if ($main::options{chrome_jars})
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
# installing files.
|
||||
# nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# WriteOutJarFiles
|
||||
#
|
||||
# Now we dump out the jars
|
||||
#-------------------------------------------------------------------------------
|
||||
sub WriteOutJarFiles($$)
|
||||
{
|
||||
my($chrome_dir, $jars) = @_;
|
||||
|
||||
unless ($main::options{chrome_jars}) { return; }
|
||||
|
||||
my($full_chrome_path) = full_path_to($chrome_dir);
|
||||
|
||||
my($key);
|
||||
foreach $key (keys %$jars)
|
||||
{
|
||||
my($zip) = $jars->{$key};
|
||||
|
||||
my($rel_path) = $key;
|
||||
$rel_path =~ s/\//:/g;
|
||||
|
||||
my($output_path) = $full_chrome_path.":".$rel_path;
|
||||
|
||||
print "Writing zip file $key to $output_path\n";
|
||||
|
||||
# ensure the target dirs exist
|
||||
my($path) = $output_path;
|
||||
$path =~ s/[^:]+$//;
|
||||
mkpath($path);
|
||||
|
||||
# unlink $output_path; # remove any existing jar
|
||||
safeSaveJarFile($zip, $output_path);
|
||||
# $zip is invalid after this operation, so nuke it here
|
||||
$jars->{$key} = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# registerChromePackage
|
||||
#
|
||||
# Enter a chrome package into the installed-chrome.txt file
|
||||
#-------------------------------------------------------------------------------
|
||||
sub registerChromePackage($$$$$$)
|
||||
{
|
||||
my($jar_file, $file_path, $chrome_dir, $jar_hash, $chrome_type, $pkg_name) = @_;
|
||||
|
||||
my($manifest_subdir) = $jar_file;
|
||||
$manifest_subdir =~ s/:/\//g;
|
||||
|
||||
my($chrome_entry);
|
||||
|
||||
if ($main::options{use_jars}) {
|
||||
$chrome_entry = "$chrome_type,install,url,jar:resource:/chrome/$manifest_subdir!/$chrome_type/$pkg_name";
|
||||
} else {
|
||||
$manifest_subdir =~ s/\.jar$//;
|
||||
$chrome_entry = "$chrome_type,install,url,resource:/chrome/$manifest_subdir/$chrome_type/$pkg_name";
|
||||
}
|
||||
|
||||
# print "Entering $chrome_entry in installed-chrome.txt\n";
|
||||
|
||||
# ensure chrome_dir exists
|
||||
mkpath($chrome_dir);
|
||||
|
||||
my($inst_chrome) = ${chrome_dir}.":installed-chrome.txt";
|
||||
|
||||
if (open(CHROMEFILE, "<$inst_chrome")) {
|
||||
while (<CHROMEFILE>) {
|
||||
chomp;
|
||||
if ($_ eq $chrome_entry) {
|
||||
# $chrome_entry already appears in installed-chrome.txt file
|
||||
# just update the mod date
|
||||
my $now = time;
|
||||
utime($now, $now, $inst_chrome) || die "Error: Couldn't touch $inst_chrome";
|
||||
print "+++ updating chrome $inst_chrome\n+++\t\t$chrome_entry\n";
|
||||
close(CHROMEFILE) || die "Error: can't close $inst_chrome: $!";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
close(CHROMEFILE) || die "Error: can't close $inst_chrome: $!";
|
||||
}
|
||||
open(CHROMEFILE, ">>${inst_chrome}") || die "Error: Failed to open $inst_chrome\n";
|
||||
print(CHROMEFILE "${chrome_entry}\n");
|
||||
close(CHROMEFILE) || die "Error: Failed to close $inst_chrome\n";
|
||||
print "+++ adding chrome $inst_chrome\n+++\t\t$chrome_entry\n";
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Create or add to a jar file from a jar.mn file.
|
||||
# Both arguments are relative to the mozilla root dir.
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
sub CreateJarFromManifest($$$)
|
||||
{
|
||||
my($jar_man_path, $dest_path, $jars) = @_;
|
||||
|
||||
if ($main::options{chrome_jars}) {
|
||||
print "Jarring from $jar_man_path\n";
|
||||
}
|
||||
if ($main::options{chrome_files}) {
|
||||
print "Installing files from $jar_man_path\n";
|
||||
}
|
||||
|
||||
$jar_man_path = full_path_to($jar_man_path);
|
||||
$dest_path = full_path_to($dest_path);
|
||||
|
||||
# if the jars hash is empty, nuke installed-chrome.txt
|
||||
if (! scalar(%$jars))
|
||||
{
|
||||
print "Nuking installed-chrome.txt\n";
|
||||
my($installed_chrome) = $dest_path.":installed-chrome.txt";
|
||||
# unlink $installed_chrome;
|
||||
}
|
||||
|
||||
my $jar_man_dir = "";
|
||||
my $jar_man_file = "";
|
||||
|
||||
if ($jar_man_path =~ /(.+):([^:]+)$/)
|
||||
{
|
||||
$jar_man_dir = $1; # no trailing :
|
||||
$jar_man_file = $2;
|
||||
}
|
||||
|
||||
# Keep a hash of jar files, keyed on relative jar path (e.g. "packages/core.jar")
|
||||
# Entries are open Archive::Zips (if zipping), and installed-chrome entries.
|
||||
|
||||
my($jar_id) = ""; # Current foo/bar.jar from jar.mn file
|
||||
my($jar_file) = ""; # relative path to jar file (from $dest_path), with mac separators
|
||||
my($full_jar_path);
|
||||
|
||||
open(FILE, "<$jar_man_path") || die "Error: could not open \"$jar_man_path\": $!";
|
||||
while (<FILE>)
|
||||
{
|
||||
my($line) = $_;
|
||||
chomp($line);
|
||||
|
||||
# print "$line\n";
|
||||
|
||||
if ($line =~ /^\s*\#.*$/) { # skip comments
|
||||
next;
|
||||
}
|
||||
|
||||
if ($line =~/^([\w\d.\-\_\\\/]+)\:\s*$/) # line start jar file entries
|
||||
{
|
||||
$jar_id = $1;
|
||||
$jar_file = $jar_id;
|
||||
$jar_file =~ s|/|:|g; # slash to colons
|
||||
$full_jar_path = $dest_path.":".$jar_file;
|
||||
|
||||
setupJarFile($jar_id, $dest_path, $jars);
|
||||
|
||||
}
|
||||
elsif ($line =~ /^(\+?)\s+([\w\d.\-\_\\\/]+)\s*(\([\w\d.\-\_\\\/]+\))?$\s*/) # jar file entry
|
||||
{
|
||||
my($override) = ($1 eq "+");
|
||||
my($file_dest) = $2;
|
||||
my($file_src) = $3;
|
||||
|
||||
if ($file_src) {
|
||||
$file_src = substr($file_src, 1, -1); #strip the ()
|
||||
} else {
|
||||
$file_src = $file_dest;
|
||||
}
|
||||
|
||||
$file_src =~ s|/|:|g;
|
||||
|
||||
if ($jar_file ne "") # if jar is open, add to jar
|
||||
{
|
||||
if ($file_dest =~ /([\w\d.\-\_]+)\/([\w\d.\-\_\\\/]+)contents.rdf/)
|
||||
{
|
||||
my $chrome_type = $1;
|
||||
my $pkg_name = $2;
|
||||
registerChromePackage($jar_file, $file_dest, $dest_path, $jars, $chrome_type, $pkg_name);
|
||||
}
|
||||
|
||||
addToJarFile($jar_id, $jar_man_dir, $file_src, $full_jar_path, $file_dest, $override, $jars);
|
||||
}
|
||||
else
|
||||
{
|
||||
die "Error: bad jar.mn format at $line\n";
|
||||
}
|
||||
}
|
||||
elsif ($line =~ /^\s*$/ ) # blank line
|
||||
{
|
||||
if ($jar_file ne "") #if a jar file is open, close it
|
||||
{
|
||||
closeJarFile($full_jar_path, $jars);
|
||||
|
||||
$jar_file = "";
|
||||
$full_jar_path = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(FILE);
|
||||
|
||||
if ($jar_file ne "") #if a jar file is open, close it
|
||||
{
|
||||
closeJarFile($full_jar_path, $jars);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -1,228 +0,0 @@
|
||||
#!perl -w
|
||||
package Moz::MacCVS;
|
||||
|
||||
# package Mac::Apps::MacCVS; this should really be the name of the package
|
||||
# but due to our directory hierarchy in mozilla, I am not doing it
|
||||
|
||||
require 5.004;
|
||||
require Exporter;
|
||||
|
||||
use strict;
|
||||
use Exporter;
|
||||
|
||||
use vars qw($VERSION @ISA @EXPORT);
|
||||
|
||||
use Cwd;
|
||||
|
||||
use File::Basename;
|
||||
|
||||
use Mac::StandardFile;
|
||||
use Mac::AppleEvents;
|
||||
use Mac::AppleEvents::Simple;
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT = qw(new describe checkout update);
|
||||
$VERSION = "1.00";
|
||||
|
||||
# If you want to understand the gobbldeygook that's used to build Apple Events,
|
||||
# you should start by reading the AEGizmos documentation.
|
||||
|
||||
|
||||
# Architecture:
|
||||
# cvs session object:
|
||||
# name - session name
|
||||
# session_file - session file
|
||||
#
|
||||
#
|
||||
|
||||
my($last_error) = 0;
|
||||
my($gAppSig) = 'Mcvs'; # MacCVS Pro
|
||||
|
||||
#
|
||||
# utility routines
|
||||
#
|
||||
|
||||
|
||||
sub _checkForEventError($)
|
||||
{
|
||||
my($evt) = @_;
|
||||
|
||||
if ($evt->{ERRNO} != 0)
|
||||
{
|
||||
print STDERR "Error. Script returned '$evt->{ERROR} (error $evt->{ERRNO})\n";
|
||||
$last_error = $evt->{ERRNO};
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1; # success
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Session object methods
|
||||
#
|
||||
|
||||
sub new
|
||||
{
|
||||
my ( $proto, $session_file) = @_;
|
||||
my $class = ref($proto) || $proto;
|
||||
my $self = {};
|
||||
|
||||
if ( defined($session_file) && ( -e $session_file) )
|
||||
{
|
||||
$self->{"name"} = basename( $session_file );
|
||||
$self->{"session_file"} = $session_file;
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
else
|
||||
{
|
||||
print STDERR "MacCVS->new cvs file < $session_file > does not exist\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
# makes sure that the session is open
|
||||
# assertSessionOpen()
|
||||
# returns 1 on success
|
||||
sub assertSessionOpen()
|
||||
{
|
||||
my ($self) = shift;
|
||||
|
||||
$last_error = 0;
|
||||
|
||||
my($prm) =
|
||||
q"'----':obj {form:name, want:type(alis), seld:TEXT(@), from:'null'()}";
|
||||
|
||||
my($evt) = do_event(qw/aevt odoc/, $gAppSig, $prm, $self->{session_file});
|
||||
return _checkForEventError($evt);
|
||||
}
|
||||
|
||||
# prints the cvs object, used mostly for debugging
|
||||
sub describe
|
||||
{
|
||||
my($self) = shift;
|
||||
$last_error = 0;
|
||||
print "MacCVS:: name: ", $self->{name}, " session file: ", $self->{session_file}, "\n";
|
||||
}
|
||||
|
||||
# checkout( self, module, revision, date)
|
||||
# MacCVS checkout command
|
||||
# returns 1 on success.
|
||||
sub checkout()
|
||||
{
|
||||
my($self, $module, $revision, $date ) = @_;
|
||||
unless( defined ($module) ) { $module = ""; } # get rid of the pesky undefined warnings
|
||||
unless( defined ($revision) ) { $revision = ""; }
|
||||
unless( defined ($date) ) { $date = ""; }
|
||||
|
||||
$last_error = 0;
|
||||
|
||||
$self->assertSessionOpen() || die "Error: failed to open MacCVS session file at $self->{session_file}\n";
|
||||
|
||||
my($revstring) = ($revision ne "") ? $revision : "(none)";
|
||||
my($datestring) = ($date ne "") ? $date : "(none)";
|
||||
|
||||
print "Checking out $module with revision $revstring, date $datestring\n";
|
||||
|
||||
my($prm) =
|
||||
q"'----':obj {form:name, want:type(docu), seld:TEXT(@), from:'null'()}, ".
|
||||
q"modl:'TEXT'(@), tagr:'TEXT'(@), tagd:'TEXT'(@) ";
|
||||
|
||||
my($evt) = do_event(qw/MCvs cout/, $gAppSig, $prm, $self->{name}, $module, $revision, $date);
|
||||
return _checkForEventError($evt);
|
||||
}
|
||||
|
||||
|
||||
# update( self, branch tag, list of paths)
|
||||
# MacCVS udate command
|
||||
# returns 1 on success.
|
||||
# NOTE: MacCVS Pro does not correctly support this stuff yet (as of version 2.7d5).
|
||||
sub update()
|
||||
{
|
||||
my($self, $branch, $paths ) = @_;
|
||||
|
||||
$last_error = 0;
|
||||
|
||||
$self->assertSessionOpen() || die "Error: failed to open MacCVS session file at $self->{session_file}\n";
|
||||
|
||||
if ($branch eq "HEAD") {
|
||||
$branch = "";
|
||||
}
|
||||
|
||||
my($paths_list) = "";
|
||||
|
||||
my($path);
|
||||
foreach $path (@$paths)
|
||||
{
|
||||
if ($paths_list ne "") {
|
||||
$paths_list = $paths_list.", ";
|
||||
}
|
||||
|
||||
$paths_list = $paths_list."Ò".$path."Ó";
|
||||
}
|
||||
|
||||
my($prm) =
|
||||
q"'----':obj {form:name, want:type(docu), seld:TEXT(@), from:'null'()}, ".
|
||||
q"tagr:'TEXT'(@), tFls:[";
|
||||
|
||||
$prm = $prm.$paths_list."]";
|
||||
|
||||
my($evt) = do_event(qw/MCvs updt/, $gAppSig, $prm, $self->{name}, $branch);
|
||||
return _checkForEventError($evt);
|
||||
};
|
||||
|
||||
|
||||
sub getLastError()
|
||||
{
|
||||
return $last_error;
|
||||
}
|
||||
|
||||
1;
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
MacCVS - Interface to MacCVS
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use MacCVS;
|
||||
$session = MacCVS->new( <session_file_path>) || die "cannot create session";
|
||||
$session->checkout([module] [revision] [date]) || die "Could not check out";
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is a MacCVS interface for talking to MacCVS Pro client.
|
||||
MacCVSSession is the class used to manipulate the session
|
||||
|
||||
=item new
|
||||
MacCVS->new( <cvs session file path>);
|
||||
|
||||
Creates a new session. Returns undef on failure.
|
||||
|
||||
=item checkout( <module> [revision] [date] )
|
||||
|
||||
cvs checkout command. Revision and date are optional
|
||||
returns 0 on failure
|
||||
|
||||
=cut
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
=over
|
||||
|
||||
=item MacCVS Home Page
|
||||
|
||||
http://www.maccvs.org/
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Aleks Totic atotic@netscape.com
|
||||
Simon Fraser sfraser@netscape.com
|
||||
|
||||
=cut
|
||||
|
||||
__END__
|
||||
@@ -1,603 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
B<Moz> - routines for automating CodeWarrior builds, and some extra-curricular
|
||||
activities related to building Mozilla
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Moz;
|
||||
|
||||
OpenErrorLog(":::BuildLog");
|
||||
StopForErrors();
|
||||
|
||||
$Moz::QUIET = 1;
|
||||
InstallFromManifest(":projects:MANIFEST", $dist_dir);
|
||||
|
||||
BuildProjectClean(":projects:SomeProject.mcp", "SomeTarget");
|
||||
MakeAlias(":projects:SomeProject.shlb", $dist_dir);
|
||||
|
||||
DontStopForErrors();
|
||||
|
||||
BuildProject(":projects:SomeOtherProject.mcp", "SomeTarget");
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<Moz> comprises the routines needed to slap CodeWarrior around, force it
|
||||
to build a sequence of projects, report the results, and a few other things.
|
||||
This module should only contain functions that are generic to any build,
|
||||
not just the Mozilla build.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
package Moz::Moz;
|
||||
require Exporter;
|
||||
|
||||
use Cwd;
|
||||
|
||||
use File::Copy;
|
||||
use File::Path;
|
||||
use File::Basename;
|
||||
|
||||
use Mac::Types;
|
||||
use Mac::Events;
|
||||
use Mac::Processes;
|
||||
|
||||
use ExtUtils::Manifest 'maniread';
|
||||
|
||||
use Moz::CodeWarriorLib;
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
|
||||
@EXPORT = qw( LaunchCodeWarrior
|
||||
GetCodeWarriorRelativePath
|
||||
current_directory
|
||||
full_path_to
|
||||
DoBuildProject
|
||||
ImportXMLProject
|
||||
ExportProjectToXML
|
||||
OpenErrorLog
|
||||
MakeAlias
|
||||
GetFileModDate
|
||||
StopForErrors
|
||||
DontStopForErrors
|
||||
InstallFromManifest
|
||||
InstallResources
|
||||
RedirectOutputToFile
|
||||
Delay
|
||||
ActivateApplication
|
||||
IsProcessRunning);
|
||||
|
||||
@EXPORT_OK = qw(CloseErrorLog QUIET);
|
||||
|
||||
|
||||
sub current_directory()
|
||||
{
|
||||
my $current_directory = cwd();
|
||||
chop($current_directory) if ( $current_directory =~ m/:$/ );
|
||||
return $current_directory;
|
||||
}
|
||||
|
||||
sub full_path_to($)
|
||||
{
|
||||
my ($path) = @_;
|
||||
if ( $path =~ m/^[^:]+$/ )
|
||||
{
|
||||
$path = ":" . $path;
|
||||
}
|
||||
|
||||
if ( $path =~ m/^:/ )
|
||||
{
|
||||
$path = current_directory() . $path;
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
$logging = 0;
|
||||
$recent_errors_file = "";
|
||||
$stop_on_1st_error = 1;
|
||||
$QUIET = 0;
|
||||
|
||||
|
||||
|
||||
=head2 Logging all the errors and warnings - C<OpenErrorLog($log_file)>, C<CloseErrorLog()>
|
||||
|
||||
The warnings and errors generated in the course of building projects can be logged to a file.
|
||||
Tinderbox uses this facility to show why a remote build failed.
|
||||
|
||||
Logging is off by default.
|
||||
Start logging at any point in your build process with C<OpenErrorLog($log_file)>.
|
||||
Stop with C<CloseErrorLog()>.
|
||||
You never need to close the log explicitly, unless you want to just log a couple of projects in the middle of a big list.
|
||||
C<CloseErrorLog()> is not exported by default.
|
||||
|
||||
=cut
|
||||
|
||||
sub CloseErrorLog()
|
||||
{
|
||||
if ( $logging )
|
||||
{
|
||||
close(ERROR_LOG);
|
||||
$logging = 0;
|
||||
StopForErrors() if $stop_on_1st_error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub OpenErrorLog($)
|
||||
{
|
||||
my ($log_file) = @_;
|
||||
|
||||
CloseErrorLog();
|
||||
if ( $log_file )
|
||||
{
|
||||
$log_file = full_path_to($log_file);
|
||||
|
||||
open(ERROR_LOG, ">$log_file") || die "Error: Can't open $log_file\n";
|
||||
MacPerl::SetFileInfo("CWIE", "TEXT", $log_file);
|
||||
|
||||
$log_file =~ m/.+:(.+)/;
|
||||
$recent_errors_file = full_path_to("$1.part");
|
||||
$logging = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
=head2 Stopping before it's too late - C<StopForErrors()>, C<DontStopForErrors()>
|
||||
|
||||
When building a long list of projects, you decide whether to continue building subsequent projects when one fails.
|
||||
By default, your build script will C<die> after the first project that generates an error while building.
|
||||
Change this behavior with C<DontStopForErrors()>.
|
||||
Re-enable it with C<StopForErrors()>.
|
||||
|
||||
=cut
|
||||
|
||||
sub StopForErrors()
|
||||
{
|
||||
$stop_on_1st_error = 1;
|
||||
|
||||
# Can't stop for errors unless we notice them.
|
||||
# Can't notice them unless we are logging.
|
||||
# If the user didn't explicitly request logging, log to a temporary file.
|
||||
|
||||
if ( ! $recent_errors_file )
|
||||
{
|
||||
OpenErrorLog("${TMPDIR}BuildResults");
|
||||
}
|
||||
}
|
||||
|
||||
sub DontStopForErrors()
|
||||
{
|
||||
$stop_on_1st_error = 0;
|
||||
}
|
||||
|
||||
sub log_message($)
|
||||
{
|
||||
if ( $logging )
|
||||
{
|
||||
my ($message) = @_;
|
||||
print ERROR_LOG $message;
|
||||
}
|
||||
}
|
||||
|
||||
sub log_message_with_time($)
|
||||
{
|
||||
if ( $logging )
|
||||
{
|
||||
my ($message) = @_;
|
||||
my $time_stamp = localtime();
|
||||
log_message("$message ($time_stamp)\n");
|
||||
}
|
||||
}
|
||||
|
||||
sub log_recent_errors($)
|
||||
{
|
||||
my ($project_name) = @_;
|
||||
my $found_errors = 0;
|
||||
|
||||
if ( $logging )
|
||||
{
|
||||
open(RECENT_ERRORS, "<$recent_errors_file");
|
||||
|
||||
while( <RECENT_ERRORS> )
|
||||
{
|
||||
if ( /^Error/ || /^CouldnÕt find project file/ || /^Link Error/ )
|
||||
{
|
||||
# if (!$found_errors)
|
||||
# print $_;
|
||||
$found_errors = 1;
|
||||
}
|
||||
print ERROR_LOG $_;
|
||||
}
|
||||
|
||||
close(RECENT_ERRORS);
|
||||
unlink("$recent_errors_file");
|
||||
}
|
||||
|
||||
if ( $stop_on_1st_error && $found_errors )
|
||||
{
|
||||
print ERROR_LOG "### Build failed.\n";
|
||||
die "### Errors encountered building \"$project_name\".\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub DoBuildProject($$$)
|
||||
{
|
||||
my ($project_path, $target_name, $clean_build) = @_;
|
||||
$project_path = full_path_to($project_path);
|
||||
|
||||
# $project_path =~ m/.+:(.+)/;
|
||||
# my $project_name = $1;
|
||||
|
||||
log_message_with_time("### Building \"$project_path\"");
|
||||
|
||||
# Check that the given project exists
|
||||
if (! -e $project_path)
|
||||
{
|
||||
print ERROR_LOG "### Build failed.\n";
|
||||
die "### Can't find project file \"$project_path\".\n";
|
||||
}
|
||||
|
||||
print "Building \"$project_path\[$target_name\]\"\n";
|
||||
|
||||
$had_errors = Moz::CodeWarriorLib::build_project(
|
||||
$project_path, $target_name, $recent_errors_file, $clean_build
|
||||
);
|
||||
WaitNextEvent();
|
||||
|
||||
# $had_errors =
|
||||
#MacPerl::DoAppleScript(<<END_OF_APPLESCRIPT);
|
||||
# tell (load script file "$CodeWarriorLib") to BuildProject("$project_path", "$project_name", "$target_name", "$recent_errors_file", $clean_build)
|
||||
#END_OF_APPLESCRIPT
|
||||
|
||||
# Append any errors to the globally accumulated log file
|
||||
# if ( $had_errors ) # Removed this test, because we want warnings, too. -- jrm
|
||||
{
|
||||
log_recent_errors($project_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub ImportXMLProject($$)
|
||||
{
|
||||
my ($xml_path, $project_path) = @_;
|
||||
|
||||
# my ($codewarrior_ide_name) = Moz::CodeWarriorLib::getCodeWarriorIDEName();
|
||||
# my $ascript = <<EOS;
|
||||
# tell application "$codewarrior_ide_name"
|
||||
# make new (project document) as ("$project_path") with data ("$xml_path")
|
||||
# end tell
|
||||
#EOS
|
||||
# print $ascript."\n";
|
||||
# my($result) = MacPerl::DoAppleScript($ascript);
|
||||
# unless ($result) { die "Error: ImportXMLProject AppleScript failed $^E $result\n"; }
|
||||
#
|
||||
|
||||
my($import_error) = Moz::CodeWarriorLib::import_project($xml_path, $project_path);
|
||||
if ($import_error ne "") {
|
||||
die "Error: ImportXMLProject failed with error $import_error\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub ExportProjectToXML($$)
|
||||
{
|
||||
my ($project_path, $xml_path) = @_;
|
||||
|
||||
my (@suffix_list) = (".mcp");
|
||||
my ($project_name, $project_dir, $suffix) = fileparse($project_path, @suffix_list);
|
||||
if ($suffix eq "") { die "Project: $project_path doesn't look like a project file.\n"; }
|
||||
|
||||
if (-e $xml_path) {
|
||||
print "$xml_path exists - not exporting $project_path\n";
|
||||
}
|
||||
else {
|
||||
print "Exporting $project_path to $xml_path\n";
|
||||
my($export_error) = Moz::CodeWarriorLib::export_project($project_path, $xml_path);
|
||||
if ($export_error ne "") {
|
||||
die "Error: export_project failed with error '$export_error'\n";
|
||||
}
|
||||
|
||||
if (! -e $xml_path) {
|
||||
die "Error: XML export to $xml_path failed\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
=head2 Miscellaneous
|
||||
|
||||
C<MakeAlias($old_file, $new_file)> functions like C<symlink()>, except with better argument defaulting and more explicit error messages.
|
||||
|
||||
=cut
|
||||
|
||||
sub MakeAlias($$)
|
||||
{
|
||||
my ($old_file, $new_file) = @_;
|
||||
|
||||
# if the directory to hold $new_file doesn't exist, create it
|
||||
if ( ($new_file =~ m/(.+:)/) && !-d $1 )
|
||||
{
|
||||
mkpath($1);
|
||||
}
|
||||
|
||||
# if a leaf name wasn't specified for $new_file, use the leaf from $old_file
|
||||
if ( ($new_file =~ m/:$/) && ($old_file =~ m/.+:(.+)/) )
|
||||
{
|
||||
$new_file .= $1;
|
||||
}
|
||||
|
||||
my $message = "Can't create a Finder alias (at \"$new_file\")\n for \"$old_file\"; because ";
|
||||
|
||||
die "Error: $message \"$old_file\" doesn't exist.\n" unless -e $old_file;
|
||||
die "Error: $message I won't replace an existing (non-alias) file with an alias.\n" if ( -e $new_file && ! -l $new_file );
|
||||
|
||||
# now: $old_file exists; $new_file doesn't (or else, is an alias already)
|
||||
|
||||
if ( -l $new_file )
|
||||
{
|
||||
# ...then see if it already points to $old_file
|
||||
my $current_target = full_path_to(readlink($new_file));
|
||||
my $new_target = full_path_to($old_file);
|
||||
|
||||
return if ( $current_target eq $new_target );
|
||||
# if the desired alias already exists and points to the right thing, then we're done
|
||||
|
||||
unlink $new_file;
|
||||
}
|
||||
|
||||
symlink($old_file, $new_file) || die "Error: $message symlink returned an unexpected error.\n";
|
||||
}
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
C<InstallFromManifest()>
|
||||
|
||||
=cut
|
||||
|
||||
sub InstallFromManifest($;$$)
|
||||
{
|
||||
my ($manifest_file, $dest_dir, $flat) = @_;
|
||||
|
||||
$flat = 0 unless defined($flat); # if $flat, all rel. paths in MANIFEST get aliased to the root of $dest_dir
|
||||
|
||||
$dest_dir ||= ":";
|
||||
|
||||
$manifest_file =~ m/(.+):/;
|
||||
my $source_dir = $1;
|
||||
|
||||
chop($dest_dir) if $dest_dir =~ m/:$/;
|
||||
|
||||
#Mac::Events->import();
|
||||
WaitNextEvent();
|
||||
if ($flat)
|
||||
{
|
||||
print "Doing manifest on \"$manifest_file\" FLAT\n" unless $QUIET;
|
||||
}
|
||||
else
|
||||
{
|
||||
print "Doing manifest on \"$manifest_file\"\n" unless $QUIET;
|
||||
}
|
||||
|
||||
my $read = maniread(full_path_to($manifest_file));
|
||||
foreach $file (keys %$read)
|
||||
{
|
||||
next unless $file;
|
||||
|
||||
$subdir = ":";
|
||||
if (!$flat && ($file =~ /:.+:/ ))
|
||||
{
|
||||
$subdir = $&;
|
||||
}
|
||||
|
||||
$file = ":$file" unless $file =~ m/^:/;
|
||||
MakeAlias("$source_dir$file", "$dest_dir$subdir");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
C<InstallResources()>
|
||||
|
||||
=cut
|
||||
|
||||
# parameters are path to MANIFEST file, destination dir, true (to make copies) or false (to make aliases)
|
||||
sub InstallResources($;$;$)
|
||||
{
|
||||
my ($manifest_file, $dest_dir, $copy_files) = @_;
|
||||
|
||||
$dest_dir ||= ":";
|
||||
mkpath($dest_dir) if !-d $dest_dir;
|
||||
|
||||
$manifest_file =~ m/(.+):/;
|
||||
my $source_dir = $1;
|
||||
|
||||
chop($dest_dir) if $dest_dir =~ m/:$/;
|
||||
|
||||
WaitNextEvent();
|
||||
print "Installing resources from \"$manifest_file\"\n" unless $QUIET;
|
||||
|
||||
my $read = maniread(full_path_to($manifest_file));
|
||||
foreach $file (keys %$read)
|
||||
{
|
||||
next unless $file;
|
||||
|
||||
if ($copy_files)
|
||||
{
|
||||
copy("$source_dir:$file", "$dest_dir:$file");
|
||||
}
|
||||
else
|
||||
{
|
||||
MakeAlias("$source_dir:$file", "$dest_dir:$file");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// Delay
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub Delay($)
|
||||
{
|
||||
my ($delay_seconds) = @_;
|
||||
|
||||
$now = time;
|
||||
|
||||
$exit_time = $now + $delay_seconds;
|
||||
|
||||
while ($exit_time > $now) {
|
||||
$now = time;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// GetFileModDate
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub GetFileModDate($)
|
||||
{
|
||||
my($filePath)=@_;
|
||||
my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
|
||||
$atime,$mtime,$ctime,$blksize,$blocks) = stat($filePath);
|
||||
return $mtime;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// LaunchCodeWarrior
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub LaunchCodeWarrior($)
|
||||
{
|
||||
my($idepath_file) = @_; # full path to IDE location file
|
||||
my($cur_dir) = cwd();
|
||||
|
||||
# this both launches and writes the IDE path file
|
||||
Moz::CodeWarriorLib::activate($idepath_file);
|
||||
|
||||
chdir($cur_dir);
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// GetCodeWarriorRelativePath
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub GetCodeWarriorRelativePath($)
|
||||
{
|
||||
my($rel_path) = @_;
|
||||
return Moz::CodeWarriorLib::getCodeWarriorPath($rel_path);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// RedirectOutputToFile
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub RedirectOutputToFile($)
|
||||
{
|
||||
my($log_file) = @_;
|
||||
|
||||
# ensure that folders in the path exist
|
||||
my($logdir) = "";
|
||||
my($logfile) = $log_file;
|
||||
|
||||
if ($log_file =~ /(.+?:)([^:]+)$/) # ? for non-greedy match
|
||||
{
|
||||
$logdir = $1;
|
||||
$logfile = $2;
|
||||
|
||||
mkpath($logdir);
|
||||
}
|
||||
|
||||
print "Output is now being redirected to the file '$log_file'\n";
|
||||
|
||||
open(STDOUT, "> $log_file") || die "Can't redirect stdout";
|
||||
open(STDERR, ">&STDOUT") || die "Can't dup stdout";
|
||||
select(STDERR); $| = 1; # make unbuffered
|
||||
select(STDOUT); $| = 1; # make unbuffered
|
||||
|
||||
MacPerl::SetFileInfo("CWIE", "TEXT", $log_file);
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// ActivateApplication
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub ActivateApplication($)
|
||||
{
|
||||
my ($appSignature) = @_;
|
||||
my ($psi, $found);
|
||||
my ($appPSN);
|
||||
|
||||
$found = 0;
|
||||
|
||||
foreach $psi (values(%Process))
|
||||
{
|
||||
if ($psi->processSignature() eq $appSignature)
|
||||
{
|
||||
$appPSN = $psi->processNumber();
|
||||
$found = 1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
if ($found == 0 || SameProcess($appPSN, GetFrontProcess()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SetFrontProcess($appPSN);
|
||||
|
||||
while (GetFrontProcess() != $appPSN)
|
||||
{
|
||||
WaitNextEvent();
|
||||
}
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// IsProcessRunning
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub IsProcessRunning($)
|
||||
{
|
||||
my($processName, $psn, $psi) = @_;
|
||||
while ( ($psn, $psi) = each(%Process) ) {
|
||||
if ($psi->processName eq $processName) { return 1; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Scott Collins <scc@netscape.com>, Simon Fraser <sfraser@netscape.com>, Chris Yeh <cyeh@netscape.com>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
BuildMozillaDebug.pl (et al), BuildList.pm, CodeWarriorLib (an AppleScript library)
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
The contents of this file are subject to the Netscape Public
|
||||
License Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License. You may obtain a copy of
|
||||
the License at http://www.mozilla.org/NPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS
|
||||
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
rights and limitations under the License.
|
||||
|
||||
The Original Code is Mozilla Communicator client code, released
|
||||
March 31, 1998.
|
||||
|
||||
The Initial Developer of the Original Code is Netscape
|
||||
Communications Corporation. Portions created by Netscape are
|
||||
Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
=cut
|
||||
@@ -1,272 +0,0 @@
|
||||
|
||||
package Moz::Prefs;
|
||||
|
||||
require 5.004;
|
||||
require Exporter;
|
||||
|
||||
# Package that attempts to read a file from the Preferences folder,
|
||||
# and get build settings out of it
|
||||
|
||||
use strict;
|
||||
|
||||
use Exporter;
|
||||
use File::Path;
|
||||
|
||||
use Mac::Files;
|
||||
|
||||
use vars qw(@ISA @EXPORT);
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT = qw(ReadMozUserPrefs);
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# GetPrefsFolder
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub GetPrefsFolder()
|
||||
{
|
||||
my($prefs_folder) = FindFolder(kOnSystemDisk, kPreferencesFolderType, 1);
|
||||
return $prefs_folder.":Mozilla build prefs";
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# SetArrayValue
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
sub SetArrayValue($$$)
|
||||
{
|
||||
my($array_ref, $index1, $index2) = @_;
|
||||
|
||||
my($index);
|
||||
foreach $index (@$array_ref)
|
||||
{
|
||||
if ($index->[0] eq $index1)
|
||||
{
|
||||
$index->[1] = $index2;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# WriteDefaultPrefsFile
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub WriteDefaultPrefsFile($)
|
||||
{
|
||||
my($file_path) = @_;
|
||||
|
||||
my($file_contents);
|
||||
$file_contents = <<'EOS';
|
||||
% You can use this file to customize the Mozilla build system.
|
||||
% The following kinds of lines are allowable:
|
||||
% Comment lines, which start with a '%' in the first column
|
||||
% Lines which modify the default build settings. For the list of flags,
|
||||
% see MozBuildFlags.pm. Examples are:
|
||||
%
|
||||
% build pull 0 % don't pull
|
||||
% options mng 1 % turn mng on
|
||||
%
|
||||
% Line containing the special 'buildfrom' flag, which specifies
|
||||
% where to start the build. Example:
|
||||
%
|
||||
% buildfrom nglayout % where to start the build
|
||||
%
|
||||
% Lines which specify the location of the files used to store paths
|
||||
% to the CodeWarrior IDE, and the MacCVS Pro session file. Note quoting
|
||||
% of paths containing whitespace. Examples:
|
||||
%
|
||||
% filepath idepath ::codewarrior.txt
|
||||
% filepath sessionpath ":Some folder:MacCVS session path.txt"
|
||||
%
|
||||
% Lines which modify the build settings like %main::DEBUG.
|
||||
% Any lines which do not match either of the above are assumed
|
||||
% to set variables on $main::. Examples:
|
||||
%
|
||||
% MOZILLA_OFFICIAL 1
|
||||
%
|
||||
EOS
|
||||
|
||||
$file_contents =~ s/%/#/g;
|
||||
|
||||
local(*PREFS_FILE);
|
||||
|
||||
open(PREFS_FILE, "> $file_path") || die "Could not write default prefs file\n";
|
||||
print PREFS_FILE ($file_contents);
|
||||
close(PREFS_FILE);
|
||||
|
||||
MacPerl::SetFileInfo("McPL", "TEXT", $file_path);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# HandlePrefSet
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
sub HandlePrefSet($$$$)
|
||||
{
|
||||
my($flags, $name, $value, $desc) = @_;
|
||||
|
||||
if (SetArrayValue($flags, $name, $value)) {
|
||||
print "Prefs set $desc flag '$name' to '$value'\n";
|
||||
} else {
|
||||
die "$desc setting '$name' is not a valid option\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# HandleBuildFromPref
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
sub HandleBuildFromPref($$)
|
||||
{
|
||||
my($build_array, $name) = @_;
|
||||
|
||||
my($setting) = 0;
|
||||
my($index);
|
||||
foreach $index (@$build_array)
|
||||
{
|
||||
if ($index->[0] eq $name) {
|
||||
$setting = 1;
|
||||
}
|
||||
|
||||
$index->[1] = $setting;
|
||||
}
|
||||
|
||||
if ($setting == 1) {
|
||||
print "Building from $name onwards, as specified by prefs\n";
|
||||
} else {
|
||||
printf "Failed to find buildfrom setting '$name'\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# ReadPrefsFile
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub ReadPrefsFile($$$$$)
|
||||
{
|
||||
my($file_path, $build_flags, $options_flags, $filepath_flags, $create_if_missing) = @_;
|
||||
|
||||
local(*PREFS_FILE);
|
||||
|
||||
if (open(PREFS_FILE, "< $file_path"))
|
||||
{
|
||||
print "Reading build prefs from '$file_path'\n";
|
||||
|
||||
while (<PREFS_FILE>)
|
||||
{
|
||||
my($line) = $_;
|
||||
chomp($line);
|
||||
|
||||
if ($line =~ /^\#/ || $line =~ /^\s*$/) { # ignore comments and empty lines
|
||||
next;
|
||||
}
|
||||
|
||||
if (($line =~ /^\s*([^#\s]+)\s+([^#\s]+)\s+\"(.+)\"(\s+#.+)?/) ||
|
||||
($line =~ /^\s*([^#\s]+)\s+([^#\s]+)\s+\'(.+)\'(\s+#.+)?/) ||
|
||||
($line =~ /^\s*([^#\s]+)\s+([^#\s]+)\s+([^#\s]+)(\s+#.+)?/))
|
||||
{
|
||||
my($array_name) = $1;
|
||||
my($option_name) = $2;
|
||||
my($option_value) = $3;
|
||||
|
||||
# print "Read '$array_name' '$option_name' '$option_value'\n";
|
||||
|
||||
if ($array_name eq "build")
|
||||
{
|
||||
HandlePrefSet($build_flags, $option_name, $option_value, "Build");
|
||||
}
|
||||
elsif ($array_name eq "options")
|
||||
{
|
||||
HandlePrefSet($options_flags, $option_name, $option_value, "Options");
|
||||
}
|
||||
elsif ($array_name eq "filepath" && $option_name && $option_value)
|
||||
{
|
||||
HandlePrefSet($filepath_flags, $option_name, $option_value, "Filepath");
|
||||
}
|
||||
else
|
||||
{
|
||||
print "Unknown pref option at $line\n";
|
||||
}
|
||||
}
|
||||
elsif ($line =~ /^\s*buildfrom\s+([^#\s]+)(\s+#.+)?/)
|
||||
{
|
||||
my($build_start) = $1;
|
||||
HandleBuildFromPref($build_flags, $build_start);
|
||||
}
|
||||
elsif ($line =~ /^\s*([^#\s]+)\s+([^#\s]+)(\s+#.+)?/)
|
||||
{
|
||||
my($build_var) = $1;
|
||||
my($var_setting) = $2;
|
||||
|
||||
print "Setting \$main::$build_var to $var_setting\n";
|
||||
eval "\$main::$build_var = \"$var_setting\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
print "Unrecognized input line at $line\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
close(PREFS_FILE);
|
||||
}
|
||||
elsif ($create_if_missing)
|
||||
{
|
||||
print "No prefs file found at $file_path; using defaults\n";
|
||||
|
||||
my($folder_path) = $file_path;
|
||||
$folder_path =~ s/[^:]+$//;
|
||||
mkpath($folder_path);
|
||||
WriteDefaultPrefsFile($file_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# ReadMozUserPrefs
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub ReadMozUserPrefs($$$$)
|
||||
{
|
||||
my($prefs_file_name, $build_flags, $options_flags, $filepath_flags) = @_;
|
||||
|
||||
if ($prefs_file_name eq "") { return; }
|
||||
|
||||
# if local prefs exist, just use those. Othewise, look in the prefs folder
|
||||
if (-e $prefs_file_name)
|
||||
{
|
||||
# read local prefs
|
||||
ReadPrefsFile($prefs_file_name, $build_flags, $options_flags, $filepath_flags, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
# first read prefs folder prefs
|
||||
my($prefs_path) = GetPrefsFolder();
|
||||
$prefs_path .= ":$prefs_file_name";
|
||||
|
||||
ReadPrefsFile($prefs_path, $build_flags, $options_flags, $filepath_flags, 1);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -1,932 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Simon Fraser <sfraser@netscape.com>
|
||||
#
|
||||
|
||||
package Moz::ProjectXML;
|
||||
|
||||
require 5.004;
|
||||
require Exporter;
|
||||
|
||||
use strict;
|
||||
use Exporter;
|
||||
|
||||
use Cwd;
|
||||
use XML::DOM;
|
||||
|
||||
use vars qw(@ISA @EXPORT);
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT = qw(
|
||||
ParseXMLDocument
|
||||
DisposeXMLDocument
|
||||
WriteXMLDocument
|
||||
CleanupPro5XML
|
||||
GetTargetsList
|
||||
CloneTarget
|
||||
SetAsSharedLibraryTarget
|
||||
SetAsStaticLibraryTarget
|
||||
AddTarget
|
||||
RemoveTarget
|
||||
GetTargetSetting
|
||||
SetTargetSetting
|
||||
getChildElementTextContents
|
||||
);
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
# A module for reading, manipulating, and writing XML-format CodeWarrior project files.
|
||||
#
|
||||
# Sample usage:
|
||||
#
|
||||
# use ProjectXML;
|
||||
#
|
||||
# my $doc = ProjectXML::ParseXMLDocument("Test.mcp.xml");
|
||||
# ProjectXML::CloneTarget($doc, "Test.shlb", "Test.lib");
|
||||
# ProjectXML::SetAsStaticLibraryTarget($doc, "Test.lib", "TestOutput.lib");
|
||||
# ProjectXML::WriteXMLDocument($doc, "Test_out.xml");
|
||||
# ProjectXML::DisposeXMLDocument($doc);
|
||||
#
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// ParseXMLDocument
|
||||
#// Note that the caller must call DisposeXMLDocument on the returned doc
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub ParseXMLDocument($)
|
||||
{
|
||||
my($doc_path) = @_;
|
||||
|
||||
my $parser = new XML::DOM::Parser(ErrorContext => 2);
|
||||
my $doc = $parser->parsefile($doc_path);
|
||||
|
||||
return $doc;
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// DisposeXMLDocument
|
||||
#// Needed to avoid memory leaks - cleanup circular references for garbage collection
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub DisposeXMLDocument($)
|
||||
{
|
||||
my($doc) = @_;
|
||||
|
||||
$doc->dispose();
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// WriteXMLDocument
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub _pro5_tag_compression($$)
|
||||
{
|
||||
return 1; # Pro 5 is broken and can't import XML with <foo/> style tags
|
||||
}
|
||||
|
||||
sub _pro6plus_tag_compression($$)
|
||||
{
|
||||
return 0; # Pro 6 can deal with empty XML tags like <foo/>
|
||||
}
|
||||
|
||||
sub WriteXMLDocument($$$)
|
||||
{
|
||||
my($doc, $file_path, $ide_version) = @_;
|
||||
|
||||
if ($ide_version eq "4.0")
|
||||
{
|
||||
XML::DOM::setTagCompression(\&_pro5_tag_compression);
|
||||
}
|
||||
else
|
||||
{
|
||||
XML::DOM::setTagCompression(\&_pro6plus_tag_compression);
|
||||
}
|
||||
|
||||
$doc->printToFile($file_path);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// CleanupPro5XML
|
||||
#// XML Projects exported by Pro 5 contain garbage data under the MWMerge_MacOS_skipResources
|
||||
#// setting. This routine cleans this up, saving the result to a new file
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub CleanupPro5XML($$)
|
||||
{
|
||||
my($xml_path, $out_path) = @_;
|
||||
|
||||
local(*XML_FILE);
|
||||
open(XML_FILE, "< $xml_path") || die "Error: failed to open file $xml_path\n";
|
||||
|
||||
local(*CLEANED_FILE);
|
||||
open(CLEANED_FILE, "> $out_path") || die "Error: failed to open file $out_path for writing\n";
|
||||
|
||||
my $in_skip_resources_settings = 0;
|
||||
|
||||
while(<XML_FILE>)
|
||||
{
|
||||
my($line) = $_;
|
||||
|
||||
if ($line =~ /^<\?codewarrior/) # is processing inst line
|
||||
{
|
||||
my $test_line = $line;
|
||||
chomp($test_line);
|
||||
|
||||
my $out_line = $test_line;
|
||||
if ($test_line =~ /^<\?codewarrior\s+exportversion=\"(.+)\"\s+ideversion=\"(.+)\"\s*\?>$/)
|
||||
{
|
||||
my $export_version = $1;
|
||||
my $ide_version = $2;
|
||||
|
||||
$ide_version = "4.0_mozilla"; # pseudo IDE version so we know we touched it
|
||||
$out_line = "<?codewarrior exportversion=\"".$export_version."\" ideversion=\"".$ide_version."\"?>";
|
||||
}
|
||||
|
||||
print CLEANED_FILE "$out_line\n";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($line =~ /MWMerge_MacOS_skipResources/)
|
||||
{
|
||||
$in_skip_resources_settings = 1;
|
||||
print CLEANED_FILE "$line";
|
||||
}
|
||||
elsif($in_skip_resources_settings && $line =~ /<!-- Settings for/)
|
||||
{
|
||||
# leaving bad settings lines. Write closing tag
|
||||
print CLEANED_FILE " <!-- Corrupted setting entries removed by script -->\n";
|
||||
print CLEANED_FILE " </SETTING>\n\n";
|
||||
|
||||
print CLEANED_FILE "$line";
|
||||
|
||||
$in_skip_resources_settings = 0;
|
||||
}
|
||||
elsif (!$in_skip_resources_settings)
|
||||
{
|
||||
print CLEANED_FILE "$line";
|
||||
}
|
||||
}
|
||||
|
||||
close(XML_FILE);
|
||||
close(CLEANED_FILE);
|
||||
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
# SniffProjectXMLIDEVersion
|
||||
#
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
sub SniffProjectXMLIDEVersion($)
|
||||
{
|
||||
my($xml_path) = @_;
|
||||
|
||||
my $found_version = "";
|
||||
|
||||
local(*XML_FILE);
|
||||
open(XML_FILE, "< $xml_path") || die "Error: failed to open file $xml_path\n";
|
||||
|
||||
while(<XML_FILE>)
|
||||
{
|
||||
my($line) = $_;
|
||||
chomp($line);
|
||||
|
||||
if ($line =~ /^<\?codewarrior/) # is processing inst line
|
||||
{
|
||||
unless ($line =~ /^<\?codewarrior\s+exportversion=\"(.+)\"\s+ideversion=\"(.+)\"\s*\?>$/)
|
||||
{
|
||||
die "Error: Failed to find ideversion in $xml_path in line $line\n";
|
||||
}
|
||||
|
||||
my $export_version = $1;
|
||||
my $ide_version = $2;
|
||||
|
||||
$found_version = $ide_version;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
close(XML_FILE);
|
||||
|
||||
return $found_version;
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// GetTargetsList
|
||||
#// Returns an array of target names
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub GetTargetsList($)
|
||||
{
|
||||
my($doc) = @_;
|
||||
|
||||
my $nodes = $doc->getElementsByTagName("TARGET");
|
||||
my $n = $nodes->getLength;
|
||||
|
||||
my @target_names;
|
||||
|
||||
for (my $i = 0; $i < $n; $i++)
|
||||
{
|
||||
my ($node) = $nodes->item($i);
|
||||
|
||||
my($target_name) = getChildElementTextContents($node, "NAME");
|
||||
push(@target_names, $target_name);
|
||||
}
|
||||
|
||||
return @target_names;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// CloneTarget
|
||||
#// Clone the named target, renaming it to 'new_name'
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub CloneTarget($$$)
|
||||
{
|
||||
my($doc, $target_name, $new_name) = @_;
|
||||
|
||||
my $target_node = getTargetNode($doc, $target_name);
|
||||
|
||||
# clone here
|
||||
my $target_clone = $target_node->cloneNode(1); # deep clone
|
||||
|
||||
# -- munge target settings --
|
||||
|
||||
# set the target name field
|
||||
setChildElementTextContents($doc, $target_clone, "NAME", $new_name);
|
||||
|
||||
# set the targetname pref
|
||||
setTargetNodeSetting($doc, $target_clone, "Targetname", $new_name);
|
||||
|
||||
# -- insert new target subtree --
|
||||
|
||||
my $target_list = $target_node->getParentNode();
|
||||
$target_list->appendChild($target_clone);
|
||||
|
||||
# -- now add to targetorder --
|
||||
my (@target_order_nodes) = getChildOfDocument($doc, "TARGETORDER");
|
||||
|
||||
my $target_order = @target_order_nodes[0];
|
||||
|
||||
my $new_order = $doc->createElement("ORDEREDTARGET");
|
||||
my $order_name = $doc->createElement("NAME");
|
||||
|
||||
$new_order->appendChild($order_name);
|
||||
|
||||
setChildElementTextContents($doc, $new_order, "NAME", $new_name);
|
||||
$target_order->appendChild($new_order);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// SetAsSharedLibraryTarget
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub SetAsSharedLibraryTarget($$$)
|
||||
{
|
||||
my($doc, $target_name, $output_name) = @_;
|
||||
|
||||
my $target_node = getTargetNode($doc, $target_name);
|
||||
|
||||
setTargetNodeSetting($doc, $target_node, "MWProject_PPC_type", "SharedLibrary");
|
||||
setTargetNodeSetting($doc, $target_node, "MWProject_PPC_filetype", "1936223330"); #'shlb'
|
||||
setTargetNodeSetting($doc, $target_node, "MWProject_PPC_outfile", $output_name);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// AddFileToTarget
|
||||
#//
|
||||
#// Add a file to the specified target(s).
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub AddFileToTarget($$$)
|
||||
{
|
||||
my($doc, $target_list, $file_name) = @_;
|
||||
|
||||
# the file must be added in 3 places:
|
||||
# 1. in <TARGET><FILELIST><FILE> (with linkage flags if necessary)
|
||||
# 2. in <TARGET><LINKORDER><FILEREF>
|
||||
# 3. in <GROUPLIST><GROUP><FILEREF>
|
||||
die "Write me\n";
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// RemoveFileFromTarget
|
||||
#//
|
||||
#// Remove a file from the specified target, removing it from the entire project
|
||||
#// if no other targets reference it.
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub RemoveFileFromTarget($$$)
|
||||
{
|
||||
my($doc, $target_node, $file_name) = @_;
|
||||
|
||||
# the file must be removed in 3 places:
|
||||
# 1. in <TARGET><FILELIST><FILE>
|
||||
# 2. in <TARGET><LINKORDER><FILEREF>
|
||||
# 3. in <GROUPLIST><GROUP><FILEREF>
|
||||
|
||||
# first, remove from <FILELIST>
|
||||
my $filelist_node = getFirstChildElement($target_node, "FILELIST");
|
||||
unless ($filelist_node) { die "Error: failed to find FILELIST node\n"; }
|
||||
|
||||
my $file_node = getChildNodeByGrandchildContents($doc, $filelist_node, "FILE", "PATH", $file_name);
|
||||
unless ($file_node) { return; }
|
||||
|
||||
$filelist_node->removeChild($file_node);
|
||||
|
||||
# next, remove from <LINKORDER>
|
||||
my $linkorder_node = getFirstChildElement($target_node, "LINKORDER");
|
||||
unless ($linkorder_node) { die "Error: failed to find LINKORDER node\n"; }
|
||||
|
||||
my $fileref_node = getChildNodeByGrandchildContents($doc, $linkorder_node, "FILEREF", "PATH", $file_name);
|
||||
unless ($fileref_node) { die "Error: link order node for file $file_name not found\n"; }
|
||||
|
||||
$linkorder_node->removeChild($fileref_node);
|
||||
|
||||
# last, remove from <GROUPLIST>
|
||||
# <GROUPLIST> is cross-target, so we have to be careful here.
|
||||
my $grouplist_node = getChildOfDocument($doc, "GROUPLIST");
|
||||
unless ($grouplist_node) { die "Error: failed to find GROUPLIST node\n"; }
|
||||
|
||||
# if the file isn't in any other targets, remove it from the groups
|
||||
if (!GetFileInUse($doc, $file_name))
|
||||
{
|
||||
print "File $file_name is in no other targest. Removing from project\n";
|
||||
|
||||
my @group_nodes;
|
||||
getChildElementsOfType($doc, $grouplist_node, "GROUP", \@group_nodes);
|
||||
my $group_node;
|
||||
foreach $group_node (@group_nodes)
|
||||
{
|
||||
my @fileref_nodes;
|
||||
getChildElementsOfType($doc, $group_node, "FILEREF", \@fileref_nodes);
|
||||
|
||||
my $fileref_node;
|
||||
foreach $fileref_node (@fileref_nodes)
|
||||
{
|
||||
my $path_name = getChildElementTextContents($fileref_node, "PATH");
|
||||
if ($path_name eq $file_name)
|
||||
{
|
||||
print "Removing $file_name from project group list\n";
|
||||
$group_node->removeChild($fileref_node);
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# can a file appear in more than one group?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// SetAsStaticLibraryTarget
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub SetAsStaticLibraryTarget($$$)
|
||||
{
|
||||
my($doc, $target_name, $output_name) = @_;
|
||||
|
||||
my $target_node = getTargetNode($doc, $target_name);
|
||||
|
||||
setTargetNodeSetting($doc, $target_node, "MWProject_PPC_type", "Library");
|
||||
setTargetNodeSetting($doc, $target_node, "MWProject_PPC_filetype", "1061109567"); #'????'
|
||||
setTargetNodeSetting($doc, $target_node, "MWProject_PPC_outfile", $output_name);
|
||||
|
||||
# static targets don't need any library linkage, so we can remove linkage
|
||||
# with all .shlb and .Lib files.
|
||||
|
||||
my(@obsolete_files) = ("NSStdLibStubs", "InterfacesStubs", "InterfaceLib", "InternetConfigLib");
|
||||
|
||||
print " Removing libraries etc. from target\n";
|
||||
|
||||
# get all files in target
|
||||
my @target_files = GetTargetFilesList($doc, $target_name);
|
||||
my $target_file;
|
||||
foreach $target_file (@target_files)
|
||||
{
|
||||
if ($target_file =~ /(\.shlb|\.lib|\.Lib|\.o|\.exp)$/)
|
||||
{
|
||||
RemoveFileFromTarget($doc, $target_node, $target_file);
|
||||
}
|
||||
}
|
||||
|
||||
print " Removing stub libraries from target\n";
|
||||
|
||||
# then remove files with known names
|
||||
my $obs_file;
|
||||
foreach $obs_file (@obsolete_files)
|
||||
{
|
||||
RemoveFileFromTarget($doc, $target_node, $obs_file);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// AddTarget
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub AddTarget($$)
|
||||
{
|
||||
my($doc, $target_name) = @_;
|
||||
|
||||
die "Write me\n";
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// RemoveTarget
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub RemoveTarget($$)
|
||||
{
|
||||
my($doc, $target_name) = @_;
|
||||
|
||||
die "Write me\n";
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// GetTargetSetting
|
||||
#// Get the value for the specified setting in the specified target
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub GetTargetSetting($$$)
|
||||
{
|
||||
my($doc, $target_name, $setting_name) = @_;
|
||||
|
||||
my $target_node = getTargetNode($doc, $target_name);
|
||||
return getTargetNodeSetting($target_node, "VALUE");
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// SetTargetSetting
|
||||
#// Set the value for the specified setting in the specified target
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub SetTargetSetting($$$$)
|
||||
{
|
||||
my($doc, $target_name, $setting_name, $new_value) = @_;
|
||||
|
||||
my $target_node = getTargetNode($doc, $target_name);
|
||||
setTargetNodeSetting($doc, $target_node, "VALUE", $new_value);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// GetTargetFilesList
|
||||
#// Return an array of the files in the target (in filelist order)
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub GetTargetFilesList($$)
|
||||
{
|
||||
my($doc, $target_name) = @_;
|
||||
|
||||
my $target_node = getTargetNode($doc, $target_name);
|
||||
|
||||
my @files_list;
|
||||
|
||||
my $filelist_node = getFirstChildElement($target_node, "FILELIST");
|
||||
unless ($filelist_node) { die "Error: failed to find FILELIST node\n"; }
|
||||
|
||||
my @file_nodes;
|
||||
getChildElementsOfType($doc, $filelist_node, "FILE", \@file_nodes);
|
||||
|
||||
my $node;
|
||||
foreach $node (@file_nodes)
|
||||
{
|
||||
my $file_name = getChildElementTextContents($node, "PATH");
|
||||
push(@files_list, $file_name);
|
||||
}
|
||||
|
||||
return @files_list;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// FileIsInTarget
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub FileIsInTarget($$$)
|
||||
{
|
||||
my($doc, $file_name, $target_name) = @_;
|
||||
|
||||
my $target_node = getTargetNode($doc, $target_name);
|
||||
unless ($target_node) { die "Error: no target found called $target_name\n"; }
|
||||
|
||||
my $file_node = GetTargetFileNode($doc, $target_node, $file_name);
|
||||
if ($file_node) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// GetFileTargetsList
|
||||
#// Return an array of the targets that a file is in (expensive)
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub GetFileTargetsList($$)
|
||||
{
|
||||
my ($doc, $file_name) = @_;
|
||||
|
||||
my @target_list;
|
||||
|
||||
my @targets = GetTargetsList($doc);
|
||||
my $target;
|
||||
|
||||
foreach $target (@targets)
|
||||
{
|
||||
if (FileIsInTarget($doc, $file_name, $target))
|
||||
{
|
||||
push(@target_list, $target);
|
||||
}
|
||||
}
|
||||
|
||||
return @target_list;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// GetTargetFileNode
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub GetTargetFileNode($$$)
|
||||
{
|
||||
my($doc, $target_node, $file_name) = @_;
|
||||
|
||||
my $filelist_node = getFirstChildElement($target_node, "FILELIST");
|
||||
unless ($filelist_node) { die "Error: failed to find FILELIST node\n"; }
|
||||
|
||||
my $file_node = getChildNodeByGrandchildContents($doc, $filelist_node, "FILE", "PATH", $file_name);
|
||||
|
||||
return $file_node;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// GetFileInUse
|
||||
#// Return true if the file is used by any target
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub GetFileInUse($$)
|
||||
{
|
||||
my($doc, $file_name) = @_;
|
||||
|
||||
my $targetlist_node = getChildOfDocument($doc, "TARGETLIST");
|
||||
|
||||
my $target_node = $targetlist_node->getFirstChild();
|
||||
|
||||
while ($target_node)
|
||||
{
|
||||
if ($target_node->getNodeTypeName eq "ELEMENT_NODE" &&
|
||||
$target_node->getTagName() eq "TARGET")
|
||||
{
|
||||
# if this is a target node
|
||||
my $file_node = GetTargetFileNode($doc, $target_node, $file_name);
|
||||
if ($file_node) {
|
||||
return 1; # found it
|
||||
}
|
||||
}
|
||||
|
||||
$target_node = $target_node->getNextSibling();
|
||||
}
|
||||
|
||||
# not found
|
||||
return 0;
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getChildOfDocument
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub getChildOfDocument($$)
|
||||
{
|
||||
my($doc, $child_type) = @_;
|
||||
|
||||
return getFirstChildElement($doc->getDocumentElement(), $child_type);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getFirstChildElement
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub getFirstChildElement($$)
|
||||
{
|
||||
my($node, $element_name) = @_;
|
||||
|
||||
my $found_node;
|
||||
|
||||
unless ($node) { die "getFirstChildElement called with empty node\n"; }
|
||||
|
||||
#look for the first "element_name" child
|
||||
|
||||
my $child_node = $node->getFirstChild();
|
||||
|
||||
while ($child_node)
|
||||
{
|
||||
if ($child_node->getNodeTypeName eq "ELEMENT_NODE" &&
|
||||
$child_node->getTagName() eq $element_name)
|
||||
{
|
||||
$found_node = $child_node;
|
||||
last;
|
||||
}
|
||||
|
||||
$child_node = $child_node->getNextSibling();
|
||||
}
|
||||
|
||||
return $found_node;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getChildElementsOfType
|
||||
#//
|
||||
#// Return an array of refs to child nodes of the given type
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub getChildElementsOfType($$$$)
|
||||
{
|
||||
my($doc, $node, $child_type, $array_ref) = @_;
|
||||
|
||||
my $child_node = $node->getFirstChild();
|
||||
|
||||
while ($child_node)
|
||||
{
|
||||
if ($child_node->getNodeTypeName eq "ELEMENT_NODE" &&
|
||||
$child_node->getTagName() eq $child_type)
|
||||
{
|
||||
push(@$array_ref, $child_node);
|
||||
}
|
||||
|
||||
$child_node = $child_node->getNextSibling();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getChildElementTextContents
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#
|
||||
# Given <FOOPY><NERD>Hi!</NERD></FOOPY>, where $node is <FOOPY>,
|
||||
# returns "Hi!". If > 1 <NERD> node, returns the contents of the first.
|
||||
#
|
||||
sub getChildElementTextContents($$)
|
||||
{
|
||||
my($node, $tag_name) = @_;
|
||||
|
||||
my $first_element = getFirstChildElement($node, $tag_name);
|
||||
my $text_node = $first_element->getFirstChild();
|
||||
|
||||
my $text_contents = "";
|
||||
|
||||
# concat adjacent text nodes
|
||||
while ($text_node)
|
||||
{
|
||||
if ($text_node->getNodeTypeName() ne "TEXT_NODE")
|
||||
{
|
||||
last;
|
||||
}
|
||||
|
||||
$text_contents = $text_contents.$text_node->getData();
|
||||
$text_node = $text_node->getNextSibling();
|
||||
}
|
||||
|
||||
return $text_contents;
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// setChildElementTextContents
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub setChildElementTextContents($$$$)
|
||||
{
|
||||
my($doc, $node, $tag_name, $contents_text) = @_;
|
||||
|
||||
my $first_element = getFirstChildElement($node, $tag_name);
|
||||
my $new_text_node = $doc->createTextNode($contents_text);
|
||||
|
||||
# replace all child elements with a text element
|
||||
removeAllChildren($first_element);
|
||||
|
||||
$first_element->appendChild($new_text_node);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getChildNodeByContents
|
||||
#//
|
||||
#// Consider <foo><bar><baz>Foopy</baz></bar><bar><baz>Loopy</baz></bar></foo>
|
||||
#// This function, when called with getChildNodeByContents($foonode, "bar", "baz", "Loopy")
|
||||
#// returns the second <bar> node.
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub getChildNodeByGrandchildContents($$$$$)
|
||||
{
|
||||
my($doc, $node, $child_type, $gc_type, $gc_contents) = @_; # gc = grandchild
|
||||
|
||||
my $found_node;
|
||||
my $child_node = $node->getFirstChild();
|
||||
while ($child_node)
|
||||
{
|
||||
if ($child_node->getNodeTypeName eq "ELEMENT_NODE" &&
|
||||
$child_node->getTagName() eq $child_type)
|
||||
{
|
||||
# check for a child of this node of type
|
||||
my $child_contents = getChildElementTextContents($child_node, $gc_type);
|
||||
|
||||
if ($child_contents eq $gc_contents)
|
||||
{
|
||||
$found_node = $child_node;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
$child_node = $child_node->getNextSibling();
|
||||
}
|
||||
|
||||
return $found_node;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getTargetNode
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub getTargetNode($$)
|
||||
{
|
||||
my($doc, $target_name) = @_;
|
||||
|
||||
my $targetlist_node = getChildOfDocument($doc, "TARGETLIST");
|
||||
return getChildNodeByGrandchildContents($doc, $targetlist_node, "TARGET", "NAME", $target_name);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getTargetNamedSettingNode
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub getTargetNamedSettingNode($$)
|
||||
{
|
||||
my($target_node, $setting_name) = @_;
|
||||
|
||||
my $setting_node;
|
||||
|
||||
my $settinglist_node = getFirstChildElement($target_node, "SETTINGLIST");
|
||||
my $child_node = $settinglist_node->getFirstChild();
|
||||
|
||||
while ($child_node)
|
||||
{
|
||||
if ($child_node->getNodeTypeName ne "ELEMENT_NODE")
|
||||
{
|
||||
$child_node = $child_node->getNextSibling();
|
||||
next;
|
||||
}
|
||||
|
||||
if ($child_node->getTagName() eq "SETTING")
|
||||
{
|
||||
my $set_name = getChildElementTextContents($child_node, "NAME");
|
||||
|
||||
if ($set_name eq $setting_name)
|
||||
{
|
||||
$setting_node = $child_node;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
$child_node = $child_node->getNextSibling();
|
||||
}
|
||||
|
||||
return $setting_node;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getTargetNodeSetting
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub getTargetNodeSetting($$)
|
||||
{
|
||||
my($target_node, $setting_name) = @_;
|
||||
|
||||
my $setting_node = getTargetNamedSettingNode($target_node, $setting_name);
|
||||
return getChildElementTextContents($setting_node, "VALUE");
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// setTargetNodeSetting
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub setTargetNodeSetting($$$$)
|
||||
{
|
||||
my($doc, $target_node, $setting_name, $new_value) = @_;
|
||||
|
||||
my $setting_node = getTargetNamedSettingNode($target_node, $setting_name);
|
||||
|
||||
setChildElementTextContents($doc, $setting_node, "VALUE", $new_value);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// elementInArray
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub elementInArray($$)
|
||||
{
|
||||
my($element, $array) = @_;
|
||||
my $test;
|
||||
foreach $test (@$array)
|
||||
{
|
||||
if ($test eq $element) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// removeAllChildren
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub removeAllChildren($)
|
||||
{
|
||||
my($node) = @_;
|
||||
|
||||
my $child_node = $node->getFirstChild();
|
||||
|
||||
while ($child_node)
|
||||
{
|
||||
$node->removeChild($child_node);
|
||||
$child_node = $node->getFirstChild();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// dumpNodeData
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub dumpNodeData($)
|
||||
{
|
||||
my($node) = @_;
|
||||
|
||||
unless ($node) { die "Null node passed to dumpNodeData\n"; }
|
||||
|
||||
print "Dumping node $node\n";
|
||||
|
||||
my($node_type) = $node->getNodeTypeName();
|
||||
|
||||
if ($node_type eq "ELEMENT_NODE")
|
||||
{
|
||||
my($node_name) = $node->getTagName();
|
||||
print "Element $node_name\n";
|
||||
}
|
||||
elsif ($node_type eq "TEXT_NODE")
|
||||
{
|
||||
my($node_data) = $node->getData;
|
||||
# my(@node_vals) = unpack("C*", $node_data);
|
||||
print "Text '$node_data'\n"; # may contain LF chars
|
||||
}
|
||||
else
|
||||
{
|
||||
print "Node $node_type\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// dumpNodeTree
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub dumpNodeTree($)
|
||||
{
|
||||
my($node) = @_;
|
||||
|
||||
my($child_node) = $node->getFirstChild();
|
||||
|
||||
unless ($child_node) { return; }
|
||||
|
||||
# recurse
|
||||
dumpNodeData($child_node);
|
||||
|
||||
# then go through child nodes
|
||||
while ($child_node)
|
||||
{
|
||||
dumpNodeTree($child_node);
|
||||
|
||||
$child_node = $child_node->getNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
1;
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
# These 3 lists are the 'master lists' to control what gets built.
|
||||
#
|
||||
# Ordering in these arrays is important; it has to reflect the order in
|
||||
# which the build occurs.
|
||||
#
|
||||
# Setting containing spaces must be quoted with double quotes.
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
build_flags
|
||||
all 1
|
||||
pull 0
|
||||
dist 0
|
||||
config 0
|
||||
xpidl 0
|
||||
idl 0
|
||||
stubs 0
|
||||
runtime 0
|
||||
common 0
|
||||
imglib 0
|
||||
libimg2 0
|
||||
necko 0
|
||||
security 0
|
||||
browserutils 0
|
||||
intl 0
|
||||
nglayout 0
|
||||
accessiblity 0
|
||||
editor 0
|
||||
embedding 0
|
||||
viewer 0
|
||||
xpapp 0
|
||||
extensions 0
|
||||
plugins 0
|
||||
mailnews 0
|
||||
apprunner 0
|
||||
resources 0
|
||||
|
||||
options_flags
|
||||
pull_by_date 0
|
||||
chrome_jars 1
|
||||
chrome_files 0
|
||||
use_jars 1
|
||||
transformiix 1
|
||||
mathml 0 MOZ_MATHML
|
||||
svg 0 MOZ_SVG
|
||||
# svg requires libart, which is an lgpl library. You need to pull it
|
||||
# explicitly.
|
||||
libart_lgpl 0
|
||||
mng 1
|
||||
ldap 1 MOZ_LDAP_XPCOM
|
||||
ldap_experimental 0 MOZ_LDAP_XPCOM_EXPERIMENTAL
|
||||
xmlextras 1
|
||||
wsp 0 MOZ_WSP
|
||||
inspector 1
|
||||
mailextras 1
|
||||
xptlink 0
|
||||
psm 0 MOZ_PSM
|
||||
embedding_test 1
|
||||
embedding_chrome 0
|
||||
embedding_xulprefs 0
|
||||
embedding_xulsecurity 0
|
||||
carbon 0 TARGET_CARBON
|
||||
useimg2 1 USE_IMG2
|
||||
lowmem 0 MOZ_MAC_LOWMEM
|
||||
accessible 1 ACCESSIBILITY
|
||||
bidi 1 IBMBIDI
|
||||
p3p 0
|
||||
jsd 1
|
||||
venkman 1
|
||||
moz_logging 1 MOZ_LOGGING
|
||||
chatzilla 1
|
||||
content_packs 1
|
||||
xml_rpc 1
|
||||
cview 1
|
||||
help 1
|
||||
timeline 0 MOZ_TIMELINE
|
||||
static_build 0 MOZ_STATIC_COMPONENT_LIBS
|
||||
string_debug 0 DEBUG_STRING
|
||||
string_stats 0 DEBUG_STRING_STATS
|
||||
xpctools 0 XPC_TOOLS_SUPPORT
|
||||
smime 1
|
||||
mdn 1
|
||||
print_preview 1 NS_PRINT_PREVIEW
|
||||
moz_xul 1 MOZ_XUL
|
||||
|
||||
filepath_flags
|
||||
idepath ":CodeWarrior IDE Path.txt"
|
||||
sessionpath ":Mozilla session path.txt"
|
||||
buildlogfilepath ":Build Logs:Mozilla build log.txt" # this is a path
|
||||
scriptlogfilepath ":Build Logs:Mozilla script log.txt"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,22 +0,0 @@
|
||||
# List of modules to check out. Format is
|
||||
# module, (tag), (date)
|
||||
# where tag and date are optional (non-trailing commas are required)
|
||||
#
|
||||
# Examples:
|
||||
# mozilla/nsprpub, NSPRPUB_CLIENT_TAG
|
||||
# mozilla/gc, , 10/25/2000 12:00:00
|
||||
#
|
||||
|
||||
mozilla/nsprpub, NETSCAPE_7_0_RTM
|
||||
mozilla/security/nss, NETSCAPE_7_0_RTM
|
||||
mozilla/security/manager, NETSCAPE_7_0_RTM
|
||||
mozilla/accessible, NETSCAPE_7_0_RTM
|
||||
mozilla/directory/c-sdk, NETSCAPE_7_0_RTM
|
||||
mozilla/lib/mac/Instrumentation, NETSCAPE_7_0_RTM
|
||||
mozilla/gfx2, NETSCAPE_7_0_RTM
|
||||
mozilla/modules/libpr0n, NETSCAPE_7_0_RTM
|
||||
SeaMonkeyAll, NETSCAPE_7_0_RTM
|
||||
|
||||
## You need this if you want to be able to use SVG
|
||||
## Note that this library is under the LGPL, not the MPL
|
||||
#mozilla/other-licenses/libart_lgpl
|
||||
@@ -1,79 +0,0 @@
|
||||
#!perl
|
||||
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Simon Fraser <sfraser@netscape.com>
|
||||
#
|
||||
|
||||
require 5.004;
|
||||
|
||||
use strict;
|
||||
|
||||
use Cwd;
|
||||
use Moz::BuildUtils;
|
||||
use Moz::BuildCore;
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# Where have the build options gone?
|
||||
#
|
||||
# The various build flags have been centralized into one place.
|
||||
# The master list of options is in MozBuildFlags.txt. However,
|
||||
# you should never need to edit that file, or this one.
|
||||
#
|
||||
# To customize what gets built, or where to start the build,
|
||||
# edit the $prefs_file_name file in
|
||||
# System Folder:Preferences:Mozilla build prefs:
|
||||
# Documentation is provided in that file.
|
||||
#-------------------------------------------------------------
|
||||
|
||||
my($prefs_file_name) = "Mozilla pull prefs";
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# hashes to hold build options
|
||||
#-------------------------------------------------------------
|
||||
my(%build);
|
||||
my(%options);
|
||||
my(%filepaths);
|
||||
my(%optiondefines);
|
||||
|
||||
# Hash of input files for this build. Eventually, there will be
|
||||
# input files for manifests, and projects too.
|
||||
my(%inputfiles) = (
|
||||
"buildflags", "MozillaBuildFlags.txt",
|
||||
"checkoutdata", "MozillaCheckoutList.txt",
|
||||
"buildprogress", "",
|
||||
"buildmodule", "MozillaBuildList.pm",
|
||||
"checkouttime", "Mozilla last checkout"
|
||||
);
|
||||
#-------------------------------------------------------------
|
||||
# end build hashes
|
||||
#-------------------------------------------------------------
|
||||
|
||||
# set the build root directory, which is the the dir above mozilla
|
||||
SetupBuildRootDir(":mozilla:build:mac:build_scripts");
|
||||
|
||||
# Set up all the flags on $main::, like DEBUG, CARBON etc.
|
||||
# Override the defaults using the preferences files.
|
||||
SetupDefaultBuildOptions(0, ":mozilla:dist:viewer:", "");
|
||||
|
||||
my($do_checkout) = 1;
|
||||
my($do_build) = 0;
|
||||
|
||||
RunBuild($do_checkout, $do_build, \%inputfiles, $prefs_file_name);
|
||||
@@ -1,511 +0,0 @@
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
|
||||
DEPTH=.
|
||||
|
||||
!if !defined(MOZ_TOP)
|
||||
#enable builds from changed top level directories
|
||||
MOZ_TOP=mozilla
|
||||
!endif
|
||||
|
||||
MOZ_SRC_FLIPPED = $(MOZ_SRC:\=/)
|
||||
MOZ_DIST_FLIPPED = $(MOZ_SRC_FLIPPED)/mozilla/dist
|
||||
!ifdef MOZ_DEBUG
|
||||
MOZ_OBJDIR = WIN32_D.OBJ
|
||||
!else
|
||||
MOZ_OBJDIR = WIN32_O.OBJ
|
||||
!endif
|
||||
|
||||
#
|
||||
# Command macro defines
|
||||
#
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Figure out how to do the pull.
|
||||
#//------------------------------------------------------------------------
|
||||
# uncomment these, modify branch tag, and check in to branch for milestones
|
||||
MOZ_BRANCH=NETSCAPE_7_0_RTM
|
||||
NSPR_CO_TAG=NETSCAPE_7_0_RTM
|
||||
PSM_CO_TAG=NETSCAPE_7_0_RTM
|
||||
NSS_CO_TAG=NETSCAPE_7_0_RTM
|
||||
LDAPCSDK_CO_TAG=NETSCAPE_7_0_RTM
|
||||
ACCESSIBLE_CO_TAG=NETSCAPE_7_0_RTM
|
||||
IMGLIB2_CO_TAG=NETSCAPE_7_0_RTM
|
||||
GFX2_CO_TAG=NETSCAPE_7_0_RTM
|
||||
|
||||
|
||||
!ifdef MOZ_BRANCH
|
||||
CVS_BRANCH=-r $(MOZ_BRANCH)
|
||||
!endif
|
||||
|
||||
!ifdef MOZ_DATE
|
||||
CVS_BRANCH=$(CVS_BRANCH) -D "$(MOZ_DATE)"
|
||||
!endif
|
||||
|
||||
# default pull is "quiet" but it can be overridden with MOZ_CVS_VERBOSE
|
||||
!ifndef MOZ_CVS_VERBOSE
|
||||
CVS_FLAGS=-q
|
||||
!endif
|
||||
|
||||
# honor any user-defined CVS flags
|
||||
!ifdef MOZ_CVS_FLAGS
|
||||
CVS_FLAGS=$(CVS_FLAGS) $(MOZ_CVS_FLAGS)
|
||||
!endif
|
||||
|
||||
# let's be explicit about CVSROOT... some windows cvs clients
|
||||
# are too stupid to correctly work without the -d option
|
||||
#
|
||||
# if they are too stupid, they should fail. I am
|
||||
# commenting this out because this does not work
|
||||
# under 4nt. (%'s are evaluted differently)
|
||||
#
|
||||
# If it breaks you, mail dougt@netscape.com
|
||||
# and leaf@mozilla.org
|
||||
#
|
||||
!if 0
|
||||
!if defined(CVSROOT)
|
||||
CVS_FLAGS=$(CVS_FLAGS) -d "$(CVSROOT)"
|
||||
!endif
|
||||
!endif
|
||||
|
||||
!ifndef MOZ_CO_FLAGS
|
||||
MOZ_CO_FLAGS = -P
|
||||
!endif
|
||||
|
||||
CVSCO = cvs $(CVS_FLAGS) co $(MOZ_CO_FLAGS) $(CVS_BRANCH)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Figure out how to pull NSPR.
|
||||
#// If no NSPR_CO_TAG is specified, use the default static tag
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
!ifndef NSPR_CO_FLAGS
|
||||
NSPR_CO_FLAGS=$(MOZ_CO_FLAGS)
|
||||
!endif
|
||||
|
||||
NSPR_CO_FLAGS=$(NSPR_CO_FLAGS) $(CVS_BRANCH)
|
||||
|
||||
|
||||
CVSCO_NSPR = cvs $(CVS_FLAGS) co $(NSPR_CO_FLAGS)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Figure out how to pull NSS and PSM libs.
|
||||
#// If no NSS_CO_TAG or PSM_CO_TAG is specified, use the default static tag
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
!ifndef NSS_CO_FLAGS
|
||||
NSS_CO_FLAGS=$(MOZ_CO_FLAGS)
|
||||
!endif
|
||||
|
||||
NSS_CO_FLAGS=$(NSS_CO_FLAGS) $(CVS_BRANCH)
|
||||
|
||||
CVSCO_NSS = cvs $(CVS_FLAGS) co $(NSS_CO_FLAGS)
|
||||
|
||||
!ifndef PSM_CO_FLAGS
|
||||
PSM_CO_FLAGS=$(MOZ_CO_FLAGS)
|
||||
!endif
|
||||
|
||||
PSM_CO_FLAGS=$(PSM_CO_FLAGS) $(CVS_BRANCH)
|
||||
|
||||
CVSCO_PSM = cvs $(CVS_FLAGS) co $(PSM_CO_FLAGS)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Figure out how to pull LDAP C SDK client libs.
|
||||
#// If no LDAPCSDK_CO_TAG is specified, use the default tag
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
|
||||
!ifndef LDAPCSDK_CO_FLAGS
|
||||
LDAPCSDK_CO_FLAGS=$(MOZ_CO_FLAGS)
|
||||
!endif
|
||||
|
||||
LDAPCSDK_CO_FLAGS=$(LDAPCSDK_CO_FLAGS) $(CVS_BRANCH)
|
||||
|
||||
CVSCO_LDAPCSDK = cvs $(CVS_FLAGS) co $(LDAPCSDK_CO_FLAGS)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Figure out how to pull accessibility libs.
|
||||
#// If no ACCESSIBLE_CO_TAG is specified, use the default tag
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
!ifndef ACCESSIBLE_CO_FLAGS
|
||||
ACCESSIBLE_CO_FLAGS=$(MOZ_CO_FLAGS)
|
||||
!endif
|
||||
|
||||
ACCESSIBLE_CO_FLAGS=$(ACCESSIBLE_CO_FLAGS) $(CVS_BRANCH)
|
||||
|
||||
CVSCO_ACCESSIBLE = cvs $(CVS_FLAGS) co $(ACCESSIBLE_CO_FLAGS)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Figure out how to pull new image library.
|
||||
#// If no IMGLIB2_CO_TAG is specified, use the default tag
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
!ifndef IMGLIB2_CO_FLAGS
|
||||
IMGLIB2_CO_FLAGS=$(MOZ_CO_FLAGS)
|
||||
!endif
|
||||
|
||||
IMGLIB2_CO_FLAGS=$(IMGLIB2_CO_FLAGS) $(CVS_BRANCH)
|
||||
|
||||
CVSCO_IMGLIB2 = cvs $(CVS_FLAGS) co $(IMGLIB2_CO_FLAGS)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Figure out how to pull new image library.
|
||||
#// If no GFX2_CO_TAG is specified, use the default tag
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
!ifndef GFX2_CO_FLAGS
|
||||
GFX2_CO_FLAGS=$(MOZ_CO_FLAGS)
|
||||
!endif
|
||||
|
||||
GFX2_CO_FLAGS=$(GFX2_CO_FLAGS) $(CVS_BRANCH)
|
||||
|
||||
CVSCO_GFX2 = cvs $(CVS_FLAGS) co $(GFX2_CO_FLAGS)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Figure out how to pull the internal libart
|
||||
#// (only pulled and built if MOZ_INTERNAL_LIBART_LGPL is set)
|
||||
#// If no MOZ_INTERNAL_LIBART_CO_TAG is specified, use the default tag
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
!if defined(MOZ_SVG) && !defined(MOZ_INTERNAL_LIBART_LGPL)
|
||||
ERR_MESSAGE = ^
|
||||
You are trying to build Mozilla with SVG support (MOZ_SVG=1), but you ^
|
||||
haven not specified that mozilla/other-licenses/libart_lgpl should be ^
|
||||
pulled and built. At the moment Mozilla SVG builds need this patched ^
|
||||
version of libart. You either need to disable SVG support (unset MOZ_SVG) ^
|
||||
or enable pulling and building by setting MOZ_INTERNAL_LIBART_LGPL=1.^
|
||||
^
|
||||
If you choose to pull and build libart, note that it is only licensed^
|
||||
under the terms of the LGPL, not the MPL. (Which is why you have to opt^
|
||||
in explicitly.)
|
||||
!endif
|
||||
|
||||
!if defined(MOZ_INTERNAL_LIBART_LGPL)
|
||||
|
||||
!ifndef MOZ_INTERNAL_LIBART_CO_FLAGS
|
||||
MOZ_INTERNAL_LIBART_CO_FLAGS=$(MOZ_CO_FLAGS)
|
||||
!endif
|
||||
|
||||
!if "$(MOZ_INTERNAL_LIBART_CO_TAG)" != ""
|
||||
MOZ_INTERNAL_LIBART_CO_FLAGS=$(MOZ_INTERNAL_LIBART_CO_FLAGS) -r $(MOZ_INTERNAL_LIBART_CO_TAG)
|
||||
!else
|
||||
MOZ_INTERNAL_LIBART_CO_FLAGS=$(MOZ_INTERNAL_LIBART_CO_FLAGS) $(CVS_BRANCH)
|
||||
!endif
|
||||
|
||||
CVSCO_MOZ_INTERNAL_LIBART = cvs $(CVS_FLAGS) co $(MOZ_INTERNAL_LIBART_CO_FLAGS)
|
||||
|
||||
!endif
|
||||
|
||||
## The master target
|
||||
############################################################
|
||||
|
||||
pull_and_build_all: pull_all build_all_dep
|
||||
|
||||
|
||||
## Rules for pulling the source from the cvs repository
|
||||
############################################################
|
||||
|
||||
pull_clobber_and_build_all: pull_all clobber_all build_all
|
||||
|
||||
!if !defined(MOZ_INTERNAL_LIBART_LGPL)
|
||||
pull_all: pull_nspr pull_psm pull_ldapcsdk pull_accessible pull_gfx2 pull_imglib2 pull_seamonkey
|
||||
!else
|
||||
pull_all: pull_nspr pull_psm pull_ldapcsdk pull_accessible pull_gfx2 pull_imglib2 pull_moz_internal_libart pull_seamonkey
|
||||
!endif
|
||||
|
||||
pull_nspr: pull_clientmak
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO_NSPR) mozilla/nsprpub
|
||||
|
||||
pull_nss:
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO_NSS) mozilla/security/coreconf
|
||||
$(CVSCO_NSS) mozilla/security/nss
|
||||
|
||||
pull_psm: pull_nss
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO_PSM) mozilla/security/manager
|
||||
$(CVSCO_PSM) mozilla/security/makefile.win
|
||||
|
||||
pull_ldapcsdk:
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO_LDAPCSDK) mozilla/directory/c-sdk
|
||||
|
||||
pull_accessible:
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO_ACCESSIBLE) mozilla/accessible
|
||||
|
||||
pull_gfx2:
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO_GFX2) mozilla/gfx2
|
||||
|
||||
pull_imglib2:
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO_IMGLIB2) mozilla/modules/libpr0n
|
||||
|
||||
!if defined(MOZ_INTERNAL_LIBART_LGPL)
|
||||
pull_moz_internal_libart:
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO_MOZ_INTERNAL_LIBART) mozilla/other-licenses/libart_lgpl
|
||||
!endif
|
||||
|
||||
pull_xpconnect: pull_nspr
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO) mozilla/include
|
||||
$(CVSCO) mozilla/config
|
||||
$(CVSCO) -l mozilla/js
|
||||
$(CVSCO) -l mozilla/js/src
|
||||
$(CVSCO) mozilla/js/src/fdlibm
|
||||
$(CVSCO) mozilla/js/src/xpconnect
|
||||
$(CVSCO) mozilla/modules/libreg
|
||||
$(CVSCO) mozilla/xpcom
|
||||
$(CVSCO) mozilla/string
|
||||
|
||||
# pull either layout only or seamonkey the browser
|
||||
pull_layout:
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO) RaptorWin
|
||||
|
||||
pull_seamonkey: pull_clientmak
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO) SeaMonkeyAll
|
||||
|
||||
pull_clientmak:
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO) mozilla/client.mak
|
||||
|
||||
############################################################
|
||||
|
||||
# nmake has to be hardcoded, or we have to depend on mozilla/config
|
||||
# being pulled already to figure out what $(NMAKE) should be.
|
||||
|
||||
clobber_all: clobber_nspr clobber_ldapcsdk clobber_psm clobber_seamonkey
|
||||
|
||||
build_all: build_nspr build_ldapcsdk build_seamonkey
|
||||
|
||||
build_all_dep: depend libs
|
||||
|
||||
distclean:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\directory\c-sdk
|
||||
gmake -f gmakefile.win distclean MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED)
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\nsprpub
|
||||
gmake -f gmakefile.win distclean MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED)
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)
|
||||
nmake /f client.mak clobber_psm
|
||||
nmake /f client.mak clobber_seamonkey
|
||||
|
||||
clobber_ldapcsdk:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\directory\c-sdk
|
||||
gmake -f gmakefile.win clobber_all MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED) \
|
||||
SHELL=sh
|
||||
|
||||
clobber_nspr:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\nsprpub
|
||||
gmake -f gmakefile.win clobber_all MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED)
|
||||
|
||||
clobber_psm:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\security
|
||||
nmake -f makefile.win clobber_all
|
||||
|
||||
clobber_xpconnect:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\.
|
||||
-rd /s /q dist
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\nsprpub
|
||||
gmake -f gmakefile.win clobber_all MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED)
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\include
|
||||
nmake -f makefile.win clobber_all
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\modules\libreg
|
||||
nmake -f makefile.win clobber_all
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\string
|
||||
nmake -f makefile.win clobber_all
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\xpcom
|
||||
nmake -f makefile.win clobber_all
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\js
|
||||
nmake -f makefile.win clobber_all
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\js\src\xpconnect
|
||||
nmake -f makefile.win clobber_all
|
||||
|
||||
clobber_seamonkey:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\.
|
||||
-rd /s /q dist
|
||||
nmake -f makefile.win clobber_all
|
||||
|
||||
depend: export
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\.
|
||||
nmake -f makefile.win depend
|
||||
|
||||
depend_xpconnect:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\include
|
||||
nmake -f makefile.win depend
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\modules\libreg
|
||||
nmake -f makefile.win depend
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\string
|
||||
nmake -f makefile.win depend
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\xpcom
|
||||
nmake -f makefile.win depend
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\js\src
|
||||
nmake -f makefile.win depend
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\js\src\xpconnect
|
||||
nmake -f makefile.win depend
|
||||
|
||||
build_nspr:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\nsprpub
|
||||
gmake -f gmakefile.win MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED)
|
||||
|
||||
build_ldapcsdk:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\directory\c-sdk
|
||||
gmake -f gmakefile.win MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED) SHELL=sh
|
||||
|
||||
build_psm:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\security
|
||||
nmake -f makefile.win
|
||||
|
||||
build_xpconnect: build_nspr
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\include
|
||||
nmake -f makefile.win all
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\modules\libreg
|
||||
nmake -f makefile.win all
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\xpcom
|
||||
nmake -f makefile.win export
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\string
|
||||
nmake -f makefile.win all
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\xpcom
|
||||
nmake -f makefile.win libs
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\js\src
|
||||
nmake -f makefile.win all
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\js\src\xpconnect
|
||||
nmake -f makefile.win all
|
||||
|
||||
build_seamonkey:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\.
|
||||
nmake -f makefile.win all
|
||||
|
||||
build_client:
|
||||
@cd $(MOZ_SRC)\mozilla\.
|
||||
nmake -f makefile.win all
|
||||
|
||||
build_layout:
|
||||
@cd $(MOZ_SRC)\mozilla\.
|
||||
nmake -f makefile.win all
|
||||
|
||||
build_dist:
|
||||
@cd $(MOZ_SRC)\mozilla\.
|
||||
nmake -f makefile.win all
|
||||
|
||||
libs:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\.
|
||||
nmake -f makefile.win libs
|
||||
|
||||
export: build_nspr build_ldapcsdk
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\.
|
||||
nmake -f makefile.win export
|
||||
|
||||
clobber_dist:
|
||||
@cd $(MOZ_SRC)\mozilla\.
|
||||
nmake -f makefile.win clobber_all
|
||||
|
||||
clobber_client:
|
||||
@cd $(MOZ_SRC)\mozilla\.
|
||||
nmake -f makefile.win clobber_all
|
||||
|
||||
clobber_layout:
|
||||
@cd $(MOZ_SRC)\mozilla\.
|
||||
nmake -f makefile.win clobber_all
|
||||
|
||||
browse_info::
|
||||
cd $(MOZ_SRC)\$(MOZ_TOP)
|
||||
-dir /s /b *.sbr > sbrlist.tmp
|
||||
-bscmake /Es /o mozilla.bsc @sbrlist.tmp
|
||||
-rm sbrlist.tmp
|
||||
|
||||
regchrome::
|
||||
@cd $(MOZ_SRC)\mozilla\.
|
||||
nmake /f makefile.win regchrome
|
||||
|
||||
deliver::
|
||||
@cd $(MOZ_SRC)\mozilla\.
|
||||
nmake /f makefile.win splitsymbols
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Utility stuff...
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
# Verify that MOZ_SRC is set correctly
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
# Check to see if it is set at all
|
||||
!if "$(MOZ_SRC)"==""
|
||||
MOZ_SRC = $(MAKEDIR)\..
|
||||
!endif
|
||||
|
||||
#
|
||||
# create a temp file at the root and make sure it is visible from MOZ_SRC
|
||||
#
|
||||
!if [copy $(MAKEDIR)\client.mak $(MAKEDIR)\xyzzy.tmp > NUL] == 0
|
||||
!endif
|
||||
|
||||
!if !EXIST( $(MOZ_SRC)\mozilla\xyzzy.tmp )
|
||||
ERR_MESSAGE=$(ERR_MESSAGE)^
|
||||
MOZ_SRC isn't set correctly: [$(MOZ_SRC)\mozilla]!=[$(MAKEDIR)]
|
||||
!endif
|
||||
|
||||
!if [del $(MAKEDIR)\xyzzy.tmp]
|
||||
!endif
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
# Verify that MOZ_BITS is set
|
||||
#//------------------------------------------------------------------------
|
||||
!if !defined(MOZ_BITS)
|
||||
ERR_MESSAGE=$(ERR_MESSAGE)^
|
||||
Environment variable MOZ_BITS isn't set.
|
||||
!endif
|
||||
|
||||
!if !defined(MOZ_TOOLS)
|
||||
ERR_MESSAGE=$(ERR_MESSAGE)^
|
||||
Environment variable MOZ_TOOLS isn't set.
|
||||
!endif
|
||||
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Display error
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
!if "$(ERR_MESSAGE)" != ""
|
||||
ERR_MESSAGE = ^
|
||||
client.mak: ^
|
||||
$(ERR_MESSAGE) ^
|
||||
^
|
||||
client.mak: usage^
|
||||
^
|
||||
nmake -f client.mak [MOZ_BRANCH=<cvs_branch_name>] ^
|
||||
[MOZ_DATE=<cvs_date>]^
|
||||
[pull_and_build_all]^
|
||||
[pull_all]^
|
||||
[build_all]^
|
||||
^
|
||||
Environment variables:^
|
||||
^
|
||||
MOZ_BITS set to 32^
|
||||
MOZ_TOOLS set to the directory containing the needed tools ^
|
||||
|
||||
!ERROR $(ERR_MESSAGE)
|
||||
|
||||
!endif
|
||||
@@ -1,650 +0,0 @@
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Stephen Lamm
|
||||
|
||||
# Build the Mozilla client.
|
||||
#
|
||||
# This needs CVSROOT set to work, e.g.,
|
||||
# setenv CVSROOT :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
|
||||
# or
|
||||
# setenv CVSROOT :pserver:username%somedomain.org@cvs.mozilla.org:/cvsroot
|
||||
#
|
||||
# To checkout and build a tree,
|
||||
# 1. cvs co mozilla/client.mk
|
||||
# 2. cd mozilla
|
||||
# 3. gmake -f client.mk
|
||||
#
|
||||
# Other targets (gmake -f client.mk [targets...]),
|
||||
# checkout
|
||||
# build
|
||||
# clean (realclean is now the same as clean)
|
||||
# distclean
|
||||
#
|
||||
# See http://www.mozilla.org/build/unix.html for more information.
|
||||
#
|
||||
# Options:
|
||||
# MOZ_OBJDIR - Destination object directory
|
||||
# MOZ_CO_DATE - Date tag to use for checkout (default: none)
|
||||
# MOZ_CO_MODULE - Module to checkout (default: SeaMonkeyAll)
|
||||
# MOZ_CVS_FLAGS - Flags to pass cvs (default: -q -z3)
|
||||
# MOZ_CO_FLAGS - Flags to pass after 'cvs co' (default: -P)
|
||||
# MOZ_MAKE_FLAGS - Flags to pass to $(MAKE)
|
||||
# MOZ_CO_BRANCH - Branch tag (Deprecated. Use MOZ_CO_TAG below.)
|
||||
#
|
||||
|
||||
#######################################################################
|
||||
# Checkout Tags
|
||||
#
|
||||
# For branches, uncomment the MOZ_CO_TAG line with the proper tag,
|
||||
# and commit this file on that tag.
|
||||
MOZ_CO_TAG = NETSCAPE_7_0_RTM
|
||||
NSPR_CO_TAG = NETSCAPE_7_0_RTM
|
||||
PSM_CO_TAG = NETSCAPE_7_0_RTM
|
||||
NSS_CO_TAG = NETSCAPE_7_0_RTM
|
||||
LDAPCSDK_CO_TAG = NETSCAPE_7_0_RTM
|
||||
ACCESSIBLE_CO_TAG = NETSCAPE_7_0_RTM
|
||||
GFX2_CO_TAG = NETSCAPE_7_0_RTM
|
||||
IMGLIB2_CO_TAG = NETSCAPE_7_0_RTM
|
||||
BUILD_MODULES = all
|
||||
|
||||
#######################################################################
|
||||
# Defines
|
||||
#
|
||||
CVS = cvs
|
||||
|
||||
CWD := $(shell pwd)
|
||||
|
||||
ifeq "$(CWD)" "/"
|
||||
CWD := /.
|
||||
endif
|
||||
|
||||
ifneq (, $(wildcard client.mk))
|
||||
# Ran from mozilla directory
|
||||
ROOTDIR := $(shell dirname $(CWD))
|
||||
TOPSRCDIR := $(CWD)
|
||||
else
|
||||
# Ran from mozilla/.. directory (?)
|
||||
ROOTDIR := $(CWD)
|
||||
TOPSRCDIR := $(CWD)/mozilla
|
||||
endif
|
||||
|
||||
# on os2, TOPSRCDIR may have two forward slashes in a row, which doesn't
|
||||
# work; replace first instance with one forward slash
|
||||
TOPSRCDIR := $(shell echo "$(TOPSRCDIR)" | sed -e 's%//%/%')
|
||||
|
||||
ifndef TOPSRCDIR_MOZ
|
||||
TOPSRCDIR_MOZ=$(TOPSRCDIR)
|
||||
endif
|
||||
|
||||
# if ROOTDIR equals only drive letter (i.e. "C:"), set to "/"
|
||||
DIRNAME := $(shell echo "$(ROOTDIR)" | sed -e 's/^.://')
|
||||
ifeq ($(DIRNAME),)
|
||||
ROOTDIR := /.
|
||||
endif
|
||||
|
||||
AUTOCONF := autoconf
|
||||
MKDIR := mkdir
|
||||
SH := /bin/sh
|
||||
ifndef MAKE
|
||||
MAKE := gmake
|
||||
endif
|
||||
|
||||
CONFIG_GUESS_SCRIPT := $(wildcard $(TOPSRCDIR)/build/autoconf/config.guess)
|
||||
ifdef CONFIG_GUESS_SCRIPT
|
||||
CONFIG_GUESS = $(shell $(CONFIG_GUESS_SCRIPT))
|
||||
else
|
||||
_IS_FIRST_CHECKOUT := 1
|
||||
endif
|
||||
|
||||
####################################
|
||||
# CVS
|
||||
|
||||
# Add the CVS root to CVS_FLAGS if needed
|
||||
CVS_ROOT_IN_TREE := $(shell cat $(TOPSRCDIR)/CVS/Root 2>/dev/null)
|
||||
ifneq ($(CVS_ROOT_IN_TREE),)
|
||||
ifneq ($(CVS_ROOT_IN_TREE),$(CVSROOT))
|
||||
CVS_FLAGS := -d $(CVS_ROOT_IN_TREE)
|
||||
endif
|
||||
endif
|
||||
|
||||
CVSCO = $(strip $(CVS) $(CVS_FLAGS) co $(CVS_CO_FLAGS))
|
||||
CVSCO_LOGFILE := $(ROOTDIR)/cvsco.log
|
||||
CVSCO_LOGFILE := $(shell echo $(CVSCO_LOGFILE) | sed s%//%/%)
|
||||
|
||||
ifdef MOZ_CO_TAG
|
||||
CVS_CO_FLAGS := -r $(MOZ_CO_TAG)
|
||||
endif
|
||||
|
||||
####################################
|
||||
# Load mozconfig Options
|
||||
|
||||
# See build pages, http://www.mozilla.org/build/unix.html,
|
||||
# for how to set up mozconfig.
|
||||
MOZCONFIG_LOADER := mozilla/build/autoconf/mozconfig2client-mk
|
||||
MOZCONFIG_FINDER := mozilla/build/autoconf/mozconfig-find
|
||||
MOZCONFIG_MODULES := mozilla/build/unix/modules.mk
|
||||
run_for_side_effects := \
|
||||
$(shell cd $(ROOTDIR); \
|
||||
if test "$(_IS_FIRST_CHECKOUT)"; then \
|
||||
$(CVSCO) $(MOZCONFIG_FINDER) $(MOZCONFIG_LOADER) $(MOZCONFIG_MODULES); \
|
||||
else true; \
|
||||
fi; \
|
||||
$(MOZCONFIG_LOADER) $(TOPSRCDIR) mozilla/.mozconfig.mk > mozilla/.mozconfig.out)
|
||||
include $(TOPSRCDIR)/.mozconfig.mk
|
||||
include $(TOPSRCDIR)/build/unix/modules.mk
|
||||
|
||||
####################################
|
||||
# Options that may come from mozconfig
|
||||
|
||||
# Change CVS flags if anonymous root is requested
|
||||
ifdef MOZ_CO_USE_MIRROR
|
||||
CVS_FLAGS := -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
|
||||
endif
|
||||
|
||||
# MOZ_CVS_FLAGS - Basic CVS flags
|
||||
ifeq "$(origin MOZ_CVS_FLAGS)" "undefined"
|
||||
CVS_FLAGS := $(CVS_FLAGS) -q -z 3
|
||||
else
|
||||
CVS_FLAGS := $(MOZ_CVS_FLAGS)
|
||||
endif
|
||||
|
||||
# This option is deprecated. The best way to have client.mk pull a tag
|
||||
# is to set MOZ_CO_TAG (see above) and commit that change on the tag.
|
||||
ifdef MOZ_CO_BRANCH
|
||||
$(warning Use MOZ_CO_TAG instead of MOZ_CO_BRANCH)
|
||||
CVS_CO_FLAGS := -r $(MOZ_CO_BRANCH)
|
||||
endif
|
||||
|
||||
# MOZ_CO_FLAGS - Anything that we should use on all checkouts
|
||||
ifeq "$(origin MOZ_CO_FLAGS)" "undefined"
|
||||
CVS_CO_FLAGS := $(CVS_CO_FLAGS) -P
|
||||
else
|
||||
CVS_CO_FLAGS := $(CVS_CO_FLAGS) $(MOZ_CO_FLAGS)
|
||||
endif
|
||||
|
||||
ifdef MOZ_CO_DATE
|
||||
CVS_CO_DATE_FLAGS := -D "$(MOZ_CO_DATE)"
|
||||
endif
|
||||
|
||||
ifdef MOZ_OBJDIR
|
||||
OBJDIR := $(MOZ_OBJDIR)
|
||||
MOZ_MAKE := $(MAKE) $(MOZ_MAKE_FLAGS) -C $(OBJDIR)
|
||||
else
|
||||
OBJDIR := $(TOPSRCDIR)
|
||||
MOZ_MAKE := $(MAKE) $(MOZ_MAKE_FLAGS)
|
||||
endif
|
||||
|
||||
####################################
|
||||
# CVS defines for PSM
|
||||
#
|
||||
PSM_CO_MODULE= mozilla/security/manager
|
||||
PSM_CO_FLAGS := -P -A
|
||||
ifdef MOZ_CO_FLAGS
|
||||
PSM_CO_FLAGS := $(MOZ_CO_FLAGS)
|
||||
endif
|
||||
ifdef PSM_CO_TAG
|
||||
PSM_CO_FLAGS := $(PSM_CO_FLAGS) -r $(PSM_CO_TAG)
|
||||
endif
|
||||
CVSCO_PSM = $(CVS) $(CVS_FLAGS) co $(PSM_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(PSM_CO_MODULE)
|
||||
|
||||
####################################
|
||||
# CVS defines for NSS
|
||||
#
|
||||
NSS_CO_MODULE = mozilla/security/nss \
|
||||
mozilla/security/coreconf \
|
||||
$(NULL)
|
||||
|
||||
NSS_CO_FLAGS := -P
|
||||
ifdef MOZ_CO_FLAGS
|
||||
NSS_CO_FLAGS := $(MOZ_CO_FLAGS)
|
||||
endif
|
||||
ifdef NSS_CO_TAG
|
||||
NSS_CO_FLAGS := $(NSS_CO_FLAGS) -r $(NSS_CO_TAG)
|
||||
endif
|
||||
# Cannot pull static tags by date
|
||||
ifeq ($(NSS_CO_TAG),NSS_CLIENT_TAG)
|
||||
CVSCO_NSS = $(CVS) $(CVS_FLAGS) co $(NSS_CO_FLAGS) $(NSS_CO_MODULE)
|
||||
else
|
||||
CVSCO_NSS = $(CVS) $(CVS_FLAGS) co $(NSS_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(NSS_CO_MODULE)
|
||||
endif
|
||||
|
||||
####################################
|
||||
# CVS defines for NSPR
|
||||
#
|
||||
NSPR_CO_MODULE = mozilla/nsprpub
|
||||
NSPR_CO_FLAGS := -P
|
||||
ifdef MOZ_CO_FLAGS
|
||||
NSPR_CO_FLAGS := $(MOZ_CO_FLAGS)
|
||||
endif
|
||||
ifdef NSPR_CO_TAG
|
||||
NSPR_CO_FLAGS := $(NSPR_CO_FLAGS) -r $(NSPR_CO_TAG)
|
||||
endif
|
||||
# Cannot pull static tags by date
|
||||
ifeq ($(NSPR_CO_TAG),NSPRPUB_CLIENT_TAG)
|
||||
CVSCO_NSPR = $(CVS) $(CVS_FLAGS) co $(NSPR_CO_FLAGS) $(NSPR_CO_MODULE)
|
||||
else
|
||||
CVSCO_NSPR = $(CVS) $(CVS_FLAGS) co $(NSPR_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(NSPR_CO_MODULE)
|
||||
endif
|
||||
|
||||
####################################
|
||||
# CVS defines for the C LDAP SDK
|
||||
#
|
||||
LDAPCSDK_CO_MODULE = mozilla/directory/c-sdk
|
||||
LDAPCSDK_CO_FLAGS := -P
|
||||
ifdef MOZ_CO_FLAGS
|
||||
LDAPCSDK_CO_FLAGS := $(MOZ_CO_FLAGS)
|
||||
endif
|
||||
ifdef LDAPCSDK_CO_TAG
|
||||
LDAPCSDK_CO_FLAGS := $(LDAPCSDK_CO_FLAGS) -r $(LDAPCSDK_CO_TAG)
|
||||
endif
|
||||
CVSCO_LDAPCSDK = $(CVS) $(CVS_FLAGS) co $(LDAPCSDK_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(LDAPCSDK_CO_MODULE)
|
||||
|
||||
####################################
|
||||
# CVS defines for the C LDAP SDK
|
||||
#
|
||||
ACCESSIBLE_CO_MODULE = mozilla/accessible
|
||||
ACCESSIBLE_CO_FLAGS := -P
|
||||
ifdef MOZ_CO_FLAGS
|
||||
ACCESSIBLE_CO_FLAGS := $(MOZ_CO_FLAGS)
|
||||
endif
|
||||
ifdef ACCESSIBLE_CO_TAG
|
||||
ACCESSIBLE_CO_FLAGS := $(ACCESSIBLE_CO_FLAGS) -r $(ACCESSIBLE_CO_TAG)
|
||||
endif
|
||||
CVSCO_ACCESSIBLE = $(CVS) $(CVS_FLAGS) co $(ACCESSIBLE_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(ACCESSIBLE_CO_MODULE)
|
||||
|
||||
####################################
|
||||
# CVS defines for gfx2
|
||||
#
|
||||
GFX2_CO_MODULE = mozilla/gfx2
|
||||
GFX2_CO_FLAGS := -P
|
||||
ifdef MOZ_CO_FLAGS
|
||||
GFX2_CO_FLAGS := $(MOZ_CO_FLAGS)
|
||||
endif
|
||||
ifdef GFX2_CO_TAG
|
||||
GFX2_CO_FLAGS := $(GFX2_CO_FLAGS) -r $(GFX2_CO_TAG)
|
||||
endif
|
||||
CVSCO_GFX2 = $(CVS) $(CVS_FLAGS) co $(GFX2_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(GFX2_CO_MODULE)
|
||||
|
||||
####################################
|
||||
# CVS defines for new image library
|
||||
#
|
||||
IMGLIB2_CO_MODULE = mozilla/modules/libpr0n
|
||||
IMGLIB2_CO_FLAGS := -P
|
||||
ifdef MOZ_CO_FLAGS
|
||||
IMGLIB2_CO_FLAGS := $(MOZ_CO_FLAGS)
|
||||
endif
|
||||
ifdef IMGLIB2_CO_TAG
|
||||
IMGLIB2_CO_FLAGS := $(IMGLIB2_CO_FLAGS) -r $(IMGLIB2_CO_TAG)
|
||||
endif
|
||||
CVSCO_IMGLIB2 = $(CVS) $(CVS_FLAGS) co $(IMGLIB2_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(IMGLIB2_CO_MODULE)
|
||||
|
||||
####################################
|
||||
# CVS defines for standalone modules
|
||||
#
|
||||
ifneq ($(BUILD_MODULES),all)
|
||||
MOZ_CO_MODULE := $(filter-out $(NSPRPUB_DIR) security directory/c-sdk, $(BUILD_MODULE_CVS))
|
||||
MOZ_CO_MODULE += allmakefiles.sh client.mk aclocal.m4 configure configure.in
|
||||
MOZ_CO_MODULE += Makefile.in
|
||||
MOZ_CO_MODULE := $(addprefix mozilla/, $(MOZ_CO_MODULE))
|
||||
|
||||
NOSUBDIRS_MODULE := $(addprefix mozilla/, $(BUILD_MODULE_CVS_NS))
|
||||
ifneq ($(NOSUBDIRS_MODULE),)
|
||||
CVSCO_NOSUBDIRS := $(CVSCO) -l $(CVS_CO_DATE_FLAGS) $(NOSUBDIRS_MODULE)
|
||||
endif
|
||||
|
||||
ifeq (,$(filter $(NSPRPUB_DIR), $(BUILD_MODULE_CVS)))
|
||||
CVSCO_NSPR :=
|
||||
endif
|
||||
ifeq (,$(filter security security/manager, $(BUILD_MODULE_CVS)))
|
||||
CVSCO_PSM :=
|
||||
CVSCO_NSS :=
|
||||
endif
|
||||
ifeq (,$(filter directory/c-sdk, $(BUILD_MODULE_CVS)))
|
||||
CVSCO_LDAPCSDK :=
|
||||
endif
|
||||
ifeq (,$(filter accessible, $(BUILD_MODULE_CVS)))
|
||||
CVSCO_ACCESSIBLE :=
|
||||
endif
|
||||
ifeq (,$(filter gfx2, $(BUILD_MODULE_CVS)))
|
||||
CVSCO_GFX2 :=
|
||||
endif
|
||||
ifeq (,$(filter modules/libpr0n, $(BUILD_MODULE_CVS)))
|
||||
CVSCO_IMGLIB2 :=
|
||||
endif
|
||||
endif
|
||||
|
||||
####################################
|
||||
# CVS defines for SeaMonkey
|
||||
#
|
||||
ifeq ($(MOZ_CO_MODULE),)
|
||||
MOZ_CO_MODULE := SeaMonkeyAll
|
||||
endif
|
||||
CVSCO_SEAMONKEY := $(CVSCO) $(CVS_CO_DATE_FLAGS) $(MOZ_CO_MODULE)
|
||||
|
||||
####################################
|
||||
# CVS defined for libart (pulled and built if MOZ_INTERNAL_LIBART_LGPL is set)
|
||||
#
|
||||
CVSCO_LIBART := $(CVSCO) $(CVS_CO_DATE_FLAGS) mozilla/other-licenses/libart_lgpl
|
||||
|
||||
ifdef MOZ_INTERNAL_LIBART_LGPL
|
||||
FASTUPDATE_LIBART := fast_update $(CVSCO_LIBART)
|
||||
CHECKOUT_LIBART := cvs_co $(CVSCO_LIBART)
|
||||
else
|
||||
CHECKOUT_LIBART := true
|
||||
FASTUPDATE_LIBART := true
|
||||
endif
|
||||
|
||||
####################################
|
||||
# CVS defines for Calendar (pulled and built if MOZ_CALENDAR is set)
|
||||
#
|
||||
CVSCO_CALENDAR := $(CVSCO) $(CVS_CO_DATE_FLAGS) mozilla/calendar
|
||||
|
||||
ifdef MOZ_CALENDAR
|
||||
FASTUPDATE_CALENDAR := fast_update $(CVSCO_CALENDAR)
|
||||
CHECKOUT_CALENDAR := cvs_co $(CVSCO_CALENDAR)
|
||||
else
|
||||
CHECKOUT_CALENDAR := true
|
||||
FASTUPDATE_CALENDAR := true
|
||||
endif
|
||||
|
||||
|
||||
# because some cygwin tools can't handle native dos-drive paths & vice-versa
|
||||
# force configure to use a relative path for --srcdir
|
||||
# need a better check for win32
|
||||
# and we need to get OBJDIR earlier
|
||||
ifdef MOZ_TOOLS
|
||||
_tmpobjdir := $(shell cygpath -u $(OBJDIR))
|
||||
_abs2rel := $(shell cygpath -w $(TOPSRCDIR)/build/unix/abs2rel.pl | sed -e 's|\\|/|g')
|
||||
_OBJ2SRCPATH := $(shell $(_abs2rel) $(TOPSRCDIR) $(_tmpobjdir))
|
||||
endif
|
||||
|
||||
#######################################################################
|
||||
# Rules
|
||||
#
|
||||
|
||||
# Print out any options loaded from mozconfig.
|
||||
all build checkout clean depend distclean export libs install realclean::
|
||||
@if test -f .mozconfig.out; then \
|
||||
cat .mozconfig.out; \
|
||||
rm -f .mozconfig.out; \
|
||||
else true; \
|
||||
fi
|
||||
|
||||
ifdef _IS_FIRST_CHECKOUT
|
||||
all:: checkout build
|
||||
else
|
||||
all:: checkout alldep
|
||||
endif
|
||||
|
||||
# Windows equivalents
|
||||
pull_all: checkout
|
||||
build_all: build
|
||||
build_all_dep: alldep
|
||||
build_all_depend: alldep
|
||||
clobber clobber_all: clean
|
||||
pull_and_build_all: checkout alldep
|
||||
|
||||
# Do everything from scratch
|
||||
everything: checkout clean build
|
||||
|
||||
####################################
|
||||
# CVS checkout
|
||||
#
|
||||
checkout::
|
||||
# @: Backup the last checkout log.
|
||||
@if test -f $(CVSCO_LOGFILE) ; then \
|
||||
mv $(CVSCO_LOGFILE) $(CVSCO_LOGFILE).old; \
|
||||
else true; \
|
||||
fi
|
||||
ifdef RUN_AUTOCONF_LOCALLY
|
||||
@echo "Removing local configures" ; \
|
||||
cd $(ROOTDIR) && \
|
||||
$(RM) -f mozilla/configure mozilla/nsprpub/configure \
|
||||
mozilla/directory/c-sdk/configure
|
||||
endif
|
||||
@echo "checkout start: "`date` | tee $(CVSCO_LOGFILE)
|
||||
@echo '$(CVSCO) mozilla/client.mk mozilla/build/unix/modules.mk'; \
|
||||
cd $(ROOTDIR) && \
|
||||
$(CVSCO) mozilla/client.mk mozilla/build/unix/modules.mk
|
||||
@cd $(ROOTDIR) && $(MAKE) -f mozilla/client.mk real_checkout
|
||||
|
||||
real_checkout:
|
||||
# @: Start the checkout. Split the output to the tty and a log file. \
|
||||
# : If it fails, touch an error file because "tee" hides the error.
|
||||
@failed=.cvs-failed.tmp; rm -f $$failed*; \
|
||||
cvs_co() { echo "$$@" ; \
|
||||
("$$@" || touch $$failed) 2>&1 | tee -a $(CVSCO_LOGFILE) && \
|
||||
if test -f $$failed; then false; else true; fi; }; \
|
||||
cvs_co $(CVSCO_NSPR) && \
|
||||
cvs_co $(CVSCO_NSS) && \
|
||||
cvs_co $(CVSCO_PSM) && \
|
||||
cvs_co $(CVSCO_LDAPCSDK) && \
|
||||
cvs_co $(CVSCO_ACCESSIBLE) && \
|
||||
cvs_co $(CVSCO_GFX2) && \
|
||||
cvs_co $(CVSCO_IMGLIB2) && \
|
||||
$(CHECKOUT_CALENDAR) && \
|
||||
$(CHECKOUT_LIBART) && \
|
||||
cvs_co $(CVSCO_SEAMONKEY) && \
|
||||
cvs_co $(CVSCO_NOSUBDIRS)
|
||||
@echo "checkout finish: "`date` | tee -a $(CVSCO_LOGFILE)
|
||||
# @: Check the log for conflicts. ;
|
||||
@conflicts=`egrep "^C " $(CVSCO_LOGFILE)` ;\
|
||||
if test "$$conflicts" ; then \
|
||||
echo "$(MAKE): *** Conflicts during checkout." ;\
|
||||
echo "$$conflicts" ;\
|
||||
echo "$(MAKE): Refer to $(CVSCO_LOGFILE) for full log." ;\
|
||||
false; \
|
||||
else true; \
|
||||
fi
|
||||
ifdef RUN_AUTOCONF_LOCALLY
|
||||
@echo Generating configures using $(AUTOCONF) ; \
|
||||
cd $(TOPSRCDIR) && $(AUTOCONF) && \
|
||||
cd $(TOPSRCDIR)/nsprpub && $(AUTOCONF) && \
|
||||
cd $(TOPSRCDIR)/directory/c-sdk && $(AUTOCONF)
|
||||
endif
|
||||
|
||||
fast-update:
|
||||
# @: Backup the last checkout log.
|
||||
@if test -f $(CVSCO_LOGFILE) ; then \
|
||||
mv $(CVSCO_LOGFILE) $(CVSCO_LOGFILE).old; \
|
||||
else true; \
|
||||
fi
|
||||
ifdef RUN_AUTOCONF_LOCALLY
|
||||
@echo "Removing local configures" ; \
|
||||
cd $(ROOTDIR) && \
|
||||
$(RM) -f mozilla/configure mozilla/nsprpub/configure \
|
||||
mozilla/directory/c-sdk/configure
|
||||
endif
|
||||
@echo "checkout start: "`date` | tee $(CVSCO_LOGFILE)
|
||||
@echo '$(CVSCO) mozilla/client.mk mozilla/build/unix/modules.mk'; \
|
||||
cd $(ROOTDIR) && \
|
||||
$(CVSCO) mozilla/client.mk mozilla/build/unix/modules.mk
|
||||
@cd $(TOPSRCDIR) && \
|
||||
$(MAKE) -f client.mk real_fast-update
|
||||
|
||||
real_fast-update:
|
||||
# @: Start the update. Split the output to the tty and a log file. \
|
||||
# : If it fails, touch an error file because "tee" hides the error.
|
||||
@failed=.fast_update-failed.tmp; rm -f $$failed*; \
|
||||
fast_update() { (config/cvsco-fast-update.pl $$@ || touch $$failed) 2>&1 | tee -a $(CVSCO_LOGFILE) && \
|
||||
if test -f $$failed; then false; else true; fi; }; \
|
||||
cvs_co() { echo "$$@" ; \
|
||||
("$$@" || touch $$failed) 2>&1 | tee -a $(CVSCO_LOGFILE) && \
|
||||
if test -f $$failed; then false; else true; fi; }; \
|
||||
fast_update $(CVSCO_NSPR) && \
|
||||
cd $(ROOTDIR) && \
|
||||
failed=mozilla/.fast_update-failed.tmp && \
|
||||
cvs_co $(CVSCO_NSS) && \
|
||||
failed=.fast_update-failed.tmp && \
|
||||
cd mozilla && \
|
||||
fast_update $(CVSCO_PSM) && \
|
||||
fast_update $(CVSCO_LDAPCSDK) && \
|
||||
fast_update $(CVSCO_ACCESSIBLE) && \
|
||||
fast_update $(CVSCO_GFX2) && \
|
||||
fast_update $(CVSCO_IMGLIB2) && \
|
||||
$(FASTUPDATE_CALENDAR) && \
|
||||
$(FASTUPDATE_LIBART) && \
|
||||
fast_update $(CVSCO_SEAMONKEY) && \
|
||||
fast_update $(CVSCO_NOSUBDIRS)
|
||||
@echo "fast_update finish: "`date` | tee -a $(CVSCO_LOGFILE)
|
||||
# @: Check the log for conflicts. ;
|
||||
@conflicts=`egrep "^C " $(CVSCO_LOGFILE)` ;\
|
||||
if test "$$conflicts" ; then \
|
||||
echo "$(MAKE): *** Conflicts during fast-update." ;\
|
||||
echo "$$conflicts" ;\
|
||||
echo "$(MAKE): Refer to $(CVSCO_LOGFILE) for full log." ;\
|
||||
false; \
|
||||
else true; \
|
||||
fi
|
||||
ifdef RUN_AUTOCONF_LOCALLY
|
||||
@echo Generating configures using $(AUTOCONF) ; \
|
||||
cd $(TOPSRCDIR) && $(AUTOCONF) && \
|
||||
cd $(TOPSRCDIR)/nsprpub && $(AUTOCONF) && \
|
||||
cd $(TOPSRCDIR)/directory/c-sdk && $(AUTOCONF)
|
||||
endif
|
||||
|
||||
####################################
|
||||
# Web configure
|
||||
|
||||
WEBCONFIG_FILE := $(HOME)/.mozconfig
|
||||
|
||||
MOZCONFIG2CONFIGURATOR := build/autoconf/mozconfig2configurator
|
||||
webconfig:
|
||||
@cd $(TOPSRCDIR); \
|
||||
url=`$(MOZCONFIG2CONFIGURATOR) $(TOPSRCDIR)`; \
|
||||
echo Running mozilla with the following url: ;\
|
||||
echo ;\
|
||||
echo $$url ;\
|
||||
mozilla -remote "openURL($$url)" || \
|
||||
netscape -remote "openURL($$url)" || \
|
||||
mozilla $$url || \
|
||||
netscape $$url ;\
|
||||
echo ;\
|
||||
echo 1. Fill out the form on the browser. ;\
|
||||
echo 2. Save the results to $(WEBCONFIG_FILE)
|
||||
|
||||
#####################################################
|
||||
# First Checkout
|
||||
|
||||
ifdef _IS_FIRST_CHECKOUT
|
||||
# First time, do build target in a new process to pick up new files.
|
||||
build::
|
||||
$(MAKE) -f $(TOPSRCDIR)/client.mk build
|
||||
else
|
||||
|
||||
#####################################################
|
||||
# After First Checkout
|
||||
|
||||
|
||||
####################################
|
||||
# Configure
|
||||
|
||||
CONFIG_STATUS := $(wildcard $(OBJDIR)/config.status)
|
||||
CONFIG_CACHE := $(wildcard $(OBJDIR)/config.cache)
|
||||
|
||||
ifdef RUN_AUTOCONF_LOCALLY
|
||||
EXTRA_CONFIG_DEPS := \
|
||||
$(TOPSRCDIR)/aclocal.m4 \
|
||||
$(wildcard $(TOPSRCDIR)/build/autoconf/*.m4) \
|
||||
$(NULL)
|
||||
|
||||
$(TOPSRCDIR)/configure: $(TOPSRCDIR)/configure.in $(EXTRA_CONFIG_DEPS)
|
||||
@echo Generating $@ using autoconf
|
||||
cd $(TOPSRCDIR); $(AUTOCONF)
|
||||
endif
|
||||
|
||||
CONFIG_STATUS_DEPS_L10N := $(wildcard $(TOPSRCDIR)/l10n/makefiles.all)
|
||||
|
||||
CONFIG_STATUS_DEPS := \
|
||||
$(TOPSRCDIR)/configure \
|
||||
$(TOPSRCDIR)/allmakefiles.sh \
|
||||
$(TOPSRCDIR)/.mozconfig.mk \
|
||||
$(wildcard $(TOPSRCDIR)/nsprpub/configure) \
|
||||
$(wildcard $(TOPSRCDIR)/directory/c-sdk/configure) \
|
||||
$(wildcard $(TOPSRCDIR)/mailnews/makefiles) \
|
||||
$(CONFIG_STATUS_DEPS_L10N) \
|
||||
$(wildcard $(TOPSRCDIR)/themes/makefiles) \
|
||||
$(NULL)
|
||||
|
||||
# configure uses the program name to determine @srcdir@. Calling it without
|
||||
# $(TOPSRCDIR) will set @srcdir@ to "."; otherwise, it is set to the full
|
||||
# path of $(TOPSRCDIR).
|
||||
ifeq ($(TOPSRCDIR),$(OBJDIR))
|
||||
CONFIGURE := ./configure
|
||||
else
|
||||
CONFIGURE := $(TOPSRCDIR)/configure
|
||||
endif
|
||||
|
||||
ifdef _OBJ2SRCPATH
|
||||
CONFIGURE_ARGS := --srcdir=$(_OBJ2SRCPATH) $(CONFIGURE_ARGS)
|
||||
endif
|
||||
|
||||
$(OBJDIR)/Makefile $(OBJDIR)/config.status: $(CONFIG_STATUS_DEPS)
|
||||
@if test ! -d $(OBJDIR); then $(MKDIR) $(OBJDIR); else true; fi
|
||||
@echo cd $(OBJDIR);
|
||||
@echo $(CONFIGURE) $(CONFIGURE_ARGS)
|
||||
@cd $(OBJDIR) && $(CONFIGURE_ENV_ARGS) $(CONFIGURE) $(CONFIGURE_ARGS) \
|
||||
|| ( echo "*** Fix above errors and then restart with\
|
||||
\"$(MAKE) -f client.mk build\"" && exit 1 )
|
||||
@touch $(OBJDIR)/Makefile
|
||||
|
||||
ifdef CONFIG_STATUS
|
||||
$(OBJDIR)/config/autoconf.mk: $(TOPSRCDIR)/config/autoconf.mk.in
|
||||
cd $(OBJDIR); \
|
||||
CONFIG_FILES=config/autoconf.mk ./config.status
|
||||
endif
|
||||
|
||||
|
||||
####################################
|
||||
# Depend
|
||||
|
||||
depend:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
|
||||
$(MOZ_MAKE) export && $(MOZ_MAKE) depend
|
||||
|
||||
####################################
|
||||
# Build it
|
||||
|
||||
build:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
|
||||
$(MOZ_MAKE)
|
||||
|
||||
####################################
|
||||
# Other targets
|
||||
|
||||
# Pass these target onto the real build system
|
||||
install export libs clean realclean distclean alldep:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
|
||||
$(MOZ_MAKE) $@
|
||||
|
||||
cleansrcdir:
|
||||
@cd $(TOPSRCDIR); \
|
||||
if [ -f webshell/embed/gtk/Makefile ]; then \
|
||||
$(MAKE) -C webshell/embed/gtk distclean; \
|
||||
fi; \
|
||||
if [ -f Makefile ]; then \
|
||||
$(MAKE) distclean ; \
|
||||
else \
|
||||
echo "Removing object files from srcdir..."; \
|
||||
rm -fr `find . -type d \( -name .deps -print -o -name CVS \
|
||||
-o -exec test ! -d {}/CVS \; \) -prune \
|
||||
-o \( -name '*.[ao]' -o -name '*.so' \) -type f -print`; \
|
||||
build/autoconf/clean-config.sh; \
|
||||
fi;
|
||||
|
||||
# (! IS_FIRST_CHECKOUT)
|
||||
endif
|
||||
|
||||
.PHONY: checkout real_checkout depend build export libs alldep install clean realclean distclean cleansrcdir pull_all build_all clobber clobber_all pull_and_build_all everything
|
||||
208
mozilla/directory/buildjsdk.txt
Normal file
208
mozilla/directory/buildjsdk.txt
Normal file
@@ -0,0 +1,208 @@
|
||||
======================================================================
|
||||
NETSCAPE DIRECTORY SDK FOR JAVA:
|
||||
BUILD INSTRUCTIONS
|
||||
Last updated: August 2, 1999
|
||||
======================================================================
|
||||
For information on the Netscape Directory SDK source release,
|
||||
see http://www.mozilla.org/directory/
|
||||
|
||||
Note the following:
|
||||
- The LDAP filter classes (in the netscape.ldap.util package)
|
||||
use the OROMatcher(tm) regular expression package (from ORO Java Software).
|
||||
This is not provided with the source code release. If you want this
|
||||
package, you need to get it from ORO, Inc. (For details, see the
|
||||
ORO, Inc. home page at http://www.oroinc.com/.)
|
||||
|
||||
|
||||
Unix/Linux Build Instructions
|
||||
-----------------------------
|
||||
|
||||
System Requirements:
|
||||
32MB of RAM, 128MB of swap, recommended 64MB of RAM.
|
||||
|
||||
Tool Requirements:
|
||||
Sun Microsystems Java Development Kit (JDK) 1.1.7
|
||||
(or a more recent version)
|
||||
GNU make 3.74 or a more recent version
|
||||
|
||||
Instructions:
|
||||
1. Uncompress and extract the source files by entering the
|
||||
following command (or your preferred variant of this command):
|
||||
|
||||
gzip -dc <filename>.tar.gz | tar -xvf -
|
||||
|
||||
2. Set and unset the following environment variables.
|
||||
|
||||
In csh/tcsh:
|
||||
setenv JAVA_HOME "<directory where the JDK is installed>"
|
||||
For example:
|
||||
setenv JAVA_HOME "/usr/local/jdk1.1.7"
|
||||
setenv CLASSPATH "<location of the JDK classes.zip file>"
|
||||
For example:
|
||||
setenv CLASSPATH "/usr/local/jdk1.1.7/lib/classes.zip"
|
||||
|
||||
In sh/bash/ksh:
|
||||
JAVA_HOME="<directory where the JDK is installed>"
|
||||
CLASSPATH="<location of the JDK classes.zip file>"
|
||||
export JAVA_HOME CLASSPATH
|
||||
|
||||
3. Build the LDAP Java classes by entering the following commands:
|
||||
|
||||
cd mozilla/directory/java-sdk
|
||||
gmake -f ldap.mk
|
||||
|
||||
If you also want the classes packaged in a JAR file,
|
||||
specify "basepackage" as the target:
|
||||
|
||||
gmake -f ldap.mk basepackage
|
||||
|
||||
To generate javadoc specify "doc" as the target:
|
||||
|
||||
gmake -f ldap.mk doc
|
||||
|
||||
Note that if you are using JDK1.1, javadoc images will be missing
|
||||
and you'll need to copy those images from somewhere else into
|
||||
mozilla/directory/java-sdk/dist/doc/images. If you are using JDK1.2
|
||||
you do not need to do that.
|
||||
|
||||
The SDK will be built and copied into the following directories:
|
||||
mozilla/directory/java-sdk/dist/classes - class files and manifest file
|
||||
mozilla/directory/java-sdk/dist/packages - ldapjdk.jar JAR file
|
||||
(if you've specified "basepackage" as the target)
|
||||
mozilla/directory/java-sdk/dist/doc - ldapjdk javadoc
|
||||
(if you've specified "doc" as the target)
|
||||
|
||||
4. Build the JNDI LDAP Service Provider classes by entering the following commands:
|
||||
|
||||
gmake -f ldapsp.mk
|
||||
|
||||
If you also want the classes packaged in a JAR file,
|
||||
specify "basepackage" as the target:
|
||||
|
||||
gmake -f ldapsp.mk basepackage
|
||||
|
||||
To generate javadoc specify "doc" as the target:
|
||||
|
||||
gmake -f ldapsp.mk doc
|
||||
|
||||
The SDK will be built and copied into the following directories:
|
||||
mozilla/directory/java-sdk/dist/classes - class files
|
||||
mozilla/directory/java-sdk/dist/packages - ldapsp.jar JAR file
|
||||
(if you've specified "basepackage" as the target)
|
||||
mozilla/directory/java-sdk/dist/doc/ldapsp - ldapsp controls' javadoc
|
||||
(if you've specified "doc" as the target)
|
||||
|
||||
The JNDI LDAP Service Provider depends on the LDAP Java classes, so you
|
||||
always must build the LDAP Java first. For more information on JNDI see
|
||||
ldapsp/Readme.html and http://java.sun.com/products/jndi/index.html
|
||||
|
||||
|
||||
Windows Build Instructions
|
||||
--------------------------
|
||||
|
||||
System Requirements:
|
||||
Windows NT 3.51 or 4.0 (4.0 preferred).
|
||||
|
||||
Tool Requirements:
|
||||
Sun Microsystems Java Development Kit (JDK) 1.1.7
|
||||
(or a more recent version)
|
||||
GNU Tools for Windows (you can find these on the Internet).
|
||||
Specifically, you'll need:
|
||||
cp.exe
|
||||
rm.exe
|
||||
Here are some sample download sites to find these:
|
||||
Cygnus (http://www.cygnus.com/misc/gnu-win32)
|
||||
GNU (http://www.gnu.org/order/ftp.html)
|
||||
MIT (ftp://prep.ai.mit.edu/pub/gnu)
|
||||
Netscape uses internally modified versions of the following tools:
|
||||
gmake.exe
|
||||
shmsdos.exe
|
||||
uname.exe
|
||||
You can download them from http://www.mozilla.org/download-mozilla.html
|
||||
(click the Windows Build Tools link). When you unzip the file, the
|
||||
tools will be located in the windows\bin\x86 directory.
|
||||
|
||||
All of these tools need to be put in your path.
|
||||
|
||||
Extracting the Source Files:
|
||||
The source files for the Directory SDK are zipped in a file.
|
||||
When unzipping the file, make sure to specify that you want to
|
||||
preserve the directory structure. For example,
|
||||
make sure that "Use Folder Names" is checked.
|
||||
|
||||
Instructions:
|
||||
NOTE: Make sure to run the commands from a standard Windows NT
|
||||
command prompt. Although you may be able to use other shells
|
||||
to build the SDK, you may need to adjust the makefiles for
|
||||
the shell that you are using.
|
||||
1. Set the following environment variables (within the command session,
|
||||
either manually or via a script), or within the system environment
|
||||
through the Control Panel | System control panel):
|
||||
|
||||
set MOZ_SRC=(top of your source tree, drive letter and path.
|
||||
For example, set MOZ_SRC=d:\mozilla_src, if the mozilla
|
||||
directory is at d:\mozilla_src\mozilla.)
|
||||
set JAVA_HOME=(directory where the JDK is installed)
|
||||
For example:
|
||||
set JAVA_HOME=D:\jdk1.1.7
|
||||
set CLASSPATH=(location of the JDK classes.zip file)
|
||||
For example:
|
||||
set CLASSPATH=D:\jdk1.1.7\lib\classes.zip
|
||||
|
||||
In addition, make sure to set your PATH environment variable to
|
||||
include the tools that you have downloaded.
|
||||
|
||||
2. Enter the following commands to build the LDAP Java classes:
|
||||
cd mozilla\directory\java-sdk
|
||||
gmake -f ldap.mk
|
||||
|
||||
If you also want the classes packaged in a JAR file,
|
||||
specify "basepackage" as the target:
|
||||
|
||||
gmake -f ldap.mk basepackage
|
||||
|
||||
To generate javadoc specify "doc" as the target:
|
||||
|
||||
gmake -f ldap.mk doc
|
||||
|
||||
Note that if you are using JDK1.1, javadoc images will be missing
|
||||
and you'll need to copy those images from somewhere else into
|
||||
mozilla\directory\java-sdk\dist\doc\images. If you are using JDK1.2
|
||||
you do not need to do that.
|
||||
|
||||
The SDK will be built and copied into the following directories:
|
||||
mozilla\directory\java-sdk\dist\classes - class files and manifest file
|
||||
mozilla\directory\java-sdk\dist\packages - ldapjdk.jar JAR file
|
||||
(if you've specified "basepackage" as the target)
|
||||
mozilla\directory\java-sdk\dist\doc - ldapjdk javadoc
|
||||
(if you've specified "doc" as the target)
|
||||
|
||||
|
||||
3. Build the JNDI LDAP Service Provider classes by entering the following commands:
|
||||
|
||||
gmake -f ldapsp.mk
|
||||
|
||||
If you also want the classes packaged in a JAR file,
|
||||
specify "basepackage" as the target:
|
||||
|
||||
gmake -f ldapsp.mk basepackage
|
||||
|
||||
To generate javadoc specify "doc" as the target:
|
||||
|
||||
gmake -f ldapsp.mk doc
|
||||
|
||||
The SDK will be built and copied into the following directories:
|
||||
mozilla/directory/java-sdk/dist/classes - class files
|
||||
mozilla/directory/java-sdk/dist/packages - ldapsp.jar JAR file
|
||||
(if you've specified "basepackage" as the target)
|
||||
mozilla\directory\java-sdk\dist\doc\ldapsp - ldapsp controls' javadoc
|
||||
(if you've specified "doc" as the target)
|
||||
|
||||
The JNDI LDAP Service Provider depends on the LDAP Java classes, so you
|
||||
always must build the LDAP Java first. For more information on JNDI see
|
||||
ldapsp/Readme.html and http://java.sun.com/products/jndi/index.html
|
||||
|
||||
--------------------------------------------------------
|
||||
Copyright (c) 1999 Netscape Communications Corporation.
|
||||
(http://home.netscape.com/misc/contact_info.html)
|
||||
|
||||
238
mozilla/directory/java-sdk/ldap.mk
Normal file
238
mozilla/directory/java-sdk/ldap.mk
Normal file
@@ -0,0 +1,238 @@
|
||||
# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
# Makefile for the LDAP classes
|
||||
#
|
||||
# An optimized compile is done by default. You can specify "DEBUG=1" on
|
||||
# the make line to generate debug symbols in the bytecode.
|
||||
#
|
||||
# The package includes com.netscape.sasl (until there is another
|
||||
# home for it)
|
||||
#
|
||||
# You can compile only subsets of the classes by specifying one of the
|
||||
# following:
|
||||
# doc
|
||||
# classes
|
||||
# LDAPCLASSES
|
||||
# MAIN
|
||||
# CLIENT
|
||||
# OPERS
|
||||
# UTIL
|
||||
# BER
|
||||
# BEANS
|
||||
# SASL
|
||||
# TOOLS
|
||||
# FILTER
|
||||
#
|
||||
# Create the JAR files with the following targets:
|
||||
# package
|
||||
# basepackage
|
||||
# filterpackage
|
||||
# beanpackage
|
||||
# docpackage
|
||||
#
|
||||
# The usual mozilla environment variable must be defined:
|
||||
# MOZ_SRC (the root of your CVS tree)
|
||||
#
|
||||
# And the Java root directory
|
||||
# JAVA_HOME
|
||||
#
|
||||
ARCH := $(shell uname -s)
|
||||
|
||||
MCOM_ROOT=.
|
||||
ifeq ($(ARCH), WINNT)
|
||||
MOZ_DIR:=$(subst \,/,$(MOZ_SRC))
|
||||
BASEDIR:=$(MOZ_DIR)/mozilla/directory/java-sdk
|
||||
else
|
||||
ifeq ($(ARCH), WIN95)
|
||||
MOZ_DIR:=$(subst \,/,$(MOZ_SRC))
|
||||
BASEDIR:=$(MOZ_DIR)/mozilla/directory/java-sdk
|
||||
else
|
||||
BASEDIR := $(shell cd $(MCOM_ROOT); pwd)
|
||||
endif
|
||||
endif
|
||||
# Destination for class files and packages
|
||||
CLASS_DEST=$(BASEDIR)/dist/classes
|
||||
FILTER_CLASS_DEST=$(BASEDIR)/dist/ldapfilt
|
||||
|
||||
# Set up the CLASSPATH automatically,
|
||||
ifeq ($(ARCH), WINNT)
|
||||
JDK := $(subst \,/,$(JAVA_HOME))
|
||||
JAR:=$(JDK)/bin/jar
|
||||
SEP=;
|
||||
else
|
||||
ifeq ($(ARCH), WIN95)
|
||||
JDK := $(subst \,/,$(JAVA_HOME))
|
||||
JAR:=$(JDK)/bin/jar
|
||||
SEP=;
|
||||
else
|
||||
JDK := $(JAVA_HOME)
|
||||
JAR:=$(JAVA_HOME)/bin/jar
|
||||
SEP=:
|
||||
endif
|
||||
endif
|
||||
JAASLIB=$(BASEDIR)/ldapjdk/lib/jaas.jar
|
||||
JAVACLASSPATH:=$(BASEDIR)/ldapjdk$(SEP)$(JAASLIB)$(SEP)$(BASEDIR)/ldapbeans$(SEP)$(JDK)/lib/classes.zip$(SEP)$(CLASSPATH)
|
||||
|
||||
SRCDIR=netscape/ldap
|
||||
BEANDIR=$(BASEDIR)/ldapbeans/netscape/ldap/beans
|
||||
DISTDIR=$(MCOM_ROOT)/dist
|
||||
CLASSDIR=$(MCOM_ROOT)/dist/classes
|
||||
FILTERCLASSDIR=$(MCOM_ROOT)/dist/ldapfilt
|
||||
CLASSPACKAGEDIR=$(DISTDIR)/packages
|
||||
PACKAGENAME=javaldap.zip
|
||||
ifeq ($(DEBUG), 1)
|
||||
BASEPACKAGENAME=ldapjdk_debug.jar
|
||||
else
|
||||
BASEPACKAGENAME=ldapjdk.jar
|
||||
endif
|
||||
FILTERJAR=ldapfilt.jar
|
||||
CLASSPACKAGE=$(CLASSPACKAGEDIR)/$(PACKAGENAME)
|
||||
BEANPACKAGENAME=ldapbeans.jar
|
||||
TOOLSTARGETDIR=$(DISTDIR)/tools
|
||||
TOOLSDIR=$(BASEDIR)/tools
|
||||
DOCDIR=$(DISTDIR)/doc
|
||||
BERDOCPACKAGEDIR=$(DISTDIR)/doc/ber
|
||||
DOCNAME=ldapdoc.zip
|
||||
DOCPACKAGE=$(CLASSPACKAGEDIR)/$(DOCNAME)
|
||||
EXAMPLEDIR=$(DISTDIR)/examples
|
||||
#TESTSRCDIR=$(BASEDIR)/netsite/ldap/java/netscape/ldap/tests
|
||||
ERRORSDIR=$(CLASSDIR)/netscape/ldap/errors
|
||||
SASLDIR=com/netscape/sasl
|
||||
SASLMECHANISMDIR=com/netscape/sasl/mechanisms
|
||||
|
||||
ifndef JAVADOC
|
||||
JAVADOC=$(JDKBIN)javadoc -classpath "$(JAVACLASSPATH)"
|
||||
endif
|
||||
ifndef JAVAC
|
||||
ifdef JAVA_HOME
|
||||
JDKBIN=$(JDK)/bin/
|
||||
endif
|
||||
ifeq ($(DEBUG), 1)
|
||||
JAVAC=$(JDKBIN)javac -g -classpath "$(JAVACLASSPATH)"
|
||||
else
|
||||
JAVAC=$(JDKBIN)javac -O -classpath "$(JAVACLASSPATH)"
|
||||
endif
|
||||
endif
|
||||
|
||||
BERDOCCLASSES=netscape.ldap.ber.stream
|
||||
|
||||
DOCCLASSES=netscape.ldap netscape.ldap.beans netscape.ldap.controls \
|
||||
netscape.ldap.util $(TOOLSDIR)/*.java $(BERDOCCLASSES)
|
||||
|
||||
all: classes
|
||||
|
||||
basics: $(DISTDIR) $(CLASSDIR)
|
||||
cp -p manifest.mf $(CLASS_DEST)
|
||||
|
||||
classes: LDAPCLASSES BEANS TOOLS
|
||||
|
||||
doc: $(DISTDIR) $(DOCDIR) DOCS
|
||||
|
||||
berdoc: $(DISTDIR) $(BERDOCPACKAGEDIR) BERDOCS
|
||||
|
||||
examples: $(DISTDIR) $(EXAMPLEDIR)/java $(EXAMPLEDIR)/js $(EXAMPLEDIR)/java/beans EXAMPLES
|
||||
|
||||
tests: $(CLASSDIR)
|
||||
cd $(TESTSRCDIR); $(JAVAC) -d $(CLASS_DEST) *.java
|
||||
|
||||
package: basepackage filterpackage beanpackage docpackage
|
||||
|
||||
basepackage: $(CLASSPACKAGEDIR)
|
||||
cd $(DISTDIR)/classes; rm -f ../packages/$(BASEPACKAGENAME); $(JAR) cvfm ../packages/$(BASEPACKAGENAME) manifest.mf netscape/ldap/*.class netscape/ldap/client/*.class netscape/ldap/client/opers/*.class netscape/ldap/ber/stream/*.class netscape/ldap/controls/*.class netscape/ldap/util/*.class netscape/ldap/errors/*.props com/netscape/sasl/*.class com/netscape/sasl/mechanisms/*.class tools/*.class
|
||||
|
||||
beanpackage: $(CLASSPACKAGEDIR)
|
||||
cd $(DISTDIR)/classes; rm -f ../packages/$(BEANPACKAGENAME); $(JAR) cvf ../packages/$(BEANPACKAGENAME) netscape/ldap/beans
|
||||
|
||||
docpackage: $(DOCDIR) $(CLASSPACKAGEDIR)
|
||||
cd $(DOCDIR); rm -f ../packages/$(DOCNAME); $(JAR) cvf ../packages/$(DOCNAME) *.html *.css netscape/ldap/*.html netscape/ldap/beans/*.html netscape/ldap/controls/*.html netscape/ldap/util/*.html netscape/ldap/ber/stream/*.html
|
||||
|
||||
MAIN: basics
|
||||
cd ldapjdk/$(SRCDIR); $(JAVAC) -d "$(CLASS_DEST)" *.java
|
||||
|
||||
CLIENT: basics
|
||||
cd ldapjdk/$(SRCDIR)/client; $(JAVAC) -d "$(CLASS_DEST)" *.java
|
||||
|
||||
OPERS: basics
|
||||
cd ldapjdk/$(SRCDIR)/client/opers; $(JAVAC) -d "$(CLASS_DEST)" *.java
|
||||
|
||||
BER: basics
|
||||
cd ldapjdk/$(SRCDIR)/ber/stream; $(JAVAC) -d "$(CLASS_DEST)" *.java
|
||||
|
||||
UTIL: basics
|
||||
cd ldapjdk/$(SRCDIR)/util; $(JAVAC) -d "$(CLASS_DEST)" *.java
|
||||
|
||||
SASLMECHANISM: basics
|
||||
cd ldapjdk/$(SASLMECHANISMDIR); $(JAVAC) -d "$(CLASS_DEST)" *.java
|
||||
|
||||
SASL: basics
|
||||
cd ldapjdk/$(SASLDIR); $(JAVAC) -d "$(CLASS_DEST)" *.java
|
||||
|
||||
ERRORS: basics $(ERRORSDIR)
|
||||
cp -p ldapjdk/$(SRCDIR)/errors/*.props $(ERRORSDIR)
|
||||
|
||||
CONTROLS: basics
|
||||
cd ldapjdk/$(SRCDIR)/controls; $(JAVAC) -d "$(CLASS_DEST)" *.java
|
||||
|
||||
LDAPCLASSES: BER OPERS CLIENT MAIN UTIL CONTROLS ERRORS SASL SASLMECHANISM
|
||||
|
||||
BEANS: OTHERBEANS
|
||||
|
||||
OTHERBEANS: basics
|
||||
cd ldapbeans/$(SRCDIR)/beans; $(JAVAC) -d "$(CLASS_DEST)" *.java
|
||||
|
||||
TOOLS: basics
|
||||
cd tools; $(JAVAC) -d "$(CLASS_DEST)" *.java
|
||||
|
||||
FILTER: $(FILTERCLASSDIR)
|
||||
cd ldapfilter/netscape/ldap/util; $(JAVAC) -d "$(FILTER_CLASS_DEST)" *.java
|
||||
|
||||
filterpackage: $(CLASSPACKAGEDIR)
|
||||
cd "$(FILTER_CLASS_DEST)"; rm -f ../packages/$(FILTERJAR); $(JAR) cvf ../packages/$(FILTERJAR) netscape/ldap/util/*.class
|
||||
|
||||
DOCS:
|
||||
$(JAVADOC) -d $(DOCDIR) $(DOCCLASSES)
|
||||
|
||||
BERDOCS:
|
||||
$(JAVADOC) -d $(BERDOCPACKAGEDIR) $(BERDOCCLASSES)
|
||||
|
||||
EXAMPLES:
|
||||
-cp -p $(EXAMPLESRCDIR)/java/* $(EXAMPLEDIR)/java
|
||||
-cp -p $(EXAMPLESRCDIR)/java/beans/* $(EXAMPLEDIR)/java/beans
|
||||
-cp -p $(EXAMPLESRCDIR)/java/beans/makejars.* $(CLASSDIR)
|
||||
-cp -p $(EXAMPLESRCDIR)/js/* $(EXAMPLEDIR)/js
|
||||
|
||||
clean:
|
||||
rm -rf $(DISTDIR)
|
||||
|
||||
$(CLASSPACKAGEDIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(DOCDIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(DISTDIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(CLASSDIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(ERRORSDIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(FILTERCLASSDIR):
|
||||
mkdir -p $@
|
||||
@@ -0,0 +1,67 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.beans;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.beans.*;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class DisplayString extends TextArea implements Serializable {
|
||||
|
||||
public DisplayString() {
|
||||
super();
|
||||
setEditable(false);
|
||||
}
|
||||
|
||||
public void reportChange(PropertyChangeEvent evt) {
|
||||
Object obj = (Object)evt.getNewValue();
|
||||
if (obj == null) {
|
||||
append("null\n");
|
||||
return;
|
||||
}
|
||||
|
||||
String[] values = null;
|
||||
if (obj instanceof String) {
|
||||
values = new String[1];
|
||||
values[0] = (String)obj;
|
||||
}
|
||||
else
|
||||
values = (String[])obj;
|
||||
|
||||
int width = getSize().width - 10;
|
||||
Font f = getFont();
|
||||
for (int i=0; i<values.length; i++) {
|
||||
String text = values[i];
|
||||
if (f != null) {
|
||||
// Trim the text to fit.
|
||||
FontMetrics fm = getFontMetrics(f);
|
||||
while (fm.stringWidth(text) > width) {
|
||||
text = text.substring(0, text.length()-1);
|
||||
}
|
||||
}
|
||||
append(text+'\n');
|
||||
}
|
||||
}
|
||||
|
||||
public void clear (ActionEvent e) {
|
||||
setText("");
|
||||
invalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
Name: netscape/ldap/beans/DisplayString.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: netscape/ldap/beans/DisplayStringBeanInfo.class
|
||||
@@ -0,0 +1,63 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.beans;
|
||||
|
||||
import java.beans.SimpleBeanInfo;
|
||||
import java.beans.BeanDescriptor;
|
||||
import java.beans.EventSetDescriptor;
|
||||
import java.beans.MethodDescriptor;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.beans.ParameterDescriptor;
|
||||
import java.beans.BeanInfo;
|
||||
|
||||
/**
|
||||
* BeanInfo for displaying string
|
||||
*
|
||||
*/
|
||||
|
||||
public class DisplayStringBeanInfo extends SimpleBeanInfo {
|
||||
|
||||
public DisplayStringBeanInfo() throws Exception {
|
||||
|
||||
beanClass = Class.forName( "netscape.ldap.beans.DisplayString" );
|
||||
|
||||
// Publish descriptor ---------------------------------------------
|
||||
try {
|
||||
_beanDescriptor = new BeanDescriptor(beanClass);
|
||||
_beanDescriptor.setDisplayName( "Text Field" );
|
||||
_beanDescriptor.setShortDescription(
|
||||
"LDAP property retrieval -"
|
||||
+ " provided a host, port, base, search filter,"
|
||||
+ " and optionally a username and password,"
|
||||
+ " return an array of string values both as a"
|
||||
+ " function return and as a Property change event." );
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
public BeanDescriptor getBeanDescriptor() {
|
||||
return _beanDescriptor;
|
||||
}
|
||||
|
||||
private static Class beanClass;
|
||||
private BeanDescriptor _beanDescriptor;
|
||||
private EventSetDescriptor[] _eventSetDescriptor;
|
||||
private PropertyDescriptor[] _propertyDescriptor;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,391 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.beans;
|
||||
|
||||
import netscape.ldap.*;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
// This class has a bound property
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* This is a base class that is extended by various specialized LDAP
|
||||
* Beans. It provides the common properties and accessors used by
|
||||
* them.
|
||||
*/
|
||||
|
||||
public class LDAPBasePropertySupport implements Serializable {
|
||||
|
||||
/**
|
||||
* Constructor with no parameters
|
||||
*/
|
||||
public LDAPBasePropertySupport() {}
|
||||
|
||||
/**
|
||||
* Returns the host to search at.
|
||||
* @return DNS name or dotted IP name of host to search at
|
||||
*/
|
||||
public String getHost() {
|
||||
return _host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets host string.
|
||||
* @param theHost host name
|
||||
*/
|
||||
public void setHost( String theHost ) {
|
||||
_host = theHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the port to search at.
|
||||
* @return Port to search at
|
||||
*/
|
||||
public int getPort() {
|
||||
return _port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets port number.
|
||||
* @param thePort port
|
||||
*/
|
||||
public void setPort( int thePort ) {
|
||||
_port = thePort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the directory base to search at.
|
||||
* @return directory base to search
|
||||
*/
|
||||
public String getBase() {
|
||||
return _base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the starting base
|
||||
* @param theBase starting base
|
||||
*/
|
||||
public void setBase( String theBase ) {
|
||||
_base = theBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DN to authenticate as; null or empty for anonymous.
|
||||
* @return DN to authenticate as
|
||||
*/
|
||||
public String getAuthDN() {
|
||||
return _authDN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the DN to authenticate as; null or empty for anonymous.
|
||||
* @param authDN the DN to authenticate as
|
||||
*/
|
||||
public void setAuthDN( String authDN ) {
|
||||
this._authDN = authDN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the password for the DN to authenticate as
|
||||
* @return Password of DN to authenticate as
|
||||
*/
|
||||
public String getAuthPassword() {
|
||||
return _authPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the password for the DN to authenticate as
|
||||
* @param authPassword the password to use in authentication
|
||||
*/
|
||||
public void setAuthPassword( String authPassword ) {
|
||||
this._authPassword = authPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user name
|
||||
* @return The user name
|
||||
*/
|
||||
public String getUserName() {
|
||||
return _userName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user name. The name should be of the form "Polly Plum".
|
||||
* @param name The user name
|
||||
*/
|
||||
public void setUserName( String name ) {
|
||||
_userName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user ID.
|
||||
* @return name the user id
|
||||
*/
|
||||
public String getUserID() {
|
||||
return _userID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user ID.
|
||||
* @param name the value of the user id
|
||||
*/
|
||||
public void setUserID( String name ) {
|
||||
_userID = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current search scope
|
||||
* @return the current search scope as integer
|
||||
*/
|
||||
public int getScope() {
|
||||
return _scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the search scope using an integer
|
||||
* @param scope one of LDAPConnection.SCOPE_BASE,
|
||||
* LDAPConnection.SCOPE_SUB, LDAPConnection.SCOPE_ONE
|
||||
*/
|
||||
public void setScope( int scope ) {
|
||||
_scope = scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the search filter
|
||||
* @return search filter
|
||||
*/
|
||||
public String getFilter() {
|
||||
return _filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the search filter
|
||||
* @param filter search filter
|
||||
*/
|
||||
public void setFilter( String filter ) {
|
||||
_filter = filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if debug output is on
|
||||
* @return true if debug output is on
|
||||
*/
|
||||
public boolean getDebug() {
|
||||
return _debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns debug output on or off
|
||||
* @param on true for debug output
|
||||
*/
|
||||
public void setDebug( boolean on ) {
|
||||
_debug = on;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the latest error code
|
||||
* @return The latest error code
|
||||
*/
|
||||
public int getErrorCode() {
|
||||
return _errCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an error code for retrieval by a client
|
||||
* @param code An error code
|
||||
*/
|
||||
public void setErrorCode( int code ) {
|
||||
_errCode = code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a client to be notified when an authentication result is in
|
||||
* @param listener a client to be notified of changes
|
||||
*/
|
||||
public void addPropertyChangeListener( PropertyChangeListener listener ) {
|
||||
printDebug( "Adding listener " + listener );
|
||||
m_propSupport.addPropertyChangeListener( listener );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a client which had requested notification on authentication
|
||||
* @param listener a client to not be notified of changes
|
||||
*/
|
||||
public void removePropertyChangeListener(
|
||||
PropertyChangeListener listener ) {
|
||||
m_propSupport.removePropertyChangeListener( listener );
|
||||
}
|
||||
|
||||
/**
|
||||
* Support for bound property notification
|
||||
* @param propName Name of changed property
|
||||
* @param oldValue Previous value of property
|
||||
* @param newValue New value of property
|
||||
*/
|
||||
public void firePropertyChange(
|
||||
String propName,
|
||||
Object oldValue,
|
||||
Object newValue ) {
|
||||
|
||||
if (m_propSupport == null)
|
||||
m_propSupport = new PropertyChangeSupport( this );
|
||||
|
||||
m_propSupport.firePropertyChange( propName, oldValue, newValue );
|
||||
}
|
||||
|
||||
protected void printDebug( String s ) {
|
||||
if ( _debug )
|
||||
System.out.println( s );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up basic connection privileges for Communicator if necessary,
|
||||
* and connects
|
||||
* @param host Host to connect to.
|
||||
* @param port Port number.
|
||||
* @exception LDAPException from connect()
|
||||
*/
|
||||
protected void connect( LDAPConnection conn, String host, int port )
|
||||
throws LDAPException {
|
||||
boolean needsPrivileges = true;
|
||||
/* Running standalone? */
|
||||
SecurityManager sec = System.getSecurityManager();
|
||||
printDebug( "Security manager = " + sec );
|
||||
if ( sec == null ) {
|
||||
printDebug( "No security manager" );
|
||||
/* Not an applet, we can do what we want to */
|
||||
needsPrivileges = false;
|
||||
/* Can't do instanceof on an abstract class */
|
||||
} else if ( sec.toString().startsWith("java.lang.NullSecurityManager") ) {
|
||||
printDebug( "No security manager" );
|
||||
/* Not an applet, we can do what we want to */
|
||||
needsPrivileges = false;
|
||||
} else if ( sec.toString().startsWith(
|
||||
"netscape.security.AppletSecurity" ) ) {
|
||||
|
||||
/* Connecting to the local host? */
|
||||
try {
|
||||
if ( host.equalsIgnoreCase(
|
||||
java.net.InetAddress.getLocalHost().getHostName() ) )
|
||||
needsPrivileges = false;
|
||||
} catch ( java.net.UnknownHostException e ) {
|
||||
}
|
||||
}
|
||||
|
||||
if ( needsPrivileges ) {
|
||||
/* Running as applet. Is PrivilegeManager around? */
|
||||
String mgr = "netscape.security.PrivilegeManager";
|
||||
try {
|
||||
Class c = Class.forName( mgr );
|
||||
java.lang.reflect.Method[] m = c.getMethods();
|
||||
if ( m != null ) {
|
||||
for( int i = 0; i < m.length; i++ ) {
|
||||
if ( m[i].getName().equals( "enablePrivilege" ) ) {
|
||||
try {
|
||||
Object[] args = new Object[1];
|
||||
args[0] = new String( "UniversalConnect" );
|
||||
m[i].invoke( null, args );
|
||||
printDebug( "UniversalConnect enabled" );
|
||||
args[0] = new String( "UniversalPropertyRead" );
|
||||
m[i].invoke( null, args );
|
||||
printDebug( "UniversalPropertyRead enabled" );
|
||||
} catch ( Exception e ) {
|
||||
printDebug( "Exception on invoking " +
|
||||
"enablePrivilege: " +
|
||||
e.toString() );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch ( ClassNotFoundException e ) {
|
||||
printDebug( "no " + mgr );
|
||||
}
|
||||
}
|
||||
|
||||
conn.connect( host, port );
|
||||
setDefaultReferralCredentials( conn );
|
||||
}
|
||||
|
||||
protected void setDefaultReferralCredentials(
|
||||
LDAPConnection conn ) {
|
||||
final LDAPConnection m_conn = conn;
|
||||
LDAPRebind rebind = new LDAPRebind() {
|
||||
public LDAPRebindAuth getRebindAuthentication(
|
||||
String host,
|
||||
int port ) {
|
||||
return new LDAPRebindAuth(
|
||||
m_conn.getAuthenticationDN(),
|
||||
m_conn.getAuthenticationPassword() );
|
||||
}
|
||||
};
|
||||
try {
|
||||
conn.setOption(LDAPConnection.REFERRALS, Boolean.TRUE);
|
||||
conn.setOption(LDAPConnection.REFERRALS_REBIND_PROC, rebind);
|
||||
} catch (LDAPException e) {
|
||||
//will never happen
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to convert an array of Strings to a single String
|
||||
* with line feeds between elements.
|
||||
* @param aResult The array of Strings to convert
|
||||
* @return A String with the elements separated by line feeds
|
||||
*/
|
||||
public String convertToString( String[] aResult ) {
|
||||
String sResult = "";
|
||||
if ( null != aResult ) {
|
||||
for ( int i = 0; i < aResult.length; i++ ) {
|
||||
sResult += aResult[i] + "\n";
|
||||
}
|
||||
}
|
||||
return sResult;
|
||||
}
|
||||
|
||||
/*
|
||||
* Variables
|
||||
*/
|
||||
/* Error codes from search operations, etc */
|
||||
public static final int OK = 0;
|
||||
public static final int INVALID_PARAMETER = 1;
|
||||
public static final int CONNECT_ERROR = 2;
|
||||
public static final int AUTHENTICATION_ERROR = 3;
|
||||
public static final int PROPERTY_NOT_FOUND = 4;
|
||||
public static final int AMBIGUOUS_RESULTS = 5;
|
||||
public static final int NO_SUCH_OBJECT = 6;
|
||||
|
||||
private boolean _debug = false;
|
||||
private int _errCode = 0;
|
||||
private String _host = new String("localhost");
|
||||
private int _port = 389;
|
||||
private int _scope = LDAPConnection.SCOPE_SUB;
|
||||
private String _base = new String("");
|
||||
private String _filter = new String("");
|
||||
private String _authDN = new String("");
|
||||
private String _authPassword = new String("");
|
||||
private String _userName = new String("");
|
||||
private String _userID = new String("");
|
||||
transient private PropertyChangeSupport m_propSupport =
|
||||
new PropertyChangeSupport( this );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,358 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.beans;
|
||||
|
||||
import netscape.ldap.*;
|
||||
import netscape.ldap.beans.LDAPBasePropertySupport;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
import java.io.Serializable;
|
||||
import java.awt.event.*;
|
||||
|
||||
|
||||
/**
|
||||
* Invisible Bean that just takes a host, port, directory base,
|
||||
* search string, and optional authentication name and password,
|
||||
* and returns a list of all matching DNs. The search has the scope
|
||||
* "SUB", which means that it will find an entry anywhere at or
|
||||
* below the directory base, unless a different scope is specified.
|
||||
* <BR><BR>
|
||||
* Optionally, a client can register as a PropertyChangeListener
|
||||
* and will be notified when the values are available.
|
||||
*<BR><BR>
|
||||
* A null result means no matching DNs were found. The reason is
|
||||
* available through getErrorCode(), which returns one of
|
||||
* the following:
|
||||
*<PRE>
|
||||
* OK
|
||||
* INVALID_PARAMETER
|
||||
* CONNECT_ERROR
|
||||
* AUTHENTICATION_ERROR
|
||||
* PROPERTY_NOT_FOUND
|
||||
* AMBIGUOUS_RESULTS
|
||||
*</PRE>
|
||||
*
|
||||
*/
|
||||
public class LDAPGetEntries extends LDAPBasePropertySupport implements Serializable {
|
||||
|
||||
/**
|
||||
* Constructor with no parameters
|
||||
*/
|
||||
public LDAPGetEntries() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with host, port, and base initializers
|
||||
* @param theHost host string
|
||||
* @param thePort port number
|
||||
* @param theBase directory base string
|
||||
*/
|
||||
public LDAPGetEntries( String theHost, int thePort, String theBase ) {
|
||||
setHost( theHost );
|
||||
setPort( thePort );
|
||||
setBase( theBase );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with host, port, base, and scope initializers
|
||||
* @param theHost host string
|
||||
* @param thePort port number
|
||||
* @param theBase directory base string
|
||||
* @param theScope one of LDAPConnection.SCOPE_BASE,
|
||||
* LDAPConnection.SCOPE_SUB, LDAPConnection.SCOPE_ONE
|
||||
*/
|
||||
public LDAPGetEntries( String theHost,
|
||||
int thePort,
|
||||
String theBase,
|
||||
int theScope ) {
|
||||
setHost( theHost );
|
||||
setPort( thePort );
|
||||
setBase( theBase );
|
||||
setScope( theScope );
|
||||
}
|
||||
|
||||
private void notifyResult( String error ) {
|
||||
firePropertyChange( "error", _errorMsg, error );
|
||||
_errorMsg = error;
|
||||
}
|
||||
|
||||
private void notifyResult( String[] newResult ) {
|
||||
String sNewResult = convertToString( newResult );
|
||||
firePropertyChange( "result", _result, newResult );
|
||||
_sResult = sNewResult;
|
||||
_result = newResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the attribute to retrieve
|
||||
* @return attribute name to retrieve
|
||||
*/
|
||||
public String getAttribute() {
|
||||
return _attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attribute to retrieve
|
||||
*/
|
||||
public void setAttribute( String attr ) {
|
||||
_attribute = attr;
|
||||
}
|
||||
|
||||
public void setResultString( String sNewValue ) {
|
||||
_sResult = sNewValue;
|
||||
}
|
||||
|
||||
public String getResultString() {
|
||||
return _sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches and returns values for a specified attribute
|
||||
* @param host host string
|
||||
* @param port port number
|
||||
* @param base directory base string
|
||||
* @param scope one of LDAPConnection.SCOPE_BASE,
|
||||
* LDAPConnection.SCOPE_SUB, LDAPConnection.SCOPE_ONE
|
||||
* @param filter search filter
|
||||
* @param attribute name of property to return values for
|
||||
* @return Array of values for the property
|
||||
*/
|
||||
public String[] getEntries( String host,
|
||||
int port,
|
||||
String base,
|
||||
int scope,
|
||||
String filter) {
|
||||
setHost( host );
|
||||
setPort( port );
|
||||
setBase( base );
|
||||
setScope( scope );
|
||||
setFilter( filter );
|
||||
return getEntries();
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches and returns values for a specified attribute
|
||||
* @param host host string
|
||||
* @param port port number
|
||||
* @param base directory base string
|
||||
* @param scope one of LDAPConnection.SCOPE_BASE,
|
||||
* LDAPConnection.SCOPE_SUB, LDAPConnection.SCOPE_ONE
|
||||
* @param userName The user name
|
||||
* @param userid The user id
|
||||
* @return Array of DNs
|
||||
*/
|
||||
public String[] getEntries( String host,
|
||||
int port,
|
||||
String base,
|
||||
int scope,
|
||||
String userid,
|
||||
String userName) {
|
||||
setHost( host );
|
||||
setPort( port );
|
||||
setBase( base );
|
||||
setScope( scope );
|
||||
if (userName == null)
|
||||
userName = new String("");
|
||||
setUserName( userName );
|
||||
if (userid == null)
|
||||
userid = new String("");
|
||||
setUserID( userid );
|
||||
return getEntries();
|
||||
}
|
||||
|
||||
// Added this method in order to get exposed in BDK
|
||||
public void getEntries(ActionEvent x) {
|
||||
getEntries();
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches and returns values of a previously registered property,
|
||||
* using previously set parameters
|
||||
* @return Array of values for the property
|
||||
*/
|
||||
public String[] getEntries() {
|
||||
boolean invalid = false;
|
||||
if ((getUserName().length() < 1) && (getUserID().length() < 1) &&
|
||||
(getFilter().length() < 1)) {
|
||||
printDebug("No user name or user ID");
|
||||
invalid = true;
|
||||
} else if ( (getHost().length() < 1) || (getBase().length() < 1) ) {
|
||||
printDebug( "Invalid host name or search base" );
|
||||
invalid = true;
|
||||
}
|
||||
if ( invalid ) {
|
||||
setErrorCode( INVALID_PARAMETER );
|
||||
notifyResult( (String)null);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (getFilter().length() < 1) {
|
||||
String filter = new String("");
|
||||
if ((getUserName().length() > 1) && (getUserID().length() > 1)) {
|
||||
filter = "(|(cn="+getUserName()+")(uid="+getUserID()+"))";
|
||||
} else if (getUserName().length() > 1) {
|
||||
filter = "cn="+getUserName();
|
||||
} else if (getUserID().length() > 1) {
|
||||
filter = "uid="+getUserID();
|
||||
}
|
||||
setFilter(filter);
|
||||
}
|
||||
|
||||
String[] res = null;
|
||||
LDAPConnection m_ldc = new LDAPConnection();
|
||||
try {
|
||||
try {
|
||||
printDebug("Connecting to " + getHost() +
|
||||
" " + getPort());
|
||||
connect( m_ldc, getHost(), getPort());
|
||||
} catch (Exception e) {
|
||||
printDebug( "Failed to connect to " + getHost() + ": " +
|
||||
e.toString() );
|
||||
setErrorCode( CONNECT_ERROR );
|
||||
notifyResult( (String)null );
|
||||
m_ldc = null;
|
||||
throw( new Exception() );
|
||||
}
|
||||
|
||||
// Authenticate?
|
||||
if ( (!getAuthDN().equals("")) &&
|
||||
(!getAuthPassword().equals("")) ) {
|
||||
|
||||
printDebug( "Authenticating " + getAuthDN() );
|
||||
try {
|
||||
m_ldc.authenticate( getAuthDN(), getAuthPassword() );
|
||||
} catch (Exception e) {
|
||||
printDebug( "Failed to authenticate: " + e.toString() );
|
||||
setErrorCode( AUTHENTICATION_ERROR );
|
||||
notifyResult( (String)null );
|
||||
throw( new Exception() );
|
||||
}
|
||||
}
|
||||
|
||||
// Search
|
||||
try {
|
||||
printDebug("Searching " + getBase() +
|
||||
" for " + getFilter() + ", scope = " + getScope());
|
||||
String[] attrs = { _attribute };
|
||||
LDAPSearchResults results = m_ldc.search( getBase(),
|
||||
getScope(),
|
||||
getFilter(),
|
||||
attrs,
|
||||
false);
|
||||
|
||||
// Create a vector for the results
|
||||
Vector v = new Vector();
|
||||
LDAPEntry entry = null;
|
||||
while ( results.hasMoreElements() ) {
|
||||
try {
|
||||
entry = results.next();
|
||||
} catch (LDAPException e) {
|
||||
if (getDebug())
|
||||
notifyResult(e.toString());
|
||||
continue;
|
||||
}
|
||||
// Add the DN to the list
|
||||
String value = "";
|
||||
if ( _attribute.equals("dn") ) {
|
||||
value = entry.getDN();
|
||||
} else {
|
||||
LDAPAttribute attr = entry.getAttribute( _attribute );
|
||||
if ( attr != null ) {
|
||||
Enumeration vals = attr.getStringValues();
|
||||
if ( (vals != null) && (vals.hasMoreElements()) ) {
|
||||
value = (String)vals.nextElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
v.addElement( value );
|
||||
printDebug( "... " + value );
|
||||
}
|
||||
// Pull out the DNs and create a string array
|
||||
if ( v.size() > 0 ) {
|
||||
res = new String[v.size()];
|
||||
v.copyInto( res );
|
||||
v.removeAllElements();
|
||||
setErrorCode( OK );
|
||||
} else {
|
||||
printDebug( "No entries found for " + getFilter() );
|
||||
setErrorCode( PROPERTY_NOT_FOUND );
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (getDebug()) {
|
||||
printDebug( "Failed to search for " + getFilter() + ": " +
|
||||
e.toString() );
|
||||
}
|
||||
setErrorCode( PROPERTY_NOT_FOUND );
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
// Disconnect
|
||||
try {
|
||||
if ( (m_ldc != null) && m_ldc.isConnected() )
|
||||
m_ldc.disconnect();
|
||||
} catch ( Exception e ) {
|
||||
}
|
||||
|
||||
// Notify any clients with a PropertyChangeEvent
|
||||
notifyResult( res );
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main body if we run it as application instead of applet.
|
||||
* @param args list of arguments
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
String[] scope = { "base", "one", "sub" };
|
||||
int scopeIndex = -1;
|
||||
for( int i = 0; (i < scope.length) && (args.length == 5); i++ ) {
|
||||
if ( args[3].equalsIgnoreCase(scope[i]) ) {
|
||||
scopeIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( scopeIndex < 0 ) {
|
||||
System.out.println( "Usage: LDAPGetEntries host port base" +
|
||||
" scope filter" );
|
||||
System.exit(1);
|
||||
}
|
||||
LDAPGetEntries app = new LDAPGetEntries();
|
||||
app.setHost( args[0] );
|
||||
app.setPort( java.lang.Integer.parseInt( args[1] ) );
|
||||
app.setBase( args[2] );
|
||||
app.setScope( scopeIndex );
|
||||
app.setFilter( args[4] );
|
||||
String[] response = app.getEntries();
|
||||
if ( response != null ) {
|
||||
for( int i = 0; i < response.length; i++ )
|
||||
System.out.println( "\t" + response[i] );
|
||||
}
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Variables
|
||||
*/
|
||||
private String _attribute = "dn";
|
||||
private String[] _result;
|
||||
private String _sResult = null;
|
||||
private String _errorMsg = null;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
Name: netscape/ldap/beans/LDAPGetEntries.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: netscape/ldap/beans/LDAPBasePropertySupport.class
|
||||
|
||||
Name: netscape/ldap/beans/LDAPGetEntriesBeanInfo.class
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.beans;
|
||||
|
||||
import java.beans.SimpleBeanInfo;
|
||||
import java.beans.BeanDescriptor;
|
||||
import java.beans.EventSetDescriptor;
|
||||
import java.beans.MethodDescriptor;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.beans.ParameterDescriptor;
|
||||
import java.beans.BeanInfo;
|
||||
|
||||
/**
|
||||
* BeanInfo for LDAPGetEntries
|
||||
*/
|
||||
|
||||
public class LDAPGetEntriesBeanInfo extends SimpleBeanInfo {
|
||||
|
||||
public LDAPGetEntriesBeanInfo() throws Exception {
|
||||
|
||||
beanClass = Class.forName( "netscape.ldap.beans.LDAPGetEntries" );
|
||||
|
||||
try {
|
||||
PropertyDescriptor host =
|
||||
new PropertyDescriptor("host", beanClass);
|
||||
PropertyDescriptor port =
|
||||
new PropertyDescriptor("port", beanClass);
|
||||
PropertyDescriptor authDN =
|
||||
new PropertyDescriptor("authDN", beanClass);
|
||||
PropertyDescriptor authPassword =
|
||||
new PropertyDescriptor("authPassword", beanClass);
|
||||
PropertyDescriptor base =
|
||||
new PropertyDescriptor("base", beanClass);
|
||||
PropertyDescriptor userName =
|
||||
new PropertyDescriptor("userName", beanClass);
|
||||
PropertyDescriptor userID =
|
||||
new PropertyDescriptor("userID", beanClass);
|
||||
PropertyDescriptor filter =
|
||||
new PropertyDescriptor("filter", beanClass);
|
||||
PropertyDescriptor scope =
|
||||
new PropertyDescriptor("scope", beanClass);
|
||||
PropertyDescriptor debug =
|
||||
new PropertyDescriptor("debug", beanClass);
|
||||
|
||||
PropertyDescriptor rv[] =
|
||||
{host, port, authDN, authPassword, base, filter,
|
||||
scope, userName, userID, debug};
|
||||
_propertyDescriptor = new PropertyDescriptor[rv.length];
|
||||
for( int i = 0; i < rv.length; i++ )
|
||||
_propertyDescriptor[i] = rv[i];
|
||||
} catch (Exception e) {
|
||||
throw new Error(e.toString());
|
||||
}
|
||||
|
||||
// Publish events --------------------------------------------------
|
||||
try {
|
||||
_eventSetDescriptor = new EventSetDescriptor[1];
|
||||
|
||||
_eventSetDescriptor[0] = new EventSetDescriptor(beanClass,
|
||||
"propertyChange",
|
||||
Class.forName("java.beans.PropertyChangeListener"),
|
||||
"propertyChange");
|
||||
} catch (Exception e) {
|
||||
throw new Error(e.toString());
|
||||
}
|
||||
|
||||
// Publish descriptor ---------------------------------------------
|
||||
try {
|
||||
_beanDescriptor = new BeanDescriptor(beanClass);
|
||||
_beanDescriptor.setDisplayName( "LDAP entry retrieval" );
|
||||
_beanDescriptor.setShortDescription(
|
||||
"LDAP property retrieval -"
|
||||
+ " provided a host, port, base, search filter,"
|
||||
+ " and optionally a username and password,"
|
||||
+ " return an array of string values both as a"
|
||||
+ " function return and as a Property change event." );
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the public properties
|
||||
*/
|
||||
public PropertyDescriptor[] getPropertyDescriptors() {
|
||||
return _propertyDescriptor;
|
||||
}
|
||||
|
||||
public EventSetDescriptor[] getEventSetDescriptors() {
|
||||
return _eventSetDescriptor;
|
||||
}
|
||||
|
||||
public BeanInfo[] getAdditionalBeanInfo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getDefaultEventIndex() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getDefaultPropertyIndex() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public BeanDescriptor getBeanDescriptor() {
|
||||
return _beanDescriptor;
|
||||
}
|
||||
|
||||
private static Class beanClass;
|
||||
private BeanDescriptor _beanDescriptor;
|
||||
private EventSetDescriptor[] _eventSetDescriptor;
|
||||
private PropertyDescriptor[] _propertyDescriptor;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,332 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.beans;
|
||||
|
||||
import netscape.ldap.*;
|
||||
import netscape.ldap.beans.LDAPBasePropertySupport;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
import java.io.Serializable;
|
||||
import java.beans.*;
|
||||
import java.awt.event.*;
|
||||
|
||||
|
||||
/**
|
||||
* Invisible Bean that just takes a name and password, host and
|
||||
* port, and directory base and attribute name, and returns an
|
||||
* attribute's values from a Directory Server. The values are
|
||||
* assumed to be strings, and are returned as an array. The
|
||||
* search has the scope "SUB", which means that it will find
|
||||
* an entry anywhere at or below the directory base.
|
||||
* <BR><BR>
|
||||
* Optionally, a client can register as a PropertyChangeListener
|
||||
* and will be notified when the values are available.
|
||||
*<BR><BR>
|
||||
* A null result means the property fetch failed. The reason is
|
||||
* available through getErrorCode(), which returns one of
|
||||
* the following:
|
||||
*<PRE>
|
||||
* OK
|
||||
* INVALID_PARAMETER
|
||||
* CONNECT_ERROR
|
||||
* AUTHENTICATION_ERROR
|
||||
* PROPERTY_NOT_FOUND
|
||||
* AMBIGUOUS_RESULTS
|
||||
*</PRE>
|
||||
*/
|
||||
public class LDAPGetProperty extends LDAPBasePropertySupport implements
|
||||
Serializable {
|
||||
|
||||
/**
|
||||
* Constructor with no parameters
|
||||
*/
|
||||
public LDAPGetProperty() {}
|
||||
|
||||
/**
|
||||
* Constructor with host, port, and base initializers
|
||||
* @param theHost host string
|
||||
* @param thePort port number
|
||||
* @param theBase directory base string
|
||||
*/
|
||||
public LDAPGetProperty( String theHost, int thePort, String theBase ) {
|
||||
setHost( theHost );
|
||||
setPort( thePort );
|
||||
setBase( theBase );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the attribute to retrieve
|
||||
* @return attribute name to retrieve
|
||||
*/
|
||||
public String getAttribute() {
|
||||
return _attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attribute to retrieve
|
||||
*/
|
||||
public void setAttribute( String attr ) {
|
||||
_attribute = attr;
|
||||
}
|
||||
|
||||
private void notifyResult( String[] newResult ) {
|
||||
String sNewResult = convertToString( newResult );
|
||||
firePropertyChange( "result", _result, newResult );
|
||||
_sResult = sNewResult;
|
||||
_result = newResult;
|
||||
}
|
||||
|
||||
private void notifyResult( Vector newResult ) {
|
||||
firePropertyChange( "result", _resultV, newResult );
|
||||
_resultV = (Vector)newResult.clone();
|
||||
}
|
||||
|
||||
private void notifyResult( String error ) {
|
||||
firePropertyChange( "error", _errorMsg, error );
|
||||
_errorMsg = error;
|
||||
}
|
||||
|
||||
public void setDNs(PropertyChangeEvent evt) {
|
||||
Object obj = (Object)evt.getNewValue();
|
||||
if ((obj != null) && (obj instanceof String[])) {
|
||||
String[] strings = (String[])obj;
|
||||
if (strings.length == 0)
|
||||
return;
|
||||
_dns = new String[strings.length];
|
||||
System.arraycopy(obj, 0, _dns, 0, strings.length);
|
||||
System.out.println("length of dns -> "+_dns.length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches and returns values for a specified attribute
|
||||
* @param host host string
|
||||
* @param port port number
|
||||
* @param base directory base string
|
||||
* @param filter search filter
|
||||
* @param attribute name of property to return values for
|
||||
* @return Array of values for the property
|
||||
*/
|
||||
public String[] getProperty( String host, int port, String base,
|
||||
String filter, String attribute) {
|
||||
setHost( host );
|
||||
setPort( port );
|
||||
setBase( base );
|
||||
setFilter( filter );
|
||||
setAttribute( attribute );
|
||||
return getProperty();
|
||||
}
|
||||
|
||||
// Added this method in order to get exposed in BDK
|
||||
public void getProperty(ActionEvent x) {
|
||||
getProperty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches and returns values of a previously registered property,
|
||||
* using previously set parameters
|
||||
* @return Array of values for the property
|
||||
*/
|
||||
public String[] getProperty() {
|
||||
if ( (_attribute.length() < 1) || (getFilter().length() < 1) ) {
|
||||
printDebug( "Invalid attribute name or filter" );
|
||||
setErrorCode( INVALID_PARAMETER );
|
||||
notifyResult( (String[])null );
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] res = null;
|
||||
LDAPConnection m_ldc;
|
||||
try {
|
||||
m_ldc = new LDAPConnection();
|
||||
printDebug("Connecting to " + getHost() +
|
||||
" " + getPort());
|
||||
connect( m_ldc, getHost(), getPort());
|
||||
} catch (Exception e) {
|
||||
printDebug( "Failed to connect to " + getHost() + ": "
|
||||
+ e.toString() );
|
||||
setErrorCode( CONNECT_ERROR );
|
||||
notifyResult( (String[])null );
|
||||
return null;
|
||||
}
|
||||
|
||||
// Authenticate?
|
||||
if (_dns != null) {
|
||||
for (int i=0; i<_dns.length; i++) {
|
||||
try {
|
||||
m_ldc.authenticate(_dns[i], getAuthPassword());
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
if (i == _dns.length-1) {
|
||||
printDebug( "Failed to authenticate to " +
|
||||
getHost() + ": " + e.toString() );
|
||||
setErrorCode( AUTHENTICATION_ERROR );
|
||||
notifyResult( (String[])null );
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ( (!getAuthDN().equals("")) && (!getAuthPassword().equals("")) ) {
|
||||
printDebug( "Authenticating " + getAuthDN() + " - " +
|
||||
getAuthPassword() );
|
||||
try {
|
||||
m_ldc.authenticate( getAuthDN(), getAuthPassword() );
|
||||
} catch (Exception e) {
|
||||
printDebug( "Failed to authenticate to " +
|
||||
getHost() + ": " + e.toString() );
|
||||
setErrorCode( AUTHENTICATION_ERROR );
|
||||
notifyResult( (String[])null );
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
int numDataEntries = 0;
|
||||
// Search
|
||||
try {
|
||||
String[] attrs = new String[1];
|
||||
attrs[0] = _attribute;
|
||||
LDAPSearchResults results = m_ldc.search(getBase(),
|
||||
getScope(),
|
||||
getFilter(),
|
||||
attrs, false);
|
||||
|
||||
// Should be only one result, at most
|
||||
LDAPEntry currEntry = null;
|
||||
LDAPEntry entry = null;
|
||||
while ( results.hasMoreElements() ) {
|
||||
try {
|
||||
currEntry = results.next();
|
||||
if (numDataEntries == 0)
|
||||
entry = currEntry;
|
||||
if (++numDataEntries > 1) {
|
||||
printDebug( "More than one entry found for " +
|
||||
getFilter() );
|
||||
setErrorCode( AMBIGUOUS_RESULTS );
|
||||
break;
|
||||
}
|
||||
} catch (LDAPException e) {
|
||||
if (getDebug())
|
||||
notifyResult(e.toString());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (numDataEntries == 1) {
|
||||
printDebug( "... " + entry.getDN() );
|
||||
// Good - exactly one entry found; get the attribute
|
||||
// Treat DN as a special case
|
||||
if ( _attribute.equalsIgnoreCase( "dn" ) ) {
|
||||
res = new String[1];
|
||||
res[0] = entry.getDN();
|
||||
setErrorCode( OK );
|
||||
} else {
|
||||
LDAPAttributeSet attrset = entry.getAttributeSet();
|
||||
Enumeration attrsenum = attrset.getAttributes();
|
||||
if (attrsenum.hasMoreElements()) {
|
||||
LDAPAttribute attr =
|
||||
(LDAPAttribute)attrsenum.nextElement();
|
||||
printDebug( attr.getName() + " = " );
|
||||
// Get the values as strings
|
||||
Enumeration valuesenum = attr.getStringValues();
|
||||
if (valuesenum != null) {
|
||||
// Create a string array for the results
|
||||
Vector v = new Vector();
|
||||
while (valuesenum.hasMoreElements()) {
|
||||
String val = (String)valuesenum.nextElement();
|
||||
v.addElement( val );
|
||||
printDebug( "\t\t" + val );
|
||||
}
|
||||
res = new String[v.size()];
|
||||
v.copyInto( res );
|
||||
setErrorCode( OK );
|
||||
} else {
|
||||
Enumeration byteEnum = attr.getByteValues();
|
||||
Vector v = new Vector();
|
||||
while (byteEnum.hasMoreElements()) {
|
||||
byte[] val = (byte[])byteEnum.nextElement();
|
||||
v.addElement( val );
|
||||
printDebug( "\t\t" + val );
|
||||
}
|
||||
setErrorCode( OK );
|
||||
notifyResult(v);
|
||||
return (res = null);
|
||||
}
|
||||
} else {
|
||||
printDebug( "No properties found for " +
|
||||
_attribute );
|
||||
setErrorCode( PROPERTY_NOT_FOUND );
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (getDebug()) {
|
||||
printDebug( "Failed to search for " + getFilter() + ": "
|
||||
+ e.toString() );
|
||||
}
|
||||
setErrorCode( PROPERTY_NOT_FOUND );
|
||||
}
|
||||
|
||||
if (numDataEntries == 0) {
|
||||
printDebug( "No entries found for " + getFilter() );
|
||||
setErrorCode( PROPERTY_NOT_FOUND );
|
||||
}
|
||||
|
||||
// Disconnect
|
||||
try {
|
||||
if ( (m_ldc != null) && m_ldc.isConnected() )
|
||||
m_ldc.disconnect();
|
||||
} catch ( Exception e ) {
|
||||
}
|
||||
|
||||
notifyResult( res );
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main body if we run it as application instead of applet.
|
||||
* @param args list of arguments
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
if (args.length != 5) {
|
||||
System.out.println( "Usage: LDAPGetProperty host port base" +
|
||||
" filter attribute" );
|
||||
System.exit(1);
|
||||
}
|
||||
LDAPGetProperty app = new LDAPGetProperty();
|
||||
app.setHost( args[0] );
|
||||
app.setPort( java.lang.Integer.parseInt( args[1] ) );
|
||||
app.setBase( args[2] );
|
||||
app.setFilter( args[3] );
|
||||
app.setAttribute( args[4] );
|
||||
String[] response = app.getProperty();
|
||||
if ( response != null ) {
|
||||
for( int i = 0; i < response.length; i++ )
|
||||
System.out.println( "\t" + response[i] );
|
||||
}
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Variables
|
||||
*/
|
||||
private String[] _dns = null;
|
||||
private String _attribute = new String("cn");
|
||||
transient private String[] _result;
|
||||
private Vector _resultV = null;
|
||||
private String _sResult = null;
|
||||
private String _errorMsg = null;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
Name: netscape/ldap/beans/LDAPGetProperty.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: netscape/ldap/beans/LDAPBasePropertySupport.class
|
||||
|
||||
Name: netscape/ldap/beans/LDAPGetPropertyBeanInfo.class
|
||||
@@ -0,0 +1,138 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.beans;
|
||||
|
||||
import java.beans.SimpleBeanInfo;
|
||||
import java.beans.BeanDescriptor;
|
||||
import java.beans.EventSetDescriptor;
|
||||
import java.beans.MethodDescriptor;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.beans.ParameterDescriptor;
|
||||
import java.beans.BeanInfo;
|
||||
|
||||
|
||||
/**
|
||||
* BeanInfo for LDAPGetProperty
|
||||
*/
|
||||
|
||||
public class LDAPGetPropertyBeanInfo extends SimpleBeanInfo {
|
||||
|
||||
public LDAPGetPropertyBeanInfo() throws Exception {
|
||||
|
||||
beanClass = Class.forName( "netscape.ldap.beans.LDAPGetProperty" );
|
||||
|
||||
try {
|
||||
PropertyDescriptor host =
|
||||
new PropertyDescriptor("host", beanClass);
|
||||
PropertyDescriptor port =
|
||||
new PropertyDescriptor("port", beanClass);
|
||||
PropertyDescriptor authDN =
|
||||
new PropertyDescriptor("authDN", beanClass);
|
||||
PropertyDescriptor authPassword =
|
||||
new PropertyDescriptor("authPassword", beanClass);
|
||||
PropertyDescriptor base =
|
||||
new PropertyDescriptor("base", beanClass);
|
||||
PropertyDescriptor filter =
|
||||
new PropertyDescriptor("filter", beanClass);
|
||||
PropertyDescriptor scope =
|
||||
new PropertyDescriptor("scope", beanClass);
|
||||
PropertyDescriptor attribute =
|
||||
new PropertyDescriptor("attribute", beanClass);
|
||||
PropertyDescriptor debug =
|
||||
new PropertyDescriptor("debug", beanClass);
|
||||
|
||||
PropertyDescriptor rv[] =
|
||||
{host, port, authDN, authPassword, base, scope, attribute,
|
||||
filter, debug};
|
||||
_propertyDescriptor = new PropertyDescriptor[rv.length];
|
||||
for( int i = 0; i < rv.length; i++ )
|
||||
_propertyDescriptor[i] = rv[i];
|
||||
} catch (Exception e) {
|
||||
throw new Error(e.toString());
|
||||
}
|
||||
|
||||
// Publish events --------------------------------------------------
|
||||
try {
|
||||
_eventSetDescriptor = new EventSetDescriptor[1];
|
||||
|
||||
_eventSetDescriptor[0] = new EventSetDescriptor(beanClass,
|
||||
"propertyChange",
|
||||
Class.forName("java.beans.PropertyChangeListener"),
|
||||
"propertyChange");
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new Error(e.toString());
|
||||
}
|
||||
|
||||
// Publish descriptor ---------------------------------------------
|
||||
try {
|
||||
_beanDescriptor = new BeanDescriptor(beanClass);
|
||||
_beanDescriptor.setDisplayName( "LDAP property retrieval" );
|
||||
_beanDescriptor.setShortDescription(
|
||||
"LDAP property retrieval -"
|
||||
+ " provided a host, port, base, search filter,"
|
||||
+ " and optionally a username and password,"
|
||||
+ " return an array of string values both as a"
|
||||
+ " function return and as a Property change event." );
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the public properties
|
||||
*/
|
||||
public PropertyDescriptor[] getPropertyDescriptors() {
|
||||
return _propertyDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the public methods
|
||||
*/
|
||||
public MethodDescriptor[] getMethodDescriptors() {
|
||||
return _methodDescriptor;
|
||||
}
|
||||
|
||||
public EventSetDescriptor[] getEventSetDescriptors() {
|
||||
return _eventSetDescriptor;
|
||||
}
|
||||
|
||||
public BeanInfo[] getAdditionalBeanInfo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getDefaultEventIndex() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getDefaultPropertyIndex() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public BeanDescriptor getBeanDescriptor() {
|
||||
return _beanDescriptor;
|
||||
}
|
||||
|
||||
private static Class beanClass;
|
||||
private BeanDescriptor _beanDescriptor;
|
||||
private EventSetDescriptor[] _eventSetDescriptor;
|
||||
private MethodDescriptor[] _methodDescriptor;
|
||||
private PropertyDescriptor[] _propertyDescriptor;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,433 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.beans;
|
||||
|
||||
import netscape.ldap.*;
|
||||
import netscape.ldap.util.*;
|
||||
import java.util.Enumeration;
|
||||
import java.util.StringTokenizer;
|
||||
import java.io.Serializable;
|
||||
import java.awt.event.*;
|
||||
|
||||
/**
|
||||
* Invisible Bean that just takes a host and port, optional
|
||||
* authentication name and password, and DN of a group and another DN
|
||||
* which might be a member of the group, and returns true or
|
||||
* false, depending on whether the second DN is a member of the first.
|
||||
* <BR>
|
||||
* Also handles the case of dynamic groups by derefencing the URL
|
||||
* and searching for membership based on the url search.
|
||||
* <BR>
|
||||
* It doesn't handle nested groups.
|
||||
* <BR><BR>
|
||||
* A false result means the member could not be identified as
|
||||
* belonging to the group. The exact reason is
|
||||
* available through getErrorCode(), which returns one of
|
||||
* the following:
|
||||
*<PRE>
|
||||
* OK
|
||||
* INVALID_PARAMETER
|
||||
* CONNECT_ERROR
|
||||
* AUTHENTICATION_ERROR
|
||||
* PROPERTY_NOT_FOUND
|
||||
* AMBIGUOUS_RESULTS
|
||||
* NO_SUCH_OBJECT
|
||||
*</PRE>
|
||||
*/
|
||||
public class LDAPIsMember extends LDAPBasePropertySupport
|
||||
implements Serializable {
|
||||
|
||||
/**
|
||||
* Constructor with no parameters
|
||||
*/
|
||||
public LDAPIsMember() {}
|
||||
|
||||
/**
|
||||
* Constructor with host, port, and group DN initializers
|
||||
* @param host host string
|
||||
* @param port port number
|
||||
* @param group distinguished name of the group
|
||||
*/
|
||||
public LDAPIsMember( String host, int port, String group ) {
|
||||
setHost( host );
|
||||
setPort( port );
|
||||
setGroup( group );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with host, port, authentication DN and password
|
||||
* and group DN initializers
|
||||
* @param host host string
|
||||
* @param port port number
|
||||
* @param dn fully qualified distinguished name to authenticate
|
||||
* @param password password for authenticating the dn
|
||||
* @param group distinguished name of the group
|
||||
*/
|
||||
public LDAPIsMember( String host, int port,
|
||||
String dn, String password, String theGroup ) {
|
||||
setHost( host );
|
||||
setPort( port );
|
||||
setGroup( theGroup );
|
||||
setAuthDN( dn );
|
||||
setAuthPassword( password );
|
||||
}
|
||||
|
||||
private void notifyResult( String newResult ) {
|
||||
firePropertyChange( "result", _result, newResult );
|
||||
_result = newResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an entity (specified by distinguished name) is a
|
||||
* member of a particular group (specified by distinguished name)
|
||||
* @return true if the specified member belongs to the group
|
||||
*/
|
||||
public boolean isMember() {
|
||||
String host = getHost();
|
||||
int port = getPort();
|
||||
String dn = getAuthDN();
|
||||
String password = getAuthPassword();
|
||||
String group = getGroup();
|
||||
String member = getMember();
|
||||
_result = new String("");
|
||||
|
||||
if ( (host == null) || (host.length() < 1) ) {
|
||||
printDebug( "Invalid host name" );
|
||||
setErrorCode( INVALID_PARAMETER );
|
||||
notifyResult(null);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( (member == null) || (group == null) ||
|
||||
(member.length() < 1) || (group.length() < 1) ) {
|
||||
printDebug( "Invalid member or group name" );
|
||||
setErrorCode( INVALID_PARAMETER );
|
||||
notifyResult(null);
|
||||
return false;
|
||||
}
|
||||
|
||||
LDAPConnection m_ldc;
|
||||
boolean isMember = false;
|
||||
try {
|
||||
m_ldc = new LDAPConnection();
|
||||
printDebug("Connecting to " + host +
|
||||
" " + port);
|
||||
connect( m_ldc, getHost(), getPort());
|
||||
} catch (Exception e) {
|
||||
printDebug( "Failed to connect to " + host + ": "
|
||||
+ e.toString() );
|
||||
setErrorCode( CONNECT_ERROR );
|
||||
notifyResult(null);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Authenticate?
|
||||
if ( (dn != null) && (password != null) &&
|
||||
(dn.length() > 0) && (password.length() > 0) ) {
|
||||
printDebug( "Authenticating " + dn + " - " + password );
|
||||
try {
|
||||
m_ldc.authenticate( dn, password );
|
||||
} catch (Exception e) {
|
||||
printDebug( "Failed to authenticate to " +
|
||||
host + ": " + e.toString() );
|
||||
setErrorCode( AUTHENTICATION_ERROR );
|
||||
notifyResult(null);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int numDataEntries = 0;
|
||||
// Search
|
||||
try {
|
||||
String[] attrs = new String[4];
|
||||
attrs[0] = "member";
|
||||
attrs[1] = "uniqueMember";
|
||||
attrs[2] = "memberOfGroup";
|
||||
attrs[3] = "memberurl";
|
||||
LDAPSearchResults results =
|
||||
m_ldc.search( group,
|
||||
LDAPConnection.SCOPE_BASE,
|
||||
"objectclass=*",
|
||||
attrs, false);
|
||||
|
||||
// Should be only one result, at most
|
||||
LDAPEntry entry = null;
|
||||
LDAPEntry currEntry = null;
|
||||
while ( results.hasMoreElements() ) {
|
||||
try {
|
||||
currEntry = (LDAPEntry)results.next();
|
||||
if (numDataEntries == 0)
|
||||
entry = currEntry;
|
||||
if (++numDataEntries > 1) {
|
||||
printDebug( "More than one entry found for " +
|
||||
getFilter() );
|
||||
setErrorCode( AMBIGUOUS_RESULTS );
|
||||
break;
|
||||
}
|
||||
} catch (LDAPReferralException e) {
|
||||
if (getDebug()) {
|
||||
notifyResult("Referral URLs: ");
|
||||
LDAPUrl refUrls[] = e.getURLs();
|
||||
for (int i = 0; i < refUrls.length; i++)
|
||||
notifyResult(refUrls[i].getUrl());
|
||||
}
|
||||
continue;
|
||||
} catch (LDAPException e) {
|
||||
if (getDebug())
|
||||
notifyResult(e.toString());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (numDataEntries == 1) {
|
||||
printDebug( "... " + entry.getDN() );
|
||||
String normMember = normalizeDN( member );
|
||||
// Good - exactly one entry found; get the attributes
|
||||
LDAPAttributeSet attrset = entry.getAttributeSet();
|
||||
Enumeration attrsenum = attrset.getAttributes();
|
||||
while ( attrsenum.hasMoreElements() && !isMember ) {
|
||||
LDAPAttribute attr =
|
||||
(LDAPAttribute)attrsenum.nextElement();
|
||||
printDebug( attr.getName() + " = " );
|
||||
boolean urlHandler =
|
||||
attr.getName().equalsIgnoreCase("memberurl");
|
||||
/* Get the values as strings.
|
||||
The following code also handles dynamic
|
||||
groups by calling URLMatch to see if an entry
|
||||
DN is found via a URL search.
|
||||
This is transparent to the caller of the bean.
|
||||
*/
|
||||
Enumeration valuesenum = attr.getStringValues();
|
||||
if (valuesenum != null) {
|
||||
while (valuesenum.hasMoreElements()) {
|
||||
String val = (String)valuesenum.nextElement();
|
||||
if (urlHandler) {
|
||||
if ( URLMatch(m_ldc, val, normMember) ) {
|
||||
isMember = true;
|
||||
setErrorCode( OK );
|
||||
break;
|
||||
}
|
||||
}
|
||||
printDebug( "\t\t" + val );
|
||||
String normFound = normalizeDN( val );
|
||||
if ( normMember.equals( normFound ) ) {
|
||||
isMember = true;
|
||||
setErrorCode( OK );
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setErrorCode(PROPERTY_NOT_FOUND);
|
||||
printDebug("Failed to do string conversion for "+
|
||||
attr.getName());
|
||||
}
|
||||
}
|
||||
if ( !isMember )
|
||||
setErrorCode( PROPERTY_NOT_FOUND );
|
||||
}
|
||||
} catch (Exception e) {
|
||||
printDebug( "Failed to search for " + group + ": "
|
||||
+ e.toString() );
|
||||
setErrorCode( NO_SUCH_OBJECT );
|
||||
}
|
||||
|
||||
if (numDataEntries == 0) {
|
||||
printDebug( "No entries found for " + group );
|
||||
setErrorCode( NO_SUCH_OBJECT );
|
||||
}
|
||||
|
||||
try {
|
||||
if ( (m_ldc != null) && m_ldc.isConnected() )
|
||||
m_ldc.disconnect();
|
||||
} catch ( Exception e ) {
|
||||
}
|
||||
|
||||
if (isMember)
|
||||
notifyResult("Y");
|
||||
else
|
||||
notifyResult("N");
|
||||
|
||||
return isMember;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an entity (specified by distinguished name) is a
|
||||
* member of a particular group (specified by distinguished name)
|
||||
* @param host host string
|
||||
* @param port port number
|
||||
* @param dn fully qualified distinguished name to authenticate;
|
||||
* can be null or ""
|
||||
* @param password password for authenticating the dn; can be null
|
||||
* or ""
|
||||
* @param group distinguished name of the group
|
||||
* @param member distinguished name of member to be checked
|
||||
* @return true if the specified member belongs to the group
|
||||
*/
|
||||
public boolean isMember( String host, int port,
|
||||
String dn, String password,
|
||||
String group, String member ) {
|
||||
setHost(host);
|
||||
setPort(port);
|
||||
setAuthDN(dn);
|
||||
setAuthPassword(password);
|
||||
setGroup(group);
|
||||
setMember(member);
|
||||
return isMember();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an entity (specified by distinguished name) is a
|
||||
* member of a particular group (specified by distinguished name)
|
||||
* @return true if the specified member belongs to the group
|
||||
*/
|
||||
public void isMember(ActionEvent e) {
|
||||
isMember();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distinguished name of the group
|
||||
* @return group name
|
||||
*/
|
||||
public String getGroup() {
|
||||
return _group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the distinguished name of the group
|
||||
* @param group group name
|
||||
*/
|
||||
public void setGroup( String group ) {
|
||||
_group = group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distinguished name of the member
|
||||
* @return member name
|
||||
*/
|
||||
public String getMember() {
|
||||
return _member;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the distinguished name of the member
|
||||
* @param member member name
|
||||
*/
|
||||
public void setMember( String member ) {
|
||||
_member = member;
|
||||
}
|
||||
|
||||
private String normalizeDN( String dn ) {
|
||||
return new DN( dn ).toRFCString().toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if normMember is result of url search.
|
||||
* Urls from dynamic groups do not typically contain
|
||||
* the host and port so we need to fix them before
|
||||
* constructing an LDAP URL.
|
||||
* current ldap:///.... make ldap://host:port/...
|
||||
**/
|
||||
private boolean URLMatch(LDAPConnection ld, String URL,
|
||||
String normMemberDN) {
|
||||
String cURL = URL;
|
||||
boolean isMember = false;
|
||||
int loc = URL.indexOf(":///");
|
||||
if ( loc > 0) {
|
||||
cURL = URL.substring(0,loc) + "://" + ld.getHost() +
|
||||
":" + ld.getPort() + URL.substring(loc+3);
|
||||
}
|
||||
printDebug("URLMatch: url = " + cURL +
|
||||
", member DN = " + normMemberDN);
|
||||
LDAPUrl ldapurl;
|
||||
try {
|
||||
ldapurl = new LDAPUrl(cURL);
|
||||
printDebug("URL ->"+ldapurl.getUrl());
|
||||
} catch (java.net.MalformedURLException murl) {
|
||||
printDebug("bad URL");
|
||||
return isMember;
|
||||
}
|
||||
|
||||
try {
|
||||
LDAPSearchResults results = ld.search(ldapurl);
|
||||
String entry = "";
|
||||
while ( results.hasMoreElements() && !isMember ) {
|
||||
try {
|
||||
entry = ((LDAPEntry)results.next()).getDN();
|
||||
String normEntry = normalizeDN( entry );
|
||||
if (normEntry.equals(normMemberDN)) {
|
||||
isMember = true;
|
||||
break;
|
||||
}
|
||||
} catch (LDAPReferralException e) {
|
||||
if (getDebug()) {
|
||||
notifyResult("Referral URLs: ");
|
||||
LDAPUrl refUrls[] = e.getURLs();
|
||||
for (int i = 0; i < refUrls.length; i++)
|
||||
notifyResult(refUrls[i].getUrl());
|
||||
}
|
||||
continue;
|
||||
} catch (LDAPException e) {
|
||||
if (getDebug())
|
||||
notifyResult(e.toString());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} catch (LDAPException lde) {
|
||||
printDebug("Failed search for url " + ldapurl.getUrl());
|
||||
setErrorCode(NO_SUCH_OBJECT);
|
||||
}
|
||||
|
||||
return isMember;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main body if we run it as application instead of applet.
|
||||
* @param args list of arguments
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
if (args.length != 4) {
|
||||
System.out.println( "Usage: LDAPIsMember host port group" +
|
||||
" member" );
|
||||
System.exit(1);
|
||||
}
|
||||
LDAPIsMember app = new LDAPIsMember();
|
||||
app.setHost( args[0] );
|
||||
app.setPort( java.lang.Integer.parseInt( args[1] ) );
|
||||
app.setGroup( args[2] );
|
||||
app.setMember( args[3] );
|
||||
boolean response = app.isMember();
|
||||
if ( response == false )
|
||||
System.out.println( "Not a member" );
|
||||
else
|
||||
System.out.println( "Is a member" );
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Variables
|
||||
*/
|
||||
public static final int OK = 0;
|
||||
public static final int INVALID_PARAMETER = 1;
|
||||
public static final int CONNECT_ERROR = 2;
|
||||
public static final int AUTHENTICATION_ERROR = 3;
|
||||
public static final int PROPERTY_NOT_FOUND = 4;
|
||||
public static final int AMBIGUOUS_RESULTS = 5;
|
||||
public static final int NO_SUCH_OBJECT = 5;
|
||||
private String _group = new String("");
|
||||
private String _member = new String("");
|
||||
private String _result = new String("");
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
Name: netscape/ldap/beans/LDAPIsMember.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: netscape/ldap/beans/LDAPBasePropertySupport.class
|
||||
|
||||
Name: netscape/ldap/beans/LDAPIsMemberBeanInfo.class
|
||||
@@ -0,0 +1,110 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.beans;
|
||||
|
||||
import java.beans.SimpleBeanInfo;
|
||||
import java.beans.BeanDescriptor;
|
||||
import java.beans.EventSetDescriptor;
|
||||
import java.beans.MethodDescriptor;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.beans.ParameterDescriptor;
|
||||
import java.beans.BeanInfo;
|
||||
|
||||
/**
|
||||
* BeanInfo for LDAPIsMember
|
||||
*/
|
||||
|
||||
public class LDAPIsMemberBeanInfo extends SimpleBeanInfo {
|
||||
|
||||
public LDAPIsMemberBeanInfo() throws Exception {
|
||||
|
||||
beanClass = Class.forName( "netscape.ldap.beans.LDAPIsMember" );
|
||||
// Publish properties -------------------------------------------------
|
||||
|
||||
try {
|
||||
PropertyDescriptor host =
|
||||
new PropertyDescriptor("host", beanClass);
|
||||
PropertyDescriptor port =
|
||||
new PropertyDescriptor("port", beanClass);
|
||||
PropertyDescriptor authDN =
|
||||
new PropertyDescriptor("authDN", beanClass);
|
||||
PropertyDescriptor authPassword =
|
||||
new PropertyDescriptor("authPassword", beanClass);
|
||||
PropertyDescriptor group =
|
||||
new PropertyDescriptor("group", beanClass);
|
||||
PropertyDescriptor member =
|
||||
new PropertyDescriptor("member", beanClass);
|
||||
PropertyDescriptor debug =
|
||||
new PropertyDescriptor("debug", beanClass);
|
||||
|
||||
PropertyDescriptor rv[] =
|
||||
{host, port, authDN, authPassword, group, member, debug};
|
||||
_propertyDescriptor = new PropertyDescriptor[rv.length];
|
||||
for( int i = 0; i < rv.length; i++ )
|
||||
_propertyDescriptor[i] = rv[i];
|
||||
} catch (Exception e) {
|
||||
throw new Error(e.toString());
|
||||
}
|
||||
|
||||
// Publish descriptor ---------------------------------------------
|
||||
try {
|
||||
_beanDescriptor = new BeanDescriptor(beanClass);
|
||||
_beanDescriptor.setDisplayName( "LDAP IsMember" );
|
||||
_beanDescriptor.setShortDescription(
|
||||
"LDAP IsMember -"
|
||||
+ " provided a host, port, group name and member name,"
|
||||
+ " and optionally an authentication name and password,"
|
||||
+ " return true if the member belongs to the group." );
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the public properties
|
||||
*/
|
||||
public PropertyDescriptor[] getPropertyDescriptors() {
|
||||
return _propertyDescriptor;
|
||||
}
|
||||
|
||||
public EventSetDescriptor[] getEventSetDescriptors() {
|
||||
return _eventSetDescriptor;
|
||||
}
|
||||
|
||||
public BeanInfo[] getAdditionalBeanInfo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getDefaultEventIndex() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getDefaultPropertyIndex() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public BeanDescriptor getBeanDescriptor() {
|
||||
return _beanDescriptor;
|
||||
}
|
||||
|
||||
private static Class beanClass;
|
||||
private BeanDescriptor _beanDescriptor;
|
||||
private EventSetDescriptor[] _eventSetDescriptor;
|
||||
private PropertyDescriptor[] _propertyDescriptor;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.beans;
|
||||
|
||||
import netscape.ldap.*;
|
||||
import netscape.ldap.beans.LDAPBasePropertySupport;
|
||||
import java.io.Serializable;
|
||||
import java.awt.event.*;
|
||||
|
||||
/**
|
||||
* Invisible Bean that just authenticates a user with a Directory
|
||||
* Server and returns Y or N. It takes a host and port, and then either
|
||||
* a full distinguished name and password, an RDN and directory base, or
|
||||
* a cn value and directory base.
|
||||
* <BR><BR>
|
||||
* Optionally, a client can register as
|
||||
* a PropertyChangeListener and will be notified when an authentication
|
||||
* completes.
|
||||
* <BR><BR>
|
||||
* The Bean can be used from JavaScript, as in the following example
|
||||
* where the parameters are taken from HTML text fields in an HTML
|
||||
* form called "input":
|
||||
* <PRE>
|
||||
* <XMP>
|
||||
* <SCRIPT LANGUAGE="JavaScript">
|
||||
* function checkAuthentication() {
|
||||
* auth = new Packages.netscape.ldap.beans.LDAPSimpleAuth();
|
||||
* auth.setHost( document.input.host.value );
|
||||
* auth.setPort( parseInt(document.input.port.value) );
|
||||
* auth.setAuthDN( document.input.username.value );
|
||||
* auth.setAuthPassword( document.input.password.value );
|
||||
* result = auth.authenticate();
|
||||
* alert( "The response is: " + result );
|
||||
* }
|
||||
* </SCRIPT>
|
||||
* </XMP>
|
||||
*</PRE>
|
||||
*/
|
||||
|
||||
public class LDAPSimpleAuth extends LDAPBasePropertySupport implements
|
||||
Serializable {
|
||||
|
||||
/**
|
||||
* Constructor with no parameters
|
||||
*/
|
||||
public LDAPSimpleAuth() {}
|
||||
|
||||
/**
|
||||
* Constructor with host and port initializers
|
||||
* @param theHost host string
|
||||
* @param thePort port number
|
||||
*/
|
||||
public LDAPSimpleAuth( String theHost,
|
||||
int thePort ) {
|
||||
setHost( theHost );
|
||||
setPort( thePort );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with all required authentication parameters
|
||||
* @param theHost host string
|
||||
* @param thePort port number
|
||||
* @param dn fully qualified distinguished name to authenticate
|
||||
* @param password password for authenticating the dn
|
||||
*/
|
||||
public LDAPSimpleAuth( String theHost,
|
||||
int thePort,
|
||||
String dn,
|
||||
String password ) {
|
||||
setHost( theHost );
|
||||
setPort( thePort );
|
||||
setAuthDN( dn );
|
||||
setAuthPassword( password );
|
||||
}
|
||||
|
||||
private void notifyResult( String newResult ) {
|
||||
firePropertyChange( "result", result, newResult );
|
||||
result = newResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to LDAP server using parameters specified in
|
||||
* constructor and/or by setting properties and attempt to
|
||||
* authenticate.
|
||||
* @return "Y" on successful authentication, "N" otherwise
|
||||
*/
|
||||
public String authenticate() {
|
||||
LDAPConnection m_ldc = null;
|
||||
String result = "N";
|
||||
try {
|
||||
m_ldc = new LDAPConnection();
|
||||
System.out.println("Connecting to " + getHost() +
|
||||
" " + getPort());
|
||||
connect( m_ldc, getHost(), getPort());
|
||||
} catch (Exception e) {
|
||||
System.out.println( "Failed to connect to " + getHost() +
|
||||
": " + e.toString() );
|
||||
}
|
||||
if ( m_ldc.isConnected() ) {
|
||||
System.out.println( "Authenticating " + getAuthDN() );
|
||||
try {
|
||||
m_ldc.authenticate( getAuthDN(), getAuthPassword() );
|
||||
result = "Y";
|
||||
} catch (Exception e) {
|
||||
System.out.println( "Failed to authenticate to " +
|
||||
getHost() + ": " + e.toString() );
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if ( (m_ldc != null) && m_ldc.isConnected() )
|
||||
m_ldc.disconnect();
|
||||
} catch ( Exception e ) {
|
||||
}
|
||||
|
||||
notifyResult( result );
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to LDAP server using parameters specified in
|
||||
* constructor and/or by setting properties and attempt to
|
||||
* authenticate.
|
||||
* @param dn fully qualified distinguished name to authenticate
|
||||
* @param password password for authenticating the dn
|
||||
* @return "Y" on successful authentication, "N" otherwise
|
||||
*/
|
||||
public String authenticate( String dn,
|
||||
String password ) {
|
||||
setAuthDN( dn );
|
||||
setAuthPassword( password );
|
||||
return authenticate();
|
||||
}
|
||||
|
||||
public void authenticate( ActionEvent x) {
|
||||
authenticate();
|
||||
}
|
||||
|
||||
/**
|
||||
* The main body if we run it as stand-alone application.
|
||||
* @param args list of arguments
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
if (args.length != 4) {
|
||||
System.out.println( " LDAPSimpleAuth " +
|
||||
"host port DN password" );
|
||||
System.exit(1);
|
||||
}
|
||||
LDAPSimpleAuth app = new LDAPSimpleAuth();
|
||||
app.setHost( args[0] );
|
||||
app.setPort( java.lang.Integer.parseInt( args[1] ) );
|
||||
app.setAuthDN( args[2] );
|
||||
app.setAuthPassword( args[3] );
|
||||
String response = app.authenticate();
|
||||
System.out.println( "Response: " + response );
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Variables
|
||||
*/
|
||||
transient private String result = new String("");
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
Name: netscape/ldap/beans/LDAPSimpleAuth.class
|
||||
Java-Bean: True
|
||||
|
||||
Name: netscape/ldap/beans/LDAPBasePropertySupport.class
|
||||
|
||||
Name: netscape/ldap/beans/LDAPSimpleAuthBeanInfo.class
|
||||
@@ -0,0 +1,118 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.beans;
|
||||
|
||||
import java.beans.SimpleBeanInfo;
|
||||
import java.beans.BeanDescriptor;
|
||||
import java.beans.EventSetDescriptor;
|
||||
import java.beans.MethodDescriptor;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.beans.ParameterDescriptor;
|
||||
import java.beans.BeanInfo;
|
||||
|
||||
/**
|
||||
* BeanInfo for LDAPSimpleAuth
|
||||
*/
|
||||
|
||||
public class LDAPSimpleAuthBeanInfo extends SimpleBeanInfo {
|
||||
|
||||
public LDAPSimpleAuthBeanInfo() throws Exception {
|
||||
|
||||
beanClass = Class.forName( "netscape.ldap.beans.LDAPSimpleAuth" );
|
||||
|
||||
try {
|
||||
PropertyDescriptor host =
|
||||
new PropertyDescriptor("host", beanClass);
|
||||
PropertyDescriptor port =
|
||||
new PropertyDescriptor("port", beanClass);
|
||||
PropertyDescriptor authDN =
|
||||
new PropertyDescriptor("authDN", beanClass);
|
||||
PropertyDescriptor authPassword =
|
||||
new PropertyDescriptor("authPassword", beanClass);
|
||||
PropertyDescriptor debug =
|
||||
new PropertyDescriptor("debug", beanClass);
|
||||
|
||||
PropertyDescriptor rv[] =
|
||||
{host, port, authDN, authPassword, debug};
|
||||
_propertyDescriptor = new PropertyDescriptor[rv.length];
|
||||
for( int i = 0; i < rv.length; i++ )
|
||||
_propertyDescriptor[i] = rv[i];
|
||||
} catch (Exception e) {
|
||||
throw new Error(e.toString());
|
||||
}
|
||||
|
||||
// Publish events --------------------------------------------------
|
||||
try {
|
||||
_eventSetDescriptor = new EventSetDescriptor[1];
|
||||
|
||||
_eventSetDescriptor[0] = new EventSetDescriptor(beanClass,
|
||||
"propertyChange",
|
||||
Class.forName("java.beans.PropertyChangeListener"),
|
||||
"propertyChange");
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new Error(e.toString());
|
||||
}
|
||||
|
||||
// Publish descriptor ---------------------------------------------
|
||||
try {
|
||||
_beanDescriptor = new BeanDescriptor(beanClass);
|
||||
_beanDescriptor.setDisplayName( "LDAP user authentication" );
|
||||
_beanDescriptor.setShortDescription(
|
||||
"LDAP user authentication -"
|
||||
+ " provided a host, port, base, username, and password,"
|
||||
+ " report if the user can be authenticated both as a"
|
||||
+ " function return and as a Property change event." );
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the public properties
|
||||
*/
|
||||
public PropertyDescriptor[] getPropertyDescriptors() {
|
||||
return _propertyDescriptor;
|
||||
}
|
||||
|
||||
public EventSetDescriptor[] getEventSetDescriptors() {
|
||||
return _eventSetDescriptor;
|
||||
}
|
||||
|
||||
public BeanInfo[] getAdditionalBeanInfo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getDefaultEventIndex() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getDefaultPropertyIndex() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public BeanDescriptor getBeanDescriptor() {
|
||||
return _beanDescriptor;
|
||||
}
|
||||
|
||||
private static Class beanClass;
|
||||
private BeanDescriptor _beanDescriptor;
|
||||
private EventSetDescriptor[] _eventSetDescriptor;
|
||||
private PropertyDescriptor[] _propertyDescriptor;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.util;
|
||||
|
||||
/**
|
||||
* The exception thrown when there is a problem with either an LDAPFilter
|
||||
* or with the File/URL/Buffer form which we're creating the LDAPFilter.
|
||||
*
|
||||
* @see LDAPFilter
|
||||
* @see LDAPFilterDescriptor
|
||||
* @version 1.0
|
||||
*/
|
||||
public class BadFilterException extends Exception {
|
||||
|
||||
private String m_strException;
|
||||
private int m_nLine = -1;
|
||||
|
||||
/**
|
||||
* Creates an <b>Unknown</b> BadFilterException
|
||||
*/
|
||||
public BadFilterException () {
|
||||
m_strException = "Unknown Error";
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BadFilterException with the
|
||||
* given string
|
||||
*/
|
||||
public BadFilterException ( String s ) {
|
||||
m_strException = s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BadFilterException with the
|
||||
* given string and line number
|
||||
*/
|
||||
public BadFilterException ( String s, int nErrorLineNumber ) {
|
||||
m_strException = s;
|
||||
m_nLine = nErrorLineNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exception string.
|
||||
*/
|
||||
public String toString() {
|
||||
return m_strException;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If appropriate, return the line number of the ldapfilter.conf
|
||||
* file (or url or buffer) where this error occurred. This method
|
||||
* will return -1 if the line number was not set.
|
||||
*/
|
||||
public int getErrorLineNumber() {
|
||||
return m_nLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the line number in the ldapfilter.conf file/url/buffer where
|
||||
* this error occurred.
|
||||
*/
|
||||
void setErrorLineNumber ( int nErrorLineNumber ) {
|
||||
m_nLine = m_nLine;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,529 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.util;
|
||||
|
||||
import netscape.ldap.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Represents an LDAP search filter, which includes the string-based
|
||||
* representation of the filter and other information retrieved from the
|
||||
* LDAP filter configuration file (or from a buffer in memory or from a URL).
|
||||
* <P>
|
||||
*
|
||||
* Although this class provides methods to create and modify LDAP
|
||||
* filters, in most cases, you do not need to use these methods.
|
||||
* In most situations, these classes are used to access individual
|
||||
* filters from filter configuration files.
|
||||
* <P>
|
||||
*
|
||||
* For example, you might do the following:
|
||||
* <P>
|
||||
*
|
||||
* <OL>
|
||||
* <LI>Connect to the LDAP server and accept a set of search criteria.
|
||||
* <LI>Create an LDAP filter configuration file.
|
||||
* <LI>Call the <CODE>LDAPFilterDescriptor</CODE> constructor to
|
||||
* read the filter configuration file into memory.
|
||||
* <LI>Call the <CODE>getFilters</CODE> method to get a list of
|
||||
* filters that match the search criteria. This list of filters
|
||||
* is represented by an <CODE>LDAPFilterList</CODE> object.
|
||||
* <LI>Iterate through the list of filters (each filter is represented
|
||||
* by an <CODE>LDAPFilter</CODE> object), and apply the filter to
|
||||
* a search.
|
||||
* </OL>
|
||||
* <P>
|
||||
*
|
||||
* For an example of using an object of this class and for more information on
|
||||
* the filter configuration file syntax, see the documentation for <a
|
||||
* href="n.l.u.LDAPFilterDescriptor.html">LDAPFilterDescriptor</a>.
|
||||
* <P>
|
||||
*
|
||||
* @see LDAPFilterDescriptor
|
||||
* @see LDAPFilterList
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class LDAPFilter implements Cloneable {
|
||||
|
||||
private static final int DEFAULT_FILTER_LENGTH = 256;
|
||||
|
||||
private String m_strFilter = null;
|
||||
private String m_strDescription; // token 4 from filter configuration file
|
||||
private int m_nScope; // token 5 from filter configuration file
|
||||
private boolean m_bIsExact;
|
||||
|
||||
private String m_strMatchPattern; // token 1 from filter configuration file
|
||||
private String m_strDelimeter; // token 2 from filter configuration file
|
||||
private String m_strFilterTemplate; // token 3 from filter configuration file
|
||||
|
||||
private int m_nLine;
|
||||
private String m_strSuffix;
|
||||
private String m_strPrefix;
|
||||
|
||||
/**
|
||||
* Constructs an <CODE>LDAPFilter</CODE> object. In most situations,
|
||||
* you do not need to construct an LDAPFilter object. Instead, you
|
||||
* work with <CODE>LDAPFilter</CODE> objects created from the
|
||||
* <CODE>LDAPFilter</CODE> objects and <CODE>LDAPFilterDescriptor</CODE>
|
||||
* objects.
|
||||
* <P>
|
||||
*
|
||||
* This constructor uses the integer value for a search scope in
|
||||
* addition to other information to construct an <CODE>LDAPFilter</CODE>
|
||||
* object. The integer value of the search scope can be one of the
|
||||
* following:
|
||||
* <ul>
|
||||
* <li><CODE>LDAPConnection.SCOPE_BASE</CODE>
|
||||
* <li><CODE>LDAPConnection.SCOPE_ONE</CODE>
|
||||
* <li><CODE>LDAPConnection.SCOPE_SUB</CODE>
|
||||
* </ul>
|
||||
*
|
||||
* If an invalid scope is specified, the constructor throws an
|
||||
* <CODE>illegalArgumentException</CODE>.
|
||||
*/
|
||||
public LDAPFilter ( String strMatchPattern,
|
||||
String strDelimeter,
|
||||
String strFilterTemplate,
|
||||
String strDescription,
|
||||
int nScope ) throws IllegalArgumentException{
|
||||
|
||||
m_strMatchPattern = convertMatchPattern ( strMatchPattern );
|
||||
m_strDelimeter = strDelimeter;
|
||||
m_strFilterTemplate = strFilterTemplate;
|
||||
m_strDescription = strDescription;
|
||||
m_nScope = nScope;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an <CODE>LDAPFilter</CODE> object. In most situations,
|
||||
* you do not need to construct an LDAPFilter object. Instead, you
|
||||
* work with <CODE>LDAPFilter</CODE> objects created from the
|
||||
* <CODE>LDAPFilter</CODE> objects and <CODE>LDAPFilterDescriptor</CODE>
|
||||
* objects.
|
||||
* <P>
|
||||
*
|
||||
* This constructor uses the string value for a search scope in
|
||||
* addition to other information to construct an <CODE>LDAPFilter</CODE>
|
||||
* object. The string value of the search scope can be one of the
|
||||
* following:
|
||||
* <ul>
|
||||
* <li><CODE>"base"</CODE>
|
||||
* <li><CODE>"onelevel"</CODE>
|
||||
* <li><CODE>"subtree"</CODE>
|
||||
* </ul>
|
||||
*
|
||||
* If an invalid scope is specified, the constructor throws an
|
||||
* <CODE>illegalArgumentException</CODE>.
|
||||
*/
|
||||
public LDAPFilter ( String strMatchPattern,
|
||||
String strDelimeter,
|
||||
String strFilterTemplate,
|
||||
String strDescription,
|
||||
String strScope )
|
||||
throws IllegalArgumentException {
|
||||
if ( strScope.equals ( "base" ) ) {
|
||||
m_nScope = LDAPConnection.SCOPE_BASE;
|
||||
|
||||
} else if ( strScope.equals ( "onelevel" ) ) {
|
||||
m_nScope = LDAPConnection.SCOPE_ONE;
|
||||
|
||||
} else if ( strScope.equals ( "subtree" ) ) {
|
||||
m_nScope = LDAPConnection.SCOPE_SUB;
|
||||
}
|
||||
|
||||
m_strMatchPattern = strMatchPattern;
|
||||
m_strDelimeter = strDelimeter;
|
||||
m_strFilterTemplate = strFilterTemplate;
|
||||
m_strDescription = strDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print out a string representation of the LDAPFilter.
|
||||
* Basically, it prints out the appropriate fields.
|
||||
* <P>
|
||||
*
|
||||
* For example, suppose you called the method in this way:
|
||||
* <P>
|
||||
*
|
||||
* <PRE>System.out.println(filter.toString());</PRE>
|
||||
*
|
||||
* The resulting output might look like this:
|
||||
* <P>
|
||||
*
|
||||
* <PRE>
|
||||
* matchPtn: "@"
|
||||
* delim: " "
|
||||
* filttmpl: "(mail=%v*)"
|
||||
* descript: "start of email address"
|
||||
* scope: "LDAPConnection.SCOPE_SUB"
|
||||
* line: "32"
|
||||
* FILTER: "(mail=babs@aceindustry.com*)"
|
||||
* </PRE>
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer strBuf = new StringBuffer ( 300 );
|
||||
strBuf.append ( " matchPtn: \"" + m_strMatchPattern+"\"\n" );
|
||||
strBuf.append ( " delim: \"" + m_strDelimeter+"\"\n" );
|
||||
strBuf.append ( " filttmpl: \"" + m_strFilterTemplate+"\"\n" );
|
||||
strBuf.append ( " descript: \"" + m_strDescription+"\"\n" );
|
||||
switch ( m_nScope ) {
|
||||
case LDAPConnection.SCOPE_BASE:
|
||||
strBuf.append ( " scope: \"LDAPConnection.SCOPE_BASE\"\n" );
|
||||
break;
|
||||
case LDAPConnection.SCOPE_ONE:
|
||||
strBuf.append ( " scope: \"LDAPConnection.SCOPE_ONE\"\n" );
|
||||
break;
|
||||
case LDAPConnection.SCOPE_SUB:
|
||||
strBuf.append ( " scope: \"LDAPConnection.SCOPE_SUB\"\n" );
|
||||
break;
|
||||
}
|
||||
strBuf.append ( " line: \"" + m_nLine+"\"\n" );
|
||||
strBuf.append ( " FILTER: \"" + m_strFilter+"\"\n" );
|
||||
|
||||
return strBuf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the filter string, given the string <CODE>strValue</CODE>.
|
||||
* If the <CODE>strPrefix</CODE> and <CODE>strSuffix</CODE> arguments
|
||||
* are non-null strings, they are prepended and appended
|
||||
* to the filter string (respectively).
|
||||
* <P>
|
||||
*
|
||||
* This string, which is available through the <CODE>getFilter()</CODE>
|
||||
* method, should be suitable for use as search criteria when
|
||||
* calling the <CODE>LDAPConnection.search()</CODE> method.
|
||||
* <P>
|
||||
*
|
||||
* <b>Notes:</b>
|
||||
* <P>
|
||||
*
|
||||
* <UL>
|
||||
* <LI>This method <i>does not</i> maintain the affixes
|
||||
* set with the <CODE>LDAPFilterDescriptor.setFilterAffixes</CODE>
|
||||
* method, so you
|
||||
* need to explicitly define any filter prefixes or suffixes here.<p>
|
||||
*
|
||||
* <LI> This method only uses the
|
||||
* strPrefix and strSuffix for this invocation of setupFilter. It
|
||||
* does not redefine strPrefix and strSuffix for later
|
||||
* invocations. <p>
|
||||
* </UL>
|
||||
* <P>
|
||||
*
|
||||
* @see netscape.ldap.util.LDAPFilterDescriptor#setFilterAffixes
|
||||
* @see #setFilterAffixes
|
||||
*/
|
||||
public void setupFilter ( String strValue, String strPrefix,
|
||||
String strSuffix ) {
|
||||
createFilterString ( strValue, strPrefix, strSuffix );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the filter string, given the string <CODE>strValue</CODE>.
|
||||
* This string, which is available through the <CODE>getFilter()</CODE>
|
||||
* method, should be suitable for use as search criteria when
|
||||
* calling the <CODE>LDAPConnection.search()</CODE> method.
|
||||
* <P>
|
||||
*
|
||||
* <b>Note:</b> If you want to specify a filter prefix and suffix,
|
||||
* you need to explicitly define them by calling the
|
||||
* <CODE>setFilterAffixes()</CODE> method.
|
||||
*
|
||||
* @see netscape.ldap.util.LDAPFilterDescriptor#setFilterAffixes
|
||||
* @see #setFilterAffixes
|
||||
*
|
||||
*/
|
||||
public void setupFilter ( String strValue ) {
|
||||
createFilterString ( strValue, null, null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the filter string which can be used in
|
||||
* LDAPConnection.search() and others given the parameter
|
||||
* strValue. If strPrefix and strSuffix are non-null strings,
|
||||
* prepend strPrefix and append strSuffix.
|
||||
*/
|
||||
void createFilterString ( String strValue, String strPrefix,
|
||||
String strSuffix ) {
|
||||
StringTokenizer strTok =
|
||||
new StringTokenizer ( strValue, m_strDelimeter );
|
||||
|
||||
// Initialize an array of broken up values so that we
|
||||
// can reference them directly.
|
||||
String[] aValues = new String[strTok.countTokens()];
|
||||
int nTokens = strTok.countTokens();
|
||||
for ( int i = 0; i < nTokens; i++ ) {
|
||||
aValues[i] = strTok.nextToken();
|
||||
}
|
||||
|
||||
StringBuffer sbFilter = new StringBuffer ( DEFAULT_FILTER_LENGTH);
|
||||
if ( strPrefix != null ) {
|
||||
sbFilter.append ( strPrefix );
|
||||
}
|
||||
char[] cFilterTemplate = m_strFilterTemplate.toCharArray();
|
||||
int i = 0;
|
||||
while ( i < cFilterTemplate.length ) {
|
||||
if ( cFilterTemplate[i] == '%' ) {
|
||||
i++;
|
||||
if ( cFilterTemplate[i] == 'v' ) {
|
||||
if ( i == (cFilterTemplate.length-1) ) {
|
||||
sbFilter.append ( strValue );
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
switch ( cFilterTemplate[i] ) {
|
||||
case '$':
|
||||
sbFilter.append ( aValues[aValues.length] );
|
||||
break;
|
||||
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
int nValue = Integer.parseInt
|
||||
( new Character
|
||||
(cFilterTemplate[i]).toString() );
|
||||
nValue--;
|
||||
i++;
|
||||
if ( cFilterTemplate[i] == '-' ) {
|
||||
i++;
|
||||
if ( Character.isDigit ( cFilterTemplate[i] )) {
|
||||
int nValue2 = Integer.parseInt
|
||||
( new Character
|
||||
(cFilterTemplate[i]).toString() );
|
||||
nValue2--;
|
||||
for ( int j = nValue; j <= nValue2; j++ ) {
|
||||
sbFilter.append ( aValues[j] );
|
||||
sbFilter.append
|
||||
( ( j == nValue2 ) ? "" : " " );
|
||||
}
|
||||
} else {
|
||||
for ( int j = nValue; j < aValues.length;j++ ) {
|
||||
sbFilter.append ( aValues[j] );
|
||||
sbFilter.append
|
||||
( ( j == aValues.length - 1 ) ? "" : " " );
|
||||
}
|
||||
sbFilter.append ( cFilterTemplate[i]);
|
||||
}
|
||||
|
||||
} else {
|
||||
sbFilter.append ( aValues[nValue] );
|
||||
sbFilter.append ( cFilterTemplate[i] );
|
||||
}
|
||||
break;
|
||||
|
||||
// We just got a plain old %v, so insert the
|
||||
// strValue
|
||||
default:
|
||||
sbFilter.append ( strValue );
|
||||
sbFilter.append ( cFilterTemplate[i] );
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
sbFilter.append ( "%" );
|
||||
sbFilter.append ( cFilterTemplate[i] );
|
||||
}
|
||||
} else {
|
||||
sbFilter.append ( cFilterTemplate[i] );
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if ( strSuffix != null ) {
|
||||
sbFilter.append ( strSuffix );
|
||||
}
|
||||
m_strFilter = sbFilter.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Makes a copy of this <CODE>LDAPFilter</CODE> object.
|
||||
*/
|
||||
public Object clone() {
|
||||
try {
|
||||
return super.clone();
|
||||
} catch ( CloneNotSupportedException e ) {
|
||||
// this shouldn't happen, since we are Cloneable
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the line number from which this filter was created. This
|
||||
* is used only when the LDAPFilter is created when an
|
||||
* LDAPFilterDescriptor is initialized from a file/URL/buffer.
|
||||
*/
|
||||
void setLine ( int nLine ) {
|
||||
m_nLine = nLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* The ldapfilter.conf specifies match patterns in a funny way.
|
||||
* A "." means "any character" except when used inside of a set of
|
||||
* square brackets "[]", in which case, the "." means just a
|
||||
* plain old period (not a * special character).
|
||||
*
|
||||
* This function converts periods inside of a set of square
|
||||
* brackets into a "\." as per normal regexp code.
|
||||
*/
|
||||
String convertMatchPattern ( String strMatchPattern ) {
|
||||
StringBuffer sb = new StringBuffer ( strMatchPattern.length() + 1);
|
||||
char[] a_cMatchPattern = strMatchPattern.toCharArray();
|
||||
boolean bInBrackets = false;
|
||||
for ( int i = 0; i < a_cMatchPattern.length; i++ ) {
|
||||
if ( a_cMatchPattern[i] == '.' ) {
|
||||
if ( bInBrackets ) {
|
||||
sb.append ( "\\" );
|
||||
}
|
||||
} else if ( a_cMatchPattern[i] == '[' ) {
|
||||
bInBrackets = true;
|
||||
} else if ( a_cMatchPattern[i] == ']' ) {
|
||||
bInBrackets = false;
|
||||
}
|
||||
sb.append ( a_cMatchPattern[i] );
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the filter string. This method will return null if the
|
||||
* filter string has not been calculated by the <CODE>setupFilter()</CODE>,
|
||||
* <CODE>getFilter (strValue)</CODE>, or <CODE>getFilter (strValue,
|
||||
* strPrefix, strSuffix )</CODE> methods.
|
||||
*
|
||||
* @see #setupFilter
|
||||
* @see #getFilter
|
||||
*/
|
||||
public String getFilter () {
|
||||
return m_strFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a filter string given a string value. This method uses
|
||||
* any Prefixes or Suffixes that have been set by the
|
||||
* setFilterAffixes() method.<p>
|
||||
*
|
||||
* This is the same as doing:
|
||||
* <pre>
|
||||
* setupFilter ( strValue );
|
||||
* getFilter();
|
||||
* </pre>
|
||||
*/
|
||||
public String getFilter ( String strValue ) {
|
||||
createFilterString ( strValue, m_strPrefix, m_strSuffix );
|
||||
return m_strFilter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a filter string given a string value. If strPrefix
|
||||
* and/or strSuffix is non-null, these values are prepended and
|
||||
* appended to the returned string.<p>
|
||||
*
|
||||
* This is the same as doing:
|
||||
* <pre>
|
||||
* setupFilter ( strValue, strPrefix, strSuffix );
|
||||
* getFilter();
|
||||
* </pre>
|
||||
*/
|
||||
public String getFilter ( String strValue, String strPrefix,
|
||||
String strSuffix ) {
|
||||
createFilterString ( strValue, strPrefix, strSuffix );
|
||||
return m_strFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this filter's match pattern. The match pattern is
|
||||
* found as the first token in a filter configuration line in the
|
||||
* ldapfilter.conf file.
|
||||
*/
|
||||
public String getMatchPattern() {
|
||||
return m_strMatchPattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this filter's delimeter. The delmimeter is
|
||||
* found as the second token in a filter configuration line in the
|
||||
* ldapfilter.conf file.
|
||||
*/
|
||||
public String getDelimeter() {
|
||||
return m_strDelimeter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this filter's filter template. The filter template is
|
||||
* found as the third token in a filter configuration line in the
|
||||
* ldapfilter.conf file.
|
||||
*/
|
||||
public String getFilterTemplate() {
|
||||
return m_strFilterTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this filter's description. The description is
|
||||
* found as the fourth token in a filter configuration line in the
|
||||
* ldapfilter.conf file.
|
||||
*/
|
||||
public String getDescription() {
|
||||
return m_strDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this filter's scope. The scope is
|
||||
* found as the fifth (optional) token in a filter configuration
|
||||
* line in the ldapfilter.conf file.
|
||||
*/
|
||||
public String getScope() {
|
||||
switch ( m_nScope ) {
|
||||
case LDAPConnection.SCOPE_BASE:
|
||||
return "base";
|
||||
|
||||
case LDAPConnection.SCOPE_ONE:
|
||||
return "onelevel";
|
||||
|
||||
case LDAPConnection.SCOPE_SUB:
|
||||
return "subtree";
|
||||
|
||||
default:
|
||||
return "UNKNOWN!";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this filter's line number. The line number is
|
||||
* mostly a debugging variable to let the developer know which
|
||||
* filter from the filter configuration file is being used.
|
||||
*/
|
||||
public String getLineNumber() {
|
||||
return Integer.toString ( m_nLine );
|
||||
}
|
||||
|
||||
public void setFilterAffixes ( String strPrefix, String strSuffix ) {
|
||||
m_strPrefix = strPrefix;
|
||||
m_strSuffix = strSuffix;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,492 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.util;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.net.*;
|
||||
import com.oroinc.text.regex.*;
|
||||
import netscape.ldap.*;
|
||||
|
||||
/**
|
||||
* Represents an LDAP filter configuration file read into memory.
|
||||
* <P>
|
||||
*
|
||||
* Once you read in a filter file to create an object of this class,
|
||||
* you can access the filter information through the methods that create
|
||||
* <CODE>LDAPFilterList</CODE> and <CODE>LDAPFilter</CODE> objects.
|
||||
* (You do not need to manually construct these objects yourself.)
|
||||
* <P>
|
||||
*
|
||||
* This class (along with the other LDAP filter classes) provide
|
||||
* functionality equivalent to the LDAP filter functions in the LDAP C API.
|
||||
* <p>
|
||||
*
|
||||
* The format of the file/URL/buffer must be that as defined in the
|
||||
* ldapfilter.conf(5) man page from the University of Michigan LDAP-3.3
|
||||
* distribution. <p>
|
||||
*
|
||||
* The LDAP filter classes provide a powerful way to configure LDAP clients
|
||||
* by modifying a configuration file.<p>
|
||||
*
|
||||
* The following is a short example for how to use the
|
||||
* LDAP filter classes.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* // ... Setup LDAPConnection up here ...
|
||||
* <p>
|
||||
*
|
||||
* LDAPFilterDescriptor filterDescriptor;
|
||||
* <p>
|
||||
*
|
||||
* // Create the LDAPFilterDescriptor given the file
|
||||
* // "ldapfilter.conf".
|
||||
* try {
|
||||
* filterDescriptor = new LDAPFilterDescriptor ( "ldapfilter.conf" );
|
||||
* <p>
|
||||
*
|
||||
* // Now retrieve the Filters in the form of an
|
||||
* // LDAPFilterList
|
||||
* LDAPFilterList filterList = new filterDescriptor.getFilters("match_tag", "string_user_typed");
|
||||
* <p>
|
||||
*
|
||||
* // For each filter, do the search. Normally, you wouldn't
|
||||
* // do the search if the first filter matched, but this is
|
||||
* // just showing the enumeration type aspects of
|
||||
* // LDAPFilterList
|
||||
* LDAPFilter filter;
|
||||
* while ( filterList.hasMoreElements() ) {
|
||||
* filter = filterList.next();
|
||||
* LDAPResults results = LDAPConnection.search (
|
||||
* strBase, // base DN
|
||||
* filter.getScope(), // scope
|
||||
* filter.getFilter(), // completed filter
|
||||
* null, // all attribs
|
||||
* false ); // attrsOnly?
|
||||
* }
|
||||
* <p>
|
||||
*
|
||||
* // ...more processing here...
|
||||
* } catch ( BadFilterException e ) {
|
||||
* System.out.println ( e.toString() );
|
||||
* System.exit ( 0 );
|
||||
* } catch ( IOException e ) {
|
||||
* // ...handle exception here...
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @see LDAPFilterList
|
||||
* @see LDAPFilter
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LDAPFilterDescriptor {
|
||||
|
||||
private Vector m_vFilterSet = new Vector();
|
||||
|
||||
private String m_strLine;
|
||||
private int m_nLine;
|
||||
|
||||
private String m_strPrefix;
|
||||
private String m_strAffix;
|
||||
private LDAPIntFilterSet m_tmpFilterSet = null;
|
||||
private String m_strLastMatchPattern = null;
|
||||
private String m_strLastDelimiter = null;
|
||||
|
||||
/**
|
||||
* The Default scope is used when a scope is not defined
|
||||
* in the filter file. The scope is the only "optional" parameter
|
||||
* in the file.
|
||||
*/
|
||||
private static final int DEFAULT_SCOPE = LDAPConnection.SCOPE_SUB;
|
||||
|
||||
/**
|
||||
* Creates an LDAPFilterDescriptor object from an existing filter
|
||||
* configuration file. This file has the format as defined in the
|
||||
* ldapfilter.conf(5) man page.
|
||||
*
|
||||
* @exception netscape.ldap.util.BadFilterException
|
||||
* One of the filters was not generated properly. Most likely
|
||||
* this is due to an improperly formatted ldapfilter.conf file.
|
||||
*/
|
||||
public LDAPFilterDescriptor ( String strFile )
|
||||
throws FileNotFoundException, BadFilterException {
|
||||
DataInputStream inputStream =
|
||||
new DataInputStream ( new FileInputStream ( strFile ) );
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||
init( reader );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an LDAPFilterDescriptor object from an existing
|
||||
* StringBuffer. This file has the format as defined in the
|
||||
* ldapfilter.conf(5) man page.
|
||||
*
|
||||
* @exception netscape.ldap.util.BadFilterException
|
||||
* One of the filters was not generated properly. Most likely
|
||||
* this is due to an improperly formatted ldapfilter.conf file.
|
||||
*/
|
||||
public LDAPFilterDescriptor ( StringBuffer strBuffer )
|
||||
throws BadFilterException {
|
||||
init( strBuffer );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an LDAPFilterDescriptor object from a URL.
|
||||
* This file has the format as defined in the
|
||||
* ldapfilter.conf(5) man page.
|
||||
*
|
||||
* @exception netscape.ldap.util.BadFilterException
|
||||
* One of the filters was not generated properly. Most likely
|
||||
* this is due to an improperly formatted ldapfilter.conf file.
|
||||
*/
|
||||
public LDAPFilterDescriptor ( URL url )
|
||||
throws IOException, BadFilterException {
|
||||
URLConnection urlc = url.openConnection();
|
||||
DataInputStream inputStream =
|
||||
new DataInputStream ( urlc.getInputStream() );
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||
init( reader );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This function initializes the LDAPFilterDescriptor. It's
|
||||
* called internally, and should never be called directly by the
|
||||
* developer.
|
||||
*/
|
||||
private void init ( Object inputObj)
|
||||
throws BadFilterException {
|
||||
|
||||
String strCommentPattern = "(?:^\\s*#|^\\s*$)";
|
||||
String strDataPattern = "(?:\\s*\"([^\"]*)\"|([^\\s]*))\\s*";
|
||||
Perl5Compiler compiler = new Perl5Compiler();
|
||||
Perl5Pattern patComment;
|
||||
Perl5Pattern patData;
|
||||
Vector vStrings = new Vector ( 5 );
|
||||
|
||||
try {
|
||||
patComment = (Perl5Pattern)compiler.compile ( strCommentPattern );
|
||||
patData = (Perl5Pattern)compiler.compile ( strDataPattern );
|
||||
} catch ( MalformedPatternException e ) {
|
||||
// This should NEVER happen...
|
||||
System.out.println ( "FATAL Error, couldn't compile pattern");
|
||||
System.out.println ( " " + e.getMessage() );
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup some temporary variables.
|
||||
m_nLine = 0;
|
||||
try {
|
||||
if (inputObj instanceof StringBuffer) {
|
||||
StringBuffer ibuffer = (StringBuffer)inputObj;
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
for (int i=0; i<ibuffer.length(); i++) {
|
||||
if (ibuffer.charAt(i) == '\n') {
|
||||
m_strLine = buffer.toString();
|
||||
m_nLine++;
|
||||
setFilter(patComment, patData, vStrings);
|
||||
buffer = new StringBuffer();
|
||||
} else
|
||||
buffer.append(ibuffer.charAt(i));
|
||||
}
|
||||
} else {
|
||||
while ((m_strLine=((BufferedReader)inputObj).readLine()) != null) {
|
||||
m_nLine++;
|
||||
setFilter(patComment, patData, vStrings);
|
||||
}
|
||||
}
|
||||
|
||||
// BUGBUG: Fixed. 7-28-97
|
||||
// We're done with the input, so we need to append the
|
||||
// last temporary FilterSet into the list of FilterSets.
|
||||
if ( m_tmpFilterSet != null ) {
|
||||
m_vFilterSet.addElement ( m_tmpFilterSet );
|
||||
}
|
||||
|
||||
} catch ( IOException e ) {
|
||||
}
|
||||
}
|
||||
|
||||
private void setFilter(Perl5Pattern patComment, Perl5Pattern patData,
|
||||
Vector vStrings) throws IOException, BadFilterException {
|
||||
MatchResult result;
|
||||
Perl5Matcher matcher = new Perl5Matcher();
|
||||
PatternMatcherInput input;
|
||||
LDAPFilter tmpFilter = null;
|
||||
|
||||
input = new PatternMatcherInput ( m_strLine );
|
||||
|
||||
if ( ! ( matcher.contains ( input, patComment ) ) ) {
|
||||
input.setCurrentOffset(input.getBeginOffset());
|
||||
// System.out.println ( "\nNEW LINE: " + m_strLine );
|
||||
if ( ! vStrings.isEmpty() ) {
|
||||
vStrings.removeAllElements();
|
||||
}
|
||||
|
||||
while ( matcher.contains ( input, patData ) ) {
|
||||
// Within this while loop, we're looking for
|
||||
// all the data tokens. Our regular
|
||||
// expression is setup to look for words
|
||||
// separated by whitespace or sets of
|
||||
// characters in quotataion marks. A remnant
|
||||
// of the regexp is that we have two
|
||||
// backreferences, only one will have data at
|
||||
// any time.
|
||||
result = matcher.getMatch();
|
||||
for ( int i = 1; i <=2; i++ ) {
|
||||
if ( result.group(i) != null ) {
|
||||
if ( ! result.group(i).equals ( "" ) ) {
|
||||
//System.out.println ( "Match #" + i +
|
||||
// ": \"" + result.group(i) + "\"" );
|
||||
vStrings.addElement ( result.group(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch ( vStrings.size() ) {
|
||||
case 1:
|
||||
// If the current filter set is not null,
|
||||
// add it to the filter set vector.
|
||||
if ( m_tmpFilterSet != null ) {
|
||||
m_vFilterSet.addElement ( m_tmpFilterSet );
|
||||
}
|
||||
|
||||
// Now create a new filterset.
|
||||
m_tmpFilterSet = new LDAPIntFilterSet
|
||||
( (String)vStrings.elementAt ( 0 ) );
|
||||
|
||||
break;
|
||||
|
||||
// Two tokens mens we're the the second (or
|
||||
// higher line in a token. We need to append
|
||||
// the information stored in the list onto
|
||||
// the tmpFilter.
|
||||
case 2:
|
||||
|
||||
if ( ( m_strLastMatchPattern != null ) &&
|
||||
( m_strLastDelimiter != null ) ) {
|
||||
tmpFilter = new LDAPFilter(
|
||||
m_strLastMatchPattern,
|
||||
m_strLastDelimiter,
|
||||
(String)vStrings.elementAt ( 0 ),
|
||||
(String)vStrings.elementAt ( 1 ),
|
||||
DEFAULT_SCOPE );
|
||||
tmpFilter.setLine ( m_nLine );
|
||||
if ( m_tmpFilterSet != null ) {
|
||||
m_tmpFilterSet.appendFilter ( tmpFilter );
|
||||
} else {
|
||||
throw MakeException ( "Attempting to add a filter to a null filterset" );
|
||||
}
|
||||
} else {
|
||||
throw MakeException ( "Attempting to create a relative filter with no preceeding full filter" );
|
||||
}
|
||||
break;
|
||||
|
||||
// Three tokens means we're the second (or
|
||||
// higher line in a filter. create a new
|
||||
// filter grabbing info from the last filter
|
||||
case 3:
|
||||
|
||||
if ( ( m_strLastMatchPattern != null ) &&
|
||||
( m_strLastDelimiter != null ) ) {
|
||||
tmpFilter = new LDAPFilter (
|
||||
m_strLastMatchPattern,
|
||||
m_strLastDelimiter,
|
||||
(String)vStrings.elementAt ( 0 ),
|
||||
(String)vStrings.elementAt ( 1 ),
|
||||
(String)vStrings.elementAt ( 2 ) );
|
||||
tmpFilter.setLine ( m_nLine );
|
||||
|
||||
|
||||
if ( m_tmpFilterSet != null ) {
|
||||
m_tmpFilterSet.appendFilter ( tmpFilter );
|
||||
} else {
|
||||
throw MakeException
|
||||
("Attempting to add a filter to a null filterset");
|
||||
}
|
||||
|
||||
} else {
|
||||
throw MakeException
|
||||
("Attempting to create a relative filter with no preceeding full filter" );
|
||||
}
|
||||
break;
|
||||
|
||||
// 4 tokens means this is the first line in a
|
||||
// token. All data is new. However, we're using
|
||||
// the default scope.
|
||||
case 4:
|
||||
tmpFilter = new LDAPFilter (
|
||||
(String)vStrings.elementAt ( 0 ),
|
||||
(String)vStrings.elementAt ( 1 ),
|
||||
(String)vStrings.elementAt ( 2 ),
|
||||
(String)vStrings.elementAt ( 3 ),
|
||||
DEFAULT_SCOPE );
|
||||
tmpFilter.setLine ( m_nLine );
|
||||
m_strLastMatchPattern = (String)vStrings.elementAt ( 0 );
|
||||
m_strLastDelimiter = (String)vStrings.elementAt ( 1 );
|
||||
if ( m_tmpFilterSet != null ) {
|
||||
m_tmpFilterSet.newFilter ( tmpFilter );
|
||||
} else {
|
||||
throw MakeException
|
||||
("Attempting to add a filter to a null filterset");
|
||||
}
|
||||
break;
|
||||
|
||||
// 5 tokens means this is the first line in a
|
||||
// token. All data is new.
|
||||
case 5:
|
||||
tmpFilter = new LDAPFilter (
|
||||
(String)vStrings.elementAt ( 0 ),
|
||||
(String)vStrings.elementAt ( 1 ),
|
||||
(String)vStrings.elementAt ( 2 ),
|
||||
(String)vStrings.elementAt ( 3 ),
|
||||
(String)vStrings.elementAt ( 4 ) );
|
||||
tmpFilter.setLine ( m_nLine );
|
||||
m_strLastMatchPattern = (String)vStrings.elementAt ( 0 );
|
||||
m_strLastDelimiter = (String)vStrings.elementAt ( 1 );
|
||||
if ( m_tmpFilterSet != null ) {
|
||||
m_tmpFilterSet.newFilter ( tmpFilter );
|
||||
} else {
|
||||
throw MakeException
|
||||
("Attempting to add a filter to a null filterset");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw MakeException ( "Wrong number of tokens (" + vStrings.size() + ")" );
|
||||
|
||||
//break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* just a utility method to create an exception.
|
||||
*/
|
||||
private BadFilterException MakeException ( String strMsg ) {
|
||||
return new BadFilterException
|
||||
( "BadFilterException while creating Filters,\n" +
|
||||
"Line Number: " + m_nLine +
|
||||
",\n --> " + m_strLine + "\nThe error is: " +
|
||||
strMsg, m_nLine );
|
||||
}
|
||||
|
||||
/**
|
||||
* Output a text dump of this filter descriptor. It cycles
|
||||
* through all of the internal LDAPIntFilterSet objects and calls
|
||||
* their toString() methods.
|
||||
*
|
||||
* @see LDAPIntFilterSet#toString
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer strBuf = new StringBuffer ( 4000 );
|
||||
for ( int i = 0; i < m_vFilterSet.size(); i++ ) {
|
||||
strBuf.append ( "Filter Set number: " + i + "\n" );
|
||||
strBuf.append (
|
||||
((LDAPIntFilterSet)m_vFilterSet.elementAt ( i )).toString() +
|
||||
"\n" );
|
||||
strBuf.append ( "\n" );
|
||||
//System.out.println ( (m_vFilterSet.elementAt ( i )).toString());
|
||||
}
|
||||
return strBuf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the filters which match the strTagPat (regular
|
||||
* expression), and the user input (strValue)
|
||||
*/
|
||||
public LDAPFilterList getFilters ( String strTagPat, String strValue )
|
||||
throws IllegalArgumentException {
|
||||
|
||||
strTagPat = strTagPat.trim();
|
||||
strValue = strValue.trim();
|
||||
|
||||
if ( ( strTagPat == null ) || ( strTagPat.equals ("") ) ) {
|
||||
throw new IllegalArgumentException
|
||||
( "The Tag Pattern can not be null" );
|
||||
}
|
||||
|
||||
if ( ( strValue == null ) || ( strValue.equals ("") ) ) {
|
||||
throw new IllegalArgumentException ( "The Value can not be null" );
|
||||
}
|
||||
|
||||
LDAPFilterList retList = new LDAPFilterList();
|
||||
|
||||
Perl5Compiler compiler = new Perl5Compiler();
|
||||
Perl5Pattern patTag; // The strTagPat that's compiled
|
||||
|
||||
// For efficiency, we're pre-allocating a patternMatcherInput
|
||||
// here.
|
||||
PatternMatcherInput matcherValue = new PatternMatcherInput ( strValue );
|
||||
|
||||
// first we need to make a new regexp from the strTagPat
|
||||
// For efficiency, we're precompiling the strTagPat into
|
||||
// a pattern here. That pattern doesn't change, the Tag string
|
||||
// changes per LDAPFIlterSet.
|
||||
try {
|
||||
patTag = (Perl5Pattern)compiler.compile ( strTagPat );
|
||||
} catch ( MalformedPatternException e ) {
|
||||
throw new IllegalArgumentException
|
||||
( "The parameter: " + strTagPat + " is not valid" );
|
||||
}
|
||||
|
||||
// We "ask" each of the filterset's to see if there is
|
||||
// a matching filter.
|
||||
boolean bMatched = false;
|
||||
int i = 0;
|
||||
while ( ! bMatched ) {
|
||||
Vector vMatchingFilters =
|
||||
((LDAPIntFilterSet)m_vFilterSet.elementAt ( i )).getFilters
|
||||
(patTag, matcherValue );
|
||||
|
||||
if ( vMatchingFilters.size() > 0 ) {
|
||||
for ( int j = 0; j < vMatchingFilters.size(); j++ ) {
|
||||
LDAPFilter tmpFilter =
|
||||
(LDAPFilter)
|
||||
((LDAPFilter)
|
||||
vMatchingFilters.elementAt ( j )).clone();
|
||||
tmpFilter.setupFilter ( strValue, m_strPrefix,
|
||||
m_strAffix );
|
||||
bMatched = true; // this really doesn't matter.
|
||||
retList.add ( tmpFilter );
|
||||
}
|
||||
return retList;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prepend the parameter (strPrefix) and append the second
|
||||
* parameter (strAffix) to every filter that is returned by the
|
||||
* getFilters() method. <p>
|
||||
*/
|
||||
public void setFilterAffixes ( String strPrefix, String strAffix ) {
|
||||
m_strPrefix = strPrefix;
|
||||
m_strAffix = strAffix;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.util;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* The list of LDAPFilter objects returned from a LDAPFilterDescriptor
|
||||
* Object. Note that this is an enumeration, so if multiple iterations
|
||||
* are needed, save the results.
|
||||
*
|
||||
* @see LDAPFilterDescriptor
|
||||
* @see LDAPFilter
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class LDAPFilterList implements Enumeration {
|
||||
private Vector m_vFilterList;
|
||||
private static int DEFAULT_LIST_SIZE = 2;
|
||||
|
||||
/**
|
||||
* Constructs an LDAPFilterList object. This methos shouldn't need to
|
||||
* be called by the developer directly. Construction of the
|
||||
* LDAPFilterList object should take place when the Prepare function
|
||||
* of LDAPFilterDescriptor is called.
|
||||
*
|
||||
*/
|
||||
public LDAPFilterList () {
|
||||
m_vFilterList = new Vector ( DEFAULT_LIST_SIZE );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add an LDAPFilter to the private vector. Since the filter we're
|
||||
* being passed has already been cloned from the master
|
||||
* LDAPFilterDescriptor set, all we have to do is add it to the list.
|
||||
*/
|
||||
void add ( LDAPFilter filter ) {
|
||||
m_vFilterList.addElement ( filter );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there are any LDAPFilter objects to returned.
|
||||
*/
|
||||
public boolean hasMoreElements() {
|
||||
return ( ! m_vFilterList.isEmpty() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next LDAPFilter as an Object. Note: the preferred way
|
||||
* to return the next LDAPFilter is to call next()
|
||||
*
|
||||
* @see LDAPFilterList#next()
|
||||
* @return The next LDAPFilter object (as an instance of Object)
|
||||
*/
|
||||
public Object nextElement() {
|
||||
Object o = m_vFilterList.firstElement();
|
||||
m_vFilterList.removeElementAt ( 0 );
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next LDAPFilter
|
||||
*
|
||||
* @return The next LDAPFilter
|
||||
*/
|
||||
public LDAPFilter next() {
|
||||
Object o = m_vFilterList.firstElement();
|
||||
m_vFilterList.removeElementAt ( 0 );
|
||||
return (LDAPFilter)o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of filters in the filter list.
|
||||
* Note that this number decreases every time next() or nextElement() is
|
||||
* called because the elements are removed as they're returned.
|
||||
*/
|
||||
public int numFilters (){
|
||||
return m_vFilterList.size();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.util;
|
||||
|
||||
import java.util.*;
|
||||
import com.oroinc.text.regex.*;
|
||||
|
||||
/**
|
||||
* Represents an Internal LDAPFilterList object. This is an internal object
|
||||
* that should never be instantiated directly by the developer. We
|
||||
* store all filters that have the same match pattern here.
|
||||
*/
|
||||
|
||||
public class LDAPIntFilterList {
|
||||
private Vector m_vFilter;
|
||||
private String m_strMatchPattern;
|
||||
// a regexp pattern of m_strMatchPattern
|
||||
private Perl5Pattern m_patMatch = null;
|
||||
private Perl5Matcher m_matcher;
|
||||
private Perl5Compiler m_compiler;
|
||||
|
||||
LDAPIntFilterList ( LDAPFilter filter ) throws
|
||||
BadFilterException {
|
||||
m_strMatchPattern = filter.getMatchPattern();
|
||||
|
||||
// We're going to compile the pattern for strMatchPattern
|
||||
// now, so that we can throw an exception if it is a bad
|
||||
// pattern.
|
||||
m_matcher = new Perl5Matcher();
|
||||
m_compiler = new Perl5Compiler();
|
||||
|
||||
try {
|
||||
m_patMatch = (Perl5Pattern)m_compiler.compile
|
||||
( m_strMatchPattern );
|
||||
} catch ( MalformedPatternException e ) {
|
||||
|
||||
throw new BadFilterException (
|
||||
"The Regular Expression for this filter is bad. " +
|
||||
"Line number: " + filter.getLineNumber() );
|
||||
}
|
||||
|
||||
m_vFilter = new Vector();
|
||||
m_vFilter.addElement ( filter );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a "relative" filter to an existing filter list. We do this
|
||||
* becuse the ldapfilter file defines that we can have multiple
|
||||
* filters per match pattern (and delimeter). This method is
|
||||
* called by the parent LDAPIntFilterSet because the file specified
|
||||
* a "relative" filter (a filter in the ldapfilter.conf file that
|
||||
* only has 2 or 3 tokens).
|
||||
*/
|
||||
void AddFilter ( LDAPFilter filter ) {
|
||||
m_vFilter.addElement ( filter );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the number of Filters this InternalFilterList contains.
|
||||
*/
|
||||
// Since we're storing the filters as a vector, just return
|
||||
// Vector.size().
|
||||
int numFilters () {
|
||||
return m_vFilter.size();
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
StringBuffer strBuf = new StringBuffer ( 100 );
|
||||
strBuf.append ( " Match Pattern: \"" + m_strMatchPattern + "\"\n" );
|
||||
|
||||
for ( int i = 0; i < m_vFilter.size(); i++ ) {
|
||||
strBuf.append ( ((LDAPFilter)m_vFilter.elementAt(i)).toString() );
|
||||
strBuf.append ( "\n" );
|
||||
}
|
||||
return strBuf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the requested filter.
|
||||
*/
|
||||
LDAPFilter getFilter ( int nFilter ) {
|
||||
return (LDAPFilter)m_vFilter.elementAt ( nFilter );
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to match the filter to the given string. This method is called
|
||||
* when the user types in data. We match the expression (stored in
|
||||
* m_strMatchPattern) to the value that the user typed in (the
|
||||
* parameter to this method).
|
||||
*/
|
||||
boolean MatchFilter ( PatternMatcherInput matcherValue ) {
|
||||
matcherValue.setCurrentOffset ( matcherValue.getBeginOffset() );
|
||||
return m_matcher.contains ( matcherValue, m_patMatch );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.util;
|
||||
|
||||
import java.util.*;
|
||||
import com.oroinc.text.regex.*;
|
||||
/**
|
||||
* Represents an LDAPIntFilterSet object. This is an internal object that
|
||||
* should never be instantiated directly by the developer.
|
||||
*/
|
||||
|
||||
public class LDAPIntFilterSet {
|
||||
|
||||
private Vector m_vLDAPIntFilterList;
|
||||
private String m_strTag;
|
||||
|
||||
private PatternMatcherInput m_matcherTag = null;
|
||||
private Perl5Matcher m_matcher = null;
|
||||
/**
|
||||
* Return a Vector of filters that match botht the tag pattern
|
||||
* (in Perl5Pattern form), and the string strValue. This method
|
||||
* should only be called by LDAPFilterDescriptor().
|
||||
*/
|
||||
|
||||
// remember, we have the string (m_strTag), the pattern has
|
||||
// been precompiled by the LDAPFilterDescriptor (patTag)
|
||||
Vector getFilters ( Perl5Pattern patTag,
|
||||
PatternMatcherInput matcherValue ) {
|
||||
Vector vRet = new Vector();
|
||||
|
||||
if ( m_matcherTag == null ) {
|
||||
m_matcher = new Perl5Matcher();
|
||||
m_matcherTag = new PatternMatcherInput ( m_strTag );
|
||||
} else {
|
||||
m_matcherTag.setCurrentOffset ( m_matcherTag.getBeginOffset() );
|
||||
}
|
||||
|
||||
// Check to see if the strTag (converted into patTag)
|
||||
// matches the tag string from the file (converted into
|
||||
// m_matcherTag)
|
||||
if ( m_matcher.contains ( m_matcherTag, patTag ) ) {
|
||||
LDAPIntFilterList tmpIntFilterList;
|
||||
LDAPFilter tmpFilter;
|
||||
for ( int i = 0; i < m_vLDAPIntFilterList.size(); i++ ) {
|
||||
tmpIntFilterList =
|
||||
(LDAPIntFilterList)m_vLDAPIntFilterList.elementAt ( i );
|
||||
|
||||
if ( tmpIntFilterList.MatchFilter ( matcherValue ) ) {
|
||||
for (int j=0; j < tmpIntFilterList.numFilters(); j++ ) {
|
||||
vRet.addElement ( tmpIntFilterList.getFilter ( j ));
|
||||
}
|
||||
// potential BUGBUG, i'm not sure if we want
|
||||
// to get out of this loop now or if we just
|
||||
// want to get out of the external loop. For
|
||||
// now, go with the former.
|
||||
return vRet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return vRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an LDAPIntFilterSet with a given Tag string. The tag
|
||||
* string specifies which applications or query types should use
|
||||
* this filter set. It is normally a single token on a line by
|
||||
* itself in the filter configuration file. <p>
|
||||
* For more information about the filter configuration file, see
|
||||
* the man page for ldapfilter.conf.
|
||||
*/
|
||||
public LDAPIntFilterSet ( String strTag ) {
|
||||
m_strTag = strTag;
|
||||
m_vLDAPIntFilterList = new Vector();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new filter to this filter set.
|
||||
*
|
||||
* @exception netscape.ldap.util.BadFilterException
|
||||
* If the regular expression pattern given in the first token
|
||||
* is bad.
|
||||
*/
|
||||
void newFilter ( LDAPFilter filter ) throws BadFilterException {
|
||||
LDAPIntFilterList tmpFilterList = new LDAPIntFilterList( filter );
|
||||
m_vLDAPIntFilterList.addElement ( tmpFilterList );
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a new filter to the existing set. This happens when the
|
||||
* LDAPFilterDescriptor object reads a line from the filter
|
||||
* configuration file that has 2 or 3 tokens.
|
||||
*/
|
||||
void appendFilter ( LDAPFilter filter ) {
|
||||
((LDAPIntFilterList)m_vLDAPIntFilterList.lastElement()).AddFilter ( filter );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return true if this filter set matches the regular expression
|
||||
* string that is passed in.
|
||||
*/
|
||||
boolean match ( String strTagPat ) {
|
||||
Perl5Matcher matcher = new Perl5Matcher();
|
||||
Perl5Compiler compiler = new Perl5Compiler();
|
||||
PatternMatcherInput input;
|
||||
Perl5Pattern patTag;
|
||||
MatchResult result;
|
||||
|
||||
try {
|
||||
patTag = (Perl5Pattern)compiler.compile ( strTagPat );
|
||||
} catch ( MalformedPatternException e ) {
|
||||
// Need to do something here.
|
||||
return false;
|
||||
}
|
||||
|
||||
input = new PatternMatcherInput ( m_strTag );
|
||||
if ( matcher.contains ( input, patTag ) ) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print out the String representation of this object. It calls
|
||||
* the toString() method of all the LDAPFilter objects contained
|
||||
* within it's set.
|
||||
*
|
||||
* @see LDAPFilter#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer strBuf = new StringBuffer ( 2000 );
|
||||
strBuf.append ( " strTag: " + m_strTag + "\n" );
|
||||
for ( int i = 0; i < m_vLDAPIntFilterList.size(); i++ ) {
|
||||
strBuf.append ( " filter #: " + i + "\n" );
|
||||
strBuf.append (
|
||||
((LDAPIntFilterList)m_vLDAPIntFilterList.elementAt(i)).toString() );
|
||||
strBuf.append ( "\n" );
|
||||
}
|
||||
return strBuf.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package com.netscape.sasl;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
|
||||
/**
|
||||
* An interface for creating instances of <tt>SaslClient</tt>.
|
||||
*
|
||||
* @see SaslClient
|
||||
* @see Sasl
|
||||
*/
|
||||
public class ClientFactory implements SaslClientFactory {
|
||||
public ClientFactory() {
|
||||
_mechanismTable = new Hashtable();
|
||||
for( int i = 0; i < _mechanismNames.length; i++ ) {
|
||||
_mechanismTable.put( _mechanismNames[i],
|
||||
PACKAGENAME + '.' +
|
||||
_mechanismClasses[i] );
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Creates a SaslClient using the parameters supplied.
|
||||
*
|
||||
* @param mechanisms The non-null list of mechanism names to try.
|
||||
* Each is the IANA-registered name of a SASL mechanism. (e.g.
|
||||
* "GSSAPI", "CRAM-MD5").
|
||||
* @param authorizationId The possibly null authorization ID to
|
||||
* use. When the SASL authentication completes successfully, the
|
||||
* entity named by authorizationId is granted access.
|
||||
* @param protocol The non-null string name of the protocol for
|
||||
* which the authentication is being performed (e.g., "ldap").
|
||||
* @param serverName The non-null string name of the server to
|
||||
* which we are creating an authenticated connection.
|
||||
* @param props The possibly null properties to be used by the SASL
|
||||
* mechanisms to configure the authentication exchange. For example,
|
||||
* "javax.security.sasl.encryption.maximum" might be used to
|
||||
* specify the maximum key length to use for encryption.
|
||||
* @param cbh The possibly null callback handler to used by the
|
||||
* SASL mechanisms to get further information from the
|
||||
* application/library to complete the authentication. For example,
|
||||
* a SASL mechanism might require the authentication ID and
|
||||
* password from the caller.
|
||||
* @return A possibly null <tt>SaslClient</tt> created using the
|
||||
* parameters supplied. If null, this factory cannot produce a
|
||||
* <tt>SaslClient</tt> using the parameters supplied.
|
||||
* @exception SaslException if it cannot create a
|
||||
* <tt>SaslClient</tt> because of an error.
|
||||
*/
|
||||
public SaslClient createSaslClient(
|
||||
String[] mechanisms,
|
||||
String authorizationId,
|
||||
String protocol,
|
||||
String serverName,
|
||||
Hashtable props,
|
||||
CallbackHandler cbh ) throws SaslException {
|
||||
String mechName = null;
|
||||
if ( Sasl.debug ) {
|
||||
System.out.println(
|
||||
"ClientFactory.createSaslClient" );
|
||||
}
|
||||
for( int i = 0; (mechName == null) &&
|
||||
(i < mechanisms.length); i++ ) {
|
||||
mechName = (String)_mechanismTable.get( mechanisms[i] );
|
||||
}
|
||||
if ( mechName != null ) {
|
||||
try {
|
||||
Class c = Class.forName( mechName );
|
||||
SaslClient client = (SaslClient)c.newInstance();
|
||||
if ( Sasl.debug ) {
|
||||
System.out.println(
|
||||
"ClientFactory.createSaslClient: newInstance for " +
|
||||
mechName + " returned " + client);
|
||||
}
|
||||
return client;
|
||||
} catch ( Exception e ) {
|
||||
System.err.println(
|
||||
"ClientFactory.createSaslClient: " + e );
|
||||
}
|
||||
} else {
|
||||
if ( Sasl.debug ) {
|
||||
System.out.println(
|
||||
"ClientFactory.createSaslClient: does not support " +
|
||||
"any of the mechanisms" );
|
||||
for( int i = 0; i < mechanisms.length; i++ ) {
|
||||
System.out.println( " " + mechanisms[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of names of mechanisms supported by this
|
||||
* factory.
|
||||
* @return A non-null array containing IANA-registered SASL
|
||||
* mechanism names.
|
||||
*/
|
||||
public String[] getMechanismNames() {
|
||||
return _mechanismNames;
|
||||
}
|
||||
|
||||
private final String PACKAGENAME = "com.netscape.sasl.mechanisms";
|
||||
private final String[] _mechanismNames = { "EXTERNAL" };
|
||||
private final String[] _mechanismClasses = { "SaslExternal" };
|
||||
private Hashtable _mechanismTable;
|
||||
}
|
||||
235
mozilla/directory/java-sdk/ldapjdk/com/netscape/sasl/Sasl.java
Normal file
235
mozilla/directory/java-sdk/ldapjdk/com/netscape/sasl/Sasl.java
Normal file
@@ -0,0 +1,235 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package com.netscape.sasl;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
import java.util.StringTokenizer;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* A static class for creating SASL clients and servers.
|
||||
*<p>
|
||||
* This class defines the policy of how to locate, load, and instantiate
|
||||
* SASL clients and servers.
|
||||
* Currently, only the client methods are available.
|
||||
*<p>
|
||||
* For example, an application or library gets a SASL client by doing
|
||||
* something like:
|
||||
*<blockquote><pre>
|
||||
* SaslClient sc = Sasl.createSaslClient(mechanisms,
|
||||
* authorizationId, protocol, serverName, props, callbackHandler);
|
||||
*</pre></blockquote>
|
||||
* It can then proceed to use the client create an authentication connection.
|
||||
* For example, an LDAP library might use the client as follows:
|
||||
*<blockquote><pre>
|
||||
* InputStream is = ldap.getInputStream();
|
||||
* OutputStream os = ldap.getOutputStream();
|
||||
* byte[] toServer = sc.createInitialResponse();
|
||||
* LdapResult res = ldap.sendBindRequest(dn, sc.getName(), toServer);
|
||||
* while (!sc.isComplete() && res.status == SASL_BIND_IN_PROGRESS) {
|
||||
* toServer = sc.evaluateChallenge(res.getBytesFromServer());
|
||||
* if (toServer != null) {
|
||||
* res = ldap.sendBindRequest(dn, sc.getName(), toServer);
|
||||
* }
|
||||
* }
|
||||
* if (sc.isComplete() && res.status == SUCCESS) {
|
||||
* // Get the input and output streams; may be unchanged
|
||||
* is = sc.getInputStream( is );
|
||||
* os = sc.getOutputStream( os );
|
||||
* // Use these streams from now on
|
||||
* ldap.setInputStream( is );
|
||||
* ldap.setOutputStream( os );
|
||||
* }
|
||||
*</pre></blockquote>
|
||||
*
|
||||
* IMPLEMENTATION NOTE: To use this class on JDK1.2, the caller needs:
|
||||
*<ul><tt>
|
||||
*<li>java.lang.RuntimePermission("getSecurityManager")
|
||||
*<li>java.lang.RuntimePermission("getClassLoader")
|
||||
*<li>java.util.PropertyPermission("javax.security.sasl.client.pkgs", "read");
|
||||
*</tt></ul>
|
||||
*/
|
||||
public class Sasl {
|
||||
private static SaslClientFactory clientFactory = null;
|
||||
static final boolean debug = false;
|
||||
|
||||
// Cannot create one of these
|
||||
private Sasl() {
|
||||
}
|
||||
|
||||
/**
|
||||
* The property name containing a list of package names, separated by
|
||||
* '|'. Each package contains a class named <tt>ClientFactory</tt> that
|
||||
* implements the <tt>SaslClientFactory</tt> interface.
|
||||
* Its value is "javax.security.sasl.client.pkgs".
|
||||
*/
|
||||
public static final String CLIENTPKGS = "javax.security.sasl.client.pkgs";
|
||||
|
||||
/**
|
||||
* Creates a SaslClient using the parameters supplied.
|
||||
* The algorithm for selection is as follows:
|
||||
*<ol>
|
||||
*<li>If a factory has been installed via <tt>setSaslClientFactory()</tt>,
|
||||
* try it first. If non-null answer produced, return it.
|
||||
*<li>The <tt>javax.security.sasl.client.pkgs</tt> property contains
|
||||
* a '|'-separated list of package names. Each package contains a
|
||||
* class named <tt>ClientFactory</tt>. Load each factory
|
||||
* and try to create a <tt>SaslClient</tt>.
|
||||
* Repeat this for
|
||||
* each package on the list until a non-null answer is produced.
|
||||
* If non-null answer produced, return it.
|
||||
*<li>Repeat previous step using the <tt>javax.security.sasl.client.pkgs</tt>
|
||||
* System property.
|
||||
*<li>If no non-null answer produced, return null.
|
||||
*</ol>
|
||||
*
|
||||
* @param mechanisms The non-null list of mechanism names to try. Each is the
|
||||
* IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5").
|
||||
* @param authorizationId The possibly null authorization ID to use. When
|
||||
* the SASL authentication completes successfully, the entity named
|
||||
* by authorizationId is granted access.
|
||||
* @param protocol The non-null string name of the protocol for which
|
||||
* the authentication is being performed (e.g., "ldap").
|
||||
* @param serverName The non-null string name of the server to which
|
||||
* we are creating an authenticated connection.
|
||||
* @param props The possibly null properties to be used by the SASL
|
||||
* mechanisms to configure the authentication exchange. For example,
|
||||
* "javax.security.sasl.encryption.maximum" might be used to specify
|
||||
* the maximum key length to use for encryption.
|
||||
* @param cbh The possibly null callback handler to used by the SASL
|
||||
* mechanisms to get further information from the application/library
|
||||
* to complete the authentication. For example, a SASL mechanism might
|
||||
* require the authentication ID and password from the caller.
|
||||
*@return A possibly null <tt>SaslClient</tt> created using the parameters
|
||||
* supplied. If null, cannot find a <tt>SaslClientFactory</tt>
|
||||
* that will produce one.
|
||||
*@exception SaslException If cannot create a <tt>SaslClient</tt> because
|
||||
* of an error.
|
||||
*/
|
||||
public static SaslClient createSaslClient(
|
||||
String[] mechanisms,
|
||||
String authorizationId,
|
||||
String protocol,
|
||||
String serverName,
|
||||
Hashtable props,
|
||||
CallbackHandler cbh) throws SaslException {
|
||||
|
||||
if (debug) {
|
||||
System.out.println("Sasl.createSaslClient");
|
||||
}
|
||||
SaslClient mech = null;
|
||||
|
||||
// If factory has been set, try it first
|
||||
if (clientFactory != null) {
|
||||
mech = clientFactory.createSaslClient(
|
||||
mechanisms, authorizationId,
|
||||
protocol, serverName, props, cbh);
|
||||
}
|
||||
|
||||
// No mechanism produced
|
||||
if (mech == null) {
|
||||
String pkgs = (props == null) ? null :
|
||||
(String) props.get(CLIENTPKGS);
|
||||
|
||||
// Try properties argument
|
||||
if (pkgs != null) {
|
||||
mech = loadFromPkgList(pkgs, mechanisms,
|
||||
authorizationId,
|
||||
protocol, serverName,
|
||||
props, cbh);
|
||||
}
|
||||
|
||||
// Try system properties
|
||||
if (mech == null &&
|
||||
(pkgs = System.getProperty(CLIENTPKGS)) != null) {
|
||||
mech = loadFromPkgList(pkgs, mechanisms,
|
||||
authorizationId,
|
||||
protocol, serverName,
|
||||
props, cbh);
|
||||
}
|
||||
}
|
||||
return mech;
|
||||
}
|
||||
|
||||
private static SaslClient loadFromPkgList(String pkgs,
|
||||
String[] mechanisms,
|
||||
String authorizationId,
|
||||
String protocol,
|
||||
String serverName,
|
||||
Hashtable props,
|
||||
CallbackHandler cbh)
|
||||
throws SaslException {
|
||||
|
||||
StringTokenizer packagePrefixIter = new StringTokenizer(pkgs, "|");
|
||||
SaslClient mech = null;
|
||||
SaslClientFactory fac = null;
|
||||
|
||||
while (mech == null && packagePrefixIter.hasMoreTokens()) {
|
||||
|
||||
String pkg = packagePrefixIter.nextToken().trim();
|
||||
String clsName = pkg + ".ClientFactory";
|
||||
if (debug) {
|
||||
System.out.println("Sasl.loadFromPkgList: " + clsName);
|
||||
}
|
||||
Class cls = null;
|
||||
try {
|
||||
cls = Class.forName(clsName);
|
||||
} catch (Exception e) {
|
||||
System.err.println( "Sasl.loadFromPkgList: " + e );
|
||||
}
|
||||
if (cls != null) {
|
||||
try {
|
||||
fac = (SaslClientFactory) cls.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
throw new SaslException(
|
||||
"Cannot instantiate " + clsName);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new SaslException(
|
||||
"Cannot access constructor of " + clsName);
|
||||
}
|
||||
mech = fac.createSaslClient(mechanisms, authorizationId,
|
||||
protocol, serverName, props,
|
||||
cbh);
|
||||
}
|
||||
}
|
||||
return mech;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default <tt>SaslClientFactory</tt> to use.
|
||||
* This method sets <tt>fac</tt> to be the default factory.
|
||||
* It can only be called with a non-null value once per VM.
|
||||
* If a factory has been set already, this method throws
|
||||
* <tt>IllegalStateException</tt>.
|
||||
* @param fac The possibly null factory to set. If null, doesn't
|
||||
* do anything.
|
||||
* @exception IllegalStateException If factory already set.
|
||||
*/
|
||||
public static void setSaslClientFactory(SaslClientFactory fac) {
|
||||
if (clientFactory != null) {
|
||||
throw new IllegalStateException (
|
||||
"SaslClientFactory already defined");
|
||||
}
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
if (security != null) {
|
||||
security.checkSetFactory();
|
||||
}
|
||||
clientFactory = fac;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package com.netscape.sasl;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Performs SASL authentication as a client.
|
||||
*<p>
|
||||
* A protocol library such as one for LDAP gets an instance of this
|
||||
* class in order to perform authentication defined by a specific SASL
|
||||
* mechanism. Invoking methods on the <tt>SaslClient</tt> instance
|
||||
* process challenges and create responses according to the SASL
|
||||
* mechanism implemented by the <tt>SaslClient</tt>.
|
||||
* As the authentication proceeds, the instance
|
||||
* encapsulates the state of a SASL client's authentication exchange.
|
||||
*<p>
|
||||
* Here's an example of how an LDAP library might use a <tt>SaslClient</tt>.
|
||||
* It first gets an instance of a <tt>SaslClient</tt>:
|
||||
*<blockquote><pre>
|
||||
* SaslClient sc = Sasl.createSaslClient(mechanisms,
|
||||
* authorizationId, protocol, serverName, props, callbackHandler);
|
||||
*</pre></blockquote>
|
||||
* It can then proceed to use the client for authentication.
|
||||
* For example, an LDAP library might use the client as follows:
|
||||
*<blockquote><pre>
|
||||
* InputStream is = ldap.getInputStream();
|
||||
* OutputStream os = ldap.getOutputStream();
|
||||
* byte[] toServer = sc.createInitialResponse();
|
||||
* LdapResult res = ldap.sendBindRequest(dn, sc.getName(), toServer);
|
||||
* while (!sc.isComplete() && res.status == SASL_BIND_IN_PROGRESS) {
|
||||
* toServer = sc.evaluateChallenge(res.getBytesFromServer());
|
||||
* if (toServer != null) {
|
||||
* res = ldap.sendBindRequest(dn, sc.getName(), toServer);
|
||||
* }
|
||||
* }
|
||||
* if (sc.isComplete() && res.status == SUCCESS) {
|
||||
* // Get the input and output streams; may be unchanged
|
||||
* is = sc.getInputStream( is );
|
||||
* os = sc.getOutputStream( os );
|
||||
* // Use these streams from now on
|
||||
* ldap.setInputStream( is );
|
||||
* ldap.setOutputStream( os );
|
||||
* }
|
||||
*</pre></blockquote>
|
||||
*
|
||||
* Note that the call to <tt>createInitialResponse()</tt> is optional.
|
||||
* Protocols such as IMAP4 do not invoke it but instead only use
|
||||
* <tt>evaluateChallenge()</tt>, possibly with an empty challenge.
|
||||
* It is the responsibility of the <tt>SaslClient</tt> implementation
|
||||
* for a mechanism to take this into account so that it behaves properly
|
||||
* regardless of whether <tt>createInitialResponse()</tt> is called.
|
||||
*
|
||||
* @see Sasl
|
||||
* @see SaslClientFactory
|
||||
*/
|
||||
public abstract interface SaslClient {
|
||||
|
||||
/**
|
||||
* Returns the IANA-registered mechanism name of this SASL client.
|
||||
* (e.g. "CRAM-MD5", "GSSAPI").
|
||||
* @return A non-null string representing the IANA-registered mechanism name.
|
||||
*/
|
||||
public abstract String getMechanismName();
|
||||
|
||||
/**
|
||||
* Retrieves the initial response.
|
||||
*
|
||||
* @return The possibly null byte array containing the initial response.
|
||||
* It is null if the mechanism does not have an initial response.
|
||||
* @exception SaslException If an error occurred while creating
|
||||
* the initial response.
|
||||
*/
|
||||
public abstract byte[] createInitialResponse() throws SaslException;
|
||||
|
||||
/**
|
||||
* Evaluates the challenge data and generates a response.
|
||||
*
|
||||
* @param challenge The non-null challenge sent from the server.
|
||||
*
|
||||
* @return The possibly null reponse to send to the server.
|
||||
* It is null if the challenge accompanied a "SUCCESS" status and the challenge
|
||||
* only contains data for the client to update its state and no response
|
||||
* needs to be sent to the server.
|
||||
* @exception SaslException If an error occurred while processing
|
||||
* the challenge or generating a response.
|
||||
*/
|
||||
public abstract byte[] evaluateChallenge(byte[] challenge)
|
||||
throws SaslException;
|
||||
|
||||
/**
|
||||
* Determines whether the authentication exchange has completed.
|
||||
* @return true if the authentication exchange has completed; false otherwise.
|
||||
*/
|
||||
public abstract boolean isComplete();
|
||||
|
||||
/**
|
||||
* Retrieves an input stream for the session. It may return
|
||||
* the same stream that is passed in, if no processing is to be
|
||||
* done by the client object.
|
||||
*
|
||||
* This method can only be called if isComplete() returns true.
|
||||
* @param is The original input stream for reading from the server.
|
||||
* @return An input stream for reading from the server, which
|
||||
* may include processing the original stream.
|
||||
* @exception IOException If the authentication exchange has not completed
|
||||
* or an error occurred while getting the stream.
|
||||
*/
|
||||
public abstract InputStream getInputStream(InputStream is) throws IOException;
|
||||
|
||||
/**
|
||||
* Retrieves an output stream for the session. It may return
|
||||
* the same stream that is passed in, if no processing is to be
|
||||
* done by the client object.
|
||||
*
|
||||
* This method can only be called if isComplete() returns true.
|
||||
* @param is The original output stream for writing to the server.
|
||||
* @return An output stream for writing to the server, which
|
||||
* may include processing the original stream.
|
||||
* @exception IOException If the authentication exchange has not completed
|
||||
* or an error occurred while getting the stream.
|
||||
*/
|
||||
public abstract OutputStream getOutputStream(OutputStream os) throws IOException;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package com.netscape.sasl;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
|
||||
/**
|
||||
* An interface for creating instances of <tt>SaslClient</tt>.
|
||||
*
|
||||
* @see SaslClient
|
||||
* @see Sasl
|
||||
*/
|
||||
public abstract interface SaslClientFactory {
|
||||
/**
|
||||
* Creates a SaslClient using the parameters supplied.
|
||||
*
|
||||
* @param mechanisms The non-null list of mechanism names to try. Each is the
|
||||
* IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5").
|
||||
* @param authorizationId The possibly null authorization ID to use. When
|
||||
* the SASL authentication completes successfully, the entity named
|
||||
* by authorizationId is granted access.
|
||||
* @param protocol The non-null string name of the protocol for which
|
||||
* the authentication is being performed (e.g., "ldap").
|
||||
* @param serverName The non-null string name of the server to which
|
||||
* we are creating an authenticated connection.
|
||||
* @param props The possibly null properties to be used by the SASL
|
||||
* mechanisms to configure the authentication exchange. For example,
|
||||
* "javax.security.sasl.encryption.maximum" might be used to specify
|
||||
* the maximum key length to use for encryption.
|
||||
* @param cbh The possibly null callback handler to used by the SASL
|
||||
* mechanisms to get further information from the application/library
|
||||
* to complete the authentication. For example, a SASL mechanism might
|
||||
* require the authentication ID and password from the caller.
|
||||
*@return A possibly null <tt>SaslClient</tt> created using the parameters
|
||||
* supplied. If null, this factory cannot produce a <tt>SaslClient</tt>
|
||||
* using the parameters supplied.
|
||||
*@exception SaslException If cannot create a <tt>SaslClient</tt> because
|
||||
* of an error.
|
||||
*/
|
||||
public abstract SaslClient createSaslClient(
|
||||
String[] mechanisms,
|
||||
String authorizationId,
|
||||
String protocol,
|
||||
String serverName,
|
||||
Hashtable props,
|
||||
CallbackHandler cbh) throws SaslException;
|
||||
|
||||
/**
|
||||
* Returns an array of names of mechanisms supported by this factory.
|
||||
* @return A non-null array containing a IANA-registered SASL mechanism names.
|
||||
*/
|
||||
public abstract String[] getMechanismNames();
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package com.netscape.sasl;
|
||||
|
||||
/**
|
||||
* This class represents an error that has occurred when using SASL.
|
||||
*
|
||||
*/
|
||||
public class SaslException extends java.io.IOException {
|
||||
/**
|
||||
* The possibly null root cause exception.
|
||||
* @serial
|
||||
*/
|
||||
private Throwable exception;
|
||||
|
||||
/**
|
||||
* Constructs a new instance of <tt>SaslException</tt>.
|
||||
* The root exception and the detailed message are null.
|
||||
*/
|
||||
public SaslException () {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of <tt>SaslException</tt> with a detailed message.
|
||||
* The root exception is null.
|
||||
* @param detail A possibly null string containing details of the exception.
|
||||
*
|
||||
* @see java.lang.Throwable#getMessage
|
||||
*/
|
||||
public SaslException (String detail) {
|
||||
super(detail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of <tt>SaslException</tt> with a detailed message
|
||||
* and a root exception.
|
||||
* For example, a SaslException might result from a problem with
|
||||
* the callback handler, which might throw a NoSuchCallbackException if
|
||||
* it does not support the requested callback, or throw an IOException
|
||||
* if it had problems obtaining data for the callback. The
|
||||
* SaslException's root exception would be then be the exception thrown
|
||||
* by the callback handler.
|
||||
*
|
||||
* @param detail A possibly null string containing details of the exception.
|
||||
* @param ex A possibly null root exception that caused this exception.
|
||||
*
|
||||
* @see java.lang.Throwable#getMessage
|
||||
* @see #getException
|
||||
*/
|
||||
public SaslException (String detail, Throwable ex) {
|
||||
super(detail);
|
||||
exception = ex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root exception that caused this exception.
|
||||
* @return The possibly null root exception that caused this exception.
|
||||
*/
|
||||
public Throwable getException() {
|
||||
return exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints this exception's stack trace to <tt>System.err</tt>.
|
||||
* If this exception has a root exception; the stack trace of the
|
||||
* root exception is printed to <tt>System.err</tt> instead.
|
||||
*/
|
||||
public void printStackTrace() {
|
||||
printStackTrace( System.err );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints this exception's stack trace to a print stream.
|
||||
* If this exception has a root exception; the stack trace of the
|
||||
* root exception is printed to the print stream instead.
|
||||
* @param ps The non-null print stream to which to print.
|
||||
*/
|
||||
public void printStackTrace(java.io.PrintStream ps) {
|
||||
if ( exception != null ) {
|
||||
String superString = super.toString();
|
||||
synchronized ( ps ) {
|
||||
ps.print(superString
|
||||
+ (superString.endsWith(".") ? "" : ".")
|
||||
+ " Root exception is ");
|
||||
exception.printStackTrace( ps );
|
||||
}
|
||||
} else {
|
||||
super.printStackTrace( ps );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints this exception's stack trace to a print writer.
|
||||
* If this exception has a root exception; the stack trace of the
|
||||
* root exception is printed to the print writer instead.
|
||||
* @param ps The non-null print writer to which to print.
|
||||
*/
|
||||
public void printStackTrace(java.io.PrintWriter pw) {
|
||||
if ( exception != null ) {
|
||||
String superString = super.toString();
|
||||
synchronized (pw) {
|
||||
pw.print(superString
|
||||
+ (superString.endsWith(".") ? "" : ".")
|
||||
+ " Root exception is ");
|
||||
exception.printStackTrace( pw );
|
||||
}
|
||||
} else {
|
||||
super.printStackTrace( pw );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string representation of this exception.
|
||||
* The string representation contains
|
||||
* this exception's class name, its detailed messsage, and if
|
||||
* it has a root exception, the string representation of the root
|
||||
* exception. This string representation
|
||||
* is meant for debugging and not meant to be interpreted
|
||||
* programmatically.
|
||||
* @return The non-null string representation of this exception.
|
||||
* @see java.lang.Throwable#getMessage
|
||||
*/
|
||||
public String toString() {
|
||||
String answer = super.toString();
|
||||
if (exception != null && exception != this) {
|
||||
answer += " [Root exception is " + exception.toString() + "]";
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
package com.netscape.sasl.mechanisms;
|
||||
|
||||
import java.io.*;
|
||||
import com.netscape.sasl.*;
|
||||
|
||||
/**
|
||||
* This class provides the implementation of the EXTERNAL mechanism driver.
|
||||
* This mechanism is passed in the SASL External bind request to retrieve the
|
||||
* current result code from the server.
|
||||
*/
|
||||
public class SaslExternal implements SaslClient {
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public SaslExternal() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the initial response.
|
||||
*
|
||||
* @return The possibly null byte array containing the initial response.
|
||||
* It is null if the mechanism does not have an initial response.
|
||||
* @exception SaslException If an error occurred while creating
|
||||
* the initial response.
|
||||
*/
|
||||
public byte[] createInitialResponse() throws SaslException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates the challenge data and generates a response.
|
||||
*
|
||||
* @param challenge The non-null challenge sent from the server.
|
||||
*
|
||||
* @return The possibly null reponse to send to the server.
|
||||
* It is null if the challenge accompanied a "SUCCESS" status
|
||||
* and the challenge only contains data for the client to
|
||||
* update its state and no response needs to be sent to the server.
|
||||
* @exception SaslException If an error occurred while processing
|
||||
* the challenge or generating a response.
|
||||
*/
|
||||
public byte[] evaluateChallenge(byte[] challenge)
|
||||
throws SaslException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of mechanism driver.
|
||||
* @return The mechanism name.
|
||||
*/
|
||||
public String getMechanismName() {
|
||||
return MECHANISM_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* The method may be called at any time to determine if the authentication
|
||||
* process is finished.
|
||||
* @return <CODE>true</CODE> if authentication is complete. For this class,
|
||||
* always returns <CODE>true</CODE>.
|
||||
*/
|
||||
public boolean isComplete() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an input stream for the session. It may return
|
||||
* the same stream that is passed in, if no processing is to be
|
||||
* done by the client object.
|
||||
*
|
||||
* This method can only be called if isComplete() returns true.
|
||||
* @param is The original input stream for reading from the server.
|
||||
* @return An input stream for reading from the server, which
|
||||
* may include processing the original stream. For this class, the
|
||||
* input parameter is always returned.
|
||||
* @exception IOException If the authentication exchange has not completed
|
||||
* or an error occurred while getting the stream.
|
||||
*/
|
||||
public InputStream getInputStream(InputStream is)
|
||||
throws IOException {
|
||||
return is;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an output stream for the session. It may return
|
||||
* the same stream that is passed in, if no processing is to be
|
||||
* done by the client object.
|
||||
*
|
||||
* This method can only be called if isComplete() returns true.
|
||||
* @param is The original output stream for writing to the server.
|
||||
* @return An output stream for writing to the server, which
|
||||
* may include processing the original stream. For this class, the
|
||||
* input parameter is always returned.
|
||||
* @exception IOException If the authentication exchange has not completed
|
||||
* or an error occurred while getting the stream.
|
||||
*/
|
||||
public OutputStream getOutputStream(OutputStream os)
|
||||
throws IOException {
|
||||
return os;
|
||||
}
|
||||
|
||||
private final static String MECHANISM_NAME = "EXTERNAL";
|
||||
}
|
||||
BIN
mozilla/directory/java-sdk/ldapjdk/lib/jaas.jar
Normal file
BIN
mozilla/directory/java-sdk/ldapjdk/lib/jaas.jar
Normal file
Binary file not shown.
@@ -0,0 +1,88 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
* Utility class to dynamically find methods of a class and to invoke
|
||||
* them
|
||||
*/
|
||||
class DynamicInvoker {
|
||||
static Object invokeMethod(Object obj, String packageName,
|
||||
String methodName, Object[] args, String[] argNames)
|
||||
throws LDAPException {
|
||||
try {
|
||||
java.lang.reflect.Method m = getMethod(packageName, methodName,
|
||||
argNames);
|
||||
if (m != null) {
|
||||
return (m.invoke(obj, args));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new LDAPException("Invoking "+methodName+": "+
|
||||
e.toString(), LDAPException.PARAM_ERROR);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static java.lang.reflect.Method getMethod(String packageName,
|
||||
String methodName, String[] args) throws LDAPException {
|
||||
try {
|
||||
java.lang.reflect.Method method = null;
|
||||
String suffix = "";
|
||||
if (args != null)
|
||||
for (int i=0; i<args.length; i++)
|
||||
suffix = suffix+args[i].getClass().getName();
|
||||
String key = packageName+"."+methodName+"."+suffix;
|
||||
if ((method = (java.lang.reflect.Method)(m_methodLookup.get(key)))
|
||||
!= null)
|
||||
return method;
|
||||
|
||||
Class c = Class.forName(packageName);
|
||||
java.lang.reflect.Method[] m = c.getMethods();
|
||||
for (int i = 0; i < m.length; i++ ) {
|
||||
Class[] params = m[i].getParameterTypes();
|
||||
if ((m[i].getName().equals(methodName)) &&
|
||||
signatureCorrect(params, args)) {
|
||||
m_methodLookup.put(key, m[i]);
|
||||
return m[i];
|
||||
}
|
||||
}
|
||||
throw new LDAPException("Method " + methodName + " not found in " +
|
||||
packageName);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new LDAPException("Class "+ packageName + " not found");
|
||||
}
|
||||
}
|
||||
|
||||
static private boolean signatureCorrect(Class params[], String args[]) {
|
||||
if (args == null)
|
||||
return true;
|
||||
if (params.length != args.length)
|
||||
return false;
|
||||
for (int i=0; i<params.length; i++) {
|
||||
if (!params[i].getName().equals(args[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static Hashtable m_methodLookup = new Hashtable();
|
||||
}
|
||||
@@ -0,0 +1,438 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
|
||||
/**
|
||||
* Encapsulates a connection to an LDAP server, providing access to the input queue
|
||||
* for messages received.
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public interface LDAPAsynchronousConnection {
|
||||
|
||||
/**
|
||||
* Adds an entry to the directory.
|
||||
*
|
||||
* @param entry LDAPEntry object specifying the distinguished name and
|
||||
* attributes of the new entry.
|
||||
* @param listener Handler for messages returned from a server in response
|
||||
* to this request. If it is null, a listener object is created internally.
|
||||
* @param cons Constraints specific to the operation.
|
||||
* @return LDAPSearchListener Handler for messages returned from a server
|
||||
* in response to this request.
|
||||
* @exception LDAPException Failed to send request.
|
||||
* @see netscape.ldap.LDAPEntry
|
||||
* @see netscape.ldap.LDAPResponseListener
|
||||
*/
|
||||
public LDAPResponseListener add(LDAPEntry entry,
|
||||
LDAPResponseListener listener)
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Adds an entry to the directory and allows you to specify constraints
|
||||
* for this LDAP add operation by using an <CODE>LDAPConstraints</CODE>
|
||||
* object. For example, you can specify whether or not to follow referrals.
|
||||
* You can also apply LDAP v3 controls to the operation.
|
||||
* <P>
|
||||
*
|
||||
* @param entry LDAPEntry object specifying the distinguished name and
|
||||
* attributes of the new entry.
|
||||
* @param listener Handler for messages returned from a server in response
|
||||
* to this request. If it is null, a listener object is created internally.
|
||||
* @param cons Constraints specific to the operation.
|
||||
* @return LDAPResponseListener Handler for messages returned from a server
|
||||
* in response to this request.
|
||||
* @exception LDAPException Failed to send request.
|
||||
* @see netscape.ldap.LDAPEntry
|
||||
* @see netscape.ldap.LDAPResponseListener
|
||||
* @see netscape.ldap.LDAPConstraints
|
||||
*/
|
||||
public LDAPResponseListener add(LDAPEntry entry,
|
||||
LDAPResponseListener listener,
|
||||
LDAPConstraints cons)
|
||||
throws LDAPException;
|
||||
|
||||
|
||||
/**
|
||||
* Authenticates to the LDAP server (that the object is currently
|
||||
* connected to) using the specified name and password. If the object
|
||||
* has been disconnected from an LDAP server, this method attempts to
|
||||
* reconnect to the server. If the object had already authenticated, the
|
||||
* old authentication is discarded.
|
||||
*
|
||||
* @param dn If non-null and non-empty, specifies that the connection
|
||||
* and all operations through it should be authenticated with dn as the
|
||||
* distinguished name.
|
||||
* @param passwd If non-null and non-empty, specifies that the connection
|
||||
* and all operations through it should be authenticated with dn as the
|
||||
* distinguished name and passwd as password.
|
||||
* @param listener Handler for messages returned from a server in response
|
||||
* to this request. If it is null, a listener object is created internally.
|
||||
* @return LDAPResponseListener Handler for messages returned from a server
|
||||
* in response to this request.
|
||||
* @exception LDAPException Failed to send request.
|
||||
* @see netscape.ldap.LDAPResponseListener
|
||||
*/
|
||||
public LDAPResponseListener bind(String dn,
|
||||
String passwd,
|
||||
LDAPResponseListener listener)
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Authenticates to the LDAP server (that the object is currently
|
||||
* connected to) using the specified name and password and allows you
|
||||
* to specify constraints for this LDAP add operation by using an
|
||||
* <CODE>LDAPConstraints</CODE> object. If the object
|
||||
* has been disconnected from an LDAP server, this method attempts to
|
||||
* reconnect to the server. If the object had already authenticated, the
|
||||
* old authentication is discarded.
|
||||
*
|
||||
* @param dn If non-null and non-empty, specifies that the connection
|
||||
* and all operations through it should be authenticated with dn as the
|
||||
* distinguished name.
|
||||
* @param passwd If non-null and non-empty, specifies that the connection
|
||||
* and all operations through it should be authenticated with dn as the
|
||||
* distinguished name and passwd as password.
|
||||
* @param listener Handler for messages returned from a server in response
|
||||
* to this request. If it is null, a listener object is created internally.
|
||||
* @param cons Constraints specific to the operation.
|
||||
* @return LDAPResponseListener Handler for messages returned from a server
|
||||
* in response to this request.
|
||||
* @exception LDAPException Failed to send request.
|
||||
* @see netscape.ldap.LDAPResponseListener
|
||||
* @see netscape.ldap.LDAPConstraints
|
||||
*/
|
||||
public LDAPResponseListener bind(String dn,
|
||||
String passwd,
|
||||
LDAPResponseListener listener,
|
||||
LDAPConstraints cons)
|
||||
throws LDAPException;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Deletes the entry for the specified DN from the directory.
|
||||
*
|
||||
* @param dn Distinguished name of the entry to delete.
|
||||
* @param listener Handler for messages returned from a server in response
|
||||
* to this request. If it is null, a listener object is created internally.
|
||||
* @return LDAPResponseListener Handler for messages returned from a server
|
||||
* in response to this request.
|
||||
* @exception LDAPException Failed to send request.
|
||||
* @see netscape.ldap.LDAPResponseListener
|
||||
* @see netscape.ldap.LDAPConstraints
|
||||
*/
|
||||
public LDAPResponseListener delete(String dn,
|
||||
LDAPResponseListener listener)
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Deletes the entry for the specified DN from the directory.
|
||||
*
|
||||
* @param dn Distinguished name of the entry to delete.
|
||||
* @param listener Handler for messages returned from a server in response
|
||||
* to this request. If it is null, a listener object is created internally.
|
||||
* @param cons Constraints specific to the operation.
|
||||
* @return LDAPResponseListener Handler for messages returned from a server
|
||||
* in response to this request.
|
||||
* @exception LDAPException Failed to send request.
|
||||
* @see netscape.ldap.LDAPResponseListener
|
||||
* @see netscape.ldap.LDAPConstraints
|
||||
*/
|
||||
public LDAPResponseListener delete(String dn,
|
||||
LDAPResponseListener listener,
|
||||
LDAPConstraints cons)
|
||||
throws LDAPException;
|
||||
|
||||
|
||||
/**
|
||||
* Makes a single change to an existing entry in the directory (for
|
||||
* example, changes the value of an attribute, adds a new attribute
|
||||
* value, or removes an existing attribute value).<BR>
|
||||
* The LDAPModification object specifies both the change to be made and
|
||||
* the LDAPAttribute value to be changed.
|
||||
*
|
||||
* @param dn Distinguished name of the entry to modify.
|
||||
* @param mod A single change to be made to an entry.
|
||||
* @param listener Handler for messages returned from a server in response
|
||||
* to this request. If it is null, a listener object is created internally.
|
||||
* @return LDAPResponseListener Handler for messages returned from a server
|
||||
* in response to this request.
|
||||
* @exception LDAPException Failed to send request.
|
||||
* @see netscape.ldap.LDAPModification
|
||||
* @see netscape.ldap.LDAPResponseListener
|
||||
*/
|
||||
public LDAPResponseListener modify(String dn,
|
||||
LDAPModification mod,
|
||||
LDAPResponseListener listener)
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Makes a single change to an existing entry in the directory (for
|
||||
* example, changes the value of an attribute, adds a new attribute
|
||||
* value, or removes an existing attribute value).<BR>
|
||||
* The LDAPModification object specifies both the change to be made and
|
||||
* the LDAPAttribute value to be changed.
|
||||
*
|
||||
* @param dn Distinguished name of the entry to modify.
|
||||
* @param mod A single change to be made to an entry.
|
||||
* @param listener Handler for messages returned from a server in response
|
||||
* to this request. If it is null, a listener object is created internally.
|
||||
* @param cons Constraints specific to the operation.
|
||||
* @return LDAPResponseListener Handler for messages returned from a server
|
||||
* in response to this request.
|
||||
* @exception LDAPException Failed to send request.
|
||||
* @see netscape.ldap.LDAPModification
|
||||
* @see netscape.ldap.LDAPResponseListener
|
||||
* @see netscape.ldap.LDAPConstraints
|
||||
*/
|
||||
public LDAPResponseListener modify(String dn,
|
||||
LDAPModification mod,
|
||||
LDAPResponseListener listener,
|
||||
LDAPConstraints cons)
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Makes a set of changes to an existing entry in the directory (for
|
||||
* example, changes attribute values, adds new attribute values, or
|
||||
* removes existing attribute values).
|
||||
* <P>
|
||||
* @param dn Distinguished name of the entry to modify.
|
||||
* @param mods A set of modifications to be made to the entry.
|
||||
* @param listener Handler for messages returned from a server in response
|
||||
* to this request. If it is null, a listener object is created internally.
|
||||
* @return LDAPResponseListener Handler for messages returned from a server
|
||||
* in response to this request.
|
||||
* @exception LDAPException Failed to send request.
|
||||
* @see netscape.ldap.LDAPModificationSet
|
||||
* @see netscape.ldap.LDAPResponseListener
|
||||
*/
|
||||
public LDAPResponseListener modify(String dn,
|
||||
LDAPModificationSet mods,
|
||||
LDAPResponseListener listener)
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Makes a set of changes to an existing entry in the directory (for
|
||||
* example, changes attribute values, adds new attribute values, or
|
||||
* removes existing attribute values).
|
||||
*
|
||||
* @param dn Distinguished name of the entry to modify.
|
||||
* @param mods A set of modifications to be made to the entry.
|
||||
* @param listener Handler for messages returned from a server in response
|
||||
* to this request. If it is null, a listener object is created internally.
|
||||
* @param cons Constraints specific to the operation.
|
||||
* @return LDAPResponseListener Handler for messages returned from a server
|
||||
* in response to this request.
|
||||
* @exception LDAPException Failed to send request.
|
||||
* @see netscape.ldap.LDAPModificationSet
|
||||
* @see netscape.ldap.LDAPResponseListener
|
||||
* @see netscape.ldap.LDAPConstraints
|
||||
*/
|
||||
public LDAPResponseListener modify(String dn,
|
||||
LDAPModificationSet mods,
|
||||
LDAPResponseListener listener,
|
||||
LDAPConstraints cons)
|
||||
throws LDAPException;
|
||||
|
||||
|
||||
/**
|
||||
* Renames an existing entry in the directory.
|
||||
*
|
||||
* @param dn Current distinguished name of the entry.
|
||||
* @param newRdn New relative distinguished name for the entry.
|
||||
* @param deleteOldRdn If true, the old name is not retained as an
|
||||
* attribute value.
|
||||
* @param listener Handler for messages returned from a server in response
|
||||
* to this request. If it is null, a listener object is created internally.
|
||||
* @return LDAPResponseListener Handler for messages returned from a server
|
||||
* in response to this request.
|
||||
* @exception LDAPException Failed to send request.
|
||||
* @see netscape.ldap.LDAPResponseListener
|
||||
*/
|
||||
public LDAPResponseListener rename(String dn,
|
||||
String newRdn,
|
||||
boolean deleteOldRdn,
|
||||
LDAPResponseListener listener)
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Renames an existing entry in the directory.
|
||||
*
|
||||
* @param dn Current distinguished name of the entry.
|
||||
* @param newRdn New relative distinguished name for the entry.
|
||||
* @param deleteOldRdn If true, the old name is not retained as an
|
||||
* @param listener Handler for messages returned from a server in response
|
||||
* to this request. If it is null, a listener object is created internally.
|
||||
* @param cons Constraints specific to the operation.
|
||||
* @return LDAPResponseListener Handler for messages returned from a server
|
||||
* in response to this request.
|
||||
* @exception LDAPException Failed to send request.
|
||||
* @see netscape.ldap.LDAPResponseListener
|
||||
* @see netscape.ldap.LDAPConstraints
|
||||
*/
|
||||
public LDAPResponseListener rename(String dn,
|
||||
String newRdn,
|
||||
boolean deleteOldRdn,
|
||||
LDAPResponseListener listener,
|
||||
LDAPConstraints cons)
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Performs the search specified by the criteria that you enter. <P>
|
||||
* To abandon the search, use the <CODE>abandon</CODE> method.
|
||||
*
|
||||
* @param base The base distinguished name to search from
|
||||
* @param scope The scope of the entries to search. You can specify one
|
||||
* of the following: <P>
|
||||
* <UL>
|
||||
* <LI><CODE>LDAPv2.SCOPE_BASE</CODE> (search only the base DN) <P>
|
||||
* <LI><CODE>LDAPv2.SCOPE_ONE</CODE>
|
||||
* (search only entries under the base DN) <P>
|
||||
* <LI><CODE>LDAPv2.SCOPE_SUB</CODE>
|
||||
* (search the base DN and all entries within its subtree) <P>
|
||||
* </UL>
|
||||
* <P>
|
||||
* @param filter Search filter specifying the search criteria.
|
||||
* @param attrs List of attributes that you want returned in the
|
||||
* search results.
|
||||
* @param typesOnly If true, returns the names but not the values of the
|
||||
* attributes found. If false, returns the names and values for
|
||||
* attributes found
|
||||
* @param listener Handler for messages returned from a server in response
|
||||
* to this request. If it is null, a listener object is created internally.
|
||||
* @return LDAPSearchListener Handler for messages returned from a server
|
||||
* in response to this request.
|
||||
* @exception LDAPException Failed to send request.
|
||||
* @see netscape.ldap.LDAPAsynchronousConnection#abandon(netscape.ldap.LDAPSearchListener)
|
||||
*/
|
||||
public LDAPSearchListener search(String base,
|
||||
int scope,
|
||||
String filter,
|
||||
String attrs[],
|
||||
boolean typesOnly,
|
||||
LDAPSearchListener listener)
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Performs the search specified by the criteria that you enter.
|
||||
* This method also allows you to specify constraints for the search
|
||||
* (such as the maximum number of entries to find or the
|
||||
* maximum time to wait for search results). <P>
|
||||
* To abandon the search, use the <CODE>abandon</CODE> method.
|
||||
*
|
||||
* @param base The base distinguished name to search from
|
||||
* @param scope The scope of the entries to search. You can specify one
|
||||
* of the following: <P>
|
||||
* <UL>
|
||||
* <LI><CODE>LDAPv2.SCOPE_BASE</CODE> (search only the base DN) <P>
|
||||
* <LI><CODE>LDAPv2.SCOPE_ONE</CODE>
|
||||
* (search only entries under the base DN) <P>
|
||||
* <LI><CODE>LDAPv2.SCOPE_SUB</CODE>
|
||||
* (search the base DN and all entries within its subtree) <P>
|
||||
* </UL>
|
||||
* <P>
|
||||
* @param filter Search filter specifying the search criteria.
|
||||
* @param attrs List of attributes that you want returned in the search
|
||||
* results.
|
||||
* @param typesOnly If true, returns the names but not the values of the
|
||||
* attributes found. If false, returns the names and values for
|
||||
* attributes found.
|
||||
* @param listener Handler for messages returned from a server in response
|
||||
* to this request. If it is null, a listener object is created internally.
|
||||
* @param cons Constraints specific to this search (for example, the
|
||||
* maximum number of entries to return).
|
||||
* @return LDAPSearchListener Handler for messages returned from a server
|
||||
* in response to this request.
|
||||
* @exception LDAPException Failed to send request.
|
||||
* @see netscape.ldap.LDAPAsynchronousConnection#abandon(netscape.ldap.LDAPSearchListener)
|
||||
*/
|
||||
public LDAPSearchListener search(String base,
|
||||
int scope,
|
||||
String filter,
|
||||
String attrs[],
|
||||
boolean typesOnly,
|
||||
LDAPSearchListener listener,
|
||||
LDAPSearchConstraints cons)
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Compare an attribute value with one in the directory. The result can
|
||||
* be obtained by calling <CODE>getResultCode</CODE> on the
|
||||
* <CODE>LDAPResponse</CODE> from the <CODE>LDAPResponseListener</CODE>.
|
||||
* The code will be <CODE>LDAPException.COMPARE_TRUE</CODE> or
|
||||
* <CODE>LDAPException.COMPARE_FALSE</CODE>.
|
||||
*
|
||||
* @param dn Distinguished name of the entry to compare.
|
||||
* @param attr Attribute with a value to compare.
|
||||
* @param listener Handler for messages returned from a server in response
|
||||
* to this request. If it is null, a listener object is created internally.
|
||||
* @return LDAPResponseListener Handler for messages returned from a server
|
||||
* in response to this request.
|
||||
* @exception LDAPException Failed to send request.
|
||||
*/
|
||||
public LDAPResponseListener compare(String dn,
|
||||
LDAPAttribute attr,
|
||||
LDAPResponseListener listener)
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Compare an attribute value with one in the directory. The result can
|
||||
* be obtained by calling <CODE>getResultCode</CODE> on the
|
||||
* <CODE>LDAPResponse</CODE> from the <CODE>LDAPResponseListener</CODE>.
|
||||
* The code will be <CODE>LDAPException.COMPARE_TRUE</CODE> or
|
||||
* <CODE>LDAPException.COMPARE_FALSE</CODE>.
|
||||
*
|
||||
* @param dn Distinguished name of the entry to compare.
|
||||
* @param attr Attribute with a value to compare.
|
||||
* @param listener Handler for messages returned from a server in response
|
||||
* to this request. If it is null, a listener object is created internally.
|
||||
* @param cons Constraints specific to this operation.
|
||||
* @return LDAPResponseListener Handler for messages returned from a server
|
||||
* in response to this request.
|
||||
* @exception LDAPException Failed to send request.
|
||||
*/
|
||||
public LDAPResponseListener compare(String dn,
|
||||
LDAPAttribute attr,
|
||||
LDAPResponseListener listener,
|
||||
LDAPConstraints cons)
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Cancels the ldap request with the specified id and discards
|
||||
* any results already received.
|
||||
*
|
||||
* @param id A LDAP request id
|
||||
* @exception LDAPException Failed to send request.
|
||||
*/
|
||||
public void abandon(int id) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Cancels all outstanding search requests associated with this
|
||||
* LDAPSearchListener object and discards any results already received.
|
||||
*
|
||||
* @param searchlistener A search listener returned from a search.
|
||||
* @exception LDAPException Failed to send request.
|
||||
*/
|
||||
public void abandon(LDAPSearchListener searchlistener)
|
||||
throws LDAPException;
|
||||
}
|
||||
@@ -0,0 +1,530 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import netscape.ldap.ber.stream.*;
|
||||
|
||||
/**
|
||||
* Represents the name and values of an attribute in an entry.
|
||||
*
|
||||
* @version 1.0
|
||||
* @see netscape.ldap.LDAPAttributeSet
|
||||
*/
|
||||
public class LDAPAttribute {
|
||||
|
||||
private String name = null;
|
||||
private byte[] nameBuf = null;
|
||||
/**
|
||||
* Internally, it is a list of "byte[]"-based attribute values.
|
||||
*/
|
||||
private Object values[] = new Object[0];
|
||||
|
||||
/**
|
||||
* Constructs an attribute from another existing attribute.
|
||||
* Effectively, this makes a copy of the existing attribute.
|
||||
* @param attr The attribute to copy
|
||||
*/
|
||||
public LDAPAttribute( LDAPAttribute attr ) {
|
||||
name = attr.name;
|
||||
nameBuf = attr.nameBuf;
|
||||
values = new Object[attr.values.length];
|
||||
for (int i = 0; i < attr.values.length; i++) {
|
||||
values[i] = new byte[((byte[])attr.values[i]).length];
|
||||
System.arraycopy((byte[])attr.values[i], 0, (byte[])values[i], 0,
|
||||
((byte[])attr.values[i]).length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an attribute with no values.
|
||||
* @param attrName Name of the attribute.
|
||||
*/
|
||||
public LDAPAttribute( String attrName ) {
|
||||
name = attrName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an attribute with a byte-formatted value.
|
||||
* @param attrName Name of the attribute.
|
||||
* @param attrValue Value of the attribute in byte format.
|
||||
*/
|
||||
public LDAPAttribute( String attrName, byte[] attrValue ) {
|
||||
name = attrName;
|
||||
addValue(attrValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an attribute that has a single string value.
|
||||
* @param attrName Name of the attribute.
|
||||
* @param attrValue Value of the attribute in String format.
|
||||
*/
|
||||
public LDAPAttribute( String attrName, String attrValue ) {
|
||||
name = attrName;
|
||||
addValue( attrValue );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an attribute that has an array of string values.
|
||||
* @param attrName Name of the attribute.
|
||||
* @param attrValues The list of string values for this attribute.
|
||||
*/
|
||||
public LDAPAttribute( String attrName, String[] attrValues ) {
|
||||
name = attrName;
|
||||
if (attrValues != null) {
|
||||
setValues( attrValues );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an attribute from a BER (Basic Encoding Rules) element.
|
||||
* (The protocol elements of LDAP are encoded for exchange using the
|
||||
* Basic Encoding Rules.)
|
||||
* @param element Element that you want translated into an attribute.
|
||||
* @exception IOException The attribute could not be created from
|
||||
* the specified element.
|
||||
*/
|
||||
public LDAPAttribute(BERElement element) throws IOException {
|
||||
BERSequence seq = (BERSequence)element;
|
||||
BEROctetString type = (BEROctetString)seq.elementAt(0);
|
||||
nameBuf = type.getValue();
|
||||
BERSet set = (BERSet)seq.elementAt(1);
|
||||
if (set.size() > 0) {
|
||||
Object[] vals = new Object[set.size()];
|
||||
for (int i = 0; i < set.size(); i++) {
|
||||
vals[i] = ((BEROctetString)set.elementAt(i)).getValue();
|
||||
}
|
||||
setValues( vals );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of values of the attribute.
|
||||
* @return Number of values for this attribute.
|
||||
*/
|
||||
public int size() {
|
||||
return values.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an enumerator for the string values of an attribute.
|
||||
* @return Enumerator for the string values.
|
||||
*/
|
||||
public Enumeration getStringValues() {
|
||||
Vector v = new Vector();
|
||||
synchronized(this) {
|
||||
try {
|
||||
for (int i=0; i<values.length; i++) {
|
||||
if ( values[i] != null ) {
|
||||
v.addElement(new String ((byte[])values[i], "UTF8"));
|
||||
} else {
|
||||
v.addElement( new String( "" ) );
|
||||
}
|
||||
}
|
||||
} catch ( Exception e ) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return v.elements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a array for the values of the attribute as <CODE>String</CODE> objects.
|
||||
* @return Array of attribute values. Each element in the array
|
||||
* will be a <CODE>String</CODE> object.
|
||||
*/
|
||||
public String[] getStringValueArray() {
|
||||
|
||||
String s[] = new String[values.length];
|
||||
synchronized(this) {
|
||||
try {
|
||||
for (int i=0; i < values.length; i++) {
|
||||
if ( values[i] !=null ) {
|
||||
s[i] = new String((byte[])values[i], "UTF8");
|
||||
} else {
|
||||
s[i] = new String("");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an enumerator for the values of the attribute in <CODE>byte[]</CODE>
|
||||
* format.
|
||||
* @return A set of attribute values. Each element in the enumeration
|
||||
* will be of type <CODE>byte[]</CODE>.
|
||||
*/
|
||||
public Enumeration getByteValues() {
|
||||
Vector v = new Vector();
|
||||
synchronized(this) {
|
||||
for (int i=0; i<values.length; i++) {
|
||||
if ( values[i] != null ) {
|
||||
v.addElement(values[i]);
|
||||
} else {
|
||||
v.addElement( new byte[0] );
|
||||
}
|
||||
}
|
||||
}
|
||||
return v.elements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array for the values of the attribute in <CODE>byte[]</CODE>
|
||||
* format.
|
||||
* @return Array of attribute values. Each element in the array
|
||||
* will be of type <CODE>byte[]</CODE>.
|
||||
*/
|
||||
public byte[][] getByteValueArray() {
|
||||
byte b[][] = new byte[values.length][];
|
||||
synchronized(this) {
|
||||
try {
|
||||
for (int i=0; i < values.length; i++) {
|
||||
b[i] = new byte[((byte[])(values[i])).length];
|
||||
System.arraycopy((byte[])values[i], 0, (byte[])b[i], 0,
|
||||
((byte[])(values[i])).length);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return b;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the attribute.
|
||||
* @return Name of the attribute.
|
||||
*/
|
||||
public String getName() {
|
||||
if ((name == null) && (nameBuf != null)) {
|
||||
try{
|
||||
name = new String(nameBuf, "UTF8");
|
||||
} catch(Throwable x) {}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the subtypes from the specified attribute name.
|
||||
* For example, if the attribute name is <CODE>cn;lang-ja;phonetic</CODE>,
|
||||
* this method returns an array containing <CODE>lang-ja</CODE>
|
||||
* and <CODE>phonetic</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* @param attrName Name of the attribute to extract the subtypes from
|
||||
* @return Array of subtypes, or null (if the name has no subtypes)
|
||||
* @see netscape.ldap.LDAPAttribute#getBaseName
|
||||
*/
|
||||
public static String[] getSubtypes(String attrName) {
|
||||
StringTokenizer st = new StringTokenizer(attrName, ";");
|
||||
if( st.hasMoreElements() ) {
|
||||
// First element is base name
|
||||
st.nextElement();
|
||||
String[] subtypes = new String[st.countTokens()];
|
||||
int i = 0;
|
||||
// Extract the types
|
||||
while( st.hasMoreElements() )
|
||||
subtypes[i++] = (String)st.nextElement();
|
||||
return subtypes;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the subtypes from the attribute name of the current
|
||||
* <CODE>LDAPAttribute</CODE> object. For example, if the attribute
|
||||
* name is <CODE>cn;lang-ja;phonetic</CODE>, this method returns an array
|
||||
* containing <CODE>lang-ja</CODE> and <CODE>phonetic</CODE>.
|
||||
*<P>
|
||||
*
|
||||
* @return Array of subtypes, or null (if the name has no subtypes)
|
||||
*/
|
||||
public String[] getSubtypes() {
|
||||
return getSubtypes(getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the language subtype from the attribute name of the
|
||||
* <CODE>LDAPAttribute</CODE> object, if any. For example, if the
|
||||
* attribute name is <CODE>cn;lang-ja;phonetic</CODE>, this method
|
||||
* returns the String <CODE>lang-ja</CODE>.
|
||||
*<P>
|
||||
*
|
||||
* @return The language subtype, or null (if the name has no
|
||||
* language subtype).
|
||||
*/
|
||||
public String getLangSubtype() {
|
||||
String[] subTypes = getSubtypes();
|
||||
if ( subTypes != null ) {
|
||||
for( int i = 0; i < subTypes.length; i++ ) {
|
||||
if ((subTypes[i].length() >= 5) &&
|
||||
(subTypes[i].substring(0, 5).equalsIgnoreCase("lang-")))
|
||||
return subTypes[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the base name from the specified attribute name.
|
||||
* For example, if the attribute name is <CODE>cn;lang-ja;phonetic</CODE>,
|
||||
* this method returns <CODE>cn</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* @param attrName Name of the attribute from which to extract the base name
|
||||
* @return Base name (the attribute name without any subtypes)
|
||||
* @see netscape.ldap.LDAPAttribute#getSubtypes
|
||||
*/
|
||||
public static String getBaseName(String attrName) {
|
||||
String basename = attrName;
|
||||
StringTokenizer st = new StringTokenizer(attrName, ";");
|
||||
if( st.hasMoreElements() )
|
||||
// First element is base name
|
||||
basename = (String)st.nextElement();
|
||||
return basename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the base name from the attribute name of the current
|
||||
* <CODE>LDAPAttribute</CODE> object. For example, if the attribute
|
||||
* name is <CODE>cn;lang-ja;phonetic</CODE>, this method returns
|
||||
* <CODE>cn</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* @return Base name (the attribute name without any subtypes)
|
||||
* @see netscape.ldap.LDAPAttribute#getSubtypes
|
||||
*/
|
||||
public String getBaseName() {
|
||||
return getBaseName(getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Report if the attribute name contains the specified subtype.
|
||||
* For example, if you check for the subtype <CODE>lang-en</CODE>
|
||||
* and the attribute name is <CODE>cn;lang-en</CODE>, this method
|
||||
* returns <CODE>true</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* @param subtype The single subtype that you want to check for
|
||||
* @return true if the attribute name contains the specified subtype
|
||||
* @see netscape.ldap.LDAPAttribute#getSubtypes
|
||||
*/
|
||||
public boolean hasSubtype(String subtype) {
|
||||
String[] mytypes = getSubtypes();
|
||||
for(int i = 0; i < mytypes.length; i++) {
|
||||
if( subtype.equalsIgnoreCase( mytypes[i] ) )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report if the attribute name contains all specified subtypes
|
||||
* For example, if you check for the subtypes <CODE>lang-en</CODE>
|
||||
* and <CODE>phonetic</CODE> and if the attribute name is
|
||||
* <CODE>cn;lang-en;phonetic</CODE>, this method returns <CODE>true</CODE>.
|
||||
* If the attribute name is <CODE>cn;phonetic</CODE> or
|
||||
* <CODE>cn;lang-en</CODE>, this method returns <CODE>false</CODE>.
|
||||
* <P>
|
||||
* @param subtypes An array of subtypes to check
|
||||
* @return true if the attribute name contains all subtypes
|
||||
* @see netscape.ldap.LDAPAttribute#getSubtypes
|
||||
*/
|
||||
public boolean hasSubtypes(String[] subtypes) {
|
||||
for(int i = 0; i < subtypes.length; i++) {
|
||||
if( !hasSubtype(subtypes[i]) )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a string value to the attribute.
|
||||
* @param attrValue The string value that you want to add to the attribute.
|
||||
*/
|
||||
public synchronized void addValue( String attrValue ) {
|
||||
if (attrValue != null) {
|
||||
try {
|
||||
byte[] b = attrValue.getBytes("UTF8");
|
||||
addValue( b );
|
||||
} catch(Throwable x)
|
||||
{}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the string values as the attribute's values.
|
||||
* @param attrValues The string values that you want to use in the attribute.
|
||||
*/
|
||||
protected void setValues( String[] attrValues ) {
|
||||
Object[] vals;
|
||||
if (attrValues != null) {
|
||||
vals = new Object[attrValues.length];
|
||||
for (int i = 0; i < vals.length; i++) {
|
||||
try {
|
||||
vals[i] = attrValues[i].getBytes("UTF8");
|
||||
} catch(Throwable x)
|
||||
{ vals[i] = new byte[0]; }
|
||||
}
|
||||
} else {
|
||||
vals = new Object[0];
|
||||
}
|
||||
setValues(vals);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a <CODE>byte[]</CODE>-formatted value to the attribute.
|
||||
* @param attrValue The <CODE>byte[]</CODE>-formatted value that you
|
||||
* want to add to the attribute.
|
||||
*/
|
||||
public synchronized void addValue( byte[] attrValue ) {
|
||||
if (attrValue != null) {
|
||||
Object[] vals = new Object[values.length+1];
|
||||
for (int i = 0; i < values.length; i++)
|
||||
vals[i] = values[i];
|
||||
vals[values.length] = attrValue;
|
||||
values = vals;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the byte[] values as the attribute's values.
|
||||
* @param attrValues The values that you want to use in the attribute.
|
||||
*/
|
||||
protected synchronized void setValues( Object[] attrValues ) {
|
||||
values = attrValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a string value from the attribute.
|
||||
* @param attrValue The string value that you want removed.
|
||||
*/
|
||||
public synchronized void removeValue( String attrValue) {
|
||||
if (attrValue != null) {
|
||||
try{
|
||||
byte b[] = attrValue.getBytes("UTF8");
|
||||
removeValue ( b );
|
||||
} catch(Throwable x)
|
||||
{}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a <CODE>byte[]</CODE>-formatted value from the attribute.
|
||||
* @param attrValue <CODE>byte[]</CODE>-formatted value that you want removed.
|
||||
*/
|
||||
public synchronized void removeValue( byte[] attrValue) {
|
||||
if ((attrValue == null) || (values == null)|| (values.length < 1))
|
||||
return;
|
||||
int ind = -1;
|
||||
for (int i=0; i<values.length; i++) {
|
||||
if (equalValue(attrValue, (byte[])values[i])) {
|
||||
ind = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ind >= 0) {
|
||||
Object[] vals = new Object[values.length-1];
|
||||
int j = 0;
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (i != ind) {
|
||||
vals[j++] = values[i];
|
||||
}
|
||||
}
|
||||
values = vals;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean equalValue(byte[] a, byte[] b) {
|
||||
if (a.length != b.length)
|
||||
return false;
|
||||
|
||||
for (int i=0; i<a.length; i++) {
|
||||
if (a[i] != b[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the BER (Basic Encoding Rules) representation of attribute.
|
||||
* (The protocol elements of LDAP are encoded for exchange using the
|
||||
* Basic Encoding Rules.)
|
||||
* @return The BER representation of the attribute.
|
||||
*/
|
||||
public BERElement getBERElement() {
|
||||
try {
|
||||
BERSequence seq = new BERSequence();
|
||||
seq.addElement(new BEROctetString(getName()));
|
||||
BERSet set = new BERSet();
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
set.addElement(new BEROctetString((byte[])values[i]));
|
||||
}
|
||||
seq.addElement(set);
|
||||
return seq;
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the string representation of attribute parameters.
|
||||
* @return string representation parameters
|
||||
*/
|
||||
private String getParamString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
if ( values.length > 0 ) {
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (i != 0) {
|
||||
sb.append(",");
|
||||
}
|
||||
byte[] val = (byte[])values[i];
|
||||
try {
|
||||
sb.append(new String(val, "UTF8"));
|
||||
} catch (Exception e) {
|
||||
if (val != null) {
|
||||
sb.append(val.length);
|
||||
sb.append(" bytes");
|
||||
}
|
||||
else {
|
||||
sb.append("null value");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "{type='" + getName() + "', values='" + sb.toString() + "'}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the string representation of attribute
|
||||
* in an LDAP entry. For example:
|
||||
*
|
||||
* <PRE>LDAPAttribute {type='cn', values='Barbara Jensen,Babs Jensen'}</PRE>
|
||||
*
|
||||
* @return String representation of the attribute.
|
||||
*/
|
||||
public String toString() {
|
||||
return "LDAPAttribute " + getParamString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,401 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* The definition of an attribute type in the schema.
|
||||
* <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
|
||||
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
|
||||
* Attribute Syntax Definitions</A> covers the types of information
|
||||
* that need to be specified in the definition of an attribute type.
|
||||
* According to the RFC, the description of an attribute type can
|
||||
* include the following information:
|
||||
* <P>
|
||||
*
|
||||
* <UL>
|
||||
* <LI>an OID identifying the attribute type
|
||||
* <LI>a name identifying the attribute type
|
||||
* <LI>a description of the attribute type
|
||||
* <LI>the name of the parent attribute type
|
||||
* <LI>the syntax used by the attribute (for example,
|
||||
* <CODE>cis</CODE> or <CODE>int</CODE>)
|
||||
* <LI>an indication of whether or not the attribute type is single-valued
|
||||
* or multi-valued
|
||||
* </UL>
|
||||
* <P>
|
||||
*
|
||||
* When you construct an <CODE>LDAPAttributeSchema</CODE> object, you can
|
||||
* specify these types of information as arguments to the constructor or
|
||||
* in the AttributeTypeDescription format specified in RFC 2252.
|
||||
* When an LDAP client searches an LDAP server for the schema, the server
|
||||
* returns schema information as an object with attribute values in this
|
||||
* format.
|
||||
* <P>
|
||||
|
||||
* There a number of additional optional description fields which
|
||||
* are not explicitly accessible through LDAPAttributeSchema, but which
|
||||
* can be managed with setQualifier, getQualifier, and getQualifierNames:
|
||||
* <P>
|
||||
*
|
||||
* <UL>
|
||||
* <LI>EQUALITY
|
||||
* <LI>ORDERING
|
||||
* <LI>SUBSTR
|
||||
* <LI>COLLECTIVE
|
||||
* <LI>NO-USER-MODIFICATION
|
||||
* <LI>USAGE
|
||||
* <LI>OBSOLETE
|
||||
* </UL>
|
||||
* <P>
|
||||
*
|
||||
* You can get the name, OID, and description of this attribute type
|
||||
* definition by using the <CODE>getName</CODE>, <CODE>getOID</CODE>, and
|
||||
* <CODE>getDescription</CODE> methods inherited from the abstract class
|
||||
* <CODE>LDAPSchemaElement</CODE>. Optional and custom qualifiers are
|
||||
* accessed with <CODE>getQualifier</CODE> and <CODE>getQualifierNames</CODE>
|
||||
* from <CODE>LDAPSchemaElement</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* To add or remove this attribute type definition from the
|
||||
* schema, use the <CODE>add</CODE> and <CODE>remove</CODE>
|
||||
* methods, which this class inherits from the <CODE>LDAPSchemaElement</CODE>
|
||||
* abstract class.
|
||||
* <P>
|
||||
* RFC 2252 defines AttributeTypeDescription as follows:
|
||||
* <P>
|
||||
* <PRE>
|
||||
* AttributeTypeDescription = "(" whsp
|
||||
* numericoid whsp ; AttributeType identifier
|
||||
* [ "NAME" qdescrs ] ; name used in AttributeType
|
||||
* [ "DESC" qdstring ] ; description
|
||||
* [ "OBSOLETE" whsp ]
|
||||
* [ "SUP" woid ] ; derived from this other
|
||||
* ; AttributeType
|
||||
* [ "EQUALITY" woid ; Matching Rule name
|
||||
* [ "ORDERING" woid ; Matching Rule name
|
||||
* [ "SUBSTR" woid ] ; Matching Rule name
|
||||
* [ "SYNTAX" whsp noidlen whsp ] ; see section 4.3
|
||||
* [ "SINGLE-VALUE" whsp ] ; default multi-valued
|
||||
* [ "COLLECTIVE" whsp ] ; default not collective
|
||||
* [ "NO-USER-MODIFICATION" whsp ]; default user modifiable
|
||||
* [ "USAGE" whsp AttributeUsage ]; default userApplications
|
||||
* whsp ")"
|
||||
*
|
||||
* AttributeUsage =
|
||||
* "userApplications" /
|
||||
* "directoryOperation" /
|
||||
* "distributedOperation" / ; DSA-shared
|
||||
* "dSAOperation" ; DSA-specific, value depends on server
|
||||
* </PRE>
|
||||
*
|
||||
* @version 1.0
|
||||
* @see netscape.ldap.LDAPSchemaElement
|
||||
**/
|
||||
|
||||
public class LDAPAttributeSchema extends LDAPSchemaElement {
|
||||
/**
|
||||
* Construct a blank element.
|
||||
*/
|
||||
protected LDAPAttributeSchema() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an attribute type definition, using the specified
|
||||
* information.
|
||||
* @param name Name of the attribute type.
|
||||
* @param oid Object identifier (OID) of the attribute type
|
||||
* in dotted-string format (for example, "1.2.3.4").
|
||||
* @param description Description of attribute type.
|
||||
* @param syntax Syntax of this attribute type. The value of this
|
||||
* argument can be one of the following:
|
||||
* <UL>
|
||||
* <LI><CODE>cis</CODE> (case-insensitive string)
|
||||
* <LI><CODE>ces</CODE> (case-exact string)
|
||||
* <LI><CODE>binary</CODE> (binary data)
|
||||
* <LI><CODE>int</CODE> (integer)
|
||||
* <LI><CODE>telephone</CODE> (telephone number -- identical to cis,
|
||||
* but blanks and dashes are ignored during comparisons)
|
||||
* <LI><CODE>dn</CODE> (distinguished name)
|
||||
* </UL>
|
||||
* @param single <CODE>true</CODE> if the attribute type is single-valued.
|
||||
*/
|
||||
public LDAPAttributeSchema( String name, String oid, String description,
|
||||
int syntax, boolean single ) {
|
||||
super( name, oid, description );
|
||||
attrName = "attributetypes";
|
||||
this.syntax = syntax;
|
||||
this.syntaxString = internalSyntaxToString();
|
||||
this.single = single;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an attribute type definition, using the specified
|
||||
* information.
|
||||
* @param name Name of the attribute type.
|
||||
* @param oid Object identifier (OID) of the attribute type
|
||||
* in dotted-string format (for example, "1.2.3.4").
|
||||
* @param description Description of attribute type.
|
||||
* @param syntaxString Syntax of this attribute type in dotted-string
|
||||
* format (for example, "1.2.3.4.5").
|
||||
* @param single <CODE>true</CODE> if the attribute type is single-valued.
|
||||
*/
|
||||
public LDAPAttributeSchema( String name, String oid, String description,
|
||||
String syntaxString, boolean single ) {
|
||||
super( name, oid, description );
|
||||
attrName = "attributetypes";
|
||||
this.syntaxString = syntaxString;
|
||||
this.syntax = syntaxCheck( syntaxString );
|
||||
this.single = single;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an attribute type definition based on a description in
|
||||
* the AttributeTypeDescription format. For information on this format,
|
||||
* (see <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
|
||||
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
|
||||
* Attribute Syntax Definitions</A>. This is the format that LDAP servers
|
||||
* and clients use to exchange schema information. (For example, when
|
||||
* you search an LDAP server for its schema, the server returns an entry
|
||||
* with the attributes "objectclasses" and "attributetypes". The
|
||||
* values of the "attributetypes" attribute are attribute type descriptions
|
||||
* in this format.)
|
||||
* <P>
|
||||
*
|
||||
* @param raw Definition of the attribute type in the
|
||||
* AttributeTypeDescription format.
|
||||
*/
|
||||
public LDAPAttributeSchema( String raw ) {
|
||||
attrName = "attributetypes";
|
||||
parseValue( raw );
|
||||
String val = (String)properties.get( SYNTAX );
|
||||
if ( val != null ) {
|
||||
syntaxString = val;
|
||||
syntax = syntaxCheck( val );
|
||||
}
|
||||
single = properties.containsKey( "SINGLE-VALUE" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the syntax of the attribute type.
|
||||
* @return One of the following values:
|
||||
* <UL>
|
||||
* <LI><CODE>cis</CODE> (case-insensitive string)
|
||||
* <LI><CODE>ces</CODE> (case-exact string)
|
||||
* <LI><CODE>binary</CODE> (binary data)
|
||||
* <LI><CODE>int</CODE> (integer)
|
||||
* <LI><CODE>telephone</CODE> (telephone number -- identical to cis,
|
||||
* but blanks and dashes are ignored during comparisons)
|
||||
* <LI><CODE>dn</CODE> (distinguished name)
|
||||
* <LI><CODE>unknown</CODE> (not a known syntax)
|
||||
* </UL>
|
||||
*/
|
||||
public int getSyntax() {
|
||||
return syntax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the syntax of the attribute type in dotted-decimal format,
|
||||
* for example "1.2.3.4.5"
|
||||
* @return the attribute syntax in dotted-decimal format.
|
||||
*/
|
||||
public String getSyntaxString() {
|
||||
return syntaxString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the attribute type is single-valued.
|
||||
* @return <code>true</code> if single-valued,
|
||||
* <code>false</code> if multi-valued.
|
||||
*/
|
||||
public boolean isSingleValued() {
|
||||
return single;
|
||||
}
|
||||
|
||||
protected String internalSyntaxToString() {
|
||||
String s;
|
||||
if ( syntax == cis ) {
|
||||
s = cisString;
|
||||
} else if ( syntax == binary ) {
|
||||
s = binaryString;
|
||||
} else if ( syntax == ces ) {
|
||||
s = cesString;
|
||||
} else if ( syntax == telephone ) {
|
||||
s = telephoneString;
|
||||
} else if ( syntax == dn ) {
|
||||
s = dnString;
|
||||
} else if ( syntax == integer ) {
|
||||
s = intString;
|
||||
} else {
|
||||
s = syntaxString;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
protected String syntaxToString() {
|
||||
String s;
|
||||
if ( syntax == cis ) {
|
||||
s = "case-insensitive string";
|
||||
} else if ( syntax == binary ) {
|
||||
s = "binary";
|
||||
} else if ( syntax == integer ) {
|
||||
s = "integer";
|
||||
} else if ( syntax == ces ) {
|
||||
s = "case-exact string";
|
||||
} else if ( syntax == telephone ) {
|
||||
s = "telephone";
|
||||
} else if ( syntax == dn ) {
|
||||
s = "distinguished name";
|
||||
} else {
|
||||
s = syntaxString;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a value in RFC 2252 format for submitting to a server
|
||||
*
|
||||
* @param quotingBug <CODE>true</CODE> if SUP and SYNTAX values are to
|
||||
* be quoted. That is to satisfy bugs in certain LDAP servers.
|
||||
* @return A String ready to be submitted to an LDAP server
|
||||
*/
|
||||
String getValue( boolean quotingBug ) {
|
||||
String s = getValuePrefix();
|
||||
s += getValue( SUPERIOR, false );
|
||||
String val = getOptionalValues( MATCHING_RULES );
|
||||
if ( val.length() > 0 ) {
|
||||
s += val + ' ';
|
||||
}
|
||||
s += getValue( SYNTAX, quotingBug );
|
||||
s += ' ';
|
||||
val = getOptionalValues( NOVALS );
|
||||
if ( val.length() > 0 ) {
|
||||
s += val + ' ';
|
||||
}
|
||||
val = getOptionalValues( new String[] {USAGE} );
|
||||
if ( val.length() > 0 ) {
|
||||
s += val + ' ';
|
||||
}
|
||||
val = getCustomValues();
|
||||
if ( val.length() > 0 ) {
|
||||
s += val + ' ';
|
||||
}
|
||||
s += ')';
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the definition of the attribute type in a user friendly format.
|
||||
* This is the format that the attribute type definition uses when
|
||||
* you print the attribute type or the schema.
|
||||
* @return Definition of the attribute type in a user friendly format.
|
||||
*/
|
||||
public String toString() {
|
||||
String s = "Name: " + name + "; OID: " + oid + "; Type: ";
|
||||
s += syntaxToString();
|
||||
s += "; Description: " + description + "; ";
|
||||
if ( single ) {
|
||||
s += "single-valued";
|
||||
} else {
|
||||
s += "multi-valued";
|
||||
}
|
||||
s += getQualifierString( EXPLICIT );
|
||||
return s;
|
||||
}
|
||||
|
||||
protected int syntaxCheck( String syntax ) {
|
||||
int i = unknown;
|
||||
if ( syntax.equals( cisString ) ) {
|
||||
i = cis;
|
||||
} else if ( syntax.equals( binaryString ) ) {
|
||||
i = binary;
|
||||
} else if ( syntax.equals( cesString ) ) {
|
||||
i = ces;
|
||||
} else if ( syntax.equals( intString ) ) {
|
||||
i = integer;
|
||||
} else if ( syntax.equals( telephoneString ) ) {
|
||||
i = telephone;
|
||||
} else if ( syntax.equals( dnString ) ) {
|
||||
i = dn;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an attribute schema definition to see if the SYNTAX value
|
||||
* is quoted. It shouldn't be (according to RFC 2252), but it is for
|
||||
* some LDAP servers. It will either be:<BR>
|
||||
* <CODE>SYNTAX 1.3.6.1.4.1.1466.115.121.1.15</CODE> or<BR>
|
||||
* <CODE>SYNTAX '1.3.6.1.4.1.1466.115.121.1.15'</CODE>
|
||||
* @param raw Definition of the attribute type in the
|
||||
* AttributeTypeDescription format.
|
||||
*/
|
||||
static boolean isSyntaxQuoted( String raw ) {
|
||||
int ind = raw.indexOf( " SYNTAX " );
|
||||
if ( ind >= 0 ) {
|
||||
ind += 8;
|
||||
int l = raw.length() - ind;
|
||||
// Extract characters
|
||||
char[] ch = new char[l];
|
||||
raw.getChars( ind, raw.length(), ch, 0 );
|
||||
ind = 0;
|
||||
// Skip to ' or start of syntax value
|
||||
while( (ind < ch.length) && (ch[ind] == ' ') ) {
|
||||
ind++;
|
||||
}
|
||||
if ( ind < ch.length ) {
|
||||
return ( ch[ind] == '\'' );
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Predefined qualifiers
|
||||
public static final String EQUALITY = "EQUALITY";
|
||||
public static final String ORDERING = "ORDERING";
|
||||
public static final String SUBSTR = "SUBSTR";
|
||||
public static final String SINGLE = "SINGLE-VALUE";
|
||||
public static final String COLLECTIVE = "COLLECTIVE";
|
||||
public static final String NO_USER_MODIFICATION = "NO-USER-MODIFICATION";
|
||||
public static final String USAGE = "USAGE";
|
||||
public static final String SYNTAX = "SYNTAX";
|
||||
|
||||
protected int syntax = unknown;
|
||||
protected String syntaxString = null;
|
||||
protected boolean single = false;
|
||||
|
||||
static String[] NOVALS = { SINGLE,
|
||||
COLLECTIVE,
|
||||
NO_USER_MODIFICATION };
|
||||
static {
|
||||
for( int i = 0; i < NOVALS.length; i++ ) {
|
||||
novalsTable.put( NOVALS[i], NOVALS[i] );
|
||||
}
|
||||
}
|
||||
static final String[] MATCHING_RULES = { EQUALITY,
|
||||
ORDERING,
|
||||
SUBSTR };
|
||||
// Qualifiers tracked explicitly
|
||||
static final String[] EXPLICIT = { SINGLE,
|
||||
OBSOLETE,
|
||||
COLLECTIVE,
|
||||
NO_USER_MODIFICATION,
|
||||
SYNTAX};
|
||||
}
|
||||
@@ -0,0 +1,400 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import netscape.ldap.client.*;
|
||||
import netscape.ldap.client.opers.*;
|
||||
|
||||
/**
|
||||
* Represents a set of attributes (for example, the set of attributes
|
||||
* in an entry).
|
||||
*
|
||||
* @version 1.0
|
||||
* @see netscape.ldap.LDAPAttribute
|
||||
*/
|
||||
public class LDAPAttributeSet implements Cloneable
|
||||
{
|
||||
Hashtable attrHash = null;
|
||||
LDAPAttribute[] attrs = new LDAPAttribute[0];
|
||||
/* If there are less attributes than this in the set, it's not worth
|
||||
creating a Hashtable - faster and cheaper most likely to string
|
||||
comparisons. Most applications fetch attributes once only, anyway */
|
||||
static final int ATTR_COUNT_REQUIRES_HASH = 5;
|
||||
|
||||
/**
|
||||
* Constructs a new set of attributes. This set is initially empty.
|
||||
*/
|
||||
public LDAPAttributeSet() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an attribute set.
|
||||
* @param attrs The list of attributes.
|
||||
*/
|
||||
public LDAPAttributeSet( LDAPAttribute[] attrs ) {
|
||||
this.attrs = attrs;
|
||||
}
|
||||
|
||||
public synchronized Object clone() {
|
||||
try {
|
||||
LDAPAttributeSet attributeSet = new LDAPAttributeSet();
|
||||
attributeSet.attrs = new LDAPAttribute[attrs.length];
|
||||
for (int i = 0; i < attrs.length; i++) {
|
||||
attributeSet.attrs[i] = new LDAPAttribute(attrs[i]);
|
||||
}
|
||||
return attributeSet;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an enumeration of the attributes in this attribute set.
|
||||
* @return Enumeration of the attributes in this set.
|
||||
*/
|
||||
public Enumeration getAttributes () {
|
||||
Vector v = new Vector();
|
||||
synchronized(this) {
|
||||
for (int i=0; i<attrs.length; i++) {
|
||||
v.addElement(attrs[i]);
|
||||
}
|
||||
}
|
||||
return v.elements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new attribute set containing only the attributes
|
||||
* that have the specified subtypes.
|
||||
* <P>
|
||||
*
|
||||
* For example, suppose an attribute set contains the following attributes:
|
||||
* <P>
|
||||
*
|
||||
* <PRE>
|
||||
* cn
|
||||
* cn;lang-ja
|
||||
* sn;phonetic;lang-ja
|
||||
* sn;lang-us
|
||||
* </PRE>
|
||||
*
|
||||
* If you call the <CODE>getSubset</CODE> method and pass
|
||||
* <CODE>lang-ja</CODE> as the argument, the method returns
|
||||
* an attribute set containing the following attributes:
|
||||
* <P>
|
||||
*
|
||||
* <PRE>
|
||||
* cn;lang-ja
|
||||
* sn;phonetic;lang-ja
|
||||
* </PRE>
|
||||
*
|
||||
* @param subtype Semi-colon delimited list of subtypes
|
||||
* that you want to find in attribute names.
|
||||
* For example:
|
||||
*<PRE>
|
||||
* "lang-ja" // Only Japanese language subtypes
|
||||
* "binary" // Only binary subtypes
|
||||
* "binary;lang-ja" // Only Japanese language subtypes
|
||||
* which also are binary
|
||||
*</PRE>
|
||||
* @return Attribute set containing the attributes that have
|
||||
* the specified subtypes
|
||||
* @see netscape.ldap.LDAPAttribute
|
||||
* @see netscape.ldap.LDAPAttributeSet#getAttribute
|
||||
* @see netscape.ldap.LDAPEntry#getAttributeSet
|
||||
*/
|
||||
public LDAPAttributeSet getSubset(String subtype) {
|
||||
LDAPAttributeSet attrs = new LDAPAttributeSet();
|
||||
if ( subtype == null )
|
||||
return attrs;
|
||||
StringTokenizer st = new StringTokenizer(subtype, ";");
|
||||
if( st.countTokens() < 1 )
|
||||
return attrs;
|
||||
String[] searchTypes = new String[st.countTokens()];
|
||||
int i = 0;
|
||||
while( st.hasMoreElements() ) {
|
||||
searchTypes[i] = (String)st.nextElement();
|
||||
i++;
|
||||
}
|
||||
Enumeration attrEnum = getAttributes();
|
||||
while( attrEnum.hasMoreElements() ) {
|
||||
LDAPAttribute attr = (LDAPAttribute)attrEnum.nextElement();
|
||||
if( attr.hasSubtypes( searchTypes ) )
|
||||
attrs.add( new LDAPAttribute( attr ) );
|
||||
}
|
||||
return attrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single attribute that exactly matches the specified attribute
|
||||
* name.
|
||||
* @param attrName Name of attribute to return.
|
||||
* For example:
|
||||
*<PRE>
|
||||
* "cn" // Only a non-subtyped version of cn
|
||||
* "cn;lang-ja" // Only a Japanese version of cn
|
||||
*</PRE>
|
||||
* @return Attribute that has exactly the same name, or null
|
||||
* (if no attribute in the set matches the specified name).
|
||||
* @see netscape.ldap.LDAPAttribute
|
||||
*/
|
||||
public LDAPAttribute getAttribute( String attrName ) {
|
||||
prepareHashtable();
|
||||
if (attrHash != null) {
|
||||
return (LDAPAttribute)attrHash.get( attrName.toLowerCase() );
|
||||
} else {
|
||||
for (int i = 0; i < attrs.length; i++) {
|
||||
if (attrName.equalsIgnoreCase(attrs[i].getName())) {
|
||||
return attrs[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare hashtable for fast attribute lookups
|
||||
*/
|
||||
private void prepareHashtable() {
|
||||
if ((attrHash == null) && (attrs.length >= ATTR_COUNT_REQUIRES_HASH)) {
|
||||
attrHash = new Hashtable();
|
||||
for (int j = 0; j < attrs.length; j++) {
|
||||
attrHash.put( attrs[j].getName().toLowerCase(), attrs[j] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the subtype that matches the attribute name specified
|
||||
* by <CODE>attrName</CODE> and the language specificaton identified
|
||||
* by <CODE>lang</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* If no attribute in the set has the specified name and subtype,
|
||||
* the method returns <CODE>null</CODE>.
|
||||
*
|
||||
* Attributes containing subtypes other than <CODE>lang</CODE>
|
||||
* (for example, <CODE>cn;binary</CODE>) are returned only if
|
||||
* they contain the specified <CODE>lang</CODE> subtype and if
|
||||
* the set contains no attribute having only the <CODE>lang</CODE>
|
||||
* subtype. (For example, <CODE>getAttribute( "cn", "lang-ja" )</CODE>
|
||||
* returns the <CODE>cn;lang-ja;phonetic</CODE> attribute only if
|
||||
* the <CODE>cn;lang-ja</CODE> attribute does not exist.)
|
||||
* <P>
|
||||
*
|
||||
* If null is specified for the <CODE>lang</CODE> argument,
|
||||
* calling this method is the same as calling the
|
||||
* <CODE>getAttribute(attrName)</CODE> method.
|
||||
* <P>
|
||||
*
|
||||
* For example, suppose an entry contains only the following attributes:
|
||||
* <P>
|
||||
* <UL>
|
||||
* <LI><CODE>cn;lang-en</CODE>
|
||||
* <LI><CODE>cn;lang-ja-JP-kanji</CODE>
|
||||
* <LI><CODE>sn</CODE>
|
||||
* </UL>
|
||||
* <P>
|
||||
*
|
||||
* Calling the following methods will return the following values:
|
||||
* <P>
|
||||
* <UL>
|
||||
* <LI><CODE>getAttribute( "cn" )</CODE> returns <CODE>null</CODE>.
|
||||
* <LI><CODE>getAttribute( "sn" )</CODE> returns the "<CODE>sn</CODE>" attribute.
|
||||
* <LI><CODE>getAttribute( "cn", "lang-en-us" )</CODE> returns the "<CODE>cn;lang-en</CODE>" attribute.
|
||||
* <LI><CODE>getAttribute( "cn", "lang-en" )</CODE> returns the "<CODE>cn;lang-en</CODE>" attribute.
|
||||
* <LI><CODE>getAttribute( "cn", "lang-ja" )</CODE> returns <CODE>null</CODE>.
|
||||
* <LI><CODE>getAttribute( "sn", "lang-en" )</CODE> returns the "<CODE>sn</CODE>" attribute.
|
||||
*</UL>
|
||||
* <P>
|
||||
* @param attrName Name of attribute to find in the entry.
|
||||
* @param lang A language specification.
|
||||
* @return The attribute that matches the base name and that best
|
||||
* matches any specified language subtype.
|
||||
* @see netscape.ldap.LDAPAttribute
|
||||
*/
|
||||
public LDAPAttribute getAttribute( String attrName, String lang ) {
|
||||
if ( (lang == null) || (lang.length() < 1) )
|
||||
return getAttribute( attrName );
|
||||
|
||||
String langLower = lang.toLowerCase();
|
||||
if ((langLower.length() < 5) ||
|
||||
( !langLower.substring( 0, 5 ).equals( "lang-" ) )) {
|
||||
return null;
|
||||
}
|
||||
StringTokenizer st = new StringTokenizer( langLower, "-" );
|
||||
// Skip first token, which is "lang-"
|
||||
st.nextToken();
|
||||
String[] langComponents = new String[st.countTokens()];
|
||||
int i = 0;
|
||||
while ( st.hasMoreTokens() ) {
|
||||
langComponents[i] = st.nextToken();
|
||||
i++;
|
||||
}
|
||||
|
||||
String searchBasename = LDAPAttribute.getBaseName(attrName);
|
||||
String[] searchTypes = LDAPAttribute.getSubtypes(attrName);
|
||||
LDAPAttribute found = null;
|
||||
int matchCount = 0;
|
||||
for( i = 0; i < attrs.length; i++ ) {
|
||||
boolean isCandidate = false;
|
||||
LDAPAttribute attr = attrs[i];
|
||||
// Same base name?
|
||||
if ( attr.getBaseName().equalsIgnoreCase(searchBasename) ) {
|
||||
// Accept any subtypes?
|
||||
if( (searchTypes == null) || (searchTypes.length < 1) ) {
|
||||
isCandidate = true;
|
||||
} else {
|
||||
// No, have to check each subtype for inclusion
|
||||
if( attr.hasSubtypes( searchTypes ) )
|
||||
isCandidate = true;
|
||||
}
|
||||
}
|
||||
String attrLang = null;
|
||||
if ( isCandidate ) {
|
||||
attrLang = attr.getLangSubtype();
|
||||
// At this point, the base name and subtypes are okay
|
||||
if ( attrLang == null ) {
|
||||
// If there are no language attributes, this one is okay
|
||||
found = attr;
|
||||
} else {
|
||||
// We just have to check for language match
|
||||
st = new StringTokenizer( attrLang.toLowerCase(), "-" );
|
||||
// Skip first token, which is "lang-"
|
||||
st.nextToken();
|
||||
// No match if the attribute's language spec is longer
|
||||
// than the target one
|
||||
if ( st.countTokens() > langComponents.length )
|
||||
continue;
|
||||
|
||||
// How many subcomponents of the language match?
|
||||
int j = 0;
|
||||
while ( st.hasMoreTokens() ) {
|
||||
if ( !langComponents[j].equals( st.nextToken() ) ) {
|
||||
j = 0;
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
if ( j > matchCount ) {
|
||||
found = attr;
|
||||
matchCount = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute at the position specified by the index
|
||||
* (for example, if you specify the index 0, the method returns the
|
||||
* first attribute in the set). The index is 0-based.
|
||||
*
|
||||
* @param index Index of the attribute that you want to get.
|
||||
* @return Attribute at the position specified by the index.
|
||||
*/
|
||||
public LDAPAttribute elementAt (int index) {
|
||||
return attrs[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes attribute at the position specified by the index
|
||||
* (for example, if you specify the index 0, the method removes the
|
||||
* first attribute in the set). The index is 0-based.
|
||||
*
|
||||
* @param index Index of the attribute that you want to remove.
|
||||
*/
|
||||
public void removeElementAt (int index) {
|
||||
if ((index >= 0) && (index < attrs.length)) {
|
||||
synchronized(this) {
|
||||
LDAPAttribute[] vals = new LDAPAttribute[attrs.length-1];
|
||||
int j = 0;
|
||||
for (int i = 0; i < attrs.length; i++) {
|
||||
if (i != index) {
|
||||
vals[j++] = attrs[i];
|
||||
}
|
||||
}
|
||||
attrs = vals;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of attributes in this set.
|
||||
* @return Number of attributes in this attribute set.
|
||||
*/
|
||||
public int size () {
|
||||
return attrs.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified attribute to this attribute set.
|
||||
* @param attr Attribute that you want to add to this set.
|
||||
*/
|
||||
public synchronized void add( LDAPAttribute attr ) {
|
||||
if (attr != null) {
|
||||
LDAPAttribute[] vals = new LDAPAttribute[attrs.length+1];
|
||||
for (int i = 0; i < attrs.length; i++)
|
||||
vals[i] = attrs[i];
|
||||
vals[attrs.length] = attr;
|
||||
attrs = vals;
|
||||
if (attrHash != null) {
|
||||
attrHash.put( attr.getName().toLowerCase(), attr );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified attribute from the set.
|
||||
* @param name Name of the attribute that you want removed.
|
||||
*/
|
||||
public synchronized void remove( String name ) {
|
||||
for( int i = 0; i < attrs.length; i++ ) {
|
||||
if ( name.equalsIgnoreCase( attrs[i].getName() ) ) {
|
||||
removeElementAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the string representation of all attributes
|
||||
* in the attribute set. For example:
|
||||
*
|
||||
* <PRE>
|
||||
* LDAPAttributeSet: LDAPAttribute {type='cn', values='Barbara Jensen,Babs
|
||||
* Jensen'}LDAPAttribute {type='sn', values='Jensen'}LDAPAttribute {type='
|
||||
* givenname', values='Barbara'}LDAPAttribute {type='objectclass', values=
|
||||
* 'top,person,organizationalPerson,inetOrgPerson'}LDAPAttribute {type='ou',
|
||||
* values='Product Development,People'}
|
||||
* </PRE>
|
||||
*
|
||||
* @return String representation of all attributes in the set.
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer("LDAPAttributeSet: ");
|
||||
for( int i = 0; i < attrs.length; i++ ) {
|
||||
if (i != 0) {
|
||||
sb.append(" ");
|
||||
}
|
||||
sb.append(attrs[i].toString());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
/**
|
||||
* Used to do explicit bind processing on a referral. A client may
|
||||
* specify an instance of this class to be used on a single operation
|
||||
* (through the <CODE>LDAPConstraints</CODE> object) or for all operations
|
||||
* (through <CODE>LDAPConnection.setOption()</CODE>). It is typically used
|
||||
* to control the authentication mechanism used on implicit referral
|
||||
* handling.
|
||||
*/
|
||||
|
||||
public interface LDAPBind {
|
||||
|
||||
/**
|
||||
* This method is called by <CODE>LDAPConnection</CODE> when
|
||||
* authenticating. An implementation may access the host, port,
|
||||
* credentials, and other information in the <CODE>LDAPConnection</CODE>
|
||||
* to decide on an appropriate authentication mechanism, and/or may
|
||||
* interact with a user or external module.
|
||||
* @exception netscape.ldap.LDAPException
|
||||
* @see netscape.ldap.LDAPConnection#bind
|
||||
* @param conn An established connection to an LDAP server.
|
||||
*/
|
||||
|
||||
public void bind(LDAPConnection conn) throws LDAPException;
|
||||
}
|
||||
797
mozilla/directory/java-sdk/ldapjdk/netscape/ldap/LDAPCache.java
Normal file
797
mozilla/directory/java-sdk/ldapjdk/netscape/ldap/LDAPCache.java
Normal file
@@ -0,0 +1,797 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import netscape.ldap.client.*;
|
||||
import netscape.ldap.util.*;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
/**
|
||||
* <CODE>LDAPCache</CODE> is the class that represents an
|
||||
* in-memory cache that you can use to reduce the number of
|
||||
* search requests sent to the LDAP server.
|
||||
* <P>
|
||||
*
|
||||
* Each item in the cache represents a search request and
|
||||
* its results. Each item is uniquely identified by the
|
||||
* search criteria, which includes:
|
||||
* <P>
|
||||
*
|
||||
* <UL>
|
||||
* <LI>the host name and port number of the LDAP server
|
||||
* <LI>the base DN of the search
|
||||
* <LI>the search filter
|
||||
* <LI>the scope of the search
|
||||
* <LI>the attributes to be returned in the search results
|
||||
* <LI>the DN used to authenticate the client when binding
|
||||
* to the server
|
||||
* <LI>the LDAP v3 controls specified in the search request
|
||||
* </UL>
|
||||
* <P>
|
||||
*
|
||||
* After a search request is cached, the results of any
|
||||
* subsequent search requests using the same criteria are 8
|
||||
* read from the cache. Note that if any part of the
|
||||
* criteria differs (for example, if a different DN is used
|
||||
* when binding to the server or if a different set of
|
||||
* attributes to be returned is specified), the search
|
||||
* request is sent to the server.
|
||||
* <P>
|
||||
*
|
||||
* When you create the cache, you specify the maximum amount
|
||||
* of time that an item can be kept in the cache. When an
|
||||
* item's age exceeds that time limit, the item is removed
|
||||
* from the cache.
|
||||
* <P>
|
||||
*
|
||||
* The cache also has a maximum size that you specify when
|
||||
* creating the cache. If adding a new item exceeds the
|
||||
* maximum size of the cache, the first entries in the cache
|
||||
* are removed to make enough space for the new item.
|
||||
* <P>
|
||||
*
|
||||
* Finally, when creating the cache, you can specify a list
|
||||
* of the base DNs in search requests that you want to cache.
|
||||
* For example, if you specify <CODE>o=Airius.com</CODE> as
|
||||
* a base DN to cache, your client caches search requests
|
||||
* where the base DN is <CODE>o=Airius.com</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* To specify that you want to use a cache for a particular
|
||||
* LDAP session, call the <CODE>setCache</CODE> method of
|
||||
* the <CODE>LDAPConnection</CODE> object that you are
|
||||
* working with.
|
||||
* <P>
|
||||
*
|
||||
* All clones of an <CODE>LDAPConnection</CODE> object share
|
||||
* the same <CODE>LDAPCache</CODE> object.
|
||||
* <P>
|
||||
*
|
||||
* The <CODE>LDAPCache</CODE> class includes methods for
|
||||
* getting statistics (such as hit rates) from the cache and
|
||||
* for flushing entries from the cache.
|
||||
* <P>
|
||||
*
|
||||
* @see netscape.ldap.LDAPConnection#setCache(netscape.ldap.LDAPCache)
|
||||
* @see netscape.ldap.LDAPConnection#getCache
|
||||
*/
|
||||
public class LDAPCache implements TimerEventListener {
|
||||
private Hashtable m_cache;
|
||||
private long m_timeToLive;
|
||||
private long m_maxSize;
|
||||
private String[] m_dns;
|
||||
private Vector m_orderedStruct;
|
||||
private long m_remainingSize = 0;
|
||||
/**
|
||||
* Delimiter used internally when creating keys
|
||||
* for the cache.
|
||||
*/
|
||||
public static final String DELIM = "#";
|
||||
private Timer m_timer = null;
|
||||
private static long TIMEOUT = 60000;
|
||||
private long m_totalOpers = 0;
|
||||
private static final boolean m_debug = false;
|
||||
private long m_hits = 0;
|
||||
private long m_flushes = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new <CODE>LDAPCache</CODE> object, using the
|
||||
* specified maximum size of the cache (in bytes) and the maximum
|
||||
* age of cached items (in seconds). When items in the cache
|
||||
* exceed this age, they are removed from the cache.
|
||||
* <P>
|
||||
*
|
||||
* @param ttl The maximum amount of time that an item can be cached
|
||||
* (in seconds)
|
||||
* @param size The maximum size of the cache (in bytes)
|
||||
*/
|
||||
public LDAPCache(long ttl, long size)
|
||||
{
|
||||
init(ttl, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <CODE>LDAPCache</CODE> object, using the
|
||||
* specified maximum size of the cache (in bytes), and the maximum
|
||||
* age of cached items (in seconds), and an array of the base DNs
|
||||
* of searches that you want to cache. (For example,
|
||||
* if the array of base DNs includes <CODE>o=Airius.com</CODE>,
|
||||
* the cache stores search results if the base DN in the search
|
||||
* request is <CODE>o=Airius.com</CODE>.)
|
||||
* <P>
|
||||
*
|
||||
* @param ttl The maximum amount of time that an item can be cached
|
||||
* (in seconds)
|
||||
* @param size The maximum size of the cache (in bytes)
|
||||
* @param dns The list of base DNs of searches that you want to cache.
|
||||
*/
|
||||
public LDAPCache(long ttl, long size, String[] dns)
|
||||
{
|
||||
init(ttl, size);
|
||||
|
||||
m_dns = new String[dns.length];
|
||||
if ((dns != null) && (dns.length > 0))
|
||||
for (int i=0; i<dns.length; i++) {
|
||||
m_dns[i] = (new DN(dns[i])).toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum size of the cache (in bytes).
|
||||
* <P>
|
||||
*
|
||||
* @return The maximum size of the cache (in bytes)
|
||||
*/
|
||||
public long getSize()
|
||||
{
|
||||
return m_maxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum age allowed for cached items (in
|
||||
* seconds). (Items that exceed this age are
|
||||
* removed from the cache.)
|
||||
* <P>
|
||||
*
|
||||
* @return The maximum age of items in the cache (in
|
||||
* seconds).
|
||||
*/
|
||||
public long getTimeToLive()
|
||||
{
|
||||
return m_timeToLive/1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the array of base DNs of searches to be cached.
|
||||
* (Search requests with these base DNs are cached.)
|
||||
* <P>
|
||||
*
|
||||
* @return The array of base DNs.
|
||||
*/
|
||||
public String[] getBaseDNs()
|
||||
{
|
||||
return m_dns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the entries identified by DN and scope from the cache.
|
||||
* <P>
|
||||
*
|
||||
* @param dn The distinguished name (or base DN) of the entries
|
||||
* to be removed from the cache. Use this parameter in conjunction
|
||||
* with <CODE>scope</CODE> to identify the entries that you want
|
||||
* removed from the cache. If this parameter is <CODE>null</CODE>,
|
||||
* the entire cache is flushed.
|
||||
* @param scope The scope identifying the entries that you want
|
||||
* removed from the cache. The value of this parameter can be
|
||||
* one of the following:
|
||||
* <UL>
|
||||
* <LI><CODE>LDAPv2.SCOPE_BASE</CODE> (to remove the entry identified
|
||||
* by <CODE>dn</CODE>)
|
||||
* <LI><CODE>LDAPv2.SCOPE_ONE</CODE> (to remove the entries that
|
||||
* have <CODE>dn</CODE> as their parent entry)
|
||||
* <LI><CODE>LDAPv2.SCOPE_SUB</CODE> (to remove the entries in the
|
||||
* subtree under <CODE>dn</CODE> in the directory)
|
||||
* </UL>
|
||||
* <P>
|
||||
* @return <CODE>true</CODE> if the entry is removed from the cache,
|
||||
* or <CODE>false</CODE> if the entry is not removed.
|
||||
*/
|
||||
public synchronized boolean flushEntries(String dn, int scope) {
|
||||
|
||||
if (m_debug)
|
||||
System.out.println("DEBUG: User request for flushing entry: dn "+
|
||||
dn+" and scope "+scope);
|
||||
// if the dn is null, invalidate the whole cache
|
||||
if (dn == null)
|
||||
{
|
||||
// reclaim all the cache spaces
|
||||
m_remainingSize = m_maxSize;
|
||||
m_cache.clear();
|
||||
m_orderedStruct.removeAllElements();
|
||||
return true;
|
||||
}
|
||||
|
||||
DN dn2 = new DN(dn);
|
||||
|
||||
Enumeration e = m_cache.keys();
|
||||
|
||||
while(e.hasMoreElements()) {
|
||||
Long key = (Long)e.nextElement();
|
||||
Vector val = (Vector)m_cache.get(key);
|
||||
|
||||
int j=1;
|
||||
int size2=val.size();
|
||||
|
||||
for (; j<size2; j++) {
|
||||
String d = ((LDAPEntry)val.elementAt(j)).getDN();
|
||||
DN dn1 = new DN(d);
|
||||
|
||||
if (dn1.equals(dn2))
|
||||
break;
|
||||
if (scope == LDAPConnection.SCOPE_ONE) {
|
||||
DN parentDN1 = dn1.getParent();
|
||||
if (parentDN1.equals(dn2)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((scope == LDAPConnection.SCOPE_SUB) &&
|
||||
(dn1.isDescendantOf(dn2))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j < size2) {
|
||||
for (int k=0; k<m_orderedStruct.size(); k++) {
|
||||
Vector v = (Vector)m_orderedStruct.elementAt(k);
|
||||
if (key.equals((Long)v.elementAt(0))) {
|
||||
m_orderedStruct.removeElementAt(k);
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_cache.remove(key);
|
||||
if (m_debug)
|
||||
System.out.println("DEBUG: Successfully removed entry ->"+key);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_debug)
|
||||
System.out.println("DEBUG: The number of keys in the cache is "
|
||||
+m_cache.size());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets invoked when the timer expires.
|
||||
* @param e The timer event containing the timer itself.
|
||||
*/
|
||||
public void timerExpired(TimerEvent e)
|
||||
{
|
||||
flushEntries();
|
||||
|
||||
Timer t = (Timer)e.getSource();
|
||||
t.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of available space (in bytes) left in the cache.
|
||||
* <P>
|
||||
*
|
||||
* @return The available space (in bytes) in the cache.
|
||||
*/
|
||||
public long getAvailableSize() {
|
||||
return m_remainingSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total number of requests for retrieving items from
|
||||
* the cache. This includes both items successfully found in
|
||||
* the cache and items not found in the cache.
|
||||
* <P>
|
||||
*
|
||||
* @return The total number of requests for retrieving items from
|
||||
* the cache.
|
||||
*/
|
||||
public long getTotalOperations() {
|
||||
return m_totalOpers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total number of requests which failed to find and
|
||||
* retrieve an item from the cache.
|
||||
* <P>
|
||||
*
|
||||
* @return The number of requests that did not find and retrieve
|
||||
* an item in the cache.
|
||||
*/
|
||||
public long getNumMisses() {
|
||||
return (m_totalOpers - m_hits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total number of requests which successfully found and
|
||||
* retrieved an item from the cache.
|
||||
* @return The number of requests that successfully found and
|
||||
* retrieved an item from the cache.
|
||||
*/
|
||||
public long getNumHits() {
|
||||
return m_hits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total number of entries that are flushed when timer expires
|
||||
* and <CODE>flushEntries</CODE> is called.
|
||||
* <P>
|
||||
*
|
||||
* @return The total number of entries that are flushed when timer
|
||||
* expires.
|
||||
*/
|
||||
public long getNumFlushes() {
|
||||
return m_flushes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a key for a cache entry by concatenating all input parameters
|
||||
* @return The key for a cache entry
|
||||
* @exception LDAPException Thrown when failed to create key.
|
||||
*/
|
||||
Long createKey(String host, int port, String baseDN, String filter,
|
||||
int scope, String[] attrs, String bindDN, LDAPConstraints cons)
|
||||
throws LDAPException {
|
||||
|
||||
DN dn = new DN(baseDN);
|
||||
baseDN = dn.toString();
|
||||
|
||||
if (m_dns != null) {
|
||||
int i=0;
|
||||
for (; i<m_dns.length; i++) {
|
||||
if (baseDN.equals(m_dns[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= m_dns.length)
|
||||
throw new LDAPException(baseDN+" is not a cached base DN",
|
||||
LDAPException.OTHER);
|
||||
}
|
||||
|
||||
String key = null;
|
||||
|
||||
key = appendString(baseDN);
|
||||
key = key+appendString(scope);
|
||||
key = key+appendString(host);
|
||||
key = key+appendString(port);
|
||||
key = key+appendString(filter);
|
||||
key = key+appendString(attrs);
|
||||
key = key+appendString(bindDN);
|
||||
|
||||
LDAPControl[] serverControls = null;
|
||||
LDAPControl[] clientControls = null;
|
||||
|
||||
// get server and client controls
|
||||
if (cons != null)
|
||||
{
|
||||
serverControls = cons.getServerControls();
|
||||
clientControls = cons.getClientControls();
|
||||
}
|
||||
|
||||
if ((serverControls != null) && (serverControls.length > 0))
|
||||
{
|
||||
String[] objID = new String[serverControls.length];
|
||||
|
||||
for (int i=0; i<serverControls.length; i++) {
|
||||
long val = getCRC32(serverControls[i].getValue());
|
||||
objID[i] = new Long(val).toString();
|
||||
}
|
||||
key = key + appendString(objID);
|
||||
}
|
||||
else
|
||||
key = key+appendString(0);
|
||||
|
||||
if ((clientControls != null) && (clientControls.length > 0))
|
||||
{
|
||||
String[] objID = new String[clientControls.length];
|
||||
|
||||
for (int i=0; i<clientControls.length; i++) {
|
||||
long val = getCRC32(clientControls[i].getValue());
|
||||
objID[i] = new Long(val).toString();
|
||||
}
|
||||
key = key + appendString(objID);
|
||||
}
|
||||
else
|
||||
key = key+appendString(0);
|
||||
|
||||
long val = getCRC32(key.getBytes());
|
||||
return new Long(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cache entry based on the specified key.
|
||||
* @param key The key for the cache entry.
|
||||
* @return The cache entry
|
||||
*/
|
||||
synchronized Object getEntry(Long key) {
|
||||
Object obj = null;
|
||||
|
||||
obj = m_cache.get(key);
|
||||
m_totalOpers++;
|
||||
|
||||
if (m_debug) {
|
||||
if (obj == null)
|
||||
System.out.println("DEBUG: Entry whose key -> "+key+
|
||||
" not found in the cache.");
|
||||
else
|
||||
System.out.println("DEBUG: Entry whose key -> "+key+
|
||||
" found in the cache.");
|
||||
}
|
||||
|
||||
if (obj != null)
|
||||
m_hits++;
|
||||
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush entries which stays longer or equal to the time-to-live.
|
||||
*/
|
||||
synchronized void flushEntries()
|
||||
{
|
||||
Vector v = null;
|
||||
boolean delete = false;
|
||||
|
||||
Date date = new Date();
|
||||
long currTime = date.getTime();
|
||||
|
||||
m_flushes = 0;
|
||||
while(true) {
|
||||
if (m_orderedStruct.size() <= 0)
|
||||
break;
|
||||
|
||||
v = (Vector)m_orderedStruct.firstElement();
|
||||
long diff = currTime-((Long)v.elementAt(1)).longValue();
|
||||
if (diff >= m_timeToLive) {
|
||||
Long key = (Long)v.elementAt(0);
|
||||
|
||||
if (m_debug)
|
||||
System.out.println("DEBUG: Timer flush entry whose key is "+key);
|
||||
|
||||
Vector entry = (Vector)m_cache.remove(key);
|
||||
m_remainingSize = m_remainingSize + ((Long)entry.firstElement()).longValue();
|
||||
|
||||
// always delete the first one
|
||||
m_orderedStruct.removeElementAt(0);
|
||||
|
||||
m_flushes++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_debug)
|
||||
System.out.println("DEBUG: The number of keys in the cache is "
|
||||
+m_cache.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the entry to the hashtable cache and to the vector respectively.
|
||||
* The vector is used to keep track of the order of the entries being added.
|
||||
* @param key The key for the cache entry.
|
||||
* @param value The cache entry being added to the cache for the specified
|
||||
* key.
|
||||
* @exception LDAPException Get thrown when failed to add the entry.
|
||||
*/
|
||||
synchronized void addEntry(Long key, Object value) throws LDAPException
|
||||
{
|
||||
// if entry exists, dont perform add operation
|
||||
if (m_cache.get(key) != null)
|
||||
return;
|
||||
|
||||
Vector v = (Vector)value;
|
||||
|
||||
// assume the size of the key is 4 bytes
|
||||
long size = ((Long)v.elementAt(0)).longValue()+4;
|
||||
|
||||
if (size > m_maxSize) {
|
||||
throw new LDAPException("Failed to add an entry to the cache since the new entry exceeds the cache size", LDAPException.OTHER);
|
||||
}
|
||||
|
||||
v.setElementAt(new Long(size), 0);
|
||||
|
||||
// if the size of entry being added is bigger than the spare space in the
|
||||
// cache
|
||||
if (size > m_remainingSize) {
|
||||
while (true) {
|
||||
Vector element = (Vector)m_orderedStruct.firstElement();
|
||||
Long str = (Long)element.elementAt(0);
|
||||
Vector val = (Vector)m_cache.remove(str);
|
||||
if (m_debug)
|
||||
System.out.println("DEBUG: The spare size of the cache is not big enough "+
|
||||
"to hold the new entry, deleting the entry whose key -> "+str);
|
||||
|
||||
// always remove the first one
|
||||
m_orderedStruct.removeElementAt(0);
|
||||
m_remainingSize = m_remainingSize +
|
||||
((Long)val.elementAt(0)).longValue();
|
||||
if (m_remainingSize >= size)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_remainingSize = m_remainingSize - size;
|
||||
m_cache.put(key, v);
|
||||
Vector element = new Vector();
|
||||
element.addElement(key);
|
||||
Date date = new Date();
|
||||
element.addElement(new Long(date.getTime()));
|
||||
m_orderedStruct.addElement(element);
|
||||
|
||||
if (m_debug)
|
||||
{
|
||||
System.out.println("DEBUG: Adding a new entry whose key -> "+key);
|
||||
System.out.println("DEBUG: The current number of keys in the cache "+
|
||||
m_cache.size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of entries being cached.
|
||||
* @return The number of entries being cached.
|
||||
*/
|
||||
int size()
|
||||
{
|
||||
return m_cache.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up
|
||||
*/
|
||||
void cleanup() {
|
||||
m_timer.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the instance variables.
|
||||
*/
|
||||
private void init(long ttl, long size)
|
||||
{
|
||||
m_cache = new Hashtable();
|
||||
m_timeToLive = ttl*1000;
|
||||
m_maxSize = size;
|
||||
m_remainingSize = size;
|
||||
m_dns = null;
|
||||
m_orderedStruct = new Vector();
|
||||
m_timer = new Timer(TIMEOUT);
|
||||
m_timer.addTimerExpiredEventListener((TimerEventListener)this);
|
||||
m_timer.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate the specified integer with the delimiter.
|
||||
* @param str The string which concatenate with the delimiter.
|
||||
* @return The concatenated string
|
||||
*/
|
||||
private String appendString(String str) {
|
||||
if (str == null)
|
||||
return "null"+DELIM;
|
||||
else
|
||||
return str.trim()+DELIM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate the specified integer with the delimiter.
|
||||
* @param num The integer which concatenate with the delimiter.
|
||||
* @return The concatenated string
|
||||
*/
|
||||
private String appendString(int num) {
|
||||
return num+DELIM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate the specified string array with the delimiter.
|
||||
* @param str A string array.
|
||||
* @return The concatenated string
|
||||
*/
|
||||
private String appendString(String[] str) {
|
||||
|
||||
if ((str == null) || (str.length < 1))
|
||||
return "0"+DELIM;
|
||||
else {
|
||||
String[] sorted = new String[str.length];
|
||||
System.arraycopy( str, 0, sorted, 0, str.length );
|
||||
sortStrings(sorted);
|
||||
|
||||
String s = sorted.length+DELIM;
|
||||
for (int i=0; i<sorted.length; i++)
|
||||
s = s+sorted[i].trim()+DELIM;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the array of strings using bubble sort.
|
||||
* @param str The array of string being sorted. The str parameter contains
|
||||
* the sorted result.
|
||||
*/
|
||||
private void sortStrings(String[] str) {
|
||||
|
||||
for (int i=0; i<str.length; i++)
|
||||
str[i] = str[i].trim();
|
||||
|
||||
for (int i=0; i<str.length-1; i++)
|
||||
for (int j=i+1; j<str.length; j++)
|
||||
{
|
||||
if (str[i].compareTo(str[j]) > 0)
|
||||
{
|
||||
String t = str[i];
|
||||
str[i] = str[j];
|
||||
str[j] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a 32 bits CRC from the given byte array.
|
||||
*/
|
||||
private long getCRC32(byte[] barray) {
|
||||
CRC32 crcVal = new CRC32();
|
||||
crcVal.update(barray);
|
||||
return crcVal.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a timer which will timeout for every certain interval. It
|
||||
* provides methods to start, stop, or restart timer. It also provides
|
||||
* methods to register/deregister the event listeners.
|
||||
*/
|
||||
class Timer {
|
||||
|
||||
private long m_timeout;
|
||||
private Thread t = null;
|
||||
private TimerEventListener listener;
|
||||
protected TimerEventListener stopListener = null;
|
||||
|
||||
/**
|
||||
* Constructor with the specified timout.
|
||||
* @param timeout The timeout value in milliseconds.
|
||||
*/
|
||||
Timer(long timeout) {
|
||||
m_timeout = timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the timer.
|
||||
*/
|
||||
void start() {
|
||||
TimerRunnable trun = new TimerRunnable(this);
|
||||
t = new Thread(trun);
|
||||
t.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the timer.
|
||||
*/
|
||||
void stop() {
|
||||
t.interrupt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the timeout value.
|
||||
* @return the timeout value.
|
||||
*/
|
||||
long getTimeout() {
|
||||
return m_timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the listener when the timer expires.
|
||||
*/
|
||||
void fireExpiredEvent() {
|
||||
TimerEvent event;
|
||||
|
||||
if (stopListener != null)
|
||||
{
|
||||
event = new TimerEvent(this);
|
||||
stopListener.timerExpired(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the listener to the queue who wants to be notified when the timer
|
||||
* expires.
|
||||
*/
|
||||
void addTimerExpiredEventListener(TimerEventListener listener) {
|
||||
stopListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the listener from the queue who will not get notified when the
|
||||
* timer expires.
|
||||
*/
|
||||
void removeTimerExpiredEventListener(TimerEventListener listener) {
|
||||
stopListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the starting point for the timer thread to execute.
|
||||
*/
|
||||
class TimerRunnable implements Runnable {
|
||||
Timer m_timer;
|
||||
|
||||
/**
|
||||
* Constructor with the specified timer object.
|
||||
* @param t The timer
|
||||
*/
|
||||
TimerRunnable(Timer t) {
|
||||
m_timer = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* The runnable waits until the timeout period has elapsed. It then notify
|
||||
* the registered listener who listens for the timeout event.
|
||||
*/
|
||||
public void run() {
|
||||
|
||||
synchronized(this) {
|
||||
try {
|
||||
this.wait(m_timer.getTimeout());
|
||||
} catch (InterruptedException e) {
|
||||
// This happens if the timer is stopped
|
||||
}
|
||||
}
|
||||
|
||||
m_timer.fireExpiredEvent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the timer event. When the timer expires, it will notify
|
||||
* all the registered listeners which receive the timer event. The
|
||||
* listener can retrieve the source of the event from the timer event.
|
||||
*/
|
||||
class TimerEvent extends EventObject {
|
||||
|
||||
/**
|
||||
* Constructor with the specified source of the timer event.
|
||||
* @param source The source of the timer event.
|
||||
*/
|
||||
TimerEvent(Object source) {
|
||||
super(source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The timer client needs to implement this interface if it wants to
|
||||
* receive the timeout event.
|
||||
*/
|
||||
interface TimerEventListener extends EventListener {
|
||||
/**
|
||||
* Gets invoked when the timer expires.
|
||||
* @param timeout Timeout event contains the source of the event which is
|
||||
* the timer.
|
||||
*/
|
||||
void timerExpired(TimerEvent timeout);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
/**
|
||||
* This static class checks if the caller is the applet running in the
|
||||
* communicator. If so, then it returns the appropriate method.
|
||||
*/
|
||||
class LDAPCheckComm {
|
||||
|
||||
/**
|
||||
* It returns the method whose name matches the specified argument.
|
||||
* @param classPackage The class package
|
||||
* @param name The method name
|
||||
* @return The method
|
||||
* @exception LDAPException Gets thrown it the method is not found or
|
||||
* the caller is not an applet running in the communicator
|
||||
*/
|
||||
static java.lang.reflect.Method getMethod(String classPackage, String name) throws LDAPException {
|
||||
SecurityManager sec = System.getSecurityManager();
|
||||
|
||||
if ( sec == null ) {
|
||||
/* Not an applet, we can do what we want to */
|
||||
return null;
|
||||
} else if ( sec.toString().startsWith("java.lang.NullSecurityManager") ) {
|
||||
/* Not an applet, we can do what we want to */
|
||||
return null;
|
||||
} else if (sec.toString().startsWith("netscape.security.AppletSecurity")) {
|
||||
/* Running as applet. Is PrivilegeManager around? */
|
||||
try {
|
||||
Class c = Class.forName(classPackage);
|
||||
java.lang.reflect.Method[] m = c.getMethods();
|
||||
for( int i = 0; i < m.length; i++ ) {
|
||||
if ( m[i].getName().equals(name) ) {
|
||||
return m[i];
|
||||
}
|
||||
}
|
||||
throw new LDAPException("no enable privilege in " + classPackage);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new LDAPException("Class not found");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,277 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import java.text.*;
|
||||
import netscape.ldap.client.*;
|
||||
|
||||
/**
|
||||
* Compares LDAP entries based on one or more attribute values.
|
||||
* <P>
|
||||
*
|
||||
* To use this comparison for sorting search results, pass
|
||||
* an object of this class to the <CODE>sort</CODE> method in
|
||||
* <CODE>LDAPSearchResults</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* @version 1.0
|
||||
* @see LDAPEntryComparator
|
||||
* @see LDAPSearchResults#sort
|
||||
*/
|
||||
|
||||
public class LDAPCompareAttrNames implements LDAPEntryComparator {
|
||||
|
||||
String m_attrs[];
|
||||
boolean m_ascending[];
|
||||
Locale m_locale = null;
|
||||
Collator m_collator = null;
|
||||
|
||||
/**
|
||||
* Constructs a comparator that compares the string values of
|
||||
* a named attribute in LDAP entries and sorts the entries in
|
||||
* ascending order.
|
||||
* <P>
|
||||
*
|
||||
* @param attribute Name of attribute for comparisons.
|
||||
*/
|
||||
public LDAPCompareAttrNames (String attribute) {
|
||||
m_attrs = new String[1];
|
||||
m_attrs[0] = attribute;
|
||||
m_ascending = new boolean[1];
|
||||
m_ascending[0] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a comparator that compares the string values in
|
||||
* a named attribute in LDAP entries and that allows you to sort
|
||||
* entries either in ascending or descending order.
|
||||
* <P>
|
||||
*
|
||||
* @param attribute Name of attribute for comparisons.
|
||||
* @param ascendingFlag If <CODE>true</CODE>, sort in ascending order.
|
||||
*/
|
||||
public LDAPCompareAttrNames (String attribute,
|
||||
boolean ascendingFlag) {
|
||||
m_attrs = new String[1];
|
||||
m_attrs[0] = attribute;
|
||||
m_ascending = new boolean[1];
|
||||
m_ascending[0] = ascendingFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a comparator that compares the string values in
|
||||
* a set of named attributes in LDAP entries and that sort
|
||||
* the entries in ascending order.
|
||||
* <P>
|
||||
*
|
||||
* Use an array of strings to specify the set of attributes
|
||||
* that you want to use for sorting. If the values of the
|
||||
* first attribute (the name specified in <CODE>attribute[0]</CODE>)
|
||||
* are equal, then the values of the next attribute are compared.
|
||||
* <P>
|
||||
*
|
||||
* For example, if <CODE>attributes[0] = "cn"</CODE> and
|
||||
* <CODE>attributes[1]="uid"</CODE>, results are first sorted
|
||||
* by the <CODE>cn</CODE> attribute. If two entries have the
|
||||
* same value for the <CODE>cn</CODE>, then the <CODE>uid</CODE>
|
||||
* attribute is used to sort the entries.
|
||||
* <P>
|
||||
*
|
||||
* @param attributes Array of the attribute names used for comparisons.
|
||||
*/
|
||||
public LDAPCompareAttrNames (String[] attributes) {
|
||||
m_attrs = attributes;
|
||||
m_ascending = new boolean[attributes.length];
|
||||
for( int i = 0; i < attributes.length; i++ )
|
||||
m_ascending[i] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a comparator that compares the string values in
|
||||
* a set of named attributes in LDAP entries and that allows you
|
||||
* to sort the entries in ascending or descending order.
|
||||
* <P>
|
||||
*
|
||||
* Use an array of strings to specify the set of attributes
|
||||
* that you want to use for sorting. If the values of the
|
||||
* first attribute (the name specified in <CODE>attribute[0]</CODE>)
|
||||
* are equal, then the values of the next attribute are compared.
|
||||
* <P>
|
||||
*
|
||||
* For example, if <CODE>attributes[0] = "cn"</CODE> and
|
||||
* <CODE>attributes[1]="uid"</CODE>, results are first sorted
|
||||
* by the <CODE>cn</CODE> attribute. If two entries have the
|
||||
* same value for <CODE>cn</CODE>, then the <CODE>uid</CODE>
|
||||
* attribute is used to sort the entries.
|
||||
* <P>
|
||||
*
|
||||
* Use an array of boolean values to specify whether each attribute
|
||||
* should be sorted in ascending or descending order. For example,
|
||||
* suppose that <CODE>attributes[0] = "cn"</CODE> and
|
||||
* <CODE>attributes[1]="roomNumber"</CODE>. If
|
||||
* <CODE>ascendingFlags[0]=true</CODE> and
|
||||
* <CODE>ascendingFlags[1]=false</CODE>, attributes are sorted first by
|
||||
* <CODE>cn</CODE> in ascending order, then by <CODE>roomNumber</CODE>
|
||||
* in descending order.
|
||||
* <P>
|
||||
*
|
||||
* If the size of the array of attribute names is not the same as
|
||||
* the size of the array of boolean values, an
|
||||
* <CODE>LDAPException</CODE> is thrown.
|
||||
* <P>
|
||||
*
|
||||
* @param attribute Array of the attribute names to use for comparisons.
|
||||
* @param ascendingFlags Array of boolean values specifying ascending
|
||||
* or descending order to use for each attribute name. If
|
||||
* <CODE>true</CODE>, sort the attributes in ascending order.
|
||||
*/
|
||||
public LDAPCompareAttrNames (String[] attributes,
|
||||
boolean[] ascendingFlags) {
|
||||
m_attrs = attributes;
|
||||
m_ascending = ascendingFlags;
|
||||
if ( m_ascending == null ) {
|
||||
m_ascending = new boolean[attributes.length];
|
||||
for( int i = 0; i < attributes.length; i++ )
|
||||
m_ascending[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the locale used for collation, if any. If it is null,
|
||||
* an ordinary string comparison will be used for sorting.
|
||||
*
|
||||
* @return The locale used for collation, or null.
|
||||
*/
|
||||
public Locale getLocale() {
|
||||
return m_locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the locale used for collation, if any. If it is null,
|
||||
* an ordinary string comparison will be used for sorting.
|
||||
*
|
||||
* @param locale The locale used for collation, or null.
|
||||
*/
|
||||
public void setLocale( Locale locale ) {
|
||||
m_locale = locale;
|
||||
if ( m_locale == null ) {
|
||||
m_collator = null;
|
||||
} else {
|
||||
m_collator = Collator.getInstance( m_locale );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the value of the attribute in the first entry is greater
|
||||
* than the attribute in the second entry, returns <CODE>true</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* If one of the entries is missing the attribute, the other is
|
||||
* considered greater. By default, the first entry is greater.
|
||||
* <P>
|
||||
*
|
||||
* If either entry contains multiple values, only the first value
|
||||
* is used for comparisons.
|
||||
* <P>
|
||||
*
|
||||
* @param greater Entry to be tested against.
|
||||
* @param less Entry to test.
|
||||
* @return <CODE>true</CODE> if (<CODE>greater > less</CODE>).
|
||||
*/
|
||||
public boolean isGreater (LDAPEntry greater, LDAPEntry less) {
|
||||
if (greater.equals (less)) return false;
|
||||
return attrGreater (greater, less, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares a particular attribute in both entries. If equal,
|
||||
* moves on to the next.
|
||||
* @param greater Greater arg from isGreater
|
||||
* @param less Less param is isGreater
|
||||
* @param attrPos Index into array of attributes, indicating
|
||||
* the attribute to compare
|
||||
* @return (greater > less)
|
||||
*/
|
||||
boolean attrGreater (LDAPEntry greater, LDAPEntry less,
|
||||
int attrPos) {
|
||||
Enumeration greaterAttrSet =
|
||||
greater.getAttributeSet().getAttributes();
|
||||
Enumeration lessAttrSet =
|
||||
less.getAttributeSet().getAttributes();
|
||||
|
||||
String greaterValue = null;
|
||||
String lessValue = null;
|
||||
String attrName = m_attrs[attrPos];
|
||||
boolean ascending = m_ascending[attrPos];
|
||||
|
||||
try {
|
||||
while (lessAttrSet.hasMoreElements()) {
|
||||
LDAPAttribute currAttr =
|
||||
(LDAPAttribute)(lessAttrSet.nextElement());
|
||||
if (!attrName.equalsIgnoreCase (currAttr.getName()))
|
||||
continue;
|
||||
lessValue =
|
||||
(String)(currAttr.getStringValues().nextElement());
|
||||
break;
|
||||
}
|
||||
|
||||
while (greaterAttrSet.hasMoreElements()) {
|
||||
LDAPAttribute currAttr =
|
||||
(LDAPAttribute)(greaterAttrSet.nextElement());
|
||||
if (!attrName.equalsIgnoreCase (currAttr.getName()))
|
||||
continue;
|
||||
greaterValue =
|
||||
(String)(currAttr.getStringValues().nextElement());
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (ClassCastException cce) {
|
||||
// i.e. one of the enumerations did not contain the
|
||||
// right type !?
|
||||
return false;
|
||||
}
|
||||
catch (NoSuchElementException nse) {
|
||||
// i.e. one of the attributes had no values !?
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((lessValue == null) ^ (greaterValue == null))
|
||||
return greaterValue != null;
|
||||
|
||||
if (lessValue == null ||
|
||||
lessValue.equalsIgnoreCase (greaterValue))
|
||||
if (attrPos == m_attrs.length - 1)
|
||||
return false;
|
||||
else
|
||||
return attrGreater (greater, less, attrPos+1);
|
||||
|
||||
if ( m_collator != null ) {
|
||||
if ( ascending )
|
||||
return ( m_collator.compare( greaterValue, lessValue ) > 0 );
|
||||
else
|
||||
return ( m_collator.compare( greaterValue, lessValue ) < 0 );
|
||||
} else {
|
||||
if ( ascending )
|
||||
return (greaterValue.compareTo (lessValue) > 0);
|
||||
else
|
||||
return (greaterValue.compareTo (lessValue) < 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,408 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
/**
|
||||
* Make a connection to a server from a list using "smart" failover.
|
||||
* Connection attempts can be made serially from the same thread, or
|
||||
* in parallel by creating a separate thread after the specified delay.
|
||||
* Connection setup status is preserved for later attempts, so that servers
|
||||
* that are more likely to be available will be tried first.
|
||||
* When a connection is successfully created, a socket is opened. The socket
|
||||
* is passed to the LDAPConnThread. The LDAPConnThread must call
|
||||
* invalidateConnection() if the connection is lost due to a network or
|
||||
* server error, or disconnect() if the connection is deliberately terminated
|
||||
* by the user.
|
||||
*/
|
||||
class LDAPConnSetupMgr implements Cloneable{
|
||||
|
||||
/**
|
||||
* Policy for opening a connection when multiple servers are used
|
||||
*/
|
||||
private static final int SERIAL = 0;
|
||||
private static final int PARALLEL = 1;
|
||||
|
||||
/**
|
||||
* ServerEntry.connSetupStatus possible value. The values also represent
|
||||
* the likelihood that the connection will be setup to a server. Lower
|
||||
* values have higher priority. See sortDsList() method
|
||||
*/
|
||||
private static final int CONNECTED = 0;
|
||||
private static final int DISCONNECTED = 1;
|
||||
private static final int NEVER_USED = 2;
|
||||
private static final int FAILED = 3;
|
||||
|
||||
/**
|
||||
* Representation for a server in the server list.
|
||||
*/
|
||||
class ServerEntry {
|
||||
String host;
|
||||
int port;
|
||||
int connSetupStatus;
|
||||
Thread connSetupThread;
|
||||
|
||||
ServerEntry(String host, int port, int status) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
connSetupStatus = status;
|
||||
connSetupThread = null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "{" +host+":"+port + " status="+connSetupStatus+"}";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Socket to the connected server
|
||||
*/
|
||||
private Socket m_socket = null;
|
||||
|
||||
/**
|
||||
* Last exception occured during connection setup
|
||||
*/
|
||||
private LDAPException m_connException = null;
|
||||
|
||||
/**
|
||||
* List of server to use for the connection setup
|
||||
*/
|
||||
ServerEntry[] m_dsList;
|
||||
|
||||
/**
|
||||
* Index of the last connected server
|
||||
*/
|
||||
private int m_dsIdx = -1;
|
||||
|
||||
/**
|
||||
* Socket factory for SSL connections
|
||||
*/
|
||||
LDAPSocketFactory m_factory;
|
||||
|
||||
/**
|
||||
* Connection setup policy (PARALLEL or SERIAL)
|
||||
*/
|
||||
int m_policy;
|
||||
|
||||
/**
|
||||
* Delay in ms before another connection setup thread is started.
|
||||
*/
|
||||
int m_connSetupDelay;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param host List of host names to connect to
|
||||
* @param port List of port numbers corresponding to the host list
|
||||
* @param factory Socket factory for SSL connections
|
||||
* @param delay delay in seconds for the parallel connection setup policy.
|
||||
* Possible values are: <br>(delay=-1) use serial policy,<br>
|
||||
* (delay=0) start immediately concurrent threads to each specified server
|
||||
* <br>(delay>0) create a new connection setup thread after delay seconds
|
||||
*/
|
||||
LDAPConnSetupMgr(String[] hosts, int[] ports, LDAPSocketFactory factory, int delay) {
|
||||
m_dsList = new ServerEntry[hosts.length];
|
||||
for (int i=0; i < hosts.length; i++) {
|
||||
m_dsList[i] = new ServerEntry(hosts[i], ports[i], NEVER_USED);
|
||||
}
|
||||
m_factory = factory;
|
||||
m_policy = (delay < 0) ? SERIAL : PARALLEL;
|
||||
m_connSetupDelay = delay*1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used by clone()
|
||||
*/
|
||||
private LDAPConnSetupMgr() {}
|
||||
|
||||
/**
|
||||
* Try to open the connection to any of the servers in the list.
|
||||
*/
|
||||
Socket openConnection() throws LDAPException{
|
||||
m_socket = null;
|
||||
m_connException = null;
|
||||
|
||||
// If reconnecting, sort dsList so that servers more likly to
|
||||
// be available are tried first
|
||||
sortDsList();
|
||||
|
||||
if (m_policy == SERIAL || m_dsList.length == 1) {
|
||||
openSerial();
|
||||
}
|
||||
else {
|
||||
openParallel();
|
||||
}
|
||||
|
||||
if (m_socket != null) {
|
||||
return m_socket;
|
||||
}
|
||||
|
||||
if (m_connException != null) {
|
||||
throw m_connException;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* To be called when the current connection is lost.
|
||||
* Put the connected server at the end of the server list for
|
||||
* the next connect attempt.
|
||||
*/
|
||||
void invalidateConnection() {
|
||||
if (m_socket != null) {
|
||||
m_dsList[m_dsIdx].connSetupStatus = FAILED;
|
||||
|
||||
// Move the entry to the end of the list
|
||||
int srvCnt = m_dsList.length, j=0;
|
||||
ServerEntry[] newDsList = new ServerEntry[m_dsList.length];
|
||||
for (int i=0; i < srvCnt; i++) {
|
||||
if (i != m_dsIdx) {
|
||||
newDsList[j++] = m_dsList[i];
|
||||
}
|
||||
}
|
||||
newDsList[j] = m_dsList[m_dsIdx];
|
||||
m_dsList = newDsList;
|
||||
m_dsIdx = j;
|
||||
}
|
||||
|
||||
m_socket = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* To be called when the current connection is terminated by the user
|
||||
* Mark the connected server status as DISCONNECTED. This will
|
||||
* put it at top of the server list for the next connect attempt.
|
||||
*/
|
||||
void disconnect() {
|
||||
if (m_socket != null) {
|
||||
m_dsList[m_dsIdx].connSetupStatus = DISCONNECTED;
|
||||
}
|
||||
|
||||
m_socket = null;
|
||||
}
|
||||
|
||||
Socket getSocket() {
|
||||
return m_socket;
|
||||
}
|
||||
|
||||
String getHost() {
|
||||
if (m_dsIdx >= 0) {
|
||||
return m_dsList[m_dsIdx].host;
|
||||
}
|
||||
return m_dsList[0].host;
|
||||
}
|
||||
|
||||
int getPort() {
|
||||
if (m_dsIdx >= 0) {
|
||||
return m_dsList[m_dsIdx].port;
|
||||
}
|
||||
return m_dsList[0].port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user has voluntarily closed the connection
|
||||
*/
|
||||
boolean isUserDisconnected() {
|
||||
return (m_dsIdx >=0 &&
|
||||
m_dsList[m_dsIdx].connSetupStatus == DISCONNECTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try sequentially to open a new connection to a server.
|
||||
*/
|
||||
private void openSerial() {
|
||||
for (int i=0; i < m_dsList.length; i++) {
|
||||
m_dsList[i].connSetupThread = Thread.currentThread();
|
||||
connectServer(i);
|
||||
if (m_socket != null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try concurrently to open a new connection a server. Create a separate
|
||||
* thread for each connection attempt.
|
||||
*/
|
||||
private synchronized void openParallel() {
|
||||
for (int i=0; m_socket==null && i < m_dsList.length; i++) {
|
||||
|
||||
//Create a Thread to execute connectSetver()
|
||||
final int dsIdx = i;
|
||||
String threadName = "ConnSetupMgr " +
|
||||
m_dsList[dsIdx].host + ":" + m_dsList[dsIdx].port;
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
connectServer(dsIdx);
|
||||
}
|
||||
}, threadName);
|
||||
|
||||
m_dsList[dsIdx].connSetupThread = t;
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
|
||||
// Wait before starting another thread if the delay is not zero
|
||||
if (m_connSetupDelay != 0 && i < (m_dsList.length-1)) {
|
||||
try {
|
||||
wait(m_connSetupDelay);
|
||||
}
|
||||
catch (InterruptedException e) {}
|
||||
}
|
||||
}
|
||||
|
||||
// At this point all threads are started. Wait until first thread
|
||||
// succeeds to connect or all threads terminate
|
||||
|
||||
while (m_socket == null) {
|
||||
|
||||
// Check whether there are still running threads
|
||||
boolean threadsRunning = false;
|
||||
for (int i=0; i < m_dsList.length; i++) {
|
||||
if (m_dsList[i].connSetupThread != null) {
|
||||
threadsRunning = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!threadsRunning) { return; }
|
||||
|
||||
// Wait for a thread to terminate
|
||||
try {
|
||||
wait();
|
||||
}
|
||||
catch (InterruptedException e) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to the server at the given index
|
||||
*/
|
||||
private void connectServer(int idx) {
|
||||
ServerEntry entry = m_dsList[idx];
|
||||
Thread currThread = Thread.currentThread();
|
||||
Socket sock = null;
|
||||
LDAPException conex = null;
|
||||
|
||||
try {
|
||||
/* If we are to create a socket ourselves, make sure it has
|
||||
sufficient privileges to connect to the desired host */
|
||||
if (m_factory == null) {
|
||||
sock = new Socket (entry.host, entry.port);
|
||||
//s.setSoLinger( false, -1 );
|
||||
} else {
|
||||
sock = m_factory.makeSocket(entry.host, entry.port);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
conex = new LDAPException("failed to connect to server "
|
||||
+ entry.host+":"+entry.port, LDAPException.CONNECT_ERROR);
|
||||
}
|
||||
catch (LDAPException e) {
|
||||
conex = e;
|
||||
}
|
||||
|
||||
if (currThread.isInterrupted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
if (m_socket == null && entry.connSetupThread == currThread) {
|
||||
entry.connSetupThread = null;
|
||||
if (sock != null) {
|
||||
entry.connSetupStatus = CONNECTED;
|
||||
m_socket = sock;
|
||||
m_dsIdx = idx;
|
||||
cleanup(); // Signal other concurrent threads to terminate
|
||||
}
|
||||
else {
|
||||
entry.connSetupStatus = FAILED;
|
||||
m_connException = conex;
|
||||
}
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate all concurrently running connection setup threads
|
||||
*/
|
||||
private synchronized void cleanup() {
|
||||
Thread currThread = Thread.currentThread();
|
||||
for (int i=0; i < m_dsList.length; i++) {
|
||||
ServerEntry entry = m_dsList[i];
|
||||
if (entry.connSetupThread != null && entry.connSetupThread != currThread) {
|
||||
|
||||
entry.connSetupStatus = FAILED;
|
||||
//Thread.stop() is considered to be dangerous, use Thread.interrupt().
|
||||
//interrupt() will however not work if the thread is blocked in the
|
||||
//socket library native connect() call, but the connect() will
|
||||
//eventually timeout and the thread will die.
|
||||
entry.connSetupThread.interrupt();
|
||||
|
||||
entry.connSetupThread = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sort Server List so that servers which are more likely to be available
|
||||
* are tried first. The likelihood of making a successful connection
|
||||
* is determined by the connSetupStatus. Lower values have higher
|
||||
* likelihood. Thus, the order of server access is (1) disconnected by
|
||||
* the user (2) never used (3) connection setup failed/connection lost
|
||||
*/
|
||||
private void sortDsList() {
|
||||
int srvCnt = m_dsList.length;
|
||||
for (int i=1; i < srvCnt; i++) {
|
||||
for (int j=0; j < i; j++) {
|
||||
if (m_dsList[i].connSetupStatus < m_dsList[j].connSetupStatus) {
|
||||
// swap entries
|
||||
ServerEntry entry = m_dsList[j];
|
||||
m_dsList[j] = m_dsList[i];
|
||||
m_dsList[i] = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String str = "dsIdx="+m_dsIdx+ " dsList=";
|
||||
for (int i=0; i < m_dsList.length; i++) {
|
||||
str += m_dsList[i]+ " ";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
LDAPConnSetupMgr cloneMgr = new LDAPConnSetupMgr();
|
||||
cloneMgr.m_factory = m_factory;
|
||||
cloneMgr.m_policy = m_policy;
|
||||
cloneMgr.m_connSetupDelay = m_connSetupDelay;
|
||||
cloneMgr.m_dsIdx = m_dsIdx;
|
||||
cloneMgr.m_dsList = new ServerEntry[m_dsList.length];
|
||||
cloneMgr.m_socket = m_socket;
|
||||
for (int i=0; i<m_dsList.length; i++) {
|
||||
ServerEntry e = m_dsList[i];
|
||||
cloneMgr.m_dsList[i] = new ServerEntry(e.host, e.port, e.connSetupStatus);
|
||||
}
|
||||
return cloneMgr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,543 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import netscape.ldap.client.*;
|
||||
import netscape.ldap.client.opers.*;
|
||||
import netscape.ldap.ber.stream.*;
|
||||
import netscape.ldap.util.*;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
/**
|
||||
* Multiple LDAPConnection clones can share a single physical connection,
|
||||
* which is maintained by a thread.
|
||||
*
|
||||
* +----------------+
|
||||
* | LDAPConnection | --------+
|
||||
* +----------------+ |
|
||||
* |
|
||||
* +----------------+ | +----------------+
|
||||
* | LDAPConnection | --------+------- | LDAPConnThread |
|
||||
* +----------------+ | +----------------+
|
||||
* |
|
||||
* +----------------+ |
|
||||
* | LDAPConnection | --------+
|
||||
* +----------------+
|
||||
*
|
||||
* All LDAPConnections send requests and get responses from
|
||||
* LDAPConnThread (a thread).
|
||||
*/
|
||||
class LDAPConnThread extends Thread {
|
||||
|
||||
/**
|
||||
* Constants
|
||||
*/
|
||||
private final static int MAXMSGID = Integer.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* Internal variables
|
||||
*/
|
||||
transient private static int m_highMsgId;
|
||||
transient private InputStream m_serverInput;
|
||||
transient private OutputStream m_serverOutput;
|
||||
transient private Hashtable m_requests;
|
||||
transient private Hashtable m_messages = null;
|
||||
transient private Vector m_registered;
|
||||
transient private boolean m_disconnected = false;
|
||||
transient private LDAPCache m_cache = null;
|
||||
transient private boolean m_failed = false;
|
||||
private Socket m_socket = null;
|
||||
transient private Thread m_thread = null;
|
||||
transient Object m_sendRequestLock = new Object();
|
||||
transient LDAPConnSetupMgr m_connMgr = null;
|
||||
|
||||
/**
|
||||
* Constructs a connection thread that maintains connection to the
|
||||
* LDAP server.
|
||||
* @param host LDAP host name
|
||||
* @param port LDAP port number
|
||||
* @param factory LDAP socket factory
|
||||
*/
|
||||
public LDAPConnThread(LDAPConnSetupMgr connMgr, LDAPCache cache)
|
||||
throws LDAPException {
|
||||
super("LDAPConnection " + connMgr.getHost() +":"+ connMgr.getPort());
|
||||
m_requests = new Hashtable ();
|
||||
m_registered = new Vector ();
|
||||
m_connMgr = connMgr;
|
||||
m_socket = connMgr.getSocket();
|
||||
setCache( cache );
|
||||
|
||||
setDaemon(true);
|
||||
|
||||
try {
|
||||
|
||||
m_serverInput = new BufferedInputStream (m_socket.getInputStream());
|
||||
m_serverOutput = new BufferedOutputStream (m_socket.getOutputStream());
|
||||
|
||||
} catch (IOException e) {
|
||||
|
||||
// a kludge to make the thread go away. Since the thread has already
|
||||
// been created, the only way to clean up the thread is to call the
|
||||
// start() method. Otherwise, the exit method will be never called
|
||||
// because the start() was never called. In the run method, the stop
|
||||
// method calls right away if the m_failed is set to true.
|
||||
m_failed = true;
|
||||
start();
|
||||
throw new LDAPException ( "failed to connect to server " +
|
||||
m_connMgr.getHost(), LDAPException.CONNECT_ERROR );
|
||||
}
|
||||
start(); /* start the thread */
|
||||
}
|
||||
|
||||
InputStream getInputStream() {
|
||||
return m_serverInput;
|
||||
}
|
||||
|
||||
void setInputStream( InputStream is ) {
|
||||
m_serverInput = is;
|
||||
}
|
||||
|
||||
OutputStream getOutputStream() {
|
||||
return m_serverOutput;
|
||||
}
|
||||
|
||||
void setOutputStream( OutputStream os ) {
|
||||
m_serverOutput = os;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cache to use for searches.
|
||||
* @param cache The cache to use for searches; <CODE>null</CODE> for no cache
|
||||
*/
|
||||
synchronized void setCache( LDAPCache cache ) {
|
||||
m_cache = cache;
|
||||
m_messages = (m_cache != null) ? new Hashtable() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends LDAP request via this connection thread.
|
||||
* @param request request to send
|
||||
* @param toNotify response listener to invoke when the response
|
||||
* is ready
|
||||
*/
|
||||
synchronized void sendRequest (LDAPConnection conn, JDAPProtocolOp request,
|
||||
LDAPMessageQueue toNotify, LDAPConstraints cons)
|
||||
throws LDAPException {
|
||||
if (m_serverOutput == null)
|
||||
throw new LDAPException ( "not connected to a server",
|
||||
LDAPException.SERVER_DOWN );
|
||||
|
||||
LDAPMessage msg =
|
||||
new LDAPMessage(allocateId(), request, cons.getServerControls());
|
||||
|
||||
if ( toNotify != null ) {
|
||||
if (!(request instanceof JDAPAbandonRequest ||
|
||||
request instanceof JDAPUnbindRequest)) {
|
||||
/* Only worry about toNotify if we expect a response... */
|
||||
this.m_requests.put (new Integer (msg.getId()), toNotify);
|
||||
/* Notify the backlog checker that there may be another outstanding
|
||||
request */
|
||||
resultRetrieved();
|
||||
}
|
||||
toNotify.addRequest(msg.getId(), conn, this);
|
||||
}
|
||||
|
||||
synchronized( m_sendRequestLock ) {
|
||||
try {
|
||||
msg.write (m_serverOutput);
|
||||
m_serverOutput.flush ();
|
||||
} catch (IOException e) {
|
||||
networkError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register with this connection thread.
|
||||
* @param conn LDAP connection
|
||||
*/
|
||||
public synchronized void register(LDAPConnection conn) {
|
||||
if (!m_registered.contains(conn))
|
||||
m_registered.addElement(conn);
|
||||
}
|
||||
|
||||
synchronized int getClientCount() {
|
||||
return m_registered.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* De-Register with this connection thread. If all the connection
|
||||
* is deregistered. Then, this thread should be killed.
|
||||
* @param conn LDAP connection
|
||||
*/
|
||||
public synchronized void deregister(LDAPConnection conn) {
|
||||
m_registered.removeElement(conn);
|
||||
if (m_registered.size() == 0) {
|
||||
try {
|
||||
LDAPConstraints cons = conn.getSearchConstraints();
|
||||
sendRequest (null, new JDAPUnbindRequest (), null, cons);
|
||||
cleanUp();
|
||||
if ( m_thread != null ) {
|
||||
m_thread.interrupt();
|
||||
}
|
||||
this.sleep(100); /* give enough time for threads to shutdown */
|
||||
} catch (Exception e) {
|
||||
LDAPConnection.printDebug(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean ups before shutdown the thread.
|
||||
*/
|
||||
private void cleanUp() {
|
||||
if (!m_disconnected) {
|
||||
try {
|
||||
m_serverOutput.close ();
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
m_serverOutput = null;
|
||||
}
|
||||
|
||||
try {
|
||||
m_serverInput.close ();
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
m_serverInput = null;
|
||||
}
|
||||
|
||||
try {
|
||||
m_socket.close ();
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
m_socket = null;
|
||||
}
|
||||
|
||||
m_disconnected = true;
|
||||
|
||||
/**
|
||||
* Notify the Connection Setup Manager that the connection was
|
||||
* terminated by the user
|
||||
*/
|
||||
m_connMgr.disconnect();
|
||||
|
||||
/**
|
||||
* Notify all the registered about this bad moment.
|
||||
* IMPORTANT: This needs to be done at last. Otherwise, the socket
|
||||
* input stream and output stream might never get closed and the whole
|
||||
* task will get stuck in the stop method when we tried to stop the
|
||||
* LDAPConnThread.
|
||||
*/
|
||||
|
||||
if (m_registered != null) {
|
||||
Vector registerCopy = (Vector)m_registered.clone();
|
||||
|
||||
Enumeration cancelled = registerCopy.elements();
|
||||
|
||||
while (cancelled.hasMoreElements ()) {
|
||||
LDAPConnection c = (LDAPConnection)cancelled.nextElement();
|
||||
c.deregisterConnection();
|
||||
}
|
||||
}
|
||||
m_registered = null;
|
||||
m_messages = null;
|
||||
m_requests.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleep if there is a backlog of search results
|
||||
*/
|
||||
private void checkBacklog() {
|
||||
boolean doWait;
|
||||
do {
|
||||
doWait = false;
|
||||
Enumeration listeners = m_requests.elements();
|
||||
while( listeners.hasMoreElements() ) {
|
||||
LDAPMessageQueue l =
|
||||
(LDAPMessageQueue)listeners.nextElement();
|
||||
// If there are any threads waiting for a regular response
|
||||
// message, we have to go read the next incoming message
|
||||
if ( !(l instanceof LDAPSearchListener) ) {
|
||||
doWait = false;
|
||||
break;
|
||||
}
|
||||
// If the backlog of any search thread is too great,
|
||||
// wait for it to diminish, but if this is a synchronous
|
||||
// search, then just keep reading
|
||||
LDAPSearchListener sl = (LDAPSearchListener)l;
|
||||
|
||||
// Asynch operation ?
|
||||
if (sl.isAsynchOp()) {
|
||||
if (sl.getMessageCount() >= sl.getConstraints().getMaxBacklog()) {
|
||||
doWait = true;
|
||||
}
|
||||
}
|
||||
// synch op with non-zero batch size ?
|
||||
else if (sl.getConstraints().getBatchSize() != 0) {
|
||||
if (sl.getMessageCount() >= sl.getConstraints().getMaxBacklog()) {
|
||||
doWait = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( doWait ) {
|
||||
synchronized(this) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ( doWait );
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when a search result has been retrieved from the incoming
|
||||
* queue. We use the notification to unblock the listener thread, if it
|
||||
* is waiting for the backlog to lighten.
|
||||
*/
|
||||
synchronized void resultRetrieved() {
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads from the LDAP server input stream for incoming LDAP messages.
|
||||
*/
|
||||
public void run() {
|
||||
|
||||
// if there is a problem of establishing connection to the server,
|
||||
// stop the thread right away...
|
||||
if (m_failed) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_thread = Thread.currentThread();
|
||||
LDAPMessage msg = null;
|
||||
JDAPBERTagDecoder decoder = new JDAPBERTagDecoder();
|
||||
|
||||
while (true) {
|
||||
yield();
|
||||
int[] nread = new int[1];
|
||||
nread[0] = 0;
|
||||
// Avoid too great a backlog of results
|
||||
checkBacklog();
|
||||
try {
|
||||
|
||||
if (m_thread.isInterrupted()) {
|
||||
break;
|
||||
}
|
||||
|
||||
BERElement element = BERElement.getElement(decoder,
|
||||
m_serverInput,
|
||||
nread);
|
||||
msg = LDAPMessage.parseMessage(element);
|
||||
|
||||
// passed in the ber element size to approximate the size of the cache
|
||||
// entry, thereby avoiding serialization of the entry stored in the
|
||||
// cache
|
||||
processResponse (msg, nread[0]);
|
||||
} catch (Exception e) {
|
||||
networkError(e);
|
||||
}
|
||||
|
||||
if (m_disconnected)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a new LDAP message ID. These are arbitrary numbers used to
|
||||
* correlate client requests with server responses.
|
||||
* @return new unique msgId
|
||||
*/
|
||||
private synchronized int allocateId () {
|
||||
m_highMsgId = (m_highMsgId + 1) % MAXMSGID;
|
||||
return m_highMsgId;
|
||||
}
|
||||
|
||||
/**
|
||||
* When a response arrives from the LDAP server, it is processed by
|
||||
* this routine. It will pass the message on to the listening object
|
||||
* associated with the LDAP msgId.
|
||||
* @param incoming New message from LDAP server
|
||||
*/
|
||||
private synchronized void processResponse (LDAPMessage incoming, int size) {
|
||||
Integer messageID = new Integer (incoming.getId());
|
||||
LDAPMessageQueue l = (LDAPMessageQueue)m_requests.get (messageID);
|
||||
|
||||
if (l == null) {
|
||||
return; /* nobody is waiting for this response (!) */
|
||||
}
|
||||
|
||||
// For asynch operations controls are to be read from the LDAPMessage
|
||||
// For synch operations controls are copied into the LDAPConnection
|
||||
// For synch search operations, controls are also copied into
|
||||
// LDAPSearchResults (see LDAPConnection.checkSearchMsg())
|
||||
if ( ! l.isAsynchOp()) {
|
||||
|
||||
/* Were there any controls for this client? */
|
||||
LDAPControl[] con = incoming.getControls();
|
||||
if (con != null) {
|
||||
int msgid = incoming.getId();
|
||||
LDAPConnection ldc = l.getConnection(msgid);
|
||||
if (ldc != null) {
|
||||
ldc.setResponseControls( this,
|
||||
new LDAPResponseControl(ldc, msgid, con));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector v = null;
|
||||
JDAPProtocolOp op = incoming.getProtocolOp ();
|
||||
|
||||
if ((op instanceof JDAPSearchResponse) ||
|
||||
(op instanceof JDAPSearchResultReference)) {
|
||||
|
||||
l.addMessage (incoming);
|
||||
Long key = ((LDAPSearchListener)l).getKey();
|
||||
|
||||
if ((m_cache != null) && (key != null)) {
|
||||
// get the vector containing the LDAPMessages for the specified messageID
|
||||
v = (Vector)m_messages.get(messageID);
|
||||
|
||||
if (v == null) {
|
||||
v = new Vector();
|
||||
// keeps track of the total size of all LDAPMessages belonging to the
|
||||
// same messageID, now the size is 0
|
||||
v.addElement(new Long(0));
|
||||
}
|
||||
|
||||
// add the size of the current LDAPMessage to the lump sum
|
||||
// assume the size of LDAPMessage is more or less the same as the size
|
||||
// of LDAPEntry. Eventually LDAPEntry object gets stored in the cache
|
||||
// instead of LDAPMessage object.
|
||||
long entrySize = ((Long)v.firstElement()).longValue() + size;
|
||||
|
||||
// update the lump sum located in the first element of the vector
|
||||
v.setElementAt(new Long(entrySize), 0);
|
||||
|
||||
// convert LDAPMessage object into LDAPEntry which is stored to the
|
||||
// end of the Vector
|
||||
v.addElement(((LDAPSearchResult)incoming).getEntry());
|
||||
|
||||
// replace the entry
|
||||
m_messages.put(messageID, v);
|
||||
}
|
||||
} else {
|
||||
l.addMessage (incoming);
|
||||
if (l instanceof LDAPSearchListener) {
|
||||
Long key = ((LDAPSearchListener)l).getKey();
|
||||
|
||||
if (key != null) {
|
||||
boolean fail = false;
|
||||
JDAPProtocolOp protocolOp = incoming.getProtocolOp();
|
||||
if (protocolOp instanceof JDAPSearchResult) {
|
||||
JDAPResult res = (JDAPResult)protocolOp;
|
||||
if (res.getResultCode() > 0) {
|
||||
fail = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((!fail) && (m_cache != null)) {
|
||||
|
||||
// Collect all the LDAPMessages for the specified messageID
|
||||
// no need to keep track of this entry. Remove it.
|
||||
v = (Vector)m_messages.remove(messageID);
|
||||
|
||||
// If v is null, meaning there are no search results from the
|
||||
// server
|
||||
if (v == null) {
|
||||
v = new Vector();
|
||||
|
||||
// set the entry size to be 0
|
||||
v.addElement(new Long(0));
|
||||
}
|
||||
|
||||
try {
|
||||
// add the new entry with key and value (a vector of
|
||||
// LDAPEntry objects)
|
||||
m_cache.addEntry(key, v);
|
||||
} catch (LDAPException e) {
|
||||
System.out.println("Exception: "+e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_requests.remove (messageID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop dispatching responses for a particular message ID.
|
||||
* @param id Message ID for which to discard responses.
|
||||
*/
|
||||
synchronized void abandon (int id ) {
|
||||
LDAPMessageQueue l = (LDAPMessageQueue)m_requests.remove(new Integer(id));
|
||||
if (l != null) {
|
||||
l.removeRequest(id);
|
||||
}
|
||||
notifyAll(); // If LDAPConnThread is blocked in checkBacklog()
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles network errors. Basically shuts down the whole connection.
|
||||
* @param e The exception which was caught while trying to read from
|
||||
* input stream.
|
||||
*/
|
||||
private synchronized void networkError (Exception e) {
|
||||
try {
|
||||
|
||||
// notify the Connection Setup Manager that the connection is lost
|
||||
m_connMgr.invalidateConnection();
|
||||
|
||||
// notify each listener that the server is down.
|
||||
Enumeration requests = m_requests.elements();
|
||||
while (requests.hasMoreElements()) {
|
||||
LDAPMessageQueue listener =
|
||||
(LDAPMessageQueue)requests.nextElement();
|
||||
listener.setException(this, new LDAPException("Server down",
|
||||
LDAPException.OTHER));
|
||||
}
|
||||
cleanUp();
|
||||
|
||||
} catch (NullPointerException ee) {
|
||||
System.err.println("Exception: "+ee.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all the registered connections.
|
||||
* IMPORTANT: This needs to be done last. Otherwise, the socket
|
||||
* input stream and output stream might never get closed and the whole
|
||||
* task will get stuck in the stop method when we try to stop the
|
||||
* LDAPConnThread.
|
||||
*/
|
||||
|
||||
if (m_registered != null) {
|
||||
Vector registerCopy = (Vector)m_registered.clone();
|
||||
|
||||
Enumeration cancelled = registerCopy.elements();
|
||||
|
||||
while (cancelled.hasMoreElements ()) {
|
||||
LDAPConnection c = (LDAPConnection)cancelled.nextElement();
|
||||
c.deregisterConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
4884
mozilla/directory/java-sdk/ldapjdk/netscape/ldap/LDAPConnection.java
Normal file
4884
mozilla/directory/java-sdk/ldapjdk/netscape/ldap/LDAPConnection.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,344 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
/**
|
||||
* Represents a set of operation preferences.
|
||||
* You can set these preferences for a particular operation
|
||||
* by creating an <CODE>LDAPConstraints</CODE> object,
|
||||
* specifying your preferences, and passing the object to
|
||||
* the proper <CODE>LDAPConnection</CODE> method.
|
||||
* <P>
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LDAPConstraints implements Cloneable {
|
||||
|
||||
private int m_hop_limit;
|
||||
private LDAPBind m_bind_proc;
|
||||
private LDAPRebind m_rebind_proc;
|
||||
private boolean referrals;
|
||||
private int m_time_limit;
|
||||
private LDAPControl[] m_clientControls;
|
||||
private LDAPControl[] m_serverControls;
|
||||
|
||||
/**
|
||||
* Constructs an <CODE>LDAPConstraints</CODE> object that specifies
|
||||
* the default set of constraints.
|
||||
*/
|
||||
public LDAPConstraints() {
|
||||
m_time_limit = 0;
|
||||
referrals = false;
|
||||
m_bind_proc = null;
|
||||
m_rebind_proc = null;
|
||||
m_hop_limit = 5;
|
||||
m_clientControls = null;
|
||||
m_serverControls = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <CODE>LDAPConstraints</CODE> object and allows you
|
||||
* to specify the constraints in that object.
|
||||
* <P>
|
||||
* @param msLimit Maximum time in milliseconds to wait for results (0
|
||||
* by default, which means that there is no maximum time limit)
|
||||
* @param doReferrals Specify <CODE>true</CODE> to follow referrals
|
||||
* automatically, or <CODE>False</CODE> to throw an
|
||||
* <CODE>LDAPReferralException</CODE> error if the server sends back
|
||||
* a referral (<CODE>False</CODE> by default)
|
||||
* @param rebind_proc Specifies the object that
|
||||
* implements the <CODE>LDAPRebind</CODE> interface (you need to
|
||||
* define this class). The object will be used when the client
|
||||
* follows referrals automatically. The object provides the client
|
||||
* with a method for getting the distinguished name and password
|
||||
* used to authenticate to another LDAP server during a referral.
|
||||
* (This field is <CODE>null</CODE> by default.)
|
||||
* @param hop_limit Maximum number of referrals to follow in a
|
||||
* sequence when attempting to resolve a request.
|
||||
* @see netscape.ldap.LDAPConnection#setOption(int, java.lang.Object)
|
||||
*/
|
||||
public LDAPConstraints( int msLimit, boolean doReferrals,
|
||||
LDAPRebind rebind_proc, int hop_limit) {
|
||||
m_time_limit = msLimit;
|
||||
referrals = doReferrals;
|
||||
m_bind_proc = null;
|
||||
m_rebind_proc = rebind_proc;
|
||||
m_hop_limit = hop_limit;
|
||||
m_clientControls = null;
|
||||
m_serverControls = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <CODE>LDAPConstraints</CODE> object and allows you
|
||||
* to specify the constraints in that object.
|
||||
* <P>
|
||||
* @param msLimit Maximum time in milliseconds to wait for results (0
|
||||
* by default, which means that there is no maximum time limit)
|
||||
* @param doReferrals Specify <CODE>true</CODE> to follow referrals
|
||||
* automatically, or <CODE>False</CODE> to throw an
|
||||
* <CODE>LDAPReferralException</CODE> error if the server sends back
|
||||
* a referral (<CODE>False</CODE> by default)
|
||||
* @param bind_proc Specifies the object that
|
||||
* implements the <CODE>LDAPBind</CODE> interface (you need to
|
||||
* define this class). The object will be used to authenticate to the
|
||||
* server on referrals. (This field is <CODE>null</CODE> by default.)
|
||||
* @param hop_limit Maximum number of referrals to follow in a
|
||||
* sequence when attempting to resolve a request.
|
||||
* @see netscape.ldap.LDAPConnection#setOption(int, java.lang.Object)
|
||||
*/
|
||||
public LDAPConstraints( int msLimit, boolean doReferrals,
|
||||
LDAPBind bind_proc, int hop_limit) {
|
||||
m_time_limit = msLimit;
|
||||
referrals = doReferrals;
|
||||
m_bind_proc = bind_proc;
|
||||
m_rebind_proc = null;
|
||||
m_hop_limit = hop_limit;
|
||||
m_clientControls = null;
|
||||
m_serverControls = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum number of milliseconds to wait for any operation
|
||||
* under these constraints. If 0, there is no maximum time limit
|
||||
* on waiting for the operation results.
|
||||
* @return Maximum number of milliseconds to wait for operation results.
|
||||
*/
|
||||
public int getTimeLimit() {
|
||||
return m_time_limit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specifies whether nor not referrals are followed automatically.
|
||||
* Returns <CODE>true</CODE> if referrals are to be followed automatically,
|
||||
* or <CODE>false</CODE> if referrals throw an
|
||||
* <CODE>LDAPReferralException</CODE>.
|
||||
* @return <CODE>true</CODE> if referrals are followed automatically,
|
||||
* <CODE>False</CODE> if referrals throw an
|
||||
* <CODE>LDAPReferralException</CODE>.
|
||||
*/
|
||||
public boolean getReferrals() {
|
||||
return referrals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object that provides the mechanism for authenticating to the
|
||||
* server on referrals. This object must implement the <CODE>LDAPBind</CODE>
|
||||
* interface.
|
||||
* @return Object to be used to authenticate to the server on referrals.
|
||||
* @see netscape.ldap.LDAPBind
|
||||
*/
|
||||
public LDAPBind getBindProc() {
|
||||
return m_bind_proc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object that provides the method for getting
|
||||
* authentication information. This object must
|
||||
* implement the <CODE>LDAPRebind</CODE> interface.
|
||||
* @return Object to be used to obtain information for
|
||||
* authenticating to other LDAP servers during referrals.
|
||||
* @see netscape.ldap.LDAPRebind
|
||||
* @see netscape.ldap.LDAPRebindAuth
|
||||
*/
|
||||
public LDAPRebind getRebindProc() {
|
||||
return m_rebind_proc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum number of hops to follow during a referral.
|
||||
* @return Maximum number of hops to follow during a referral.
|
||||
*/
|
||||
public int getHopLimit() {
|
||||
return m_hop_limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns any client controls to be applied by the client
|
||||
* to LDAP operations.
|
||||
* @return Client controls to be applied by the client to LDAP operations.
|
||||
* @see netscape.ldap.LDAPControl
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
*/
|
||||
public LDAPControl[] getClientControls() {
|
||||
return m_clientControls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns any server controls to be applied by the server
|
||||
* to LDAP operations.
|
||||
* @return Server controls to be applied by the server to LDAP operations.
|
||||
* @see netscape.ldap.LDAPControl
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
*/
|
||||
public LDAPControl[] getServerControls() {
|
||||
return m_serverControls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum number of milliseconds to wait for any operation
|
||||
* under these constraints. If 0, there is no maximum time limit
|
||||
* on waiting for the operation results.
|
||||
* @param msLimit Maximum number of milliseconds to wait for operation
|
||||
* results.
|
||||
* (0 by default, which means that there is no maximum time limit.)
|
||||
*/
|
||||
public void setTimeLimit( int msLimit ) {
|
||||
m_time_limit = msLimit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specifies whether nor not referrals are followed automatically.
|
||||
* Returns <CODE>true</CODE> if referrals are to be followed automatically,
|
||||
* or <CODE>false</CODE> if referrals throw an
|
||||
* <CODE>LDAPReferralException</CODE>.
|
||||
* (By default, this is set to <CODE>false</CODE>.)
|
||||
* <P>
|
||||
* If you set this to <CODE>true</CODE>, you need to create an object of
|
||||
* this class that implements either the <CODE>LDAPRebind</CODE> or
|
||||
* <CODE>LDAPBind</CODE> interface. The <CODE>LDAPRebind</CODE> object
|
||||
* identifies the method for retrieving authentication information which
|
||||
* will be used when connecting to other LDAP servers during referrals.
|
||||
* This object should be passed to the <CODE>setRebindProc</CODE> method.
|
||||
* Alternatively, the <CODE>LDAPBind</CODE> object identifies an
|
||||
* authentication mechanism to be used instead of the default
|
||||
* authentication mechanism when following referrals. This
|
||||
* object should be passed to the <CODE>setBindProc</BIND> method.
|
||||
* @param doReferrals Set to <CODE>true</CODE> if referrals should be
|
||||
* followed automatically, or <CODE>False</CODE> if referrals should throw
|
||||
* an <CODE>LDAPReferralException</CODE>.
|
||||
* @see netscape.ldap.LDAPBind
|
||||
* @see netscape.ldap.LDAPRebind
|
||||
* @see netscape.ldap.LDAPRebindAuth
|
||||
*/
|
||||
public void setReferrals( boolean doReferrals ) {
|
||||
referrals = doReferrals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the object that provides the mechanism for authenticating
|
||||
* to the server on referrals. This object must implement
|
||||
* the <CODE>LDAPBind</CODE> interface.(By default, this is
|
||||
* <CODE>null</CODE>.) This method sets the <CODE>LDAPRebind</CODE>
|
||||
* object to null for this constraint.
|
||||
* @param bind_proc Object to be used to authenticate to the server
|
||||
* on referrals.
|
||||
* @see netscape.ldap.LDAPBind
|
||||
*/
|
||||
public void setBindProc( LDAPBind bind_proc ) {
|
||||
m_bind_proc = bind_proc;
|
||||
if (bind_proc != null) {
|
||||
m_rebind_proc = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the object that provides the method for getting
|
||||
* authentication information. This object must belong to a class
|
||||
* that implements the <CODE>LDAPRebind</CODE> interface.
|
||||
* (By default, this is <CODE>null</CODE>.) This method sets the
|
||||
* <CODE>LDAPBind</CODE> object to null for this constraint.
|
||||
* @param rebind_proc Object to be used to obtain information for
|
||||
* authenticating to other LDAP servers during referrals.
|
||||
*/
|
||||
public void setRebindProc( LDAPRebind rebind_proc ) {
|
||||
m_rebind_proc = rebind_proc;
|
||||
if (rebind_proc != null) {
|
||||
m_bind_proc = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets maximum number of hops to follow in sequence during a referral.
|
||||
* (By default, this is 5.)
|
||||
* @param hop_limit Maximum number of hops to follow during a referral.
|
||||
*/
|
||||
public void setHopLimit( int hop_limit ) {
|
||||
m_hop_limit = hop_limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a client control for LDAP operations.
|
||||
* @param control Client control for LDAP operations.
|
||||
* @see netscape.ldap.LDAPControl
|
||||
*/
|
||||
public void setClientControls( LDAPControl control ) {
|
||||
m_clientControls = new LDAPControl[1];
|
||||
m_clientControls[0] = control;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an array of client controls for LDAP operations.
|
||||
* @param controls Array of client controls for LDAP operations.
|
||||
* @see netscape.ldap.LDAPControl
|
||||
*/
|
||||
public void setClientControls( LDAPControl[] controls ) {
|
||||
m_clientControls = controls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a server control for LDAP operations.
|
||||
* @param control Server control for LDAP operations.
|
||||
* @see netscape.ldap.LDAPControl
|
||||
*/
|
||||
public void setServerControls( LDAPControl control ) {
|
||||
m_serverControls = new LDAPControl[1];
|
||||
m_serverControls[0] = control;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an array of server controls for LDAP operations.
|
||||
* @param controls An array of server controls for LDAP operations.
|
||||
* @see netscape.ldap.LDAPControl
|
||||
*/
|
||||
public void setServerControls( LDAPControl[] controls ) {
|
||||
m_serverControls = controls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a copy of an existing set of constraints.
|
||||
* @returns A copy of an existing set of constraints.
|
||||
*/
|
||||
public Object clone() {
|
||||
LDAPConstraints o = new LDAPConstraints();
|
||||
|
||||
o.m_time_limit = this.m_time_limit;
|
||||
o.referrals = this.referrals;
|
||||
o.m_bind_proc = this.m_bind_proc;
|
||||
o.m_rebind_proc = this.m_rebind_proc;
|
||||
o.m_hop_limit = this.m_hop_limit;
|
||||
if ( (this.m_clientControls != null) &&
|
||||
(this.m_clientControls.length > 0) ) {
|
||||
o.m_clientControls = new LDAPControl[this.m_clientControls.length];
|
||||
for( int i = 0; i < this.m_clientControls.length; i++ )
|
||||
o.m_clientControls[i] =
|
||||
(LDAPControl)this.m_clientControls[i].clone();
|
||||
}
|
||||
if ( (this.m_serverControls != null) &&
|
||||
(this.m_serverControls.length > 0) ) {
|
||||
o.m_serverControls = new LDAPControl[this.m_serverControls.length];
|
||||
for( int i = 0; i < this.m_serverControls.length; i++ )
|
||||
o.m_serverControls[i] =
|
||||
(LDAPControl)this.m_serverControls[i].clone();
|
||||
}
|
||||
return o;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,505 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.lang.reflect.*;
|
||||
import netscape.ldap.ber.stream.*;
|
||||
import netscape.ldap.client.*;
|
||||
import netscape.ldap.util.*;
|
||||
import netscape.ldap.controls.*;
|
||||
|
||||
/**
|
||||
* Represents arbitrary control data that can be used with a
|
||||
* a particular LDAP operation. LDAP controls are part of version 3
|
||||
* of the LDAP protocol.
|
||||
* <P>
|
||||
*
|
||||
* LDAP controls allow you to extend the functionality of
|
||||
* an LDAP operation. For example, you can use an LDAP control
|
||||
* for the search operation to sort search results on an LDAP server.
|
||||
* <P>
|
||||
*
|
||||
* An LDAP control can be either a <B>server control</B> or
|
||||
* a <B>client control</B>:
|
||||
* <P>
|
||||
* <UL>
|
||||
* <LI><B>Server controls</B> can be sent to the LDAP server or returned
|
||||
* by the server on any operation.
|
||||
* <LI><B>Client controls</B> are intended to affect only the client side
|
||||
* of the operation.
|
||||
* </UL>
|
||||
* <P>
|
||||
*
|
||||
* An LDAP control consists of the following information:
|
||||
* <P>
|
||||
* <UL>
|
||||
* <LI>A unique object ID (OID) that identifies the control.<P>
|
||||
* <LI>A "criticality" field, which indicates whether or
|
||||
* not the control is critical to the operation. (If the control is
|
||||
* critical to the operation and the server does not support the control,
|
||||
* the server should not execute the operation.)<P>
|
||||
* <LI>Data pertaining to the control.<P>
|
||||
* </UL>
|
||||
* <P>
|
||||
*
|
||||
* To determine which server controls are supported by a particular server,
|
||||
* you need to search for the root DSE (DSA-specific entry, where DSA is
|
||||
* another term for "LDAP server") and find the values of the
|
||||
* <CODE>supportedControl</CODE> attribute. This attribute contains the
|
||||
* object IDs (OIDs) of the controls supported by this server.
|
||||
* <P>
|
||||
*
|
||||
* The following section of code demonstrates how to get the list
|
||||
* of the server controls supported by an LDAP server.
|
||||
* <P>
|
||||
*
|
||||
* <PRE>
|
||||
* public static void main( String[] args )
|
||||
* {
|
||||
* LDAPConnection ld = new LDAPConnection();
|
||||
* try {
|
||||
* String MY_HOST = "localhost";
|
||||
* int MY_PORT = 389;
|
||||
* ld.connect( MY_HOST, MY_PORT );
|
||||
* try {
|
||||
* ld.authenticate( 3, "cn=Directory Manager", "23skidoo" );
|
||||
* } catch( LDAPException e ) {
|
||||
* System.out.println( "LDAP server does not support v3." );
|
||||
* ld.disconnect();
|
||||
* System.exit(1);
|
||||
* }
|
||||
*
|
||||
* String MY_FILT = "(objectclass=*)";
|
||||
* String MY_BASE = "";
|
||||
* String getAttrs[] = { "supportedControl" };
|
||||
* LDAPSearchResults res = ld.search( MY_BASE,
|
||||
* LDAPConnection.SCOPE_BASE, MY_FILT, getAttrs, false );
|
||||
*
|
||||
* while ( res.hasMoreElements() ) {
|
||||
* LDAPEntry findEntry = (LDAPEntry)res.nextElement();
|
||||
* LDAPAttributeSet findAttrs = findEntry.getAttributeSet();
|
||||
* Enumeration enumAttrs = findAttrs.getAttributes();
|
||||
*
|
||||
* while ( enumAttrs.hasMoreElements() ) {
|
||||
* LDAPAttribute anAttr = (LDAPAttribute)enumAttrs.nextElement();
|
||||
* String attrName = anAttr.getName();
|
||||
* System.out.println( attrName );
|
||||
* Enumeration enumVals = anAttr.getStringValues();
|
||||
*
|
||||
* while ( enumVals.hasMoreElements() ) {
|
||||
* String aVal = ( String )enumVals.nextElement();
|
||||
* System.out.println( "\t" + aVal );
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* catch( LDAPException e ) {
|
||||
* System.out.println( "Error: " + e.toString() );
|
||||
* }
|
||||
* try {
|
||||
* ld.disconnect();
|
||||
* }
|
||||
* catch( LDAPException e ) {
|
||||
* System.exit(1);
|
||||
* }
|
||||
* System.exit(0);
|
||||
* }
|
||||
* </PRE>
|
||||
* <P>
|
||||
*
|
||||
* If you compile and run this example against an LDAP server that
|
||||
* supports v3 of the protocol, you might receive the following results:
|
||||
* <P>
|
||||
*
|
||||
* <PRE>
|
||||
* supportedcontrol
|
||||
* 2.16.840.1.113730.3.4.2
|
||||
* 2.16.840.1.113730.3.4.3
|
||||
* 2.16.840.1.113730.3.4.4
|
||||
* 2.16.840.1.113730.3.4.5
|
||||
* 1.2.840.113556.1.4.473
|
||||
* </PRE>
|
||||
* <P>
|
||||
*
|
||||
* For more information on LDAP controls, see the Internet-Draft on
|
||||
* the LDAP v3 protocol. (Note that this internet draft is still a
|
||||
* work in progress. You can find the latest draft at the <A
|
||||
* HREF="http://www.ietf.cnri.reston.va.us/html.charters/asid-charter.html"
|
||||
* TARGET="_blank">ASID home page</A>.
|
||||
* <P>
|
||||
*
|
||||
* @version 1.0
|
||||
* @see netscape.ldap.LDAPv3#CLIENTCONTROLS
|
||||
* @see netscape.ldap.LDAPv3#SERVERCONTROLS
|
||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean)
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
* @see netscape.ldap.LDAPConnection#getResponseControls
|
||||
* @see netscape.ldap.LDAPConstraints#getClientControls
|
||||
* @see netscape.ldap.LDAPConstraints#getServerControls
|
||||
* @see netscape.ldap.LDAPConstraints#setClientControls
|
||||
* @see netscape.ldap.LDAPConstraints#setServerControls
|
||||
*/
|
||||
public class LDAPControl implements Cloneable {
|
||||
public final static String MANAGEDSAIT = "2.16.840.1.113730.3.4.2";
|
||||
/* Password information sent back to client */
|
||||
public final static String PWEXPIRED = "2.16.840.1.113730.3.4.4";
|
||||
public final static String PWEXPIRING = "2.16.840.1.113730.3.4.5";
|
||||
|
||||
/**
|
||||
* Default constructor for the <CODE>LDAPControl</CODE> class.
|
||||
*/
|
||||
public LDAPControl()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <CODE>LDAPControl</CODE> object using the
|
||||
* specified object ID (OID), "criticality" field, and
|
||||
* data to be used by the control.
|
||||
* <P>
|
||||
*
|
||||
* @param id The object ID (OID) identifying the control.
|
||||
* @param critical <CODE>true</CODE> if the LDAP operation should be
|
||||
* cancelled when the server does not support this control (in other
|
||||
* words, this control is critical to the LDAP operation).
|
||||
* @param vals Control-specific data.
|
||||
* @see netscape.ldap.LDAPConstraints#setClientControls
|
||||
* @see netscape.ldap.LDAPConstraints#setServerControls
|
||||
*/
|
||||
public LDAPControl(String id,
|
||||
boolean critical,
|
||||
byte vals[]) {
|
||||
m_oid = id;
|
||||
m_critical = critical;
|
||||
m_value = vals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the object ID (OID) of the control.
|
||||
* @return Object ID (OID) of the control.
|
||||
*/
|
||||
public String getID() {
|
||||
return m_oid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies whether or not the control is critical to the LDAP operation.
|
||||
* @return <CODE>true</CODE> if the LDAP operation should be cancelled when
|
||||
* the server does not support this control.
|
||||
*/
|
||||
public boolean isCritical() {
|
||||
return m_critical;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data in the control.
|
||||
* @return Returns the data in the control as a byte array.
|
||||
*/
|
||||
public byte[] getValue() {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ber representation of control.
|
||||
* @return ber representation of control
|
||||
*/
|
||||
BERElement getBERElement() {
|
||||
BERSequence seq = new BERSequence();
|
||||
seq.addElement(new BEROctetString (m_oid));
|
||||
seq.addElement(new BERBoolean (m_critical));
|
||||
if ( (m_value == null) || (m_value.length < 1) )
|
||||
seq.addElement(new BEROctetString ((byte[])null));
|
||||
else {
|
||||
seq.addElement(new BEROctetString (m_value, 0, m_value.length));
|
||||
}
|
||||
return seq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates a class with an oid. This class must be an extension of
|
||||
* <CODE>LDAPControl</CODE>, and should implement the <CODE>LDAPControl(
|
||||
* String oid, boolean critical, byte[] value)</CODE> constructor to
|
||||
* instantiate the control.
|
||||
* @param oid The string representation of the oid.
|
||||
* @param controlClass The class that instantatiates the control associated
|
||||
* with oid.
|
||||
* @exception netscape.ldap.LDAPException If the class parameter is not
|
||||
* a subclass of <CODE>LDAPControl</CODE> or the class parameter does not
|
||||
* implement the <CODE>LDAPControl(String oid, boolean critical, byte[] value)
|
||||
* </CODE> constructor.
|
||||
*/
|
||||
public static void register(String oid, Class controlClass) throws
|
||||
LDAPException {
|
||||
|
||||
if (controlClass == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. make sure controlClass is a subclass of LDAPControl
|
||||
Class superClass = controlClass;
|
||||
while (superClass != LDAPControl.class && superClass != null) {
|
||||
superClass = superClass.getSuperclass();
|
||||
}
|
||||
|
||||
if (superClass == null)
|
||||
throw new LDAPException("controlClass must be a subclass of " +
|
||||
"LDAPControl", LDAPException.PARAM_ERROR);
|
||||
|
||||
// 2. make sure controlClass has the proper constructor
|
||||
Class[] cparams = { String.class, boolean.class, byte[].class };
|
||||
try {
|
||||
controlClass.getConstructor(cparams);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new LDAPException("controlClass does not implement the " +
|
||||
"correct contstructor",
|
||||
LDAPException.PARAM_ERROR);
|
||||
}
|
||||
|
||||
// 3. check if the hash table exists
|
||||
if (m_controlClassHash == null) {
|
||||
m_controlClassHash = new Hashtable();
|
||||
}
|
||||
|
||||
// 4. add the controlClass
|
||||
m_controlClassHash.put(oid, controlClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <CODE>Class</CODE> that has been registered to oid.
|
||||
* @param oid A String that associates the control class to a control.
|
||||
* @return A <CODE>Class</CODE> that can instantiate a control of the
|
||||
* type specified by oid.
|
||||
* @see netscape.ldap.LDAPControl#register
|
||||
*
|
||||
*/
|
||||
protected static Class lookupControlClass(String oid) {
|
||||
if (m_controlClassHash == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (Class)m_controlClassHash.get(oid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <CODE>LDAPControl</CODE> object instantiated by the Class
|
||||
* associated by <CODE>LDAPControl.register</CODE> to the oid. If
|
||||
* no Class is found for the given control, or an exception occurs when
|
||||
* attempting to instantiate the control, a basic <CODE>LDAPControl</CODE>
|
||||
* is instantiated using the parameters.
|
||||
* @param oid The oid of the control to be instantiated.
|
||||
* @param critical <CODE>true</CODE> if this is a critical control.
|
||||
* @param value the byte value for the control.
|
||||
* @return A newly instantiated <CODE>LDAPControl</CODE>.
|
||||
* @see netscape.ldap.LDAPControl#register
|
||||
*/
|
||||
protected static LDAPControl createControl(String oid, boolean critical,
|
||||
byte[] value) {
|
||||
|
||||
Class controlClass = lookupControlClass(oid);
|
||||
|
||||
if (controlClass == null) {
|
||||
return new LDAPControl(oid, critical, value);
|
||||
}
|
||||
|
||||
Class[] cparams = { String.class, boolean.class, byte[].class };
|
||||
Constructor creator = null;
|
||||
try {
|
||||
creator = controlClass.getConstructor(cparams);
|
||||
} catch (NoSuchMethodException e) {
|
||||
//shouldn't happen, but...
|
||||
System.err.println("Caught java.lang.NoSuchMethodException while" +
|
||||
" attempting to instantiate a control of type " +
|
||||
oid);
|
||||
return new LDAPControl(oid, critical, value);
|
||||
}
|
||||
|
||||
Object[] oparams = { oid, new Boolean(critical), value } ;
|
||||
LDAPControl returnControl = null;
|
||||
try {
|
||||
returnControl = (LDAPControl)creator.newInstance(oparams);
|
||||
} catch (Exception e) {
|
||||
String eString = null;
|
||||
if (e instanceof InvocationTargetException) {
|
||||
eString = ((InvocationTargetException)
|
||||
e).getTargetException().toString();
|
||||
} else {
|
||||
eString = e.toString();
|
||||
}
|
||||
|
||||
System.err.println("Caught " + eString + " while attempting to" +
|
||||
" instantiate a control of type " +
|
||||
oid);
|
||||
returnControl = new LDAPControl(oid, critical, value);
|
||||
}
|
||||
|
||||
return returnControl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <CODE>LDAPControl</CODE> object instantiated by the Class
|
||||
* associated by <CODE>LDAPControl.register</CODE> to the oid. If
|
||||
* no Class is found for the given control, or an exception occurs when
|
||||
* attempting to instantiate the control, a basic <CODE>LDAPControl</CODE>
|
||||
* is instantiated using the parameters.
|
||||
* @param el The <CODE>BERElement</CODE> containing the control.
|
||||
* @return A newly instantiated <CODE>LDAPControl</CODE>.
|
||||
* @see netscape.ldap.LPAPControl#register
|
||||
*
|
||||
* Note:
|
||||
* This code was extracted from <CODE>JDAPControl(BERElement el)</CODE>
|
||||
* constructor
|
||||
*/
|
||||
static LDAPControl parseControl(BERElement el) {
|
||||
BERSequence s = (BERSequence)el;
|
||||
String oid = null;
|
||||
boolean critical = false;
|
||||
byte[] value = null;
|
||||
try{
|
||||
oid = new String(((BEROctetString)s.elementAt(0)).getValue(), "UTF8");
|
||||
} catch(Throwable x) {}
|
||||
|
||||
Object obj = s.elementAt(1);
|
||||
if (obj instanceof BERBoolean) {
|
||||
critical = ((BERBoolean)obj).getValue();
|
||||
}
|
||||
else {
|
||||
value = ((BEROctetString)obj).getValue();
|
||||
}
|
||||
|
||||
if (s.size() >= 3) {
|
||||
value = ((BEROctetString)s.elementAt(2)).getValue();
|
||||
}
|
||||
|
||||
return createControl(oid, critical, value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates all of the controls contained within the LDAP message
|
||||
* fragment specified by data and returns them in an <CODE>LDAPControl</CODE>
|
||||
* array. This fragment can be either the entire LDAP message or just the
|
||||
* control section of the message.
|
||||
* <P>
|
||||
* If an exception occurs when instantiating a control, that control is
|
||||
* returned as a basic <CODE>LDAPControl</CODE>.
|
||||
* @param data The LDAP message fragment in raw BER format.
|
||||
* @return A <CODE>LDAPControl</CODE> array containing all of the controls
|
||||
* from the message fragment.
|
||||
* @exception java.lang.IOException If the data passed to this method
|
||||
* is not a valid LDAP message fragment.
|
||||
* @see netscape.ldap.LDAPControl#register
|
||||
*/
|
||||
public static LDAPControl[] newInstance(byte[] data) throws IOException {
|
||||
|
||||
int[] bread = { 0 };
|
||||
|
||||
BERElement el = BERElement.getElement(new JDAPBERTagDecoder(),
|
||||
new ByteArrayInputStream(data),
|
||||
bread);
|
||||
|
||||
LDAPControl[] jc = null;
|
||||
try {
|
||||
// see if data is a LDAP message
|
||||
LDAPMessage msg = LDAPMessage.parseMessage(el);
|
||||
return msg.getControls();
|
||||
} catch (IOException e) {
|
||||
// that didn't work; let's see if its just the controls
|
||||
BERTag tag = (BERTag)el;
|
||||
if ( tag.getTag() == (BERTag.CONSTRUCTED|BERTag.CONTEXT|0) ) {
|
||||
BERSequence controls = (BERSequence)tag.getValue();
|
||||
jc = new LDAPControl[controls.size()];
|
||||
for (int i = 0; i < controls.size(); i++) {
|
||||
jc[i] = parseControl(controls.elementAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return jc;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of the control.
|
||||
* @return Copy of the control.
|
||||
*/
|
||||
public Object clone() {
|
||||
byte[] vals = null;
|
||||
if ( m_value != null ) {
|
||||
vals = new byte[m_value.length];
|
||||
for( int i = 0; i < m_value.length; i++ )
|
||||
vals[i] = m_value[i];
|
||||
}
|
||||
LDAPControl control = new LDAPControl( m_oid, m_critical, vals );
|
||||
|
||||
return control;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a "flattened" BER encoding from a BER,
|
||||
* and return it as a byte array.
|
||||
* @param ber A BER encoded sequence.
|
||||
* @return The byte array of encoded data.
|
||||
*/
|
||||
protected byte[] flattenBER( BERSequence ber ) {
|
||||
/* Suck out the data and return it */
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
try {
|
||||
ber.write( outStream );
|
||||
} catch ( IOException e ) {
|
||||
return null;
|
||||
}
|
||||
return outStream.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string representation of the control for debugging
|
||||
*
|
||||
* @return A string representation of the control
|
||||
*/
|
||||
public String toString() {
|
||||
String s = getID() + ' ' + isCritical();
|
||||
if ( m_value != null ) {
|
||||
s += ' ' + LDIF.toPrintableString( m_value );
|
||||
}
|
||||
return "LDAPControl {" + s + '}';
|
||||
}
|
||||
|
||||
private String m_oid;
|
||||
protected boolean m_critical = false;
|
||||
protected byte[] m_value = null;
|
||||
static private Hashtable m_controlClassHash = null;
|
||||
static {
|
||||
try {
|
||||
LDAPControl.register( LDAPPasswordExpiringControl.EXPIRING,
|
||||
LDAPPasswordExpiringControl.class );
|
||||
LDAPControl.register( LDAPPasswordExpiredControl.EXPIRED,
|
||||
LDAPPasswordExpiredControl.class );
|
||||
LDAPControl.register( LDAPEntryChangeControl.ENTRYCHANGED,
|
||||
LDAPEntryChangeControl.class );
|
||||
LDAPControl.register( LDAPSortControl.SORTRESPONSE,
|
||||
LDAPSortControl.class );
|
||||
LDAPControl.register( LDAPVirtualListResponse.VIRTUALLISTRESPONSE,
|
||||
LDAPVirtualListResponse.class );
|
||||
} catch (LDAPException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
132
mozilla/directory/java-sdk/ldapjdk/netscape/ldap/LDAPDN.java
Normal file
132
mozilla/directory/java-sdk/ldapjdk/netscape/ldap/LDAPDN.java
Normal file
@@ -0,0 +1,132 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import netscape.ldap.util.*;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Represents a distinguished name in LDAP.
|
||||
* <P>
|
||||
*
|
||||
* You can use objects of this class to split a distinguished name
|
||||
* (DN) into its individual components. You can also escape the
|
||||
* characters in a DN.
|
||||
* <P>
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LDAPDN {
|
||||
|
||||
/**
|
||||
* Returns the individual components of a distinguished name (DN).
|
||||
* @param dn Distinguished name that you want to get the components of.
|
||||
* @param noTypes If <CODE>true</CODE>, returns only the values of the
|
||||
* components and not the names (such as 'cn=').
|
||||
* @return An array of strings representing the components of the DN.
|
||||
* @see netscape.ldap.LDAPDN#explodeRDN(java.lang.String, boolean)
|
||||
*/
|
||||
public static String[] explodeDN (String dn, boolean noTypes) {
|
||||
DN name = new DN(dn);
|
||||
return name.explodeDN(noTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the individual components of a relative distinguished name (RDN).
|
||||
* @param rdn Relative distinguished name that you want to get the components of.
|
||||
* @param noTypes If <CODE>true</CODE>, returns only the values of the
|
||||
* components and not the names (such as 'cn=').
|
||||
* @return An array of strings representing the components of the RDN.
|
||||
* @see netscape.ldap.LDAPDN#explodeDN(java.lang.String, boolean)
|
||||
*/
|
||||
public static String[] explodeRDN (String rdn, boolean noTypes) {
|
||||
RDN name = new RDN(rdn);
|
||||
return name.explodeRDN(noTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the RDN after escaping the characters specified
|
||||
* by <CODE>netscape.ldap.util.DN.ESCAPED_CHAR</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* @param rdn The RDN that you want escaped.
|
||||
* @return The RDN with the characters escaped.
|
||||
* @see netscape.ldap.util.DN#ESCAPED_CHAR
|
||||
* @see netscape.ldap.LDAPDN#unEscapeRDN(java.lang.String)
|
||||
*/
|
||||
public static String escapeRDN(String rdn) {
|
||||
|
||||
RDN name = new RDN(rdn);
|
||||
String val = name.getValue();
|
||||
if (val == null)
|
||||
return rdn;
|
||||
|
||||
StringBuffer buffer = new StringBuffer(val);
|
||||
|
||||
int i=0;
|
||||
while (i<buffer.length()) {
|
||||
if (isEscape(buffer.charAt(i))) {
|
||||
buffer.insert(i, '\\');
|
||||
i++;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return name.getType()+"="+(new String(buffer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the RDN after unescaping any escaped characters.
|
||||
* For a list of characters that are typically escaped in a
|
||||
* DN, see <CODE>netscape.ldap.LDAPDN.ESCAPED_CHAR</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* @param rdn The RDN that you want unescaped.
|
||||
* @return The unescaped RDN.
|
||||
* @see netscape.ldap.util.DN#ESCAPED_CHAR
|
||||
* @see netscape.ldap.LDAPDN#escapeRDN(java.lang.String)
|
||||
*/
|
||||
public static String unEscapeRDN(String rdn) {
|
||||
RDN name = new RDN(rdn);
|
||||
String val = name.getValue();
|
||||
if (val == null)
|
||||
return rdn;
|
||||
|
||||
StringBuffer buffer = new StringBuffer(val);
|
||||
StringBuffer copy = new StringBuffer();
|
||||
int i=0;
|
||||
while (i<buffer.length()) {
|
||||
char c = buffer.charAt(i);
|
||||
if (c != '\\')
|
||||
copy.append(c);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return name.getType()+"="+(new String(copy));
|
||||
}
|
||||
|
||||
private static boolean isEscape(char c) {
|
||||
for (int i=0; i<DN.ESCAPED_CHAR.length; i++)
|
||||
if (c == DN.ESCAPED_CHAR[i])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
201
mozilla/directory/java-sdk/ldapjdk/netscape/ldap/LDAPEntry.java
Normal file
201
mozilla/directory/java-sdk/ldapjdk/netscape/ldap/LDAPEntry.java
Normal file
@@ -0,0 +1,201 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Represents an entry in the directory.
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LDAPEntry {
|
||||
|
||||
private String dn = null;
|
||||
private LDAPAttributeSet attrSet = null;
|
||||
|
||||
/**
|
||||
* Constructs an empty entry.
|
||||
*/
|
||||
public LDAPEntry() {
|
||||
dn = null;
|
||||
attrSet = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new entry with the specified distinguished name and with
|
||||
* an empty attribute set.
|
||||
* @param distinguishedName The distinguished name of the new entry.
|
||||
*/
|
||||
public LDAPEntry( String distinguishedName ) {
|
||||
dn = distinguishedName;
|
||||
attrSet = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new entry with the specified distinguished name and
|
||||
* set of attributes.
|
||||
* @param distinguishedName The distinguished name of the new entry.
|
||||
* @param attrs The set of attributes that you want assigned to the new entry.
|
||||
* @see netscape.ldap.LDAPAttributeSet
|
||||
*/
|
||||
public LDAPEntry( String distinguishedName, LDAPAttributeSet attrs ) {
|
||||
dn = distinguishedName;
|
||||
attrSet = attrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distinguished name of the current entry.
|
||||
* @return Distinguished name of the current entry.
|
||||
*/
|
||||
public String getDN() {
|
||||
return dn;
|
||||
}
|
||||
|
||||
void setDN(String name) {
|
||||
dn = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute set of the entry.
|
||||
* @return Set of attributes in the entry.
|
||||
* @see netscape.ldap.LDAPAttributeSet
|
||||
*/
|
||||
public LDAPAttributeSet getAttributeSet() {
|
||||
return attrSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new attribute set containing only the attributes
|
||||
* that have the specified subtypes.
|
||||
* <P>
|
||||
*
|
||||
* For example, suppose an entry contains the following attributes:
|
||||
* <P>
|
||||
*
|
||||
* <PRE>
|
||||
* cn
|
||||
* cn;lang-ja
|
||||
* sn;phonetic;lang-ja
|
||||
* sn;lang-us
|
||||
* </PRE>
|
||||
*
|
||||
* If you call the <CODE>getAttributeSet</CODE> method and pass
|
||||
* <CODE>lang-ja</CODE> as the argument, the method returns
|
||||
* an attribute set containing the following attributes:
|
||||
* <P>
|
||||
*
|
||||
* <PRE>
|
||||
* cn;lang-ja
|
||||
* sn;phonetic;lang-ja
|
||||
* </PRE>
|
||||
*
|
||||
* @param subtype Semi-colon delimited list of subtypes
|
||||
* that you want to find in attribute names.
|
||||
*<PRE>
|
||||
* "lang-ja" // Only Japanese language subtypes
|
||||
* "binary" // Only binary subtypes
|
||||
* "binary;lang-ja" // Only Japanese language subtypes
|
||||
* which also are binary
|
||||
*</PRE>
|
||||
* @return Attribute set containing the attributes that have
|
||||
* the specified subtypes
|
||||
* @see netscape.ldap.LDAPAttributeSet
|
||||
* @see netscape.ldap.LDAPAttributeSet#getSubset
|
||||
*/
|
||||
public LDAPAttributeSet getAttributeSet(String subtype) {
|
||||
return attrSet.getSubset(subtype);
|
||||
}
|
||||
|
||||
/**
|
||||
* In an entry, returns the single attribute that exactly matches the
|
||||
* specified attribute name.
|
||||
* @param attrName Name of attribute to return.
|
||||
* For example:
|
||||
*<PRE>
|
||||
* "cn" // Only a non-subtyped version of cn
|
||||
* "cn;lang-ja" // Only a Japanese version of cn, will not
|
||||
* // return "cn;lang-ja-JP-kanji", for example
|
||||
*</PRE>
|
||||
* @return Attribute in the current entry that has exactly the same name,
|
||||
* or null (if no attribute in the entry matches the specified name).
|
||||
* @see netscape.ldap.LDAPAttribute
|
||||
*/
|
||||
public LDAPAttribute getAttribute(String attrName) {
|
||||
return attrSet.getAttribute(attrName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the subtype that matches "attrName" and that best matches
|
||||
* a language specification "lang". If there are subtypes other than
|
||||
* "lang" subtypes included in attrName, e.g. "cn;binary", only
|
||||
* attributes with all of those subtypes are returned. If lang is
|
||||
* null or empty, the method behaves as getAttribute(attrName). If
|
||||
* there are no matching attributes, null is returned.
|
||||
*
|
||||
* Example:<PRE>
|
||||
* Assume the entry contains only the following attributes:
|
||||
* <CODE>cn;lang-en</CODE>
|
||||
* <CODE>cn;lang-ja-JP-kanji</CODE>
|
||||
* <CODE>sn</CODE>
|
||||
* getAttribute( "cn" ) returns <CODE>null</CODE>.
|
||||
* getAttribute( "sn" ) returns the "<CODE>sn</CODE>" attribute.
|
||||
* getAttribute( "cn", "lang-en-us" ) returns the "<CODE>cn;lang-en</CODE>" attribute.
|
||||
* getAttribute( "cn", "lang-en" ) returns the "<CODE>cn;lang-en</CODE>" attribute.
|
||||
* getAttribute( "cn", "lang-ja" ) returns <CODE>null</CODE>.
|
||||
* getAttribute( "sn", "lang-en" ) returns the "<CODE>sn</CODE>" attribute.
|
||||
*</PRE>
|
||||
* <P>
|
||||
* @param attrName Name of attribute to find in the entry.
|
||||
* @param lang A language specification (for example, <CODE>lang-en</CODE>).
|
||||
* @return The attribute that matches the base name and that best
|
||||
* matches any specified language subtype.
|
||||
* @see netscape.ldap.LDAPAttribute
|
||||
*/
|
||||
public LDAPAttribute getAttribute( String attrName, String lang ) {
|
||||
return attrSet.getAttribute( attrName, lang );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the string representation of the entry's
|
||||
* distinguished name (DN) and its attributes.
|
||||
* For example:
|
||||
*
|
||||
* <PRE>
|
||||
* LDAPEntry: uid=bjensen, ou=People, o=airius.com; LDAPAttributeSet:
|
||||
* LDAPAttribute {type='cn', values='Barbara Jensen,Babs Jensen'}
|
||||
* LDAPAttribute {type='sn', values='Jensen'}LDAPAttribute {type='givenname',
|
||||
* values='Barbara'}LDAPAttribute {type='objectclass', values='top,person,
|
||||
* organizationalPerson,inetOrgPerson'}LDAPAttribute {type='ou',
|
||||
* values='Product Development,People'}
|
||||
* </PRE>
|
||||
*
|
||||
* @return String representation of the entry's DN and its attributes.
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer("LDAPEntry: ");
|
||||
if ( dn != null ) {
|
||||
sb.append(dn);
|
||||
sb.append("; ");
|
||||
}
|
||||
if ( attrSet != null ) {
|
||||
sb.append(attrSet.toString());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
/**
|
||||
* The <CODE>LDAPEntryComparator</CODE> interface represents the
|
||||
* algorithm used to sort the search results. This interface specifies
|
||||
* one method, <CODE>isGreater</CODE>, which compares two entries and
|
||||
* determines the order in which the two entries should be sorted.
|
||||
* <P>
|
||||
*
|
||||
* The <CODE>netscape.ldap</CODE> package includes a class that
|
||||
* implements this interface. The <CODE>LDAPCompareAttrNames</CODE>
|
||||
* class represents a comparator that sorts the two entries alphabetically,
|
||||
* based on the value of one or more attributes.
|
||||
* <P>
|
||||
*
|
||||
* When calling the <CODE>sort</CODE> method of the
|
||||
* <CODE>LDAPSearchResults</CODE> class, you need to specify
|
||||
* a class that implements the <CODE>LDAPEntryComparator</CODE>
|
||||
* interface.
|
||||
* <P>
|
||||
*
|
||||
* @version 1.0
|
||||
* @see netscape.ldap.LDAPCompareAttrNames
|
||||
* @see netscape.ldap.LDAPSearchResults#sort
|
||||
*/
|
||||
public interface LDAPEntryComparator {
|
||||
|
||||
/**
|
||||
* Specifies the algorithm used to
|
||||
* compare entries when sorting search results.
|
||||
* <P>
|
||||
*
|
||||
* <CODE>isGreater</CODE> returns <CODE>true</CODE>
|
||||
* if the entry specified in the first argument should
|
||||
* be sorted before the entry specified in the second
|
||||
* argument.
|
||||
* <P>
|
||||
*
|
||||
* @version 1.0
|
||||
* @see netscape.ldap.LDAPCompareAttrNames
|
||||
* @see netscape.ldap.LDAPSearchResults#sort
|
||||
*/
|
||||
public boolean isGreater (LDAPEntry greater, LDAPEntry less);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,883 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import netscape.ldap.client.*;
|
||||
import netscape.ldap.client.opers.*;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Indicates that an error has occurred. An <CODE>LDAPException</CODE>
|
||||
* can result from physical problems (such as network errors) as well as
|
||||
* problems with LDAP operations (for example, if the LDAP add operation
|
||||
* fails because of duplicate entry).
|
||||
* <P>
|
||||
*
|
||||
* Most errors that occur throw this type of exception. In order to determine
|
||||
* the cause of the error, you can call the <CODE>getLDAPResultCode()</CODE>
|
||||
* method to get the specific result code and compare this code against
|
||||
* the result codes defined as fields in this class. (For example, if
|
||||
* the result code matches the value of the field
|
||||
* <CODE>LDAPException.TIME_LIMIT_EXCEEDED</CODE>, the time limit passed
|
||||
* before the search operation could be completed.)
|
||||
* <P>
|
||||
*
|
||||
* This exception includes methods for getting an error message that
|
||||
* corresponds to the LDAP result code (for example, "Timelimit exceeded"
|
||||
* for <CODE>LDAPException.TIME_LIMIT_EXCEEDED</CODE>). These error
|
||||
* messages are specified in the following files:
|
||||
* <PRE>netscape/ldap/errors/ErrorCodes_<I>locale_string</I>.props</PRE>
|
||||
* where <I>locale_string</I> is the name of the locale that includes
|
||||
* the language and country, but not the variant.
|
||||
* <P>
|
||||
*
|
||||
* For example:
|
||||
* <PRE>netscape/ldap/errors/ErrorCodes_en_US.props</PRE>
|
||||
*
|
||||
* The LDAP Java classes get this locale name by calling the
|
||||
* <CODE>java.util.Locale.toString</CODE> method for the specified
|
||||
* locale and ignoring the variant. If no locale is specified, the
|
||||
* LDAP Java classes use the <CODE>java.util.Locale.getDefault</CODE>
|
||||
* method to get the locale of the local host system.
|
||||
* <P>
|
||||
*
|
||||
* In order to get error messages for different locales, you need to
|
||||
* provide files containing the error messages for those locales.
|
||||
* The files should be located in the <CODE>netscape/ldap/errors</CODE>
|
||||
* directory and should use the naming convention specified above.
|
||||
* <P>
|
||||
*
|
||||
* The following is a list of LDAP result codes:
|
||||
* <PRE>
|
||||
* Result
|
||||
* Code Defined Value
|
||||
* ====== =============
|
||||
* 0 <A HREF="#SUCCESS">SUCCESS</A>
|
||||
* 1 <A HREF="#OPERATION_ERROR">OPERATION_ERROR</A>
|
||||
* 2 <A HREF="#PROTOCOL_ERROR">PROTOCOL_ERROR</A>
|
||||
* 3 <A HREF="#TIME_LIMIT_EXCEEDED">TIME_LIMIT_EXCEEDED</A>
|
||||
* 4 <A HREF="#SIZE_LIMIT_EXCEEDED">SIZE_LIMIT_EXCEEDED</A>
|
||||
* 5 <A HREF="#COMPARE_FALSE">COMPARE_FALSE</A>
|
||||
* 6 <A HREF="#COMPARE_TRUE">COMPARE_TRUE</A>
|
||||
* 7 <A HREF="#AUTH_METHOD_NOT_SUPPORTED">AUTH_METHOD_NOT_SUPPORTED</A>
|
||||
* 8 <A HREF="#STRONG_AUTH_REQUIRED">STRONG_AUTH_REQUIRED</A>
|
||||
* 9 <A HREF="#LDAP_PARTIAL_RESULTS">LDAP_PARTIAL_RESULTS</A>
|
||||
* 10 <A HREF="#REFERRAL">REFERRAL</A> (LDAP v3)
|
||||
* 11 <A HREF="#ADMIN_LIMIT_EXCEEDED">ADMIN_LIMIT_EXCEEDED</A> (LDAP v3)
|
||||
* 12 <A HREF="#UNAVAILABLE_CRITICAL_EXTENSION">UNAVAILABLE_CRITICAL_EXTENSION</A> (LDAP v3)
|
||||
* 13 <A HREF="#CONFIDENTIALITY_REQUIRED">CONFIDENTIALITY_REQUIRED</A> (LDAP v3)
|
||||
* 14 <A HREF="#SASL_BIND_IN_PROGRESS">SASL_BIND_IN_PROGRESS</A> (LDAP v3)
|
||||
* 16 <A HREF="#NO_SUCH_ATTRIBUTE">NO_SUCH_ATTRIBUTE</A>
|
||||
* 17 <A HREF="#UNDEFINED_ATTRIBUTE_TYPE">UNDEFINED_ATTRIBUTE_TYPE</A>
|
||||
* 18 <A HREF="#INAPPROPRIATE_MATCHING">INAPPROPRIATE_MATCHING</A>
|
||||
* 19 <A HREF="#CONSTRAINT_VIOLATION">CONSTRAINT_VIOLATION</A>
|
||||
* 20 <A HREF="#ATTRIBUTE_OR_VALUE_EXISTS">ATTRIBUTE_OR_VALUE_EXISTS</A>
|
||||
* 21 <A HREF="#INVALID_ATTRIBUTE_SYNTAX">INVALID_ATTRIBUTE_SYNTAX</A>
|
||||
* 32 <A HREF="#NO_SUCH_OBJECT">NO_SUCH_OBJECT</A>
|
||||
* 33 <A HREF="#ALIAS_PROBLEM">ALIAS_PROBLEM</A>
|
||||
* 34 <A HREF="#INVALID_DN_SYNTAX">INVALID_DN_SYNTAX</A>
|
||||
* 35 <A HREF="#IS_LEAF">IS_LEAF</A>
|
||||
* 36 <A HREF="#ALIAS_DEREFERENCING_PROBLEM">ALIAS_DEREFERENCING_PROBLEM</A>
|
||||
* 48 <A HREF="#INAPPROPRIATE_AUTHENTICATION">INAPPROPRIATE_AUTHENTICATION</A>
|
||||
* 49 <A HREF="#INVALID_CREDENTIALS">INVALID_CREDENTIALS</A>
|
||||
* 50 <A HREF="#INSUFFICIENT_ACCESS_RIGHTS">INSUFFICIENT_ACCESS_RIGHTS</A>
|
||||
* 51 <A HREF="#BUSY">BUSY</A>
|
||||
* 52 <A HREF="#UNAVAILABLE">UNAVAILABLE</A>
|
||||
* 53 <A HREF="#UNWILLING_TO_PERFORM">UNWILLING_TO_PERFORM</A>
|
||||
* 54 <A HREF="#LOOP_DETECT">LOOP_DETECT</A>
|
||||
* 64 <A HREF="#NAMING_VIOLATION">NAMING_VIOLATION</A>
|
||||
* 65 <A HREF="#OBJECT_CLASS_VIOLATION">OBJECT_CLASS_VIOLATION</A>
|
||||
* 66 <A HREF="#NOT_ALLOWED_ON_NONLEAF">NOT_ALLOWED_ON_NONLEAF</A>
|
||||
* 67 <A HREF="#NOT_ALLOWED_ON_RDN">NOT_ALLOWED_ON_RDN</A>
|
||||
* 68 <A HREF="#ENTRY_ALREADY_EXISTS">ENTRY_ALREADY_EXISTS</A>
|
||||
* 69 <A HREF="#OBJECT_CLASS_MODS_PROHIBITED">OBJECT_CLASS_MODS_PROHIBITED</A>
|
||||
* 71 <A HREF="#AFFECTS_MULTIPLE_DSAS">AFFECTS_MULTIPLE_DSAS</A> (LDAP v3)
|
||||
* 80 <A HREF="#OTHER">OTHER</A>
|
||||
* 81 <A HREF="#SERVER_DOWN">SERVER_DOWN</A>
|
||||
* 89 <A HREF="#PARAM_ERROR">PARAM_ERROR</A>
|
||||
* 91 <A HREF="#CONNECT_ERROR">CONNECT_ERROR</A>
|
||||
* 92 <A HREF="#LDAP_NOT_SUPPORTED">LDAP_NOT_SUPPORTED</A>
|
||||
* 93 <A HREF="#CONTROL_NOT_FOUND">CONTROL_NOT_FOUND</A>
|
||||
* 94 <A HREF="#NO_RESULTS_RETURNED">NO_RESULTS_RETURNED</A>
|
||||
* 95 <A HREF="#MORE_RESULTS_TO_RETURN">MORE_RESULTS_TO_RETURN</A>
|
||||
* 96 <A HREF="#CLIENT_LOOP">CLIENT_LOOP</A>
|
||||
* 97 <A HREF="#REFERRAL_LIMIT_EXCEEDED">REFERRAL_LIMIT_EXCEEDED</A>
|
||||
* </PRE>
|
||||
* <P>
|
||||
*
|
||||
* @version 1.0
|
||||
* @see netscape.ldap.LDAPReferralException
|
||||
*/
|
||||
public class LDAPException extends java.lang.Exception {
|
||||
|
||||
/**
|
||||
* (0) The operation completed successfully.
|
||||
*/
|
||||
public final static int SUCCESS = 0;
|
||||
|
||||
/**
|
||||
* (1) An internal error occurred in the LDAP server.
|
||||
*/
|
||||
public final static int OPERATION_ERROR = 1;
|
||||
|
||||
/**
|
||||
* (2) A LDAP server could not correctly interpret the request
|
||||
* sent by your client because the request does not strictly
|
||||
* comply with the LDAP protocol. (For example, the data
|
||||
* was not correctly BER-encoded, or a specified value -- such
|
||||
* as the search scope or modification type -- does not
|
||||
* comply with the LDAP protocol. If you invent your own
|
||||
* search scope, for instance, this result code might be returned.<P>
|
||||
*/
|
||||
public final static int PROTOCOL_ERROR = 2;
|
||||
|
||||
/**
|
||||
* (3) The search operation could not be completed within
|
||||
* the maximum time limit. You can specify the maximum time
|
||||
* limit by calling the <CODE>LDAPConnection.setOption</CODE>
|
||||
* method or the <CODE>LDAPSearchConstraints.setServerTimeLimit</CODE>
|
||||
* method.<P>
|
||||
*
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
* @see netscape.ldap.LDAPSearchConstraints#setServerTimeLimit
|
||||
*/
|
||||
public final static int TIME_LIMIT_EXCEEDED = 3;
|
||||
|
||||
/**
|
||||
* (4) The search found more than the maximum number of results.
|
||||
* You can specify the maximum number of results by calling the
|
||||
* <CODE>LDAPConnection.setOption</CODE> method or the
|
||||
* <CODE>LDAPSearchConstraints.setSizeLimit</CODE> method.<P>
|
||||
*
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
* @see netscape.ldap.LDAPSearchConstraints#setMaxResults
|
||||
*/
|
||||
public final static int SIZE_LIMIT_EXCEEDED = 4;
|
||||
|
||||
/**
|
||||
* (5) Value returned by an LDAP compare operation if the
|
||||
* specified attribute and value is not found in the entry
|
||||
* (no matching value found).
|
||||
*
|
||||
* @see netscape.ldap.LDAPConnection#compare
|
||||
*/
|
||||
public final static int COMPARE_FALSE = 5;
|
||||
|
||||
/**
|
||||
* (6) Value returned by an LDAP compare operation if the
|
||||
* specified attribute and value is found in the entry
|
||||
* (matching value found).
|
||||
*
|
||||
* @see netscape.ldap.LDAPConnection#compare
|
||||
*/
|
||||
public final static int COMPARE_TRUE = 6;
|
||||
|
||||
/**
|
||||
* (7) The specified authentication method is not supported
|
||||
* by the LDAP server that you are connecting to. The
|
||||
* <CODE>LDAPConnection</CODE> class is implemented so that
|
||||
* <CODE>LDAPConnection.authenticate</CODE> always
|
||||
* uses the LDAP_AUTH_SIMPLE method of authentication.
|
||||
* (<CODE>LDAPConnection.authenticate</CODE> does not
|
||||
* allow you to select the method of authentication.)<P>
|
||||
*/
|
||||
public final static int AUTH_METHOD_NOT_SUPPORTED = 7;
|
||||
|
||||
/**
|
||||
* (8) A stronger authentication method (more than LDAP_AUTH_SIMPLE)
|
||||
* is required by the LDAP server that you are connecting to.
|
||||
* The <CODE>LDAPConnection</CODE> class is implemented so that
|
||||
* <CODE>LDAPConnection.authenticate</CODE> always
|
||||
* uses the LDAP_AUTH_SIMPLE method of authentication.
|
||||
* (<CODE>LDAPConnection.authenticate</CODE> does not
|
||||
* allow you to select the method of authentication.)<P>
|
||||
*/
|
||||
public final static int STRONG_AUTH_REQUIRED = 8;
|
||||
|
||||
/**
|
||||
* (9) The LDAP server is referring your client to another
|
||||
* LDAP server. If you set up the <CODE>LDAPConnection</CODE>
|
||||
* options or the <CODE>LDAPConstraints</CODE> options
|
||||
* for automatic referral, your client will automatically
|
||||
* connect and authenticate to the other LDAP server.
|
||||
* (This <CODE>LDAPException</CODE> will not be raised.)
|
||||
* <P>
|
||||
*
|
||||
* (To set up automatic referrals in an <CODE>LDAPConnection</CODE>
|
||||
* object, set the <CODE>LDAPConnection.REFERRALS</CODE> option
|
||||
* to <CODE>true</CODE> and the LDAPConnection.REFERRALS_REBIND_PROC</CODE>
|
||||
* option to the object containing the method for retrieving
|
||||
* authentication information (in other words, the distinguished
|
||||
* name and password to use when authenticating to other LDAP servers).
|
||||
* <P>
|
||||
*
|
||||
* If instead you set <CODE>LDAPConnection.REFERRALS</CODE>
|
||||
* to <CODE>false</CODE> (or if you set
|
||||
* <CODE>LDAPConstraints.setReferrals</CODE> to <CODE>false</CODE>,
|
||||
* an <CODE>LDAPReferralException</CODE> is raised.
|
||||
* <P>
|
||||
*
|
||||
* If an error occurs during the referral process, an
|
||||
* <CODE>LDAPException</CODE> with this result code
|
||||
* (<CODE>LDAP_PARTIAL_RESULTS</CODE>) is raised.
|
||||
* <P>
|
||||
*
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
* @see netscape.ldap.LDAPConstraints#setReferrals
|
||||
* @see netscape.ldap.LDAPConstraints#setRebindProc
|
||||
* @see netscape.ldap.LDAPRebind
|
||||
* @see netscape.ldap.LDAPRebindAuth
|
||||
* @see netscape.ldap.LDAPReferralException
|
||||
*/
|
||||
public final static int LDAP_PARTIAL_RESULTS = 9;
|
||||
|
||||
/**
|
||||
* (10) [LDAP v3] The server does not hold the requested entry.
|
||||
* The referral field of the server's response contains a
|
||||
* reference to another server (or set of servers), which
|
||||
* your client can access through LDAP or other protocols.
|
||||
* Typically, these references are LDAP URLs that identify
|
||||
* the server that may contain the requested entry.
|
||||
* <P>
|
||||
*
|
||||
* When this occurs, a <CODE>LDAPReferralException</CODE>
|
||||
* is thrown. You can catch this exception and call the
|
||||
* <CODE>getURLs</CODE> method to get the list of LDAP
|
||||
* URLs from the exception.
|
||||
* <P>
|
||||
*
|
||||
* @see netscape.ldap.LDAPReferralException
|
||||
*/
|
||||
public final static int REFERRAL = 10;
|
||||
|
||||
/**
|
||||
* (11) [LDAP v3] The adminstrative limit on the
|
||||
* maximum number of entries to return was exceeded.
|
||||
* In the Netscape Directory Server 3.0, this
|
||||
* corresponds to the "look through limit" for
|
||||
* the server. This is the maximum number of
|
||||
* entries that the server will check through
|
||||
* when determining which entries match the
|
||||
* search filter and scope.
|
||||
* <P>
|
||||
*/
|
||||
public final static int ADMIN_LIMIT_EXCEEDED = 11;
|
||||
|
||||
/**
|
||||
* (12) [LDAP v3] The server received an LDAP v3 control
|
||||
* that is marked critical and either (1) is not
|
||||
* recognized or supported by the server, or
|
||||
* (2) is inappropriate for the operation requested.
|
||||
* The Netscape Directory Server 3.0 also returns
|
||||
* this result code if the client specifies a
|
||||
* matching rule that is not supported by the server.
|
||||
* <P>
|
||||
*
|
||||
* @see netscape.ldap.LDAPControl
|
||||
*/
|
||||
public final static int UNAVAILABLE_CRITICAL_EXTENSION = 12;
|
||||
|
||||
/**
|
||||
* (13) [LDAP v3] A secure connection is required for
|
||||
* this operation.
|
||||
*/
|
||||
public final static int CONFIDENTIALITY_REQUIRED = 13;
|
||||
|
||||
/**
|
||||
* (14) [LDAP v3] While authenticating your client
|
||||
* by using a SASL (Simple Authentication Security Layer)
|
||||
* mechanism, the server requires the client to send
|
||||
* a new SASL bind request (specifying the same SASL
|
||||
* mechanism) to continue the authentication process.
|
||||
*/
|
||||
public final static int SASL_BIND_IN_PROGRESS = 14;
|
||||
|
||||
/**
|
||||
* (16) The specified attribute could not be found.
|
||||
*/
|
||||
public final static int NO_SUCH_ATTRIBUTE = 16;
|
||||
|
||||
/**
|
||||
* (17) The specified attribute is not defined.
|
||||
*/
|
||||
public final static int UNDEFINED_ATTRIBUTE_TYPE = 17;
|
||||
|
||||
/**
|
||||
* (18) An inappropriate type of matching was used.
|
||||
*/
|
||||
public final static int INAPPROPRIATE_MATCHING = 18;
|
||||
|
||||
/**
|
||||
* (19) An internal error occurred in the LDAP server.
|
||||
*/
|
||||
public final static int CONSTRAINT_VIOLATION = 19;
|
||||
|
||||
/**
|
||||
* (20) The value that you are adding to an attribute
|
||||
* already exists in the attribute.
|
||||
*/
|
||||
public final static int ATTRIBUTE_OR_VALUE_EXISTS = 20;
|
||||
|
||||
/**
|
||||
* (21) The request contains invalid syntax.
|
||||
*/
|
||||
public final static int INVALID_ATTRIBUTE_SYNTAX = 21;
|
||||
|
||||
/**
|
||||
* (32) The entry specified in the request does not exist.
|
||||
*/
|
||||
public final static int NO_SUCH_OBJECT = 32;
|
||||
|
||||
/**
|
||||
* (33) An problem occurred with an alias.
|
||||
*/
|
||||
public final static int ALIAS_PROBLEM = 33;
|
||||
|
||||
/**
|
||||
* (34) The specified distinguished name (DN) uses invalid syntax.
|
||||
*/
|
||||
public final static int INVALID_DN_SYNTAX = 34;
|
||||
|
||||
/**
|
||||
* (35) The specified entry is a "leaf" entry (it has no entries
|
||||
* beneath it in the directory tree).
|
||||
*/
|
||||
public final static int IS_LEAF = 35;
|
||||
|
||||
/**
|
||||
* (36) An error occurred when dereferencing an alias.
|
||||
*/
|
||||
public final static int ALIAS_DEREFERENCING_PROBLEM = 36;
|
||||
|
||||
/**
|
||||
* (48) The authentication presented to the server is inappropriate.
|
||||
* This result code might occur, for example, if your client
|
||||
* presents a password and the corresponding entry has no
|
||||
* userpassword attribute.
|
||||
*/
|
||||
public final static int INAPPROPRIATE_AUTHENTICATION = 48;
|
||||
|
||||
/**
|
||||
* (49) The credentials presented to the server for authentication
|
||||
* are not valid. (For example, the password sent to the server
|
||||
* does not match the user's password in the directory.)
|
||||
*/
|
||||
public final static int INVALID_CREDENTIALS = 49;
|
||||
|
||||
/**
|
||||
* (50) The client is authenticated as a user who does not have the
|
||||
* access privileges to perform this operation.
|
||||
*/
|
||||
public final static int INSUFFICIENT_ACCESS_RIGHTS = 50;
|
||||
|
||||
/**
|
||||
* (51) The LDAP server is busy.
|
||||
*/
|
||||
public final static int BUSY = 51;
|
||||
|
||||
/**
|
||||
* (52) The LDAP server is unavailable.
|
||||
*/
|
||||
public final static int UNAVAILABLE = 52;
|
||||
|
||||
/**
|
||||
* (53) The LDAP server is unable to perform the specified operation.
|
||||
*/
|
||||
public final static int UNWILLING_TO_PERFORM = 53;
|
||||
|
||||
/**
|
||||
* (54) A loop has been detected.
|
||||
*/
|
||||
public final static int LOOP_DETECT = 54;
|
||||
|
||||
/**
|
||||
* (60) The "server-side sorting" control
|
||||
* was not included with the "virtual list view"
|
||||
* control in the search request.
|
||||
*/
|
||||
public final static int SORT_CONTROL_MISSING = 60;
|
||||
|
||||
/**
|
||||
* (61) An index range error occurred.
|
||||
*/
|
||||
public final static int INDEX_RANGE_ERROR = 61;
|
||||
|
||||
/**
|
||||
* (64) A naming violation has occurred.
|
||||
*/
|
||||
public final static int NAMING_VIOLATION = 64;
|
||||
|
||||
/**
|
||||
* (65) The requested operation will add or change
|
||||
* data so that the data no longer complies with
|
||||
* the schema.
|
||||
*/
|
||||
public final static int OBJECT_CLASS_VIOLATION = 65;
|
||||
|
||||
/**
|
||||
* (66) The requested operation can only be performed
|
||||
* on an entry that has no entries beneath it in the
|
||||
* directory tree (in other words, a "leaf" entry).
|
||||
* <P>
|
||||
*
|
||||
* For example, you cannot delete or rename an entry
|
||||
* if the entry has subentries beneath it.
|
||||
* <P>
|
||||
*/
|
||||
public final static int NOT_ALLOWED_ON_NONLEAF = 66;
|
||||
|
||||
/**
|
||||
* (67) The specified operation cannot be performed on
|
||||
* a relative distinguished name (RDN).
|
||||
*/
|
||||
public final static int NOT_ALLOWED_ON_RDN = 67;
|
||||
|
||||
/**
|
||||
* (68) The specified entry already exists. You might receive
|
||||
* this error if, for example, you attempt to add an entry
|
||||
* that already exists or if you attempt to change the name
|
||||
* of an entry to the name of an entry that already exists.
|
||||
*/
|
||||
public final static int ENTRY_ALREADY_EXISTS = 68;
|
||||
|
||||
/**
|
||||
* (69) You cannot modify the specified object class.
|
||||
*/
|
||||
public final static int OBJECT_CLASS_MODS_PROHIBITED = 69;
|
||||
|
||||
/**
|
||||
* (71) [LDAP v3] The client attempted to move an entry
|
||||
* from one LDAP server to another by requesting a "modify
|
||||
* DN" operation. In general, clients should not be able
|
||||
* to arbitrarily move entries and subtrees between servers.
|
||||
* <P>
|
||||
*
|
||||
* @see netscape.ldap.LDAPConnection#rename(java.lang.String, java.lang.String, java.lang.String, boolean)
|
||||
* @see netscape.ldap.LDAPConnection#rename(java.lang.String, java.lang.String, java.lang.String, boolean, LDAPConstraints)
|
||||
*/
|
||||
public final static int AFFECTS_MULTIPLE_DSAS = 71;
|
||||
|
||||
/**
|
||||
* (80) General result code for other types of errors
|
||||
* that may occur.
|
||||
*/
|
||||
public final static int OTHER = 80;
|
||||
|
||||
/**
|
||||
* (81) The LDAP server cannot be contacted.
|
||||
*/
|
||||
public final static int SERVER_DOWN = 0x51;
|
||||
|
||||
/**
|
||||
* (89) When calling a constructor or method from your client,
|
||||
* one or more parameters were incorrectly specified.
|
||||
*/
|
||||
public final static int PARAM_ERROR = 0x59;
|
||||
|
||||
/**
|
||||
* (91) Your LDAP client failed to connect to the LDAP server.
|
||||
*/
|
||||
public final static int CONNECT_ERROR = 0x5b;
|
||||
|
||||
/**
|
||||
* (92) The request is not supported by this version of the LDAP protocol.
|
||||
*/
|
||||
public final static int LDAP_NOT_SUPPORTED = 0x5c;
|
||||
|
||||
/**
|
||||
* (93) The requested control is not found.
|
||||
* <P>
|
||||
*
|
||||
* @see netscape.ldap.LDAPControl
|
||||
*/
|
||||
public final static int CONTROL_NOT_FOUND = 0x5d;
|
||||
|
||||
/**
|
||||
* (94) No results have been returned from the server.
|
||||
*/
|
||||
public final static int NO_RESULTS_RETURNED = 0x5e;
|
||||
|
||||
/**
|
||||
* (95) More results are being returned from the server.
|
||||
*/
|
||||
public final static int MORE_RESULTS_TO_RETURN = 0x5f;
|
||||
|
||||
/**
|
||||
* (96) Your LDAP client detected a loop in the referral.
|
||||
*/
|
||||
public final static int CLIENT_LOOP = 0x60;
|
||||
|
||||
/**
|
||||
* (97) The number of sequential referrals (for example,
|
||||
* the client may be referred first from LDAP server A to
|
||||
* LDAP server B, then from LDAP server B to LDAP server C,
|
||||
* and so on) has exceeded the maximum number of referrals
|
||||
* (the <CODE>LDAPv2.REFERRALS_HOP_LIMIT</CODE> option).
|
||||
* <P>
|
||||
*
|
||||
* @see netscape.ldap.LDAPv2#REFERRALS_HOP_LIMIT
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
*/
|
||||
public final static int REFERRAL_LIMIT_EXCEEDED = 0x61;
|
||||
|
||||
/**
|
||||
* Internal variables
|
||||
*/
|
||||
private int resultCode = -1;
|
||||
private String errorMessage = null;
|
||||
private String matchedDN = null;
|
||||
private Locale m_locale = Locale.getDefault();
|
||||
private static Hashtable cacheResource = new Hashtable();
|
||||
private static final String baseName = "netscape/ldap/errors/ErrorCodes";
|
||||
|
||||
/**
|
||||
* Constructs a default exception with no specific error information.
|
||||
*/
|
||||
public LDAPException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a default exception with a specified string of
|
||||
* additional information. This string appears if you call
|
||||
* the <CODE>toString()</CODE> method.
|
||||
* <P>
|
||||
*
|
||||
* This form is used for lower-level errors.
|
||||
* It is recommended that you always use one of the constructors
|
||||
* that takes a result code as a parameter. (If your exception is
|
||||
* thrown, any code that catches the exception may need to extract
|
||||
* the result code from the exception.)
|
||||
* <P>
|
||||
* @param message The additional error information.
|
||||
* @see netscape.ldap.LDAPException#toString()
|
||||
*/
|
||||
public LDAPException( String message ) {
|
||||
super( message );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a default exception with a result code and
|
||||
* a specified string of additional information. This string
|
||||
* appears if you call the <CODE>toString()</CODE> method.
|
||||
* The result code that you set is accessible through the
|
||||
* <CODE>getLDAPResultCode()</CODE> method.
|
||||
* <P>
|
||||
*
|
||||
* @param message The additional error information that you
|
||||
* want to specify.
|
||||
* @param resultCode The result code returned from the
|
||||
* operation that caused this exception.
|
||||
* @see netscape.ldap.LDAPException#toString()
|
||||
* @see netscape.ldap.LDAPException#getLDAPResultCode()
|
||||
*/
|
||||
public LDAPException( String message, int resultCode ) {
|
||||
super( message );
|
||||
this.resultCode = resultCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a default exception with a result code, a specified
|
||||
* string of additional information, and a string containing
|
||||
* information passed back from the server.
|
||||
* <P>
|
||||
*
|
||||
* After you construct the <CODE>LDAPException</CODE> object,
|
||||
* the result code and messages will be accessible through the
|
||||
* following ways:
|
||||
* <P>
|
||||
* <UL>
|
||||
* <LI>The first string of additional information appears if you
|
||||
* call the <CODE>toString()</CODE> method. <P>
|
||||
* <LI>The result code that you set is accessible through the
|
||||
* <CODE>getLDAPResultCode()</CODE> method. <P>
|
||||
* <LI>The string of server error information that you set
|
||||
* is accessible through the <CODE>getLDAPErrorMessage</CODE>
|
||||
* method. <P>
|
||||
* </UL>
|
||||
* <P>
|
||||
*
|
||||
* Use this form of the constructor
|
||||
* for higher-level LDAP operational errors.
|
||||
* @param message The additional error information that you
|
||||
* want to specify.
|
||||
* @param resultCode The result code returned from the
|
||||
* operation that caused this exception.
|
||||
* @param serverErrorMessage Error message specifying additional
|
||||
* information returned from the server.
|
||||
* @see netscape.ldap.LDAPException#toString()
|
||||
* @see netscape.ldap.LDAPException#getLDAPResultCode()
|
||||
* @see netscape.ldap.LDAPException#getLDAPErrorMessage()
|
||||
*/
|
||||
public LDAPException( String message, int resultCode,
|
||||
String serverErrorMessage ) {
|
||||
super( message );
|
||||
this.resultCode = resultCode;
|
||||
this.errorMessage = serverErrorMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a default exception with a result code, a specified
|
||||
* string of additional information, a string containing
|
||||
* information passed back from the server, and the DN of the
|
||||
* closest matching entry, if the exception was thrown because
|
||||
* an entry could not be found (for example, if <CODE>cn=Babs Jensen,
|
||||
* ou=People, c=Airius.com</CODE> could not be found but
|
||||
* <CODE>ou=People, c=Airius.com</CODE> is a valid directory entry,
|
||||
* the "matched DN" is <CODE>ou=People, c=Airius.com</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* After you construct the <CODE>LDAPException</CODE> object,
|
||||
* the result code and messages will be accessible through the
|
||||
* following ways:
|
||||
* <P>
|
||||
* <UL>
|
||||
* <LI>This string of additional information appears if you
|
||||
* call the <CODE>toString()</CODE> method. <P>
|
||||
* <LI>The result code that you set is accessible through the
|
||||
* <CODE>getLDAPResultCode()</CODE> method. <P>
|
||||
* <LI>The string of server error information that you set
|
||||
* is accessible through the <CODE>getLDAPErrorMessage</CODE>
|
||||
* method. <P>
|
||||
* <LI>The matched DN that you set is accessible through the
|
||||
* <CODE>getMatchedDN</CODE> method.<P>
|
||||
* </UL>
|
||||
* <P>
|
||||
*
|
||||
* This form is used for higher-level LDAP operational errors.
|
||||
* @param message The additional error information.
|
||||
* @param resultCode The result code returned.
|
||||
* @param serverErrorMessage Error message specifying additional information
|
||||
* returned from the server.
|
||||
* @param matchedDN Maximal subset of a specified DN which could be
|
||||
* matched by the server.
|
||||
* @see netscape.ldap.LDAPException#toString()
|
||||
* @see netscape.ldap.LDAPException#getLDAPResultCode()
|
||||
* @see netscape.ldap.LDAPException#getLDAPErrorMessage()
|
||||
* @see netscape.ldap.LDAPException#getMatchedDN()
|
||||
*/
|
||||
public LDAPException( String message, int resultCode,
|
||||
String serverErrorMessage, String matchedDN ) {
|
||||
super( message );
|
||||
this.resultCode = resultCode;
|
||||
this.errorMessage = serverErrorMessage;
|
||||
this.matchedDN = matchedDN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result code from the last error that occurred.
|
||||
* This result code is defined as a public final static int member
|
||||
* of this class. Note that this value is not always valid.
|
||||
* -1 indicates that the result code is invalid.
|
||||
* @return The LDAP result code of the last operation.
|
||||
*/
|
||||
public int getLDAPResultCode () {
|
||||
return resultCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error message from the last error, if this message
|
||||
* is available (that is, if this message was set). If the message
|
||||
* was not set, this method returns <CODE>null</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* Note that this message is rarely set. (In order to set this message,
|
||||
* the code constructing this exception must have called the constructor
|
||||
* <CODE>LDAPException(String, int, String)</CODE>. The last argument,
|
||||
* which is additional error information returned from the server,
|
||||
* is the string returned by <CODE>getLDAPErrorMessage</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* In most cases, if you want information about
|
||||
* the error generated, you should call the <CODE>toString()</CODE>
|
||||
* method instead.
|
||||
* <P>
|
||||
*
|
||||
* @return The error message of the last error (or <CODE>null</CODE>
|
||||
* if no message was set).
|
||||
* @see netscape.ldap.LDAPException#toString()
|
||||
*/
|
||||
public String getLDAPErrorMessage () {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximal subset of a DN which could be matched by the
|
||||
* server, if the server returned one of the following errors:
|
||||
* <UL>
|
||||
* <LI><CODE>NO_SUCH_OBJECT</CODE>
|
||||
* <LI><CODE>ALIAS_PROBLEM</CODE>
|
||||
* <LI><CODE>INVALID_DN_SYNTAX</CODE>
|
||||
* <LI><CODE>ALIAS_DEREFERENCING_PROBLEM</CODE>
|
||||
* </UL>
|
||||
* </PRE>
|
||||
* For example, if the DN <CODE>cn=Babs Jensen, o=People, c=Airius.com</CODE>
|
||||
* could not be found by the DN <CODE>o=People, c=Airius.com</CODE>
|
||||
* could be found, the matched DN is
|
||||
* <CODE>o=People, c=Airius.com</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* If the exception does not specify a matching DN,
|
||||
* this method returns <CODE>null</CODE>.
|
||||
* @return The maximal subset of a DN which could be matched,
|
||||
* or <CODE>null</CODE> if the error is not one of the above.
|
||||
*/
|
||||
public String getMatchedDN () {
|
||||
return matchedDN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string representation of the exception, which
|
||||
* includes the result code, the message sent back from
|
||||
* the LDAP server, the portion of the DN that the server
|
||||
* could find in the directory (if applicable), and the
|
||||
* error message corresponding to this result code.
|
||||
* <P>
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* <PRE>netscape.ldap.LDAPException: error result (32); server error message; matchedDN = ou=people,o=airius.com; No such object</PRE>
|
||||
*
|
||||
* In this example, <CODE>error result</CODE> is the string of
|
||||
* additional information specified in the exception, <CODE>32</CODE> is
|
||||
* the result code, <CODE>server error message</CODE> is the additional
|
||||
* information from the server specified in the exception, the
|
||||
* matched DN is <CODE>ou=people,o=airius.com</CODE>, and the error message
|
||||
* corresponding to the result code <CODE>32</CODE> is <CODE>No such
|
||||
* object</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* The error message corresponding to the error code can also be
|
||||
* retrieved by using the <CODE>errorCodeToString</CODE> method.
|
||||
* Note that this method can generate error messages specific to
|
||||
* a current locale.
|
||||
* <P>
|
||||
*
|
||||
* @return String representation of exception
|
||||
* @see netscape.ldap.LDAPException#errorCodeToString(int)
|
||||
*/
|
||||
public String toString() {
|
||||
String str = super.toString() + " (" + resultCode + ")" ;
|
||||
if ( (errorMessage != null) && (errorMessage.length() > 0) )
|
||||
str += "; " + errorMessage;
|
||||
if ( (matchedDN != null) && (matchedDN.length() > 0) )
|
||||
str += "; matchedDN = " + matchedDN;
|
||||
String errorStr = null;
|
||||
if (((errorStr = errorCodeToString(m_locale)) != null) &&
|
||||
(errorStr.length() > 0))
|
||||
str += "; " + errorStr;
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error message describing the error code (for this
|
||||
* exception). The error message is specific to the default locale
|
||||
* for this system. (The LDAP Java classes determine the default
|
||||
* locale by calling the <CODE>java.util.Locale.getDefault</CODE>
|
||||
* method and retrieve the error messages from the following file:
|
||||
* <PRE>netscape/ldap/error/ErrorCodes_<I>locale_name</I>.props</PRE>
|
||||
* where <I>locale_name</I> is the language and country (concatenated
|
||||
* and delimited by an underscore) of the default locale. For example:
|
||||
* <PRE>netscape/ldap/error/ErrorCodes_en_US.props</PRE>
|
||||
*
|
||||
* @return The error message describing the error code for this
|
||||
* exception in the default locale
|
||||
*/
|
||||
public String errorCodeToString() {
|
||||
return errorCodeToString(resultCode, m_locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error message describing the error code for this
|
||||
* exception. The error message for the specified locale is retrieved
|
||||
* from the following file:
|
||||
* <PRE>netscape/ldap/error/ErrorCodes_<I>locale_name</I>.props</PRE>
|
||||
* where <I>locale_name</I> is the language and country (concatenated
|
||||
* and delimited by an underscore) of the default locale. For example:
|
||||
* <PRE>netscape/ldap/error/ErrorCodes_en_US.props</PRE>
|
||||
*
|
||||
* @param l The <CODE>java.util.Locale</CODE> object representing the
|
||||
* locale of the error message that you want to retrieve.
|
||||
* @return The error message describing the current error code
|
||||
* in the specified locale.
|
||||
*/
|
||||
public String errorCodeToString(Locale l) {
|
||||
return errorCodeToString(resultCode, l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error message describing the specified error code.
|
||||
* The error message is specific to the default locale
|
||||
* for this system. (The LDAP Java classes determine the default
|
||||
* locale by calling the <CODE>java.util.Locale.getDefault</CODE>
|
||||
* method and retrieve the error messages from the following file:
|
||||
* <PRE>netscape/ldap/error/ErrorCodes_<I>locale_name</I>.props</PRE>
|
||||
* where <I>locale_name</I> is the language and country (concatenated
|
||||
* and delimited by an underscore) of the default locale. For example:
|
||||
* <PRE>netscape/ldap/error/ErrorCodes_en_US.props</PRE>
|
||||
*
|
||||
* @param code The error code that you want to get the
|
||||
* corresponding error message for.
|
||||
* @return Error message describing the specified error code for
|
||||
* the default locale.
|
||||
*/
|
||||
public static String errorCodeToString(int code) {
|
||||
return errorCodeToString(code, Locale.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error message describing the specified error code.
|
||||
* The error message for the specified locale is retrieved from
|
||||
* the following file:
|
||||
* <PRE>netscape/ldap/error/ErrorCodes_<I>locale_name</I>.props</PRE>
|
||||
* where <I>locale_name</I> is the language and country (concatenated
|
||||
* and delimited by an underscore) of the default locale. For example:
|
||||
* <PRE>netscape/ldap/error/ErrorCodes_en_US.props</PRE>
|
||||
*
|
||||
* @param code The error code that you want to get the
|
||||
* corresponding error message for.
|
||||
* @param locale The <CODE>java.util.Locale</CODE> object representing the
|
||||
* locale of the error message that you want to retrieve.
|
||||
* @return Error message describing the specified error code for
|
||||
* the specified locale.
|
||||
*/
|
||||
public synchronized static String errorCodeToString(int code, Locale locale) {
|
||||
try {
|
||||
String localeStr = locale.toString();
|
||||
PropertyResourceBundle p =
|
||||
(PropertyResourceBundle)cacheResource.get(localeStr);
|
||||
|
||||
if (p == null) {
|
||||
p = LDAPResourceBundle.getBundle(baseName);
|
||||
|
||||
if (p != null)
|
||||
cacheResource.put(localeStr, p);
|
||||
}
|
||||
|
||||
if (p != null) {
|
||||
return (String)p.handleGetObject(Integer.toString(code));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.out.println("Cannot open resource file for LDAPException "+
|
||||
baseName);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
/**
|
||||
* Version 3 of the LDAP protocol include the means to define additional
|
||||
* operations ("extended operations") beyond the standard LDAP
|
||||
* operations. An LDAP v3 client can send an extended operation request,
|
||||
* identifying the operation by its unique object ID (OID). The server
|
||||
* receives the request and if OID corresponds to an operation supported
|
||||
* by the server, the server procoess the request and sends an extended
|
||||
* operation response back to the client.
|
||||
* <P>
|
||||
*
|
||||
* Objects of this class can be used to represent extended operation
|
||||
* requests (sent by your client) or extended operation responses
|
||||
* (returned by an LDAP v3 server).
|
||||
* <P>
|
||||
*
|
||||
* To determine which extended operations are supported by a server,
|
||||
* you need to search for the root DSE (DSA-specific entry, where DSA is
|
||||
* another term for "LDAP server") and find the values of the
|
||||
* <CODE>supportedExtension</CODE> attribute. This attribute contains the
|
||||
* object IDs (OIDs) of the extended operations supported by this server.
|
||||
* <P>
|
||||
*
|
||||
* The following section of code demonstrates how to get the list
|
||||
* of the extended operations supported by an LDAP server.
|
||||
* <P>
|
||||
*
|
||||
* <PRE>
|
||||
* public static void main( String[] args )
|
||||
* {
|
||||
* LDAPConnection ld = new LDAPConnection();
|
||||
* try {
|
||||
* String MY_HOST = "localhost";
|
||||
* int MY_PORT = 389;
|
||||
* ld.connect( MY_HOST, MY_PORT );
|
||||
* try {
|
||||
* ld.authenticate( 3, "cn=Directory Manager", "23skidoo" );
|
||||
* } catch( LDAPException e ) {
|
||||
* System.out.println( "LDAP server does not support v3." );
|
||||
* ld.disconnect();
|
||||
* System.exit(1);
|
||||
* }
|
||||
*
|
||||
* String MY_FILT = "(objectclass=*)";
|
||||
* String MY_BASE = "";
|
||||
* String getAttrs[] = { "supportedExtension" };
|
||||
* LDAPSearchResults res = ld.search( MY_BASE,
|
||||
* LDAPConnection.SCOPE_BASE, MY_FILT, getAttrs, false );
|
||||
*
|
||||
* while ( res.hasMoreElements() ) {
|
||||
* LDAPEntry findEntry = (LDAPEntry)res.nextElement();
|
||||
* LDAPAttributeSet findAttrs = findEntry.getAttributeSet();
|
||||
* Enumeration enumAttrs = findAttrs.getAttributes();
|
||||
*
|
||||
* while ( enumAttrs.hasMoreElements() ) {
|
||||
* LDAPAttribute anAttr = (LDAPAttribute)enumAttrs.nextElement();
|
||||
* String attrName = anAttr.getName();
|
||||
* System.out.println( attrName );
|
||||
* Enumeration enumVals = anAttr.getStringValues();
|
||||
*
|
||||
* while ( enumVals.hasMoreElements() ) {
|
||||
* String aVal = ( String )enumVals.nextElement();
|
||||
* System.out.println( "\t" + aVal );
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* catch( LDAPException e ) {
|
||||
* System.out.println( "Error: " + e.toString() );
|
||||
* }
|
||||
* try {
|
||||
* ld.disconnect();
|
||||
* }
|
||||
* catch( LDAPException e ) {
|
||||
* System.exit(1);
|
||||
* }
|
||||
* System.exit(0);
|
||||
* }
|
||||
* </PRE>
|
||||
* <P>
|
||||
*
|
||||
* If you compile and run this example against an LDAP server that
|
||||
* supports v3 of the protocol, you might receive the following results:
|
||||
* <P>
|
||||
*
|
||||
* <PRE>
|
||||
* supportedextension
|
||||
* 1.2.3.4
|
||||
* </PRE>
|
||||
* <P>
|
||||
*
|
||||
* For more information on LDAP controls, see the Internet-Draft on
|
||||
* the LDAP v3 protocol. (Note that this internet draft is still a
|
||||
* work in progress. You can find the latest draft at the <A
|
||||
* HREF="http://www.ietf.cnri.reston.va.us/html.charters/asid-charter.html"
|
||||
* TARGET="_blank">ASID home page</A>.
|
||||
* <P>
|
||||
*
|
||||
* @version 1.0
|
||||
* @see netscape.ldap.LDAPConnection#extendedOperation(netscape.ldap.LDAPExtendedOperation)
|
||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean)
|
||||
*
|
||||
*/
|
||||
public class LDAPExtendedOperation {
|
||||
|
||||
/**
|
||||
* Construct an object
|
||||
* @param oid Identifier for the particular operation.
|
||||
* @param vals Operation-specific data.
|
||||
*/
|
||||
public LDAPExtendedOperation( String oid, byte[] vals ) {
|
||||
m_oid = oid;
|
||||
m_vals = vals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the identifier for this operation.
|
||||
* @return oid Identifier for the particular operation.
|
||||
*/
|
||||
public String getID() {
|
||||
return m_oid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data for this operation.
|
||||
* @return vals Operation-specific data.
|
||||
*/
|
||||
public byte[] getValue() {
|
||||
return m_vals;
|
||||
}
|
||||
|
||||
private String m_oid;
|
||||
private byte[] m_vals;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import netscape.ldap.client.opers.JDAPExtendedResponse;
|
||||
|
||||
/**
|
||||
* Represents a server response to an extended operation request.
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LDAPExtendedResponse extends LDAPResponse {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param msgid message identifier
|
||||
* @param rsp Extended operation response
|
||||
* @paarm controls Array of controls of null
|
||||
*/
|
||||
LDAPExtendedResponse(int msgid, JDAPExtendedResponse rsp, LDAPControl controls[]) {
|
||||
super(msgid, rsp, controls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the OID of the response.
|
||||
*
|
||||
* @return The response OID
|
||||
*/
|
||||
public String getOID() {
|
||||
JDAPExtendedResponse result = (JDAPExtendedResponse)getProtocolOp();
|
||||
return result.getID();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw bytes of the value part of the response.
|
||||
*
|
||||
* @return Response as a raw array of bytes
|
||||
*/
|
||||
public byte[] getValue() {
|
||||
JDAPExtendedResponse result = (JDAPExtendedResponse)getProtocolOp();
|
||||
return result.getValue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
/**
|
||||
* An exception thrown when the LDAP operation being invoked has
|
||||
* been interrupted. For example, an application might interrupt a thread that
|
||||
* is performing a search.
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LDAPInterruptedException extends LDAPException {
|
||||
|
||||
/**
|
||||
* Constructs a default exception with a specified string of
|
||||
* additional information. This string appears if you call
|
||||
* the <CODE>toString()</CODE> method.
|
||||
* <P>
|
||||
*
|
||||
* @param message The additional information.
|
||||
* @see netscape.ldap.LDAPInterruptedException#toString()
|
||||
*/
|
||||
LDAPInterruptedException( String message ) {
|
||||
super( message, LDAPException.OTHER, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string representation of the exception.
|
||||
*/
|
||||
public String toString() {
|
||||
String str = "netscape.ldap.LDAPInterruptedException: ";
|
||||
String msg = super.getMessage();
|
||||
if (msg != null) {
|
||||
str +=msg;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,298 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* The definition of a matching rule in the schema.
|
||||
* <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
|
||||
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
|
||||
* Attribute Syntax Definitions</A> covers the types of information
|
||||
* that need to be specified in the definition of a matching rule.
|
||||
* According to the RFC, the description of a matching rule can
|
||||
* include the following information:
|
||||
* <P>
|
||||
*
|
||||
* <UL>
|
||||
* <LI>an OID identifying the matching rule
|
||||
* <LI>a name identifying the matching rule
|
||||
* <LI>a description of the matching rule
|
||||
* <LI>the syntax of the matching rule
|
||||
* </UL>
|
||||
* <P>
|
||||
*
|
||||
* The <CODE>LDAPMatchingRuleSchema</CODE> class also specifies
|
||||
* the matching rule "use description", which describes the
|
||||
* attributes which can be used with the matching rule.
|
||||
* <P>
|
||||
*
|
||||
* When you construct an <CODE>LDAPMatchingRuleSchema</CODE> object, you can
|
||||
* specify these types of information as arguments to the constructor or
|
||||
* in the MatchingRuleDescription and MatchingRuleUseDescription formats
|
||||
* specified in RFC 2252.
|
||||
* When an LDAP client searches an LDAP server for the schema, the server
|
||||
* returns schema information as an object with attribute values in this
|
||||
* format.
|
||||
* <P>
|
||||
*
|
||||
* You can get the name, OID, and description of this matching rule
|
||||
* definition by using the <CODE>getName</CODE>, <CODE>getOID</CODE>, and
|
||||
* <CODE>getDescription</CODE> methods inherited from the abstract class
|
||||
* <CODE>LDAPSchemaElement</CODE>. Custom qualifiers are
|
||||
* accessed with <CODE>getQualifier</CODE> and <CODE>getQualifierNames</CODE>
|
||||
* from <CODE>LDAPSchemaElement</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* To add or remove this matching rule definition from the
|
||||
* schema, use the <CODE>add</CODE> and <CODE>remove</CODE>
|
||||
* methods, which this class inherits from the <CODE>LDAPSchemaElement</CODE>
|
||||
* abstract class.
|
||||
* <P>
|
||||
* RFC 2252 defines MatchingRuleDescription and MatchingRuleUseDescription
|
||||
* as follows:
|
||||
* <P>
|
||||
* MatchingRuleDescription = "(" whsp
|
||||
* numericoid whsp ; MatchingRule identifier
|
||||
* [ "NAME" qdescrs ]
|
||||
* [ "DESC" qdstring ]
|
||||
* [ "OBSOLETE" whsp ]
|
||||
* "SYNTAX" numericoid
|
||||
* whsp ")"
|
||||
*
|
||||
* Values of the matchingRuleUse list the attributes which are suitable
|
||||
* for use with an extensible matching rule.
|
||||
*
|
||||
* MatchingRuleUseDescription = "(" whsp
|
||||
* numericoid whsp ; MatchingRule identifier
|
||||
* [ "NAME" qdescrs ]
|
||||
* [ "DESC" qdstring ]
|
||||
* [ "OBSOLETE" ]
|
||||
* "APPLIES" oids ; AttributeType identifiers
|
||||
* whsp ")" * <PRE>
|
||||
* </PRE>
|
||||
* <P>
|
||||
* <CODE>LDAPMatchingRuleSchema</CODE> abstracts away from the two types and
|
||||
* manages their relationships transparently.
|
||||
*
|
||||
* @version 1.0
|
||||
* @see netscape.ldap.LDAPSchemaElement
|
||||
**/
|
||||
|
||||
public class LDAPMatchingRuleSchema extends LDAPAttributeSchema {
|
||||
/**
|
||||
* Construct a matching rule definition, using the specified
|
||||
* information.
|
||||
* @param name Name of the matching rule.
|
||||
* @param oid Object identifier (OID) of the matching rule
|
||||
* in dotted-string format (for example, "1.2.3.4").
|
||||
* @param description Description of the matching rule.
|
||||
* @param attributes Array of the OIDs of the attributes for which
|
||||
* the matching rule is applicable.
|
||||
* @param syntax Syntax of this matching rule. The value of this
|
||||
* argument can be one of the following:
|
||||
* <UL>
|
||||
* <LI><CODE>cis</CODE> (case-insensitive string)
|
||||
* <LI><CODE>ces</CODE> (case-exact string)
|
||||
* <LI><CODE>binary</CODE> (binary data)
|
||||
* <LI><CODE>int</CODE> (integer)
|
||||
* <LI><CODE>telephone</CODE> (telephone number -- identical to cis,
|
||||
* but blanks and dashes are ignored during comparisons)
|
||||
* <LI><CODE>dn</CODE> (distinguished name)
|
||||
* </UL>
|
||||
*/
|
||||
public LDAPMatchingRuleSchema( String name, String oid, String description,
|
||||
String[] attributes, int syntax ) {
|
||||
super( name, oid, description, syntax, true );
|
||||
attrName = "matchingrules";
|
||||
this.attributes = new String[attributes.length];
|
||||
for( int i = 0; i < attributes.length; i++ )
|
||||
this.attributes[i] = new String( attributes[i] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a matching rule definition based on descriptions in
|
||||
* the MatchingRuleDescription format and MatchingRuleUseDescription
|
||||
* format. For information on this format,
|
||||
* (see <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
|
||||
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
|
||||
* Attribute Syntax Definitions</A>. This is the format that LDAP servers
|
||||
* and clients use to exchange schema information. For example, when
|
||||
* you search an LDAP server for its schema, the server returns an entry
|
||||
* with attributes that include "matchingrule" and "matchingruleuse".
|
||||
* The values of these attributes are matching rule descriptions
|
||||
* in this format.
|
||||
* <P>
|
||||
*
|
||||
* @param raw Definition of the matching rule in the
|
||||
* MatchingRuleDescription format.
|
||||
* @param use Definition of the use of the matching rule in the
|
||||
* MatchingRuleUseDescription format.
|
||||
*/
|
||||
public LDAPMatchingRuleSchema( String raw, String use ) {
|
||||
attrName = "matchingrules";
|
||||
parseValue( raw );
|
||||
if ( use != null ) {
|
||||
parseValue( use );
|
||||
}
|
||||
Vector v = (Vector)properties.get( "APPLIES" );
|
||||
if ( v != null ) {
|
||||
attributes = new String[v.size()];
|
||||
v.copyInto( attributes );
|
||||
v.removeAllElements();
|
||||
}
|
||||
String val = (String)properties.get( "SYNTAX" );
|
||||
if ( val != null ) {
|
||||
syntaxString = val;
|
||||
syntax = syntaxCheck( val );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of the OIDs of the attribute types which can be used
|
||||
* with the matching rule. The list is a deep copy.
|
||||
* @return Array of the OIDs of the attribute types which can be used
|
||||
* with the matching rule.
|
||||
*/
|
||||
public String[] getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
String getValue( boolean quotingBug ) {
|
||||
String s = getValuePrefix();
|
||||
s += "SYNTAX ";
|
||||
if ( quotingBug ) {
|
||||
s += '\'';
|
||||
}
|
||||
s += syntaxString;
|
||||
if ( quotingBug ) {
|
||||
s += '\'';
|
||||
}
|
||||
s += ' ';
|
||||
String val = getCustomValues();
|
||||
if ( val.length() > 0 ) {
|
||||
s += val + ' ';
|
||||
}
|
||||
s += ')';
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the matching rule definition in the string representation
|
||||
* of the MatchingRuleDescription data type defined in X.501 (see
|
||||
* <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
|
||||
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol
|
||||
* (v3): Attribute Syntax Definitions</A>
|
||||
* for a description of these formats).
|
||||
* This is the format that LDAP servers and clients use to exchange
|
||||
* schema information. (For example, when
|
||||
* you search an LDAP server for its schema, the server returns an entry
|
||||
* with the attributes "matchingrules" and "matchingruleuse". The
|
||||
* values of these attributes are matching rule description and
|
||||
* matching rule use description in these formats.)
|
||||
* <P>
|
||||
*
|
||||
* @return A string in a format that can be used as the value of
|
||||
* the <CODE>matchingrule</CODE> attribute (which describes
|
||||
* a matching rule in the schema) of a <CODE>subschema</CODE> object.
|
||||
*/
|
||||
public String getValue() {
|
||||
return getValue( false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the matching rule use definition in the string representation
|
||||
* of the MatchingRuleUseDescription data type defined in X.501 (see
|
||||
* <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
|
||||
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol
|
||||
* (v3): Attribute Syntax Definitions</A>
|
||||
* for a description of these formats).
|
||||
* This is the format that LDAP servers and clients use to exchange
|
||||
* schema information. (For example, when
|
||||
* you search an LDAP server for its schema, the server returns an entry
|
||||
* with the attributes "matchingrules" and "matchingruleuse". The
|
||||
* values of these attributes are matching rule description and
|
||||
* matching rule use description in these formats.)
|
||||
* <P>
|
||||
*
|
||||
* @return A string in a format that can be used as the value of
|
||||
* the <CODE>matchingruleuse</CODE> attribute (which describes the use of
|
||||
* a matching rule in the schema) of a <CODE>subschema</CODE> object.
|
||||
*/
|
||||
public String getUseValue() {
|
||||
String s = getValuePrefix();
|
||||
s += "APPLIES ( ";
|
||||
for( int i = 0; i < attributes.length; i++ ) {
|
||||
if ( i > 0 )
|
||||
s += " $ ";
|
||||
s += attributes[i];
|
||||
}
|
||||
s += ") ";
|
||||
String val = getCustomValues();
|
||||
if ( val.length() > 0 ) {
|
||||
s += val + ' ';
|
||||
}
|
||||
s += ')';
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add, remove or modify the definition from a Directory.
|
||||
* @param ld An open connection to a Directory Server. Typically the
|
||||
* connection must have been authenticated to add a definition.
|
||||
* @param op Type of modification to make.
|
||||
* @param name Name of attribute in the schema entry to modify. This
|
||||
* is ignored here.
|
||||
* @param dn The entry at which to update the schema.
|
||||
* @exception LDAPException if the definition can't be added/removed.
|
||||
*/
|
||||
protected void update( LDAPConnection ld, int op, String name, String dn )
|
||||
throws LDAPException {
|
||||
LDAPAttribute[] attrs = new LDAPAttribute[2];
|
||||
attrs[0] = new LDAPAttribute( "matchingRules",
|
||||
getValue() );
|
||||
/* Must update the matchingRuleUse value as well */
|
||||
attrs[1] = new LDAPAttribute( "matchingRuleUse",
|
||||
getUseValue() );
|
||||
update( ld, op, attrs, dn );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the definition of the matching rule in a user friendly format.
|
||||
* This is the format that the matching rule definition uses when
|
||||
* you print the matching rule or the schema.
|
||||
* @return Definition of the matching rule in a user friendly format.
|
||||
*/
|
||||
public String toString() {
|
||||
String s = "Name: " + name + "; OID: " + oid + "; Type: ";
|
||||
s += syntaxToString();
|
||||
s += "; Description: " + description;
|
||||
if ( attributes != null ) {
|
||||
s += "; Applies to: ";
|
||||
for( int i = 0; i < attributes.length; i++ ) {
|
||||
if ( i > 0 )
|
||||
s += ", ";
|
||||
s += attributes[i];
|
||||
}
|
||||
}
|
||||
s += getQualifierString( EXPLICIT );
|
||||
return s;
|
||||
}
|
||||
|
||||
private String[] attributes = null;
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import netscape.ldap.client.opers.*;
|
||||
import netscape.ldap.ber.stream.*;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
/**
|
||||
* Base class for LDAP request and response messages.
|
||||
* This class represents the LDAPMessage in RFC2251. The
|
||||
* message is the entity that got transferred back and
|
||||
* fro between the server and the client interface. Each
|
||||
* message has a protocol operation. The protocol operation
|
||||
* indicates if it is a request or response.
|
||||
* <pre>
|
||||
* LDAPMessage ::= SEQUENCE {
|
||||
* messageID MessageID,
|
||||
* protocolOp CHOICE {
|
||||
* bindRequest BindRequest,
|
||||
* ...
|
||||
* }
|
||||
* controls [0] Controls OPTIONAL
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LDAPMessage {
|
||||
|
||||
public final static int BIND_REQUEST = 0;
|
||||
public final static int BIND_RESPONSE = 1;
|
||||
public final static int UNBIND_REQUEST = 2;
|
||||
public final static int SEARCH_REQUEST = 3;
|
||||
public final static int SEARCH_RESPONSE = 4;
|
||||
public final static int SEARCH_RESULT = 5;
|
||||
public final static int MODIFY_REQUEST = 6;
|
||||
public final static int MODIFY_RESPONSE = 7;
|
||||
public final static int ADD_REQUEST = 8;
|
||||
public final static int ADD_RESPONSE = 9;
|
||||
public final static int DEL_REQUEST = 10;
|
||||
public final static int DEL_RESPONSE = 11;
|
||||
public final static int MODIFY_RDN_REQUEST = 12;
|
||||
public final static int MODIFY_RDN_RESPONSE = 13;
|
||||
public final static int COMPARE_REQUEST = 14;
|
||||
public final static int COMPARE_RESPONSE = 15;
|
||||
public final static int ABANDON_REQUEST = 16;
|
||||
public final static int SEARCH_RESULT_REFERENCE = 19;
|
||||
public final static int EXTENDED_REQUEST = 23;
|
||||
public final static int EXTENDED_RESPONSE = 24;
|
||||
|
||||
/**
|
||||
* Internal variables
|
||||
*/
|
||||
private int m_msgid;
|
||||
private JDAPProtocolOp m_protocolOp = null;
|
||||
private LDAPControl m_controls[] = null;
|
||||
|
||||
/**
|
||||
* Constructs a ldap message.
|
||||
* @param msgid message identifier
|
||||
* @param op operation protocol
|
||||
*/
|
||||
LDAPMessage(int msgid, JDAPProtocolOp op) {
|
||||
m_msgid = msgid;
|
||||
m_protocolOp = op;
|
||||
}
|
||||
|
||||
LDAPMessage(int msgid, JDAPProtocolOp op, LDAPControl controls[]) {
|
||||
m_msgid = msgid;
|
||||
m_protocolOp = op;
|
||||
m_controls = controls; /* LDAPv3 additions */
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ldap message from a BERElement. This method is used
|
||||
* to parse LDAP response messages
|
||||
*
|
||||
* @param element ber element constructed from incoming byte stream
|
||||
*/
|
||||
static LDAPMessage parseMessage(BERElement element) throws IOException {
|
||||
int l_msgid;
|
||||
JDAPProtocolOp l_protocolOp = null;
|
||||
LDAPControl l_controls[] = null;
|
||||
|
||||
if (element.getType() != BERElement.SEQUENCE)
|
||||
throw new IOException("SEQUENCE in jdap message expected");
|
||||
BERSequence seq = (BERSequence)element;
|
||||
BERInteger msgid = (BERInteger)seq.elementAt(0);
|
||||
l_msgid = msgid.getValue();
|
||||
BERElement protocolOp = (BERElement)seq.elementAt(1);
|
||||
if (protocolOp.getType() != BERElement.TAG) {
|
||||
throw new IOException("TAG in protocol operation is expected");
|
||||
}
|
||||
BERTag tag = (BERTag)protocolOp;
|
||||
switch (tag.getTag()&0x1f) {
|
||||
case JDAPProtocolOp.BIND_RESPONSE:
|
||||
l_protocolOp = new JDAPBindResponse(protocolOp);
|
||||
break;
|
||||
case JDAPProtocolOp.SEARCH_RESPONSE:
|
||||
l_protocolOp = new JDAPSearchResponse(protocolOp);
|
||||
break;
|
||||
/*
|
||||
* If doing search without bind,
|
||||
* x500.arc.nasa.gov returns tag SEARCH_REQUEST tag
|
||||
* in SEARCH_RESULT.
|
||||
*/
|
||||
case JDAPProtocolOp.SEARCH_REQUEST:
|
||||
case JDAPProtocolOp.SEARCH_RESULT:
|
||||
l_protocolOp = new JDAPSearchResult(protocolOp);
|
||||
break;
|
||||
case JDAPProtocolOp.MODIFY_RESPONSE:
|
||||
l_protocolOp = new JDAPModifyResponse(protocolOp);
|
||||
break;
|
||||
case JDAPProtocolOp.ADD_RESPONSE:
|
||||
l_protocolOp = new JDAPAddResponse(protocolOp);
|
||||
break;
|
||||
case JDAPProtocolOp.DEL_RESPONSE:
|
||||
l_protocolOp = new JDAPDeleteResponse(protocolOp);
|
||||
break;
|
||||
case JDAPProtocolOp.MODIFY_RDN_RESPONSE:
|
||||
l_protocolOp = new JDAPModifyRDNResponse(protocolOp);
|
||||
break;
|
||||
case JDAPProtocolOp.COMPARE_RESPONSE:
|
||||
l_protocolOp = new JDAPCompareResponse(protocolOp);
|
||||
break;
|
||||
case JDAPProtocolOp.SEARCH_RESULT_REFERENCE:
|
||||
l_protocolOp = new JDAPSearchResultReference(protocolOp);
|
||||
break;
|
||||
case JDAPProtocolOp.EXTENDED_RESPONSE:
|
||||
l_protocolOp = new JDAPExtendedResponse(protocolOp);
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Unknown protocol operation");
|
||||
}
|
||||
|
||||
/* parse control */
|
||||
if (seq.size() >= 3) {
|
||||
tag = (BERTag)seq.elementAt(2);
|
||||
if ( tag.getTag() == (BERTag.CONSTRUCTED|BERTag.CONTEXT|0) ) {
|
||||
BERSequence controls = (BERSequence)tag.getValue();
|
||||
l_controls = new LDAPControl[controls.size()];
|
||||
for (int i = 0; i < controls.size(); i++) {
|
||||
l_controls[i] = LDAPControl.parseControl(controls.elementAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (l_protocolOp instanceof JDAPSearchResponse) {
|
||||
return new LDAPSearchResult(l_msgid,
|
||||
(JDAPSearchResponse) l_protocolOp, l_controls);
|
||||
}
|
||||
else if (l_protocolOp instanceof JDAPSearchResultReference) {
|
||||
return new LDAPSearchResultReference(l_msgid,
|
||||
(JDAPSearchResultReference) l_protocolOp, l_controls);
|
||||
}
|
||||
else if (l_protocolOp instanceof JDAPExtendedResponse) {
|
||||
return new LDAPExtendedResponse(l_msgid,
|
||||
(JDAPExtendedResponse) l_protocolOp, l_controls);
|
||||
}
|
||||
else {
|
||||
return new LDAPResponse(l_msgid, l_protocolOp, l_controls);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message identifer.
|
||||
* @return message identifer
|
||||
*/
|
||||
public int getId(){
|
||||
return m_msgid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the LDAP operation type of the message
|
||||
* @return message type
|
||||
*/
|
||||
public int getType(){
|
||||
return m_protocolOp.getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the protocol operation.
|
||||
* @return protocol operation
|
||||
*/
|
||||
JDAPProtocolOp getProtocolOp() {
|
||||
return m_protocolOp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves list of controls.
|
||||
* @return controls
|
||||
*/
|
||||
public LDAPControl[] getControls() {
|
||||
return m_controls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the ber encoding to stream.
|
||||
* @param s output stream
|
||||
*/
|
||||
void write(OutputStream s) throws IOException {
|
||||
BERSequence seq = new BERSequence();
|
||||
BERInteger i = new BERInteger(m_msgid);
|
||||
seq.addElement(i);
|
||||
BERElement e = m_protocolOp.getBERElement();
|
||||
if (e == null) {
|
||||
throw new IOException("Bad BER element");
|
||||
}
|
||||
seq.addElement(e);
|
||||
if (m_controls != null) { /* LDAPv3 additions */
|
||||
BERSequence c = new BERSequence();
|
||||
for (int j = 0; j < m_controls.length; j++) {
|
||||
c.addElement(m_controls[j].getBERElement());
|
||||
}
|
||||
BERTag t = new BERTag(BERTag.CONTEXT|BERTag.CONSTRUCTED|0, c, true);
|
||||
seq.addElement(t);
|
||||
}
|
||||
seq.write(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns string representation of a ldap message.
|
||||
* @return ldap message
|
||||
*/
|
||||
public String toString() {
|
||||
if (m_controls == null) {
|
||||
return "[LDAPMessage] " + m_msgid + " " + m_protocolOp.toString();
|
||||
}
|
||||
else {
|
||||
StringBuffer sb = new StringBuffer(
|
||||
"[LDAPMessage] " + m_msgid + " " + m_protocolOp.toString());
|
||||
for (int i =0; i < m_controls.length; i++) {
|
||||
sb.append(" ctrl"+i+"=");
|
||||
sb.append(m_controls[i].toString());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,428 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* A queue of response messsages from the server. Multiple requests
|
||||
* can be multiplexed on the same queue. For synchronous LDAPConnection
|
||||
* requests, there will be only one request per queue. For asynchronous
|
||||
* LDAPConnection requests, the user can add multiple request to the
|
||||
* same queue.
|
||||
*
|
||||
* Superclass for LDAResponseListener and LDAPSearchListener
|
||||
*
|
||||
*/
|
||||
class LDAPMessageQueue {
|
||||
|
||||
/**
|
||||
* Request entry encapsulates request parameters
|
||||
*/
|
||||
private static class RequestEntry {
|
||||
int id;
|
||||
LDAPConnection connection;
|
||||
LDAPConnThread connThread;
|
||||
|
||||
RequestEntry(int id, LDAPConnection connection, LDAPConnThread connThread) {
|
||||
this.id= id;
|
||||
this.connection = connection;
|
||||
this.connThread = connThread;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal variables
|
||||
*/
|
||||
private /*LDAPMessage */ Vector m_messageQueue = new Vector(1);
|
||||
private /*RequestEntry*/ Vector m_requestList = new Vector(1);
|
||||
private LDAPException m_exception; /* For network errors */
|
||||
private boolean m_asynchOp;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param asynchOp A flag whether the object is used for asynchronous
|
||||
* LDAP operations
|
||||
* @see netscape.ldap.LDAPAsynchronousConnection
|
||||
*/
|
||||
LDAPMessageQueue (boolean asynchOp) {
|
||||
m_asynchOp = asynchOp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a flag whether the listener is used for asynchronous LDAP
|
||||
* operations
|
||||
* @return Asynchronous operation flag
|
||||
* @see netscape.ldap.LDAPAsynchronousConnection
|
||||
*/
|
||||
boolean isAsynchOp() {
|
||||
return m_asynchOp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocks until a response is available or until all operations
|
||||
* associated with the object have completed or been canceled.
|
||||
* @return LDAP message or null if there is no more outstanding requests
|
||||
* @exception LDAPException Network error exception
|
||||
* @exception LDAPInterruptedException The invoking thread was interrupted
|
||||
*/
|
||||
synchronized LDAPMessage nextMessage () throws LDAPException {
|
||||
|
||||
while(m_requestList.size() != 0 && m_exception == null && m_messageQueue.size() == 0) {
|
||||
try {
|
||||
wait ();
|
||||
} catch (InterruptedException e) {
|
||||
throw new LDAPInterruptedException("Interrupted LDAP operation");
|
||||
}
|
||||
}
|
||||
|
||||
// Network exception occurred ?
|
||||
if (m_exception != null) {
|
||||
LDAPException ex = m_exception;
|
||||
m_exception = null;
|
||||
throw ex;
|
||||
}
|
||||
|
||||
// Are there any outstanding requests left
|
||||
if (m_requestList.size() == 0) {
|
||||
return null; // No outstanding requests
|
||||
}
|
||||
|
||||
// Dequeue the first entry
|
||||
LDAPMessage msg = (LDAPMessage) m_messageQueue.elementAt(0);
|
||||
m_messageQueue.removeElementAt(0);
|
||||
|
||||
// Is the ldap operation completed?
|
||||
if (msg instanceof LDAPResponse) {
|
||||
removeRequest(msg.getId());
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for request to complete. This method blocks until a message of
|
||||
* type LDAPResponse has been received. Used by synchronous search
|
||||
* with batch size of zero (block until all results are received)
|
||||
* @return LDAPResponse message or null if there is no more outstanding requests
|
||||
* @exception LDAPException Network error exception
|
||||
* @exception LDAPInterruptedException The invoking thread was interrupted
|
||||
*/
|
||||
synchronized LDAPResponse completeRequest () throws LDAPException {
|
||||
|
||||
while (true) {
|
||||
while(m_requestList.size() != 0 && m_exception == null && m_messageQueue.size() == 0) {
|
||||
try {
|
||||
wait ();
|
||||
} catch (InterruptedException e) {
|
||||
throw new LDAPInterruptedException("Interrupted LDAP operation");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Network exception occurred ?
|
||||
if (m_exception != null) {
|
||||
LDAPException ex = m_exception;
|
||||
m_exception = null;
|
||||
throw ex;
|
||||
}
|
||||
|
||||
// Are there any outstanding requests left?
|
||||
if (m_requestList.size() == 0) {
|
||||
return null; // No outstanding requests
|
||||
}
|
||||
|
||||
// Search an instance of LDAPResponse
|
||||
for (int i= m_messageQueue.size()-1; i >=0; i--) {
|
||||
LDAPMessage msg = (LDAPMessage) m_messageQueue.elementAt(i);
|
||||
if (msg instanceof LDAPResponse) {
|
||||
|
||||
// Dequeue the entry and return
|
||||
m_messageQueue.removeElementAt(i);
|
||||
return (LDAPResponse)msg;
|
||||
}
|
||||
}
|
||||
|
||||
// Not found, wait for the next message
|
||||
try {
|
||||
wait ();
|
||||
} catch (InterruptedException e) {
|
||||
throw new LDAPInterruptedException("Interrupted LDAP operation");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge two message queues.
|
||||
* Move/append the content from another message queue to this one.
|
||||
*
|
||||
* To be used for synchronization of asynchronous LDAP operations where
|
||||
* requests are sent by one thread but processed by another one
|
||||
*
|
||||
* A client may be implemented in such a way that one thread makes LDAP
|
||||
* requests and calls l.getIDs(), while another thread is responsible for
|
||||
* processing of responses (call l.getResponse()). Both threads are using
|
||||
* the same listener objects. In such a case, a race
|
||||
* condition may occur, where a LDAP response message is retrieved and
|
||||
* the request terminated (request ID removed) before the first thread
|
||||
* has a chance to execute l.getIDs().
|
||||
* The proper way to handle this scenario is to create a separate listener
|
||||
* for each new request, and after l.getIDs() has been invoked, merge the
|
||||
* new request with the existing one.
|
||||
* @param mq2 Message queue to be merged with this one.
|
||||
*/
|
||||
synchronized void merge(LDAPMessageQueue mq2) {
|
||||
synchronized (mq2) {
|
||||
for (int i=0; i < mq2.m_requestList.size(); i++) {
|
||||
m_requestList.addElement(mq2.m_requestList.elementAt(i));
|
||||
}
|
||||
for (int i=0; i < mq2.m_messageQueue.size(); i++) {
|
||||
m_messageQueue.addElement(mq2.m_messageQueue.elementAt(i));
|
||||
}
|
||||
if (mq2.m_exception != null) {
|
||||
m_exception = mq2.m_exception;
|
||||
}
|
||||
|
||||
mq2.reset();
|
||||
notifyAll(); // notify for mq2
|
||||
}
|
||||
notifyAll(); // notify this mq
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves all messages currently in the queue without blocking
|
||||
* @returns Vector of messages
|
||||
*/
|
||||
synchronized Vector getAllMessages() {
|
||||
Vector result = m_messageQueue;
|
||||
m_messageQueue = new Vector(1);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues the LDAP server's response. This causes anyone waiting
|
||||
* in nextMessage() to unblock.
|
||||
* @param msg response message
|
||||
*/
|
||||
synchronized void addMessage (LDAPMessage msg) {
|
||||
m_messageQueue.addElement(msg);
|
||||
notifyAll ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals that a network exception occured while servicing the
|
||||
* request. This exception will be throw to any thread waiting
|
||||
* in nextMessage()
|
||||
* @param connThread LDAPConnThread on which the exception occurred
|
||||
* @param e exception
|
||||
*/
|
||||
synchronized void setException (LDAPConnThread connThread, LDAPException e) {
|
||||
m_exception = e;
|
||||
removeAllRequests(connThread);
|
||||
notifyAll ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if response message is received.
|
||||
* @return true or false
|
||||
*/
|
||||
boolean isMessageReceived() {
|
||||
return m_messageQueue.size() != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the count of queued messages
|
||||
* @return message count
|
||||
*/
|
||||
public int getMessageCount () {
|
||||
return m_messageQueue.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all queued messages associated with the request ID
|
||||
* Called when a LDAP operation is abandoned
|
||||
*
|
||||
* Not synchronized as its private and can be called only by
|
||||
* abandon() and removeAllRequests()
|
||||
*
|
||||
* @return Count of removed messages
|
||||
*/
|
||||
private int removeAllMessages(int id) {
|
||||
int removeCount=0;
|
||||
for (int i=(m_messageQueue.size()-1); i>=0; i--) {
|
||||
LDAPMessage msg = (LDAPMessage)m_messageQueue.elementAt(i);
|
||||
if (msg.getId() == id) {
|
||||
m_messageQueue.removeElementAt(i);
|
||||
removeCount++;
|
||||
}
|
||||
}
|
||||
return removeCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the state of this object, so it can be recycled.
|
||||
* Used by LDAPConnection synchronous operations.
|
||||
* @see netscape.ldap.LDAPConnection#getResponseListener
|
||||
* @see netscape.ldap.LDAPConnection#getSearchListener
|
||||
*/
|
||||
void reset () {
|
||||
m_exception = null;
|
||||
m_messageQueue.removeAllElements();
|
||||
m_requestList.removeAllElements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the connection associated with the specified request id
|
||||
* @parm id request id
|
||||
* @return connection
|
||||
*/
|
||||
synchronized LDAPConnection getConnection(int id) {
|
||||
for (int i=0; i < m_requestList.size(); i++) {
|
||||
RequestEntry entry = (RequestEntry)m_requestList.elementAt(i);
|
||||
if (id == entry.id) {
|
||||
return entry.connection;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the connection thread associated with the specified request id
|
||||
* @parm id request id
|
||||
* @return connection thread
|
||||
*/
|
||||
synchronized LDAPConnThread getConnThread(int id) {
|
||||
for (int i=0; i < m_requestList.size(); i++) {
|
||||
RequestEntry entry = (RequestEntry)m_requestList.elementAt(i);
|
||||
if (id == entry.id) {
|
||||
return entry.connThread;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns message id of the last request
|
||||
* @return Message id.
|
||||
*/
|
||||
synchronized int getID() {
|
||||
int reqCnt = m_requestList.size();
|
||||
if ( reqCnt == 0) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
RequestEntry entry = (RequestEntry)m_requestList.elementAt(reqCnt-1);
|
||||
return entry.id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of message ids for all outstanding requests
|
||||
* @return Message id array
|
||||
*/
|
||||
synchronized int[] getIDs() {
|
||||
int[] ids = new int[m_requestList.size()];
|
||||
for (int i=0; i < ids.length; i++) {
|
||||
RequestEntry entry = (RequestEntry)m_requestList.elementAt(i);
|
||||
ids[i] = entry.id;
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a LDAP request
|
||||
* @param id LDAP request message ID
|
||||
* @param connection LDAP Connection for the message ID
|
||||
* @param connThread A physical connection to the server
|
||||
*/
|
||||
synchronized void addRequest(int id, LDAPConnection connection,
|
||||
LDAPConnThread connThread) {
|
||||
|
||||
m_requestList.addElement(new RequestEntry(id, connection, connThread));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of outstanding requests.
|
||||
* @return Outstanding request count.
|
||||
*/
|
||||
public int getRequestCount() {
|
||||
return m_requestList.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove request with the specified ID
|
||||
* Called when a LDAP operation is abandoned (called from
|
||||
* LDAPConnThread), or terminated (called by nextMessage() when
|
||||
* LDAPResponse message is received)
|
||||
* @return Flag whether the request was removed
|
||||
*/
|
||||
synchronized boolean removeRequest(int id) {
|
||||
for (int i=0; i < m_requestList.size(); i++) {
|
||||
RequestEntry entry = (RequestEntry)m_requestList.elementAt(i);
|
||||
if (id == entry.id) {
|
||||
m_requestList.removeElementAt(i);
|
||||
removeAllMessages(id);
|
||||
notifyAll();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all requests associated with the specified connThread
|
||||
* Called when a connThread has a network error
|
||||
* @return Number of removed request
|
||||
*/
|
||||
synchronized int removeAllRequests(LDAPConnThread connThread) {
|
||||
int removeCount=0;
|
||||
for (int i=(m_requestList.size()-1); i>=0; i--) {
|
||||
RequestEntry entry = (RequestEntry)m_requestList.elementAt(i);
|
||||
if (connThread == entry.connThread) {
|
||||
m_requestList.removeElementAt(i);
|
||||
removeCount++;
|
||||
|
||||
// remove all queued messages as well
|
||||
removeAllMessages(entry.id);
|
||||
}
|
||||
}
|
||||
notifyAll();
|
||||
return removeCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation of the object
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer("LDAPMessageQueue:");
|
||||
sb.append(" requestIDs={");
|
||||
for (int i=0; i < m_requestList.size(); i++) {
|
||||
if (i>0) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append(((RequestEntry)m_requestList.elementAt(i)).id);
|
||||
}
|
||||
sb.append("} messageCount="+m_messageQueue.size());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import netscape.ldap.ber.stream.*;
|
||||
|
||||
/**
|
||||
* Specifies changes to be made to the values of an attribute. The change is
|
||||
* specified in terms of the following aspects:
|
||||
* <P>
|
||||
*
|
||||
* <UL>
|
||||
* <LI>the type of modification (add, replace, or delete the value of an attribute)
|
||||
* <LI>the type of value being modified (string or binary)
|
||||
* <LI>the name of the attribute being modified
|
||||
* <LI>the actual value
|
||||
* </UL>
|
||||
* <P>
|
||||
*
|
||||
* After you specify a change to an attribute, you can execute the change
|
||||
* by calling the <CODE>LDAPConnection.modify</CODE> method and specifying
|
||||
* the DN of the entry that you want to modify.
|
||||
* <P>
|
||||
*
|
||||
* @version 1.0
|
||||
* @see netscape.ldap.LDAPConnection#modify(java.lang.String, netscape.ldap.LDAPModification)
|
||||
*/
|
||||
public class LDAPModification {
|
||||
|
||||
/**
|
||||
* Specifies that a value should be added to an attribute.
|
||||
*/
|
||||
public static final int ADD = 0;
|
||||
|
||||
/**
|
||||
* Specifies that a value should be removed from an attribute.
|
||||
*/
|
||||
public static final int DELETE = 1;
|
||||
|
||||
/**
|
||||
* Specifies that a value should replace the existing value in an attribute.
|
||||
*/
|
||||
public static final int REPLACE = 2;
|
||||
|
||||
/**
|
||||
* Internal variables
|
||||
*/
|
||||
private int operation;
|
||||
private LDAPAttribute attribute;
|
||||
|
||||
/**
|
||||
* Specifies a modification to be made to an attribute.
|
||||
* @param op The type of modification to make, which can be one of the following:
|
||||
* <P>
|
||||
* <UL>
|
||||
* <LI><CODE>LDAPModification.ADD</CODE> (the value should be added to the attribute)
|
||||
* <LI><CODE>LDAPModification.DELETE</CODE> (the value should be removed from the attribute)
|
||||
* <LI><CODE>LDAPModification.REPLACE</CODE> (the value should replace the existing value of the attribute)
|
||||
* </UL><P>
|
||||
* @param attr The attribute (possibly with values) to be modified.
|
||||
* @see netscape.ldap.LDAPAttribute
|
||||
*/
|
||||
public LDAPModification( int op, LDAPAttribute attr ) {
|
||||
operation = op;
|
||||
attribute = attr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of modification specified by this object.
|
||||
* @return One of the following types of modifications:
|
||||
* <P>
|
||||
* <UL>
|
||||
* <LI><CODE>LDAPModification.ADD</CODE> (the value should be added to the attribute)
|
||||
* <LI><CODE>LDAPModification.DELETE</CODE> (the value should be removed from the attribute)
|
||||
* <LI><CODE>LDAPModification.REPLACE</CODE> (the value should replace the existing value of the attribute)
|
||||
* </UL><P>
|
||||
*/
|
||||
public int getOp() {
|
||||
return operation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute (possibly with values) to be modified.
|
||||
* @return The attribute to be modified.
|
||||
* @see netscape.ldap.LDAPAttribute
|
||||
*/
|
||||
public LDAPAttribute getAttribute() {
|
||||
return attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the BER (Basic Encoding Rules) representation
|
||||
* of the current modification.
|
||||
* @return BER representation of the modification.
|
||||
*/
|
||||
public BERElement getBERElement() {
|
||||
BERSequence seq = new BERSequence();
|
||||
seq.addElement(new BEREnumerated(operation));
|
||||
seq.addElement(attribute.getBERElement());
|
||||
return seq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the string representation of the current
|
||||
* modification. For example:
|
||||
*
|
||||
* <PRE>
|
||||
* LDAPModification: REPLACE, LDAPAttribute {type='mail', values='babs@ace.com'}
|
||||
* LDAPModification: ADD, LDAPAttribute {type='description', values='This entry was modified with the modattrs program'}
|
||||
* </PRE>
|
||||
*
|
||||
* @return String representation of the current modification.
|
||||
*/
|
||||
public String toString() {
|
||||
String s = "LDAPModification: ";
|
||||
if ( operation == ADD )
|
||||
s += "ADD, ";
|
||||
else if ( operation == DELETE )
|
||||
s += "DELETE, ";
|
||||
else if ( operation == REPLACE )
|
||||
s += "REPLACE, ";
|
||||
else
|
||||
s += "INVALID OP, ";
|
||||
s += attribute;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Represents a set of modifications to be made to attributes in an entry.
|
||||
* A set of modifications is made up of <CODE>LDAPModification</CODE> objects.
|
||||
* <P>
|
||||
*
|
||||
* After you specify a change to an attribute, you can execute the change
|
||||
* by calling the <CODE>LDAPConnection.modify</CODE> method and specifying
|
||||
* the DN of the entry that you want to modify.
|
||||
* <P>
|
||||
*
|
||||
* @version 1.0
|
||||
* @see netscape.ldap.LDAPModification
|
||||
* @see netscape.ldap.LDAPConnection#modify(java.lang.String, netscape.ldap.LDAPModificationSet)
|
||||
*/
|
||||
public class LDAPModificationSet {
|
||||
|
||||
private int current = 0;
|
||||
private Vector modifications;
|
||||
|
||||
/**
|
||||
* Constructs a new, empty set of modifications.
|
||||
* You can add modifications to this set by calling the
|
||||
* <CODE>LDAPModificationsSet.add</CODE> method.
|
||||
*/
|
||||
public LDAPModificationSet() {
|
||||
modifications = new Vector();
|
||||
current = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the number of <CODE>LDAPModification</CODE>
|
||||
* objects in this set.
|
||||
* @return The number of <CODE>LDAPModification</CODE>
|
||||
* objects in this set.
|
||||
*/
|
||||
public int size () {
|
||||
return modifications.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a particular <CODE>LDAPModification</CODE> object at
|
||||
* the position specified by the index.
|
||||
* @param Index position of the <CODE>LDAPModification</CODE>
|
||||
* object that you want to retrieve.
|
||||
* @return <CODE>LDAPModification</CODE> object representing
|
||||
* a change to be made to an attribute.
|
||||
*/
|
||||
public LDAPModification elementAt (int index) {
|
||||
return (LDAPModification)modifications.elementAt(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a particular <CODE>LDAPModification</CODE> object at
|
||||
* the position specified by the index.
|
||||
* @param Index position of the <CODE>LDAPModification</CODE>
|
||||
* object that you want to remove.
|
||||
*/
|
||||
public void removeElementAt( int index ) {
|
||||
modifications.removeElementAt(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies another modification to be added to the set of modifications.
|
||||
* @param op The type of modification to make, which can be one of the following:
|
||||
* <P>
|
||||
* <UL>
|
||||
* <LI><CODE>LDAPModification.ADD</CODE> (the value should be added to the attribute)
|
||||
* <LI><CODE>LDAPModification.DELETE</CODE> (the value should be removed from the attribute)
|
||||
* <LI><CODE>LDAPModification.REPLACE</CODE> (the value should replace the existing value of the attribute)
|
||||
* </UL><P>
|
||||
* If you are working with a binary value (not a string value), you need to bitwise OR (|) the
|
||||
* modification type with <CODE>LDAPModification.BVALUES</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* @param attr The attribute (possibly with values) to be modified.
|
||||
*/
|
||||
public synchronized void add( int op, LDAPAttribute attr ) {
|
||||
LDAPModification mod = new LDAPModification( op, attr );
|
||||
modifications.addElement( mod );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the first attribute with the specified name in the set of modifications.
|
||||
* @param name Name of the attribute to be removed.
|
||||
*/
|
||||
public synchronized void remove( String name ) {
|
||||
for( int i = 0; i < modifications.size(); i++ ) {
|
||||
LDAPModification mod = (LDAPModification)modifications.elementAt( i );
|
||||
LDAPAttribute attr = mod.getAttribute();
|
||||
if ( name.equalsIgnoreCase( attr.getName() ) ) {
|
||||
modifications.removeElementAt( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the string representation of the
|
||||
* modification set.
|
||||
*
|
||||
* @return String representation of the modification set.
|
||||
*/
|
||||
public String toString() {
|
||||
String s = "LDAPModificationSet: {";
|
||||
for( int i = 0; i < modifications.size(); i++ ) {
|
||||
s += (LDAPModification)modifications.elementAt(i);
|
||||
if ( i < modifications.size()-1 ) {
|
||||
s += ", ";
|
||||
}
|
||||
}
|
||||
s += "}";
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,342 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* The definition of an object class in the schema.
|
||||
* <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
|
||||
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
|
||||
* Attribute Syntax Definitions</A> covers the types of information
|
||||
* that need to be specified in the definition of an object class.
|
||||
* According to the RFC, the description of an object class can
|
||||
* include the following information:
|
||||
* <P>
|
||||
*
|
||||
* <UL>
|
||||
* <LI>an OID identifying the object class
|
||||
* <LI>a name identifying the object class
|
||||
* <LI>a description of the object class
|
||||
* <LI>the name of the parent object class
|
||||
* <LI>the list of attribute types that are required in this object class
|
||||
* <LI>the list of attribute types that are allowed (optional) in this
|
||||
* object class
|
||||
* </UL>
|
||||
* <P>
|
||||
*
|
||||
* When you construct an <CODE>LDAPObjectSchema</CODE> object, you can specify
|
||||
* these types of information as arguments to the constructor or in the
|
||||
* ObjectClassDescription format specified in RFC 2252.
|
||||
* When an LDAP client searches an LDAP server for the schema, the server
|
||||
* returns schema information as an object with attribute values in this
|
||||
* format.
|
||||
* <P>
|
||||
*
|
||||
* RFC 2252 also notes that you can specify whether or not an object class
|
||||
* is abstract, structural, or auxiliary in the object description.
|
||||
* Abstract object classes are used only to derive other object classes.
|
||||
* Entries cannot belong to an abstract object class. <CODE>top</CODE>
|
||||
* is an abstract object class. Entries must belong to a structural
|
||||
* object class, so most object classes are structural object classes.
|
||||
* Objects of the <CODE>LDAPObjectClassSchema</CODE> class are structural
|
||||
* object classes by default. Auxiliary object classes can be used to
|
||||
* add attributes to entries of different types. For example, an
|
||||
* auxiliary object class might be used to specify personal preference
|
||||
* attributes. An entry can not contain just that object class, but may
|
||||
* include it along with a structural object class, for example
|
||||
* inetOrgPerson.
|
||||
* If the definition of an object (in ObjectClassDescription format)
|
||||
* specifies the AUXILIARY keyword, an <CODE>LDAPObjectClassSchema</CODE>
|
||||
* object created from that description represents an auxiliary object class.
|
||||
* <P>
|
||||
*
|
||||
* You can get the name, OID, and description of this object class
|
||||
* definition by using the <CODE>getName</CODE>, <CODE>getOID</CODE>, and
|
||||
* <CODE>getDescription</CODE> methods inherited from the abstract class
|
||||
* <CODE>LDAPSchemaElement</CODE>. Optional and custom qualifiers are
|
||||
* accessed with <CODE>getQualifier</CODE> and <CODE>getQualifierNames</CODE>
|
||||
* from <CODE>LDAPSchemaElement</CODE>.
|
||||
|
||||
* <P>
|
||||
*
|
||||
* To add or remove this object class definition from the
|
||||
* schema, use the <CODE>add</CODE> and <CODE>remove</CODE>
|
||||
* methods, which this class inherits from the <CODE>LDAPSchemaElement</CODE>
|
||||
* abstract class.
|
||||
* <P>
|
||||
* RFC 2252 defines ObjectClassDescription as follows:
|
||||
* <P>
|
||||
* <PRE>
|
||||
* ObjectClassDescription = "(" whsp
|
||||
* numericoid whsp ; ObjectClass identifier
|
||||
* [ "NAME" qdescrs ]
|
||||
* [ "DESC" qdstring ]
|
||||
* [ "OBSOLETE" whsp ]
|
||||
* [ "SUP" oids ] ; Superior ObjectClasses
|
||||
* [ ( "ABSTRACT" / "STRUCTURAL" / "AUXILIARY" ) whsp ]
|
||||
* ; default structural
|
||||
* [ "MUST" oids ] ; AttributeTypes
|
||||
* [ "MAY" oids ] ; AttributeTypes
|
||||
* whsp ")"
|
||||
* </PRE>
|
||||
*
|
||||
* @version 1.0
|
||||
* @see netscape.ldap.LDAPSchemaElement
|
||||
**/
|
||||
public class LDAPObjectClassSchema extends LDAPSchemaElement {
|
||||
/**
|
||||
* Constructs an object class definition, using the specified
|
||||
* information.
|
||||
* @param name Name of the object class.
|
||||
* @param oid Object identifier (OID) of the object class
|
||||
* in dotted-string format (for example, "1.2.3.4").
|
||||
* @param description Description of the object class.
|
||||
* @param superior Name of the parent object class
|
||||
* (the object class that the new object class inherits from).
|
||||
* @param required Array of the names of the attributes required
|
||||
* in this object class.
|
||||
* @param optional Array of the names of the optional attributes
|
||||
* allowed in this object class.
|
||||
*/
|
||||
public LDAPObjectClassSchema( String name, String oid, String superior,
|
||||
String description,
|
||||
String[] required, String[] optional ) {
|
||||
super( name, oid, description );
|
||||
attrName = "objectclasses";
|
||||
this.superiors = new String[] { superior };
|
||||
for( int i = 0; i < required.length; i++ ) {
|
||||
must.addElement( required[i] );
|
||||
}
|
||||
for( int i = 0; i < optional.length; i++ ) {
|
||||
may.addElement( optional[i] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an object class definition, using the specified
|
||||
* information.
|
||||
* @param name Name of the object class.
|
||||
* @param oid Object identifier (OID) of the object class
|
||||
* in dotted-string format (for example, "1.2.3.4").
|
||||
* @param description Description of the object class.
|
||||
* @param superiors Name of parent object classes
|
||||
* (the object class that the new object class inherits from).
|
||||
* @param required Array of the names of the attributes required
|
||||
* in this object class.
|
||||
* @param optional Array of the names of the optional attributes
|
||||
* allowed in this object class.
|
||||
* @param type Either ABSTRACT, STRUCTURAL, or AUXILIARY
|
||||
*/
|
||||
public LDAPObjectClassSchema( String name, String oid,
|
||||
String[] superiors,
|
||||
String description,
|
||||
String[] required, String[] optional,
|
||||
int type ) {
|
||||
this( name, oid, superiors[0], description, required, optional );
|
||||
this.superiors = superiors;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an object class definition based on a description in
|
||||
* the ObjectClassDescription format. For information on this format,
|
||||
* (see <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
|
||||
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
|
||||
* Attribute Syntax Definitions</A>. This is the format that LDAP servers
|
||||
* and clients use to exchange schema information. (For example, when
|
||||
* you search an LDAP server for its schema, the server returns an entry
|
||||
* with the attributes "objectclasses" and "attributetypes". The
|
||||
* values of the "objectclasses" attribute are object class descriptions
|
||||
* in this format.)
|
||||
* <P>
|
||||
*
|
||||
* @param raw Definition of the object in the ObjectClassDescription
|
||||
* format.
|
||||
*/
|
||||
public LDAPObjectClassSchema( String raw ) {
|
||||
attrName = "objectclasses";
|
||||
parseValue( raw );
|
||||
String[] vals = getQualifier( SUPERIOR );
|
||||
if ( vals != null ) {
|
||||
superiors = vals;
|
||||
setQualifier( SUPERIOR, (String)null );
|
||||
}
|
||||
if ( properties.containsKey( "AUXILIARY" ) ) {
|
||||
type = AUXILIARY;
|
||||
} else if ( properties.containsKey( "ABSTRACT" ) ) {
|
||||
type = ABSTRACT;
|
||||
} else if ( properties.containsKey( "STRUCTURAL" ) ) {
|
||||
type = STRUCTURAL;
|
||||
}
|
||||
obsolete = properties.containsKey( OBSOLETE );
|
||||
Vector v = (Vector)properties.get( "MAY" );
|
||||
if ( v != null ) {
|
||||
may = v;
|
||||
}
|
||||
v = (Vector)properties.get( "MUST" );
|
||||
if ( v != null ) {
|
||||
must = v;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the object class that this class inherits from.
|
||||
* @return The name of the object class that this class
|
||||
* inherits from.
|
||||
*/
|
||||
public String getSuperior() {
|
||||
return superiors[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the names of all object classes that this class inherits
|
||||
* from. Typically only one, but RFC 2252 allows multiple
|
||||
* inheritance.
|
||||
* @return The names of the object classes that this class
|
||||
* inherits from.
|
||||
*/
|
||||
public String[] getSuperiors() {
|
||||
return superiors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an enumeration of the names of the required attribute for
|
||||
* this object class.
|
||||
* @return An enumeration of the names of the required attributes
|
||||
* for this object class.
|
||||
*/
|
||||
public Enumeration getRequiredAttributes() {
|
||||
return must.elements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an enumeration of names of optional attributes allowed
|
||||
* in this object class.
|
||||
* @return An enumeration of the names of optional attributes
|
||||
* allowed in this object class.
|
||||
*/
|
||||
public Enumeration getOptionalAttributes() {
|
||||
return may.elements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of the object class.
|
||||
* @return STRUCTURAL, ABSTRACT, or AUXILIARY
|
||||
*/
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a value in RFC 2252 format for submitting to a server
|
||||
*
|
||||
* @param quotingBug <CODE>true</CODE> if SUP and SYNTAX values are to
|
||||
* be quoted. That is to satisfy bugs in certain LDAP servers.
|
||||
* @return A String ready to be submitted to an LDAP server
|
||||
*/
|
||||
String getValue( boolean quotingBug ) {
|
||||
String s = getValuePrefix();
|
||||
s += getValue( SUPERIOR, quotingBug );
|
||||
s += ' ';
|
||||
String val = getOptionalValues( NOVALS );
|
||||
if ( val.length() > 0 ) {
|
||||
s += val + ' ';
|
||||
}
|
||||
s += getValue( "MUST", false );
|
||||
s += ' ';
|
||||
s += getValue( "MAY", false );
|
||||
s += ' ';
|
||||
val = getCustomValues();
|
||||
if ( val.length() > 0 ) {
|
||||
s += val + ' ';
|
||||
}
|
||||
s += ')';
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the definition of the object class in a user friendly format.
|
||||
* This is the format that the object class definition uses when
|
||||
* you print the object class or the schema.
|
||||
* @return Definition of the object class in a user friendly format.
|
||||
*/
|
||||
public String toString() {
|
||||
String s = "Name: " + name + "; OID: " + oid +
|
||||
"; Superior: ";
|
||||
for( int i = 0; i < superiors.length; i++ ) {
|
||||
s += superiors[i];
|
||||
if ( i < (superiors.length-1) ) {
|
||||
s += ", ";
|
||||
}
|
||||
}
|
||||
s += "; Description: " + description + "; Required: ";
|
||||
int i = 0;
|
||||
Enumeration e = getRequiredAttributes();
|
||||
while( e.hasMoreElements() ) {
|
||||
if ( i > 0 )
|
||||
s += ", ";
|
||||
i++;
|
||||
s += (String)e.nextElement();
|
||||
}
|
||||
s += "; Optional: ";
|
||||
e = getOptionalAttributes();
|
||||
i = 0;
|
||||
while( e.hasMoreElements() ) {
|
||||
if ( i > 0 )
|
||||
s += ", ";
|
||||
i++;
|
||||
s += (String)e.nextElement();
|
||||
}
|
||||
switch ( type ) {
|
||||
case STRUCTURAL:
|
||||
break;
|
||||
case ABSTRACT:
|
||||
s += "; ABSTRACT";
|
||||
break;
|
||||
case AUXILIARY:
|
||||
s += "; AUXILIARY";
|
||||
break;
|
||||
}
|
||||
if ( obsolete ) {
|
||||
s += "; OBSOLETE";
|
||||
}
|
||||
s += getQualifierString( IGNOREVALS );
|
||||
return s;
|
||||
}
|
||||
|
||||
public static final int STRUCTURAL = 0;
|
||||
public static final int ABSTRACT = 1;
|
||||
public static final int AUXILIARY = 2;
|
||||
|
||||
private String[] superiors = { "" };
|
||||
private Vector must = new Vector();
|
||||
private Vector may = new Vector();
|
||||
private int type = STRUCTURAL;
|
||||
|
||||
// Qualifers known to not have values
|
||||
static String[] NOVALS = { "ABSTRACT", "STRUCTURAL",
|
||||
"AUXILIARY" };
|
||||
static {
|
||||
for( int i = 0; i < NOVALS.length; i++ ) {
|
||||
novalsTable.put( NOVALS[i], NOVALS[i] );
|
||||
}
|
||||
}
|
||||
static String[] IGNOREVALS = { "ABSTRACT", "STRUCTURAL",
|
||||
"AUXILIARY", "MUST", "MAY" };
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Specifies how you can retrieve authentication information automatically
|
||||
* for referrals. If you have set up the search constraints (or the options
|
||||
* in the <CODE>LDAPConnection</CODE> object) so that automatic referral is
|
||||
* used, you must define a class that implements this interface.
|
||||
* <P>
|
||||
*
|
||||
* If no class implements this interface, clients that follow automatic
|
||||
* referrals are authenticated anonymously with subsequent LDAP servers.
|
||||
* The following example is a simple class that implements this interface.
|
||||
* Objects of this class check the host and port of the LDAP server that is
|
||||
* being referred to. If the host and port are "alway.mcom.com:389", the
|
||||
* directory manager's name and password will be used to authenticate to that
|
||||
* server. For all other LDAP servers, anonymous authentication is used.
|
||||
*
|
||||
* <PRE>
|
||||
* public class myLDAPRebind implements netscape.ldap.LDAPRebind
|
||||
* {
|
||||
* private String myDN;
|
||||
* private String myPW;
|
||||
* private LDAPRebindAuth myRebindInfo;
|
||||
|
||||
* public myLDAPRebind () {
|
||||
* myDN = "c=Directory Manager,o=Universal Exports,c=UK";
|
||||
* myPW = "alway4444";
|
||||
* }
|
||||
*
|
||||
* public LDAPRebindAuth getRebindAuthentication( String host, int port ) {
|
||||
* if ( host.equalsIgnoreCase( "alway.mcom.com" ) && ( port == 389 ) ) {
|
||||
* myRebindInfo = new LDAPRebindAuth( myDN, myPW );
|
||||
* } else {
|
||||
* myRebindInfo = new LDAPRebindAuth( "", "" );
|
||||
* }
|
||||
* return myRebindInfo;
|
||||
* }
|
||||
* } </PRE>
|
||||
*
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public interface LDAPRebind {
|
||||
|
||||
/**
|
||||
* Returns an <CODE>LDAPRebindAuth</CODE> object, which the calling function
|
||||
* can use to get the DN and password to use for authentication (if the client
|
||||
* is set up to follow referrals automatically).
|
||||
* @return LDAPRebindAuth object containing authentication information.
|
||||
* @see netscape.ldap.LDAPRebindAuth
|
||||
*/
|
||||
public LDAPRebindAuth getRebindAuthentication(String host,
|
||||
int port);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Represents information used to authenticate the client in cases where
|
||||
* the client follows referrals automatically. If you are defining a class
|
||||
* that implements the <CODE>LDAPRebind</CODE> interface, your implementation
|
||||
* of the <CODE>LDAPRebind.getRebindAuthentication</CODE> method needs to
|
||||
* construct and return an object of this class.
|
||||
* <P>
|
||||
*
|
||||
* For example, the following method sets up authentication information based
|
||||
* on the LDAP server identified in the referral. Ideally, this method would be
|
||||
* defined as part of a class implementing the <CODE>LDAPRebind</CODE> interface.
|
||||
*
|
||||
* <PRE>
|
||||
* private String myDN = "cn=Directory Manager,o=Ace Industry,c=US";
|
||||
* private String myPW = "alway4444";
|
||||
* private LDAPRebindAuth myRebindInfo;
|
||||
* ...
|
||||
* public LDAPRebindAuth getRebindAuthentication( String host, int port ) {
|
||||
* if ( host.equalsIgnoreCase( "alway.mcom.com" ) && ( port == 389 ) ) {
|
||||
* myRebindInfo = new LDAPRebindAuth( myDN, myPW );
|
||||
* } else {
|
||||
* myRebindInfo = new LDAPRebindAuth( "", "" );
|
||||
* }
|
||||
* return myRebindInfo;
|
||||
* } </PRE>
|
||||
*
|
||||
* @version 1.0
|
||||
* @see netscape.ldap.LDAPRebind
|
||||
*/
|
||||
public class LDAPRebindAuth {
|
||||
|
||||
private String m_dn;
|
||||
private String m_password;
|
||||
|
||||
/**
|
||||
* Constructs information that is used by the client
|
||||
* for authentication when following referrals automatically.
|
||||
* @param dn Distinguished name to use for authenticating to
|
||||
* the LDAP server during an automatic referral (if the client
|
||||
* is set up to follow referrals automatically)
|
||||
* @param password Password to use for authenticating to
|
||||
* the LDAP server during an automatic referral (if the client
|
||||
* is set up to follow referrals automatically)
|
||||
*/
|
||||
public LDAPRebindAuth(String dn, String password) {
|
||||
m_dn = dn;
|
||||
m_password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distinguished name to be used for reauthentication,
|
||||
* if the client is set up to follow referrals automatically.
|
||||
* @return Distinguished name to be used for authenticating to
|
||||
* other LDAP servers during referrals.
|
||||
*/
|
||||
public String getDN() {
|
||||
return m_dn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the password to be used for reauthentication,
|
||||
* if the client is set up to follow referrals automatically.
|
||||
* @return Password to be used for authenticating to other
|
||||
* LDAP servers during referrals.
|
||||
*/
|
||||
public String getPassword() {
|
||||
return m_password;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import netscape.ldap.client.*;
|
||||
import netscape.ldap.client.opers.*;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Represents the situation in which the LDAP server refers the client to
|
||||
* another LDAP server. This exception constructs a list of referral URLs from
|
||||
* the LDAP error message returned by the server. You can get this list by
|
||||
* using the <CODE>getURLs</CODE> method.
|
||||
*
|
||||
* @version 1.0
|
||||
* @see netscape.ldap.LDAPException
|
||||
*/
|
||||
public class LDAPReferralException extends LDAPException {
|
||||
|
||||
private String m_referrals[] = null; /* modified for LDAPv3 */
|
||||
|
||||
/**
|
||||
* Constructs a default exception with no specific error information.
|
||||
*/
|
||||
public LDAPReferralException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a default exception with a specified string as
|
||||
* additional information. This form is used for lower-level errors.
|
||||
* @param message The additional error information
|
||||
*/
|
||||
public LDAPReferralException( String message ) {
|
||||
super( message );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a default exception with a specified string as
|
||||
* additional information. This form is used for higher-level LDAP
|
||||
* operational errors.
|
||||
* @param message The additional error information
|
||||
* @param resultCode result code
|
||||
* @param serverErrorMessage error message
|
||||
*/
|
||||
public LDAPReferralException( String message, int resultCode,
|
||||
String serverErrorMessage ) {
|
||||
super(message, resultCode, serverErrorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an exception with a list of LDAP URLs to other LDAP servers.
|
||||
* This list of referrals points the client to LDAP servers that may
|
||||
* contain the requested entries.
|
||||
* @param message The additional error information
|
||||
* @param resultCode result code
|
||||
* @param referrals Array of LDAP URLs identifying other LDAP servers that
|
||||
* may contain the requested entries.
|
||||
*/
|
||||
public LDAPReferralException( String message, int resultCode,
|
||||
String referrals[] ) {
|
||||
super(message, resultCode, null);
|
||||
m_referrals = referrals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of referrals (LDAP URLs to other servers) returned by the LDAP server.
|
||||
* You can use this list to find the LDAP server that can fulfill your request.
|
||||
*
|
||||
* If you have set up your search constraints (or the <CODE>LDAPConnection</CODE> object)
|
||||
* to follow referrals automatically, any operation that results in a referral will use
|
||||
* this list to create new connections to the LDAP servers in this list.
|
||||
*
|
||||
* @return List of LDAP URLs to other LDAP servers.
|
||||
*/
|
||||
public LDAPUrl[] getURLs() {
|
||||
if (getLDAPErrorMessage() == null) {
|
||||
return constructsURL(m_referrals);
|
||||
} else {
|
||||
return constructsURL(extractReferrals(getLDAPErrorMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
private LDAPUrl[] constructsURL(String referrals[]) {
|
||||
if (referrals == null) {
|
||||
return null;
|
||||
}
|
||||
LDAPUrl u[] = new LDAPUrl[referrals.length];
|
||||
if (u == null) {
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < referrals.length; i++) {
|
||||
try {
|
||||
u[i] = new LDAPUrl(referrals[i]);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract referral string from the error message. The
|
||||
* error string is based on "Referrals Within the
|
||||
* LDAPv2 Protocol".
|
||||
* @param error string
|
||||
*/
|
||||
private String[] extractReferrals(String error) {
|
||||
if (error == null)
|
||||
return null;
|
||||
StringTokenizer st = new StringTokenizer(error, "\n");
|
||||
Vector v = new Vector();
|
||||
boolean referrals = false;
|
||||
while (st.hasMoreTokens()) {
|
||||
String token = st.nextToken();
|
||||
if (referrals) {
|
||||
v.addElement(token);
|
||||
} else {
|
||||
if (token.startsWith("Referral:"))
|
||||
referrals = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (v.size() == 0)
|
||||
return null;
|
||||
String res[] = new String[v.size()];
|
||||
for (int i = 0; i < v.size(); i++) {
|
||||
res[i] = (String)v.elementAt(i);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* This class represents a locale-specific resource for a property file.
|
||||
* It retrieves the property file for the given base name including the
|
||||
* absolute path name and locale. The property file has to be located in the
|
||||
* CLASSPATH and the property file's suffix is .props.
|
||||
* <p>
|
||||
* If the specified locale is en and us and the base name of the file is
|
||||
* netscape/ldap/errors/ErrorCodes, then the class loader will search for
|
||||
* the file in the following order:
|
||||
* <pre>
|
||||
*
|
||||
* ErrorCodes_en_us.props
|
||||
* ErrorCodes_en.props
|
||||
* ErrorCodes.props
|
||||
*
|
||||
* </pre>
|
||||
* @see java.util.Locale
|
||||
*/
|
||||
class LDAPResourceBundle {
|
||||
|
||||
private static final boolean m_debug = false;
|
||||
private static final String m_suffix = ".props";
|
||||
private static final String m_locale_separator = "_";
|
||||
|
||||
/**
|
||||
* Return the property resource bundle according to the base name of the
|
||||
* property file and the locale. The class loader will find the closest match
|
||||
* with the given locale.
|
||||
* @return The property resource bundle
|
||||
* @exception IOException Gets thrown when failed to open the resource
|
||||
* bundle file.
|
||||
*/
|
||||
static PropertyResourceBundle getBundle(String baseName)
|
||||
throws IOException {
|
||||
|
||||
return getBundle(baseName, Locale.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the property resource bundle according to the base name of the
|
||||
* property file and the locale. The class loader will find the closest match
|
||||
* with the given locale.
|
||||
* @param baseName The base name of the property file, ie, the name contains
|
||||
* no locale context and no . suffix
|
||||
* @param l The locale
|
||||
* @return The property resource bundle
|
||||
* @exception IOException Gets thrown when failed to create a property
|
||||
* resource
|
||||
*/
|
||||
static PropertyResourceBundle getBundle(String baseName, Locale l)
|
||||
throws IOException {
|
||||
String localeStr = m_locale_separator+l.toString();
|
||||
|
||||
InputStream fin = null;
|
||||
|
||||
while (true) {
|
||||
if ((fin=getStream(baseName, localeStr)) != null) {
|
||||
PropertyResourceBundle p = new PropertyResourceBundle(fin);
|
||||
return p;
|
||||
} else {
|
||||
|
||||
int index = localeStr.lastIndexOf(m_locale_separator);
|
||||
if (index == -1) {
|
||||
printDebug("File "+baseName+localeStr+m_suffix+" not found");
|
||||
return null;
|
||||
} else
|
||||
localeStr = localeStr.substring(0, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the whole absolute path name of a property file and retrieves
|
||||
* an input stream on the file.
|
||||
* @param baseName The base name of the property file, ie, the name contains
|
||||
* no locale context and no . suffix
|
||||
* @param The locale string being inserted within the file name.
|
||||
* @return The input stream on the property file.
|
||||
*/
|
||||
private static InputStream getStream(String baseName, String locale) {
|
||||
String fStr = baseName+locale+m_suffix;
|
||||
return (ClassLoader.getSystemResourceAsStream(fStr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints debug messages if the debug mode is on.
|
||||
* @param str The given message being printed.
|
||||
*/
|
||||
private static void printDebug(String str) {
|
||||
if (m_debug)
|
||||
System.out.println(str);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import netscape.ldap.client.opers.JDAPProtocolOp;
|
||||
import netscape.ldap.client.opers.JDAPResult;
|
||||
|
||||
/**
|
||||
* Represents the response to a particular LDAP operation.
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LDAPResponse extends LDAPMessage {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param msgid message identifier
|
||||
* @param rsp Operation response
|
||||
* @param controls Array of controls of null
|
||||
*/
|
||||
LDAPResponse(int msgid, JDAPProtocolOp rsp, LDAPControl controls[]) {
|
||||
super(msgid, rsp, controls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns any error message in the response.
|
||||
*
|
||||
* @return The error message of the last error (or <CODE>null</CODE>
|
||||
* if no message was set).
|
||||
*/
|
||||
public String getErrorMessage() {
|
||||
JDAPResult result = (JDAPResult) getProtocolOp();
|
||||
return result.getErrorMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the partially matched DN field, if any, in a server response.
|
||||
*
|
||||
* @return The maximal subset of a DN which could be matched,
|
||||
* or <CODE>null</CODE>.
|
||||
*/
|
||||
public String getMatchedDN() {
|
||||
JDAPResult result = (JDAPResult) getProtocolOp();
|
||||
return result.getMatchedDN();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all referrals, if any, in a server response.
|
||||
*
|
||||
* @return A list of referrals or <CODE>null</CODE>.
|
||||
*/
|
||||
public String[] getReferrals() {
|
||||
JDAPResult result = (JDAPResult) getProtocolOp();
|
||||
return result.getReferrals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result code in a server response.
|
||||
*
|
||||
* @return The result code.
|
||||
*/
|
||||
public int getResultCode() {
|
||||
JDAPResult result = (JDAPResult) getProtocolOp();
|
||||
return result.getResultCode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
/*
|
||||
* This object represents the value of the LDAPConnection.m_responseControlTable hashtable.
|
||||
* It stores the response controls and its corresponding LDAPConnection and
|
||||
* the message ID for its corresponding LDAPMessage.
|
||||
*/
|
||||
class LDAPResponseControl {
|
||||
private LDAPConnection m_connection;
|
||||
private int m_messageID;
|
||||
private LDAPControl[] m_controls;
|
||||
|
||||
public LDAPResponseControl(LDAPConnection conn, int msgID,
|
||||
LDAPControl[] controls) {
|
||||
|
||||
m_connection = conn;
|
||||
m_messageID = msgID;
|
||||
m_controls = new LDAPControl[controls.length];
|
||||
for (int i=0; i<controls.length; i++)
|
||||
m_controls[i] = controls[i];
|
||||
}
|
||||
|
||||
public int getMsgID() {
|
||||
return m_messageID;
|
||||
}
|
||||
|
||||
public LDAPControl[] getControls() {
|
||||
return m_controls;
|
||||
}
|
||||
|
||||
public LDAPConnection getConnection() {
|
||||
return m_connection;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
|
||||
/**
|
||||
* Represents the message queue associated with a particular LDAP
|
||||
* operation or operations.
|
||||
*
|
||||
*/
|
||||
public class LDAPResponseListener extends LDAPMessageQueue{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param asynchOp A flag whether the object is used for asynchronous
|
||||
* LDAP operations
|
||||
* @see netscape.ldap.LDAPAsynchronousConnection
|
||||
*/
|
||||
LDAPResponseListener(boolean asynchOp) {
|
||||
super(asynchOp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocks until a response is available, or until all operations
|
||||
* associated with the object have completed or been canceled, and
|
||||
* returns the response.
|
||||
*
|
||||
* @return A response for a LDAP operation or null if there is no
|
||||
* more outstanding requests
|
||||
* @exception LDAPException Network error exception
|
||||
* @exception LDAPInterruptedException The invoking thread was interrupted
|
||||
*/
|
||||
public LDAPResponse getResponse() throws LDAPException {
|
||||
return (LDAPResponse)nextMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge two response listeners
|
||||
* Move/append the content from another response listener to this one.
|
||||
*
|
||||
* To be used for synchronization of asynchronous LDAP operations where
|
||||
* requests are sent by one thread but processed by another one
|
||||
*
|
||||
* A client may be implemented in such a way that one thread makes LDAP
|
||||
* requests and calls l.getIDs(), while another thread is responsible for
|
||||
* processing of responses (call l.getResponse()). Both threads are using
|
||||
* the same listener objects. In such a case, a race
|
||||
* condition may occur, where a LDAP response message is retrieved and
|
||||
* the request terminated (request ID removed) before the first thread
|
||||
* has a chance to execute l.getIDs().
|
||||
* The proper way to handle this scenario is to create a separate listener
|
||||
* for each new request, and after l.getIDs() has been invoked, merge the
|
||||
* new request with the existing one.
|
||||
* @param listener2 The listener to be merged with.
|
||||
*/
|
||||
public void merge(LDAPSearchListener listener2) {
|
||||
super.merge(listener2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports true if a response has been received from the server.
|
||||
*
|
||||
* @return A flag whether the response message queue is empty
|
||||
*/
|
||||
public boolean isResponseReceived() {
|
||||
return super.isMessageReceived();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns message ids for all outstanding requests
|
||||
* @return Message id array
|
||||
*/
|
||||
public int[] getIDs() {
|
||||
return super.getIDs();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
/**
|
||||
* Creates an SSL socket connection to an LDAP Server. This class
|
||||
* implements the <CODE>LDAPSSLSocketFactoryExt</CODE> interface.
|
||||
* <P>
|
||||
*
|
||||
* To construct an object of this class, you need to specify the
|
||||
* name of a class that implements the <CODE>javax.net.ssl.SSLSocket</CODE>
|
||||
* interface. If you do not specify a class name, the class
|
||||
* <CODE>netscape.net.SSLSocket</CODE> is used by default. This
|
||||
* class is included with Netscape Communicator 4.05 and up.
|
||||
* <P>
|
||||
*
|
||||
* If you are using a Java VM that provides certificate database
|
||||
* management (such as Netscape Communicator), you can authenticate
|
||||
* your client to a secure LDAP server by using certificates.
|
||||
* <P>
|
||||
*
|
||||
* @version 1.0
|
||||
* @see LDAPSSLSocketFactoryExt
|
||||
* @see LDAPConnection#LDAPConnection(netscape.ldap.LDAPSocketFactory)
|
||||
*/
|
||||
public class LDAPSSLSocketFactory implements LDAPSSLSocketFactoryExt {
|
||||
|
||||
/**
|
||||
* Indicates if client authentication is on.
|
||||
*/
|
||||
private boolean m_clientAuth = false;
|
||||
/**
|
||||
* Name of class implementing SSLSocket.
|
||||
*/
|
||||
private String m_packageName = "netscape.net.SSLSocket";
|
||||
|
||||
/**
|
||||
* The cipher suites
|
||||
*/
|
||||
private Object m_cipherSuites = null;
|
||||
|
||||
/**
|
||||
* The Ldap connection
|
||||
*/
|
||||
private LDAPConnection m_connection = null;
|
||||
|
||||
/**
|
||||
* Constructs an <CODE>LDAPSSLSocketFactory</CODE> object using
|
||||
* the default SSL socket implementation,
|
||||
* <CODE>netscape.net.SSLSocket</CODE>. (This class is provided
|
||||
* with Netscape Communicator 4.05 and higher.)
|
||||
*/
|
||||
public LDAPSSLSocketFactory() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an <CODE>LDAPSSLSocketFactory</CODE> object using
|
||||
* the default SSL socket implementation,
|
||||
* <CODE>netscape.net.SSLSocket</CODE>. (This class is provided
|
||||
* with Netscape Communicator 4.05 and up.)
|
||||
* @param clientAuth <CODE>true</CODE> if certificate-based client
|
||||
* authentication is desired. By default, client authentication is
|
||||
* not used.
|
||||
*/
|
||||
public LDAPSSLSocketFactory(boolean clientAuth) {
|
||||
m_clientAuth = clientAuth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an <CODE>LDAPSSLSocketFactory</CODE> object using
|
||||
* the specified class. The class must implement the interface
|
||||
* <CODE>javax.net.ssl.SSLSocket</CODE>.
|
||||
* @param className The name of a class implementing
|
||||
* the <CODE>javax.net.ssl.SSLSocket</CODE> interface.
|
||||
* Pass <code>null</code> for this parameter to use the
|
||||
* default SSL socket implementation,
|
||||
* <CODE>netscape.net.SSLSocket</CODE>, which is included with
|
||||
* Netscape Communicator 4.05 and up.
|
||||
*/
|
||||
public LDAPSSLSocketFactory(String className) {
|
||||
m_packageName = new String(className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an <CODE>LDAPSSLSocketFactory</CODE> object using
|
||||
* the specified class. The class must implement the interface
|
||||
* <CODE>javax.net.ssl.SSLSocket</CODE>.
|
||||
* @param className The name of a class implementing
|
||||
* the <CODE>javax.net.ssl.SSLSocket</CODE> interface.
|
||||
* Pass <code>null</code> for this parameter to use the
|
||||
* default SSL socket implementation,
|
||||
* <CODE>netscape.net.SSLSocket</CODE>, which is included with
|
||||
* Netscape Communicator 4.05 and up.
|
||||
* @param clientAuth <CODE>true</CODE> if certificate-based client
|
||||
* authentication is desired. By default, client authentication is
|
||||
* not used.
|
||||
*/
|
||||
public LDAPSSLSocketFactory(String className, boolean clientAuth) {
|
||||
m_packageName = new String(className);
|
||||
m_clientAuth = clientAuth;
|
||||
}
|
||||
|
||||
/**
|
||||
* The constructor with the specified package for security and the specified
|
||||
* cipher suites.
|
||||
* @param className The name of a class implementing the interface
|
||||
* <CODE>javax.net.ssl.SSLSocket</CODE>
|
||||
* Pass <code>null</code> for this parameter to use the
|
||||
* default SSL socket implementation,
|
||||
* <CODE>netscape.net.SSLSocket</CODE>, which is included with
|
||||
* Netscape Communicator 4.05 and up.
|
||||
* @param cipherSuites The cipher suites to use for SSL connections.
|
||||
*/
|
||||
public LDAPSSLSocketFactory(String className, Object cipherSuites) {
|
||||
m_packageName = new String(className);
|
||||
m_cipherSuites = cipherSuites;
|
||||
}
|
||||
|
||||
/**
|
||||
* The constructor with the specified package for security and the specified
|
||||
* cipher suites.
|
||||
* @param className The name of a class implementing the interface
|
||||
* <CODE>javax.net.ssl.SSLSocket</CODE>
|
||||
* Pass <code>null</code> for this parameter to use the
|
||||
* default SSL socket implementation,
|
||||
* <CODE>netscape.net.SSLSocket</CODE>, which is included with
|
||||
* Netscape Communicator 4.05.
|
||||
* @param cipherSuites The cipher suites to use for SSL connections.
|
||||
* @param clientAuth <CODE>true</CODE> if certificate-based client
|
||||
* authentication is desired. By default, client authentication is
|
||||
* not used.
|
||||
*/
|
||||
public LDAPSSLSocketFactory(String className, Object cipherSuites,
|
||||
boolean clientAuth) {
|
||||
m_packageName = new String(className);
|
||||
m_cipherSuites = cipherSuites;
|
||||
m_clientAuth = clientAuth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables certificate-based client authentication for an
|
||||
* application. The application must be running in a Java VM
|
||||
* that provides transparent certificate database management
|
||||
* (for example, Netscape Communicator's Java VM).
|
||||
* Call this method before you call <CODE>makeSocket</CODE>.
|
||||
* @see netscape.ldap.LDAPSSLSocketFactory#isClientAuth
|
||||
* @see netscape.ldap.LDAPSSLSocketFactory#makeSocket
|
||||
* Note: enableClientAuth() is deprecated. This method is replaced
|
||||
* by any one of the following constructors:
|
||||
* <p>
|
||||
* <CODE>LDAPSSLSocketFactory(boolean)</CODE>
|
||||
* <CODE>LDAPSSLSocketFactory(java.lang.String, boolean)</CODE>
|
||||
* <CODE>LDAPSSLSocketFactory(java.lang.String, java.lang.Object, boolean)</CODE>
|
||||
*/
|
||||
public void enableClientAuth() {
|
||||
m_clientAuth = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <B>This method is currently not implemented.</B>
|
||||
* Enables client authentication for an application that uses
|
||||
* an external (file-based) certificate database.
|
||||
* Call this method before you call <CODE>makeSocket</CODE>.
|
||||
* @param certdb The pathname for certificate database
|
||||
* @param keydb The pathname for private key database
|
||||
* @param keypwd The password for private key database
|
||||
* @param certnickname The alias for certificate
|
||||
* @param keynickname The alias for key
|
||||
* @see netscape.ldap.LDAPSSLSocketFactory#isClientAuth
|
||||
* @see netscape.ldap.LDAPSSLSocketFactory#makeSocket
|
||||
* @exception LDAPException Since this method is not yet implemented,
|
||||
* calling this method throws an exception.
|
||||
* Note: <CODE>enableClientAuth(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)</CODE> is deprecated.
|
||||
* This method is replaced by any one of the following constructors:
|
||||
* <p>
|
||||
* <CODE>LDAPSSLSocketFactory(boolean)</CODE>
|
||||
* <CODE>LDAPSSLSocketFactory(java.lang.String, boolean)</CODE>
|
||||
* <CODE>LDAPSSLSocketFactory(java.lang.String, java.lang.Object, boolean)</CODE>
|
||||
*/
|
||||
public void enableClientAuth(String certdb, String keydb, String keypwd,
|
||||
String certnickname, String keynickname) throws LDAPException {
|
||||
throw new LDAPException("Client auth not supported now");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if client authentication is enabled.
|
||||
* @see netscape.ldap.LDAPSSLSocketFactory
|
||||
*/
|
||||
public boolean isClientAuth() {
|
||||
return m_clientAuth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the class that implements SSL sockets for this factory.
|
||||
*
|
||||
* @return The name of the class that implements SSL sockets for this factory.
|
||||
*/
|
||||
public String getSSLSocketImpl() {
|
||||
return m_packageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the suite of ciphers used for SSL connections made through
|
||||
* sockets created by this factory.
|
||||
*
|
||||
* @return The suite of ciphers used.
|
||||
*/
|
||||
public Object getCipherSuites() {
|
||||
return m_cipherSuites;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a socket to the LDAP server with the specified
|
||||
* host name and port number.
|
||||
* @param host The host to connect to
|
||||
* @param port The port number
|
||||
* @return The socket to the host name and port number.
|
||||
* @exception LDAPException A socket to the specified host and port
|
||||
* could not be created.
|
||||
* @see netscape.ldap.LDAPSSLSocketFactory
|
||||
*/
|
||||
public Socket makeSocket(String host, int port)
|
||||
throws LDAPException {
|
||||
|
||||
Socket s = null;
|
||||
|
||||
if (m_clientAuth) {
|
||||
try {
|
||||
/* Check if running in Communicator; if so, enable client
|
||||
auth */
|
||||
String[] types = { "java.lang.String" };
|
||||
java.lang.reflect.Method m =
|
||||
DynamicInvoker.getMethod(
|
||||
"netscape.security.PrivilegeManager",
|
||||
"enablePrivilege",
|
||||
types );
|
||||
if (m != null) {
|
||||
Object[] args = new Object[1];
|
||||
args[0] = new String("ClientAuth");
|
||||
m.invoke( null, args);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
String msg = "LDAPSSLSocketFactory.makeSocket: invoking " +
|
||||
"enablePrivilege: " + e.toString();
|
||||
throw new LDAPException(msg, LDAPException.PARAM_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
String cipherClassName = null;
|
||||
if (m_cipherSuites != null)
|
||||
cipherClassName = m_cipherSuites.getClass().getName();
|
||||
|
||||
/* Instantiate the SSLSocketFactory implementation, and
|
||||
find the right constructor */
|
||||
Class c = Class.forName(m_packageName);
|
||||
java.lang.reflect.Constructor[] m = c.getConstructors();
|
||||
for (int i = 0; i < m.length; i++) {
|
||||
/* Check if the signature is right: String, int */
|
||||
Class[] params = m[i].getParameterTypes();
|
||||
if ( (m_cipherSuites == null) && (params.length == 2) &&
|
||||
(params[0].getName().equals("java.lang.String")) &&
|
||||
(params[1].getName().equals("int")) ) {
|
||||
Object[] args = new Object[2];
|
||||
args[0] = host;
|
||||
args[1] = new Integer(port);
|
||||
s = (Socket)(m[i].newInstance(args));
|
||||
return s;
|
||||
} else if ( (m_cipherSuites != null) && (params.length == 3) &&
|
||||
(params[0].getName().equals("java.lang.String")) &&
|
||||
(params[1].getName().equals("int")) &&
|
||||
(params[2].getName().equals(cipherClassName)) ) {
|
||||
Object[] args = new Object[3];
|
||||
args[0] = host;
|
||||
args[1] = new Integer(port);
|
||||
args[2] = m_cipherSuites;
|
||||
s = (Socket)(m[i].newInstance(args));
|
||||
return s;
|
||||
}
|
||||
}
|
||||
throw new LDAPException("No appropriate constructor in " +
|
||||
m_packageName,
|
||||
LDAPException.PARAM_ERROR);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new LDAPException("Class " + m_packageName + " not found",
|
||||
LDAPException.PARAM_ERROR);
|
||||
} catch (Exception e) {
|
||||
throw new LDAPException("Failed to create SSL socket",
|
||||
LDAPException.CONNECT_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
/**
|
||||
* Represents a SSL socket connection that you can use to connect to an
|
||||
* LDAP server. This interface extends the base interface LDAPSocketFactory
|
||||
* and it provides the methods for SSL specific matters.
|
||||
* <P>
|
||||
*
|
||||
* @version 1.0
|
||||
* @see LDAPSocketFactory
|
||||
* @see LDAPConnection#LDAPConnection(netscape.ldap.LDAPSocketFactory)
|
||||
*/
|
||||
public interface LDAPSSLSocketFactoryExt extends LDAPSocketFactory {
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if client authentication is enabled.
|
||||
* @see netscape.ldap.LDAPSSLSocketFactory#enableClientAuth
|
||||
*/
|
||||
public boolean isClientAuth();
|
||||
|
||||
/**
|
||||
* Returns the suite of ciphers used for SSL connections made through
|
||||
* sockets created by this factory.
|
||||
*
|
||||
* @return The suite of ciphers used.
|
||||
*/
|
||||
public Object getCipherSuites();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,348 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
* Creates an SSL socket connection to an LDAP Server. This class is provided
|
||||
* by the package in which the SSL socket does not extend Socket object.
|
||||
* The class internally provides a wrapper to convert the SSL socket extending
|
||||
* the Object class to the one extending the Socket class.
|
||||
* This factory class implements the <CODE>LDAPSocketFactory</CODE> interface.
|
||||
* <P>
|
||||
*
|
||||
* To use this class, pass the instance of this factory object to the
|
||||
* <CODE>LDAPConnection</CODE> constructor.
|
||||
*
|
||||
* @version 1.0
|
||||
* @see LDAPSocketFactory
|
||||
* @see LDAPConnection#LDAPConnection(netscape.ldap.LDAPSocketFactory)
|
||||
*/
|
||||
public class LDAPSSLSocketWrapFactory implements LDAPSSLSocketFactoryExt {
|
||||
|
||||
/**
|
||||
* The constructor with the specified package for security
|
||||
* @param className The name of a class which has an implementation
|
||||
* of SSL Socket extending Object class.
|
||||
*/
|
||||
public LDAPSSLSocketWrapFactory(String className) {
|
||||
m_packageName = new String(className);
|
||||
}
|
||||
|
||||
/**
|
||||
* The constructor with the specified package for security and the
|
||||
* specified cipher suites.
|
||||
* @param className The name of a class which has an implementation
|
||||
* of SSL Socket extending Object class.
|
||||
* @param cipherSuites The cipher suites.
|
||||
*/
|
||||
public LDAPSSLSocketWrapFactory(String className, Object cipherSuites) {
|
||||
m_packageName = new String(className);
|
||||
m_cipherSuites = cipherSuites;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns socket to the specified host name and port number.
|
||||
* @param host The host to connect to
|
||||
* @param port The port number
|
||||
* @return The socket to the host name and port number as passed in.
|
||||
* @exception LDAPException A socket to the specified host and port
|
||||
* could not be created.
|
||||
*/
|
||||
public Socket makeSocket(String host, int port) throws LDAPException {
|
||||
|
||||
LDAPSSLSocket s = null;
|
||||
|
||||
try {
|
||||
if (m_cipherSuites == null)
|
||||
s = new LDAPSSLSocket(host, port, m_packageName);
|
||||
else
|
||||
s = new LDAPSSLSocket(host, port, m_packageName,
|
||||
m_cipherSuites);
|
||||
return s;
|
||||
} catch (Exception e) {
|
||||
System.err.println("Exception: "+e.toString());
|
||||
throw new LDAPException("Failed to create SSL socket",
|
||||
LDAPException.CONNECT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if client authentication is to be used.
|
||||
* @return true if client authentication is enabled, otherwise, false if
|
||||
* client authentication is disabled.
|
||||
*/
|
||||
public boolean isClientAuth() {
|
||||
return m_clientAuth;
|
||||
}
|
||||
|
||||
/**
|
||||
* <B>(Not implemented yet)</B> <BR>
|
||||
* Enables client authentication for an application running in
|
||||
* a java VM which provides transparent certificate database management.
|
||||
* Calling this method has no effect after makeSocket() has been
|
||||
* called.
|
||||
* @exception LDAPException Since this method is not yet implemented,
|
||||
* calling this method throws an exception.
|
||||
*/
|
||||
public void enableClientAuth() throws LDAPException {
|
||||
throw new LDAPException("Client Authentication is not implemented yet.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the class that implements SSL sockets for this factory.
|
||||
*
|
||||
* @return The name of the class that implements SSL sockets for this factory.
|
||||
*/
|
||||
public String getSSLSocketImpl() {
|
||||
return m_packageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the suite of ciphers used for SSL connections made through
|
||||
* sockets created by this factory.
|
||||
*
|
||||
* @return The suite of ciphers used.
|
||||
*/
|
||||
public Object getCipherSuites() {
|
||||
return m_cipherSuites;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if client authentication is on.
|
||||
*/
|
||||
private boolean m_clientAuth = false;
|
||||
|
||||
/**
|
||||
* Name of class implementing SSLSocket.
|
||||
*/
|
||||
private String m_packageName = null;
|
||||
|
||||
/**
|
||||
* The cipher suites
|
||||
*/
|
||||
private Object m_cipherSuites = null;
|
||||
}
|
||||
|
||||
// LDAPSSLSocket class wraps the implementation of the SSL socket
|
||||
class LDAPSSLSocket extends Socket {
|
||||
|
||||
public LDAPSSLSocket(String host, int port, String packageName)
|
||||
throws LDAPException {
|
||||
super();
|
||||
m_packageName = packageName;
|
||||
try {
|
||||
// instantiate the SSLSocketFactory implementation, and
|
||||
// find the right constructor
|
||||
Class c = Class.forName(m_packageName);
|
||||
java.lang.reflect.Constructor[] m = c.getConstructors();
|
||||
|
||||
for (int i = 0; i < m.length; i++) {
|
||||
/* Check if the signature is right: String, int */
|
||||
Class[] params = m[i].getParameterTypes();
|
||||
|
||||
if ((params.length == 2) &&
|
||||
(params[0].getName().equals("java.lang.String")) &&
|
||||
(params[1].getName().equals("int"))) {
|
||||
Object[] args = new Object[2];
|
||||
args[0] = host;
|
||||
args[1] = new Integer(port);
|
||||
m_socket = (Object)(m[i].newInstance(args));
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new LDAPException("No appropriate constructor in " +
|
||||
m_packageName, LDAPException.PARAM_ERROR);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new LDAPException("Class " + m_packageName + " not found",
|
||||
LDAPException.OTHER);
|
||||
} catch (Exception e) {
|
||||
throw new LDAPException("Failed to create SSL socket",
|
||||
LDAPException.CONNECT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public LDAPSSLSocket(String host, int port, String packageName,
|
||||
Object cipherSuites) throws LDAPException {
|
||||
super();
|
||||
m_packageName = packageName;
|
||||
String cipherClassName = null;
|
||||
if (cipherSuites != null)
|
||||
cipherClassName = cipherSuites.getClass().getName();
|
||||
|
||||
try {
|
||||
// instantiate the SSLSocketFactory implementation, and
|
||||
// find the right constructor
|
||||
Class c = Class.forName(m_packageName);
|
||||
java.lang.reflect.Constructor[] m = c.getConstructors();
|
||||
|
||||
for (int i = 0; i < m.length; i++) {
|
||||
/* Check if the signature is right: String, int */
|
||||
Class[] params = m[i].getParameterTypes();
|
||||
if (cipherSuites == null)
|
||||
throw new LDAPException("Cipher Suites is required");
|
||||
|
||||
if ((params.length == 3) &&
|
||||
(params[0].getName().equals("java.lang.String")) &&
|
||||
(params[1].getName().equals("int")) &&
|
||||
(params[2].getName().equals(cipherClassName))) {
|
||||
Object[] args = new Object[3];
|
||||
args[0] = host;
|
||||
args[1] = new Integer(port);
|
||||
args[2] = cipherSuites;
|
||||
m_socket = (Object)(m[i].newInstance(args));
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new LDAPException("No appropriate constructor in " +
|
||||
m_packageName, LDAPException.PARAM_ERROR);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new LDAPException("Class " + m_packageName + " not found",
|
||||
LDAPException.OTHER);
|
||||
} catch (Exception e) {
|
||||
throw new LDAPException("Failed to create SSL socket",
|
||||
LDAPException.CONNECT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
try {
|
||||
Object obj = invokeMethod(m_socket, "getInputStream", null);
|
||||
return (InputStream)obj;
|
||||
} catch (LDAPException e) {
|
||||
printDebug(e.toString());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() {
|
||||
try {
|
||||
Object obj = invokeMethod(m_socket, "getOutputStream", null);
|
||||
return (OutputStream)obj;
|
||||
} catch (LDAPException e) {
|
||||
printDebug(e.toString());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
try {
|
||||
invokeMethod(m_socket, "close", null);
|
||||
} catch (LDAPException e) {
|
||||
printDebug(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public void close(boolean wait) throws IOException {
|
||||
try {
|
||||
Object[] args = new Object[1];
|
||||
args[0] = new Boolean(wait);
|
||||
invokeMethod(m_socket, "close", args);
|
||||
} catch (LDAPException e) {
|
||||
printDebug(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public InetAddress getInetAddress() {
|
||||
try {
|
||||
Object obj = invokeMethod(m_socket, "getInetAddress", null);
|
||||
return (InetAddress)obj;
|
||||
} catch (LDAPException e) {
|
||||
printDebug(e.toString());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getLocalPort() {
|
||||
try {
|
||||
Object obj = invokeMethod(m_socket, "getLocalPort", null);
|
||||
return ((Integer)obj).intValue();
|
||||
} catch (LDAPException e) {
|
||||
printDebug(e.toString());
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
try {
|
||||
Object obj = invokeMethod(m_socket, "getPort", null);
|
||||
return ((Integer)obj).intValue();
|
||||
} catch (LDAPException e) {
|
||||
printDebug(e.toString());
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private Object invokeMethod(Object obj, String name, Object[] args) throws
|
||||
LDAPException {
|
||||
try {
|
||||
java.lang.reflect.Method m = getMethod(name);
|
||||
if (m != null) {
|
||||
return (m.invoke(obj, args));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new LDAPException("Invoking "+name+": "+
|
||||
e.toString(), LDAPException.PARAM_ERROR);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private java.lang.reflect.Method getMethod(String name) throws
|
||||
LDAPException {
|
||||
try {
|
||||
java.lang.reflect.Method method = null;
|
||||
if ((method = (java.lang.reflect.Method)(m_methodLookup.get(name)))
|
||||
!= null)
|
||||
return method;
|
||||
|
||||
Class c = Class.forName(m_packageName);
|
||||
java.lang.reflect.Method[] m = c.getMethods();
|
||||
for (int i = 0; i < m.length; i++ ) {
|
||||
if (m[i].getName().equals(name)) {
|
||||
m_methodLookup.put(name, m[i]);
|
||||
return m[i];
|
||||
}
|
||||
}
|
||||
throw new LDAPException("Method " + name + " not found in " +
|
||||
m_packageName);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new LDAPException("Class "+ m_packageName + " not found");
|
||||
}
|
||||
}
|
||||
|
||||
private void printDebug(String msg) {
|
||||
if (m_debug) {
|
||||
System.out.println(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private final boolean m_debug = true;
|
||||
private Object m_socket;
|
||||
private Hashtable m_methodLookup = new Hashtable();
|
||||
private String m_packageName = null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,273 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import netscape.ldap.client.*;
|
||||
import netscape.ldap.client.opers.*;
|
||||
import netscape.ldap.ber.stream.*;
|
||||
import netscape.ldap.util.*;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
|
||||
/**
|
||||
* Authenticates to a server using SASL
|
||||
*/
|
||||
public class LDAPSaslBind implements LDAPBind, Serializable {
|
||||
/**
|
||||
* Construct an object which can authenticate to an LDAP server
|
||||
* using the specified name and a specified SASL mechanism.
|
||||
*
|
||||
* @param dn If non-null and non-empty, specifies that the connection and
|
||||
* all operations through it should be authenticated with dn as the
|
||||
* distinguished name.
|
||||
* @param mechanisms Array of mechanism names, e.g. { "GSSAPI", "SKEY" }
|
||||
* @param props Optional additional properties of the desired
|
||||
* authentication mechanism, e.g. minimum security level.
|
||||
* @param cbh A class which may be called by the SASL framework to
|
||||
* obtain additional information required.
|
||||
*/
|
||||
public LDAPSaslBind( String dn,
|
||||
String[] mechanisms,
|
||||
String packageName,
|
||||
Hashtable props,
|
||||
CallbackHandler cbh ) {
|
||||
_dn = dn;
|
||||
_mechanisms = mechanisms;
|
||||
_packageName = packageName;
|
||||
_props = props;
|
||||
_cbh = cbh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates to the LDAP server (that the object is currently
|
||||
* connected to) using the parameter that were provided to the
|
||||
* constructor. If the requested SASL mechanism is not
|
||||
* available, an exception is thrown. If the object has been
|
||||
* disconnected from an LDAP server, this method attempts to reconnect
|
||||
* to the server. If the object had already authenticated, the old
|
||||
* authentication is discarded.
|
||||
*
|
||||
* @param ldc An active connection to a server, which will have
|
||||
* the new authentication state on return from the method.
|
||||
* @exception LDAPException Failed to authenticate to the LDAP server.
|
||||
*/
|
||||
public void bind( LDAPConnection ldc ) throws LDAPException {
|
||||
if ( _props == null ) {
|
||||
_props = new Hashtable();
|
||||
}
|
||||
if ( (!_props.containsKey( CLIENTPKGS )) &&
|
||||
(System.getProperty( CLIENTPKGS ) == null) ) {
|
||||
_props.put( CLIENTPKGS, ldc.DEFAULT_SASL_PACKAGE );
|
||||
}
|
||||
_saslClient = getClient( ldc, _packageName );
|
||||
if ( _saslClient != null ) {
|
||||
bind( ldc, true );
|
||||
return;
|
||||
} else {
|
||||
ldc.printDebug( "LDAPSaslBind.bind: getClient " +
|
||||
"returned null" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a SaslClient object from the Sasl framework
|
||||
*
|
||||
* @param ldc Contains the host name
|
||||
* @param packageName Package containing a ClientFactory
|
||||
* @return A SaslClient supporting one of the mechanisms
|
||||
* of the member variable _mechanisms
|
||||
* @exception LDAPException on error producing a client
|
||||
*/
|
||||
private Object getClient( LDAPConnection ldc, String packageName )
|
||||
throws LDAPException {
|
||||
try {
|
||||
Object[] args = new Object[6];
|
||||
args[0] = _mechanisms;
|
||||
args[1] = _dn;
|
||||
args[2] = "ldap";
|
||||
args[3] = ldc.getHost();
|
||||
args[4] = _props;
|
||||
args[5] = _cbh;
|
||||
String[] argNames = new String[6];
|
||||
argNames[0] = "[Ljava.lang.String;";
|
||||
argNames[1] = "java.lang.String";
|
||||
argNames[2] = "java.lang.String";
|
||||
argNames[3] = "java.lang.String";
|
||||
argNames[4] = "java.util.Hashtable";
|
||||
argNames[5] = CALLBACK_HANDLER;
|
||||
|
||||
// Get a mechanism driver
|
||||
return DynamicInvoker.invokeMethod(null,
|
||||
packageName+".Sasl",
|
||||
"createSaslClient",
|
||||
args, argNames);
|
||||
|
||||
} catch (Exception e) {
|
||||
ldc.printDebug( "LDAPSaslBind.getClient: " +
|
||||
packageName+".Sasl.createSaslClient: " +
|
||||
e );
|
||||
throw new LDAPException(e.toString(), LDAPException.OTHER);
|
||||
}
|
||||
}
|
||||
|
||||
void bind(LDAPConnection ldc, boolean rebind)
|
||||
throws LDAPException {
|
||||
|
||||
if ((ldc.isConnected() && rebind) ||
|
||||
!ldc.isConnected()) {
|
||||
try {
|
||||
// Get the initial request to start authentication
|
||||
String className = _saslClient.getClass().getName();
|
||||
ldc.printDebug( "LDAPSaslBind.bind: calling " +
|
||||
className+".createInitialResponse" );
|
||||
byte[] outVals =
|
||||
(byte[])DynamicInvoker.invokeMethod(
|
||||
_saslClient,
|
||||
className,
|
||||
"createInitialResponse", null, null);
|
||||
|
||||
String mechanismName =
|
||||
(String)DynamicInvoker.invokeMethod(
|
||||
_saslClient,
|
||||
className,
|
||||
"getMechanismName", null, null);
|
||||
ldc.printDebug( "LDAPSaslBind.bind: mechanism " +
|
||||
"name is " +
|
||||
mechanismName );
|
||||
boolean isExternal = isExternalMechanism(mechanismName);
|
||||
int resultCode = LDAPException.SASL_BIND_IN_PROGRESS;
|
||||
JDAPBindResponse response = null;
|
||||
while (!checkForSASLBindCompletion(resultCode)) {
|
||||
ldc.printDebug( "LDAPSaslBind.bind: calling " +
|
||||
"saslBind" );
|
||||
response = saslBind(ldc, mechanismName, outVals);
|
||||
resultCode = response.getResultCode();
|
||||
ldc.printDebug( "LDAPSaslBind.bind: saslBind " +
|
||||
"returned " + resultCode );
|
||||
if (isExternal) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String challenge = response.getCredentials();
|
||||
byte[] b = challenge.getBytes();
|
||||
|
||||
Object[] args = {b};
|
||||
String[] argNames = {"[B"}; // class name for byte array
|
||||
|
||||
outVals =
|
||||
(byte[])DynamicInvoker.invokeMethod(
|
||||
_saslClient,
|
||||
mechanismName, "evaluateChallenge",
|
||||
args, argNames);
|
||||
}
|
||||
|
||||
// Make sure authentication REALLY is complete
|
||||
Boolean bool =
|
||||
(Boolean)DynamicInvoker.invokeMethod(
|
||||
_saslClient,
|
||||
mechanismName, "isComplete", null, null);
|
||||
if (!bool.booleanValue()) {
|
||||
// Authentication session hijacked!
|
||||
throw new LDAPException("The server indicates that " +
|
||||
"authentication is successful" +
|
||||
", but the SASL driver " +
|
||||
"indicates that authentication" +
|
||||
" is not yet done.",
|
||||
LDAPException.OTHER);
|
||||
}
|
||||
|
||||
Object[] args = {ldc.getInputStream()};
|
||||
String[] argNames = {"java.io.InputStream"};
|
||||
InputStream is =
|
||||
(InputStream)DynamicInvoker.invokeMethod(
|
||||
_saslClient,
|
||||
mechanismName, "getInputStream", args, argNames);
|
||||
ldc.setInputStream(is);
|
||||
args[0] = ldc.getOutputStream();
|
||||
argNames[0] = "java.io.OutputStream";
|
||||
OutputStream os =
|
||||
(OutputStream)DynamicInvoker.invokeMethod(
|
||||
_saslClient,
|
||||
mechanismName, "getOutputStream", args, argNames);
|
||||
ldc.setOutputStream(os);
|
||||
ldc.updateThreadConnTable();
|
||||
} catch (LDAPException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new LDAPException(e.toString(), LDAPException.OTHER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isExternalMechanism(String name) {
|
||||
return name.equalsIgnoreCase( LDAPConnection.EXTERNAL_MECHANISM );
|
||||
}
|
||||
|
||||
private boolean checkForSASLBindCompletion(int resultCode)
|
||||
throws LDAPException{
|
||||
|
||||
if (resultCode == LDAPException.SUCCESS) {
|
||||
return true;
|
||||
} else if (resultCode == LDAPException.SASL_BIND_IN_PROGRESS) {
|
||||
return false;
|
||||
} else {
|
||||
throw new LDAPException("Authentication failed", resultCode);
|
||||
}
|
||||
}
|
||||
|
||||
private JDAPBindResponse saslBind(LDAPConnection ldc,
|
||||
String mechanismName,
|
||||
byte[] credentials)
|
||||
throws LDAPException {
|
||||
|
||||
LDAPResponseListener myListener = ldc.getResponseListener ();
|
||||
|
||||
try {
|
||||
ldc.sendRequest(new JDAPBindRequest(3,
|
||||
_dn,
|
||||
mechanismName,
|
||||
credentials),
|
||||
myListener, ldc.getConstraints());
|
||||
LDAPMessage response = myListener.getResponse();
|
||||
|
||||
JDAPProtocolOp protocolOp = response.getProtocolOp();
|
||||
if (protocolOp instanceof JDAPBindResponse) {
|
||||
return (JDAPBindResponse)protocolOp;
|
||||
} else {
|
||||
throw new LDAPException("Unknown response from the " +
|
||||
"server during SASL bind",
|
||||
LDAPException.OTHER);
|
||||
}
|
||||
} finally {
|
||||
ldc.releaseResponseListener(myListener);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String CALLBACK_HANDLER =
|
||||
"javax.security.auth.callback.CallbackHandler";
|
||||
private static final String CLIENTPKGS =
|
||||
"javax.security.sasl.client.pkgs";
|
||||
private String _dn;
|
||||
private String[] _mechanisms;
|
||||
private String _packageName;
|
||||
private Hashtable _props;
|
||||
private CallbackHandler _cbh;
|
||||
private Object _saslClient = null;
|
||||
}
|
||||
589
mozilla/directory/java-sdk/ldapjdk/netscape/ldap/LDAPSchema.java
Normal file
589
mozilla/directory/java-sdk/ldapjdk/netscape/ldap/LDAPSchema.java
Normal file
@@ -0,0 +1,589 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This object represents the schema of an LDAP v3 server.
|
||||
* You can use the <CODE>fetchSchema</CODE> method to retrieve
|
||||
* the schema used by a server. (The server must support LDAP v3
|
||||
* and the capability to retrieve the schema over the LDAP protocol.)
|
||||
* <P>
|
||||
*
|
||||
* After you retrieve the schema, you can use this object to get
|
||||
* the object class, attribute type, and matching rule descriptions
|
||||
* in the schema. You can also add your own object classes,
|
||||
* attribute types, and matching rules to the schema.
|
||||
* <P>
|
||||
*
|
||||
* To remove any object classes, attribute types, and matching rules
|
||||
* that you added, call the <CODE>remove</CODE> methods of the
|
||||
* <CODE>LDAPObjectClassSchema</CODE>, <CODE>LDAPAttributeSchema</CODE>,
|
||||
* and <CODE>LDAPMatchingRuleSchema</CODE> classes. (This method is
|
||||
* inherited from the <CODE>LDAPSchemaElement</CODE> class.)
|
||||
* <P>
|
||||
*
|
||||
* The following class is an example of an LDAP client that can
|
||||
* fetch the schema, get and print object class descriptions and
|
||||
* attribute type descriptions, and add object classes and attribute
|
||||
* types to the schema over the LDAP protocol.
|
||||
* <P>
|
||||
*
|
||||
* <PRE>
|
||||
* import netscape.ldap.*;
|
||||
* public class TestSchema {
|
||||
* public static void main( String[] args ) {
|
||||
* String HOSTNAME = "ldap.netscape.com";
|
||||
* int PORT_NUMBER = DEFAULT_PORT;
|
||||
* String ROOT_DN = "cn=Directory Manager";
|
||||
* String ROOT_PASSWORD = "23skidoo";
|
||||
*
|
||||
* LDAPConnection ld = new LDAPConnection();
|
||||
*
|
||||
* // Construct a new <CODE>LDAPSchema</CODE> object to get the schema.
|
||||
* LDAPSchema dirSchema = new LDAPSchema();
|
||||
*
|
||||
* try {
|
||||
* // Connect to the server.
|
||||
* ld.connect( HOSTNAME, PORT_NUMBER );
|
||||
*
|
||||
* // Get the schema from the directory.
|
||||
* dirSchema.fetchSchema( ld );
|
||||
*
|
||||
* // Get and print the inetOrgPerson object class description.
|
||||
* LDAPObjectClassSchema objClass = dirSchema.getObjectClass(
|
||||
* "inetOrgPerson" );
|
||||
* if ( objClass != null ) {
|
||||
* System.out.println("inetOrgPerson := "+objClass.toString());
|
||||
* }
|
||||
*
|
||||
* // Get and print the definition of the userPassword attribute.
|
||||
* LDAPAttributeSchema attrType = dirSchema.getAttribute(
|
||||
* "userpassword" );
|
||||
* if ( attrType != null ) {
|
||||
* System.out.println("userPassword := " + attrType.toString());
|
||||
* }
|
||||
*
|
||||
* // Create a new object class definition.
|
||||
* String[] requiredAttrs = {"cn", "mail"};
|
||||
* String[] optionalAttrs = {"sn", "phoneNumber"};
|
||||
* LDAPObjectClassSchema newObjClass =
|
||||
* new LDAPObjectClassSchema( "newInetOrgPerson",
|
||||
* "1.2.3.4.5.6.7",
|
||||
* "top",
|
||||
* "Experiment",
|
||||
* requiredAttrs,
|
||||
* optionalAttrs );
|
||||
*
|
||||
* // Authenticate as root DN to get permissions to edit the schema.
|
||||
* ld.authenticate( ROOT_DN, ROOT_PASSWORD );
|
||||
*
|
||||
* // Add the new object class to the schema.
|
||||
* newObjClass.add( ld );
|
||||
*
|
||||
* // Create a new attribute type "hairColor".
|
||||
* LDAPAttributeSchema newAttrType =
|
||||
* new LDAPAttributeSchema( "hairColor",
|
||||
* "1.2.3.4.5.4.3.2.1",
|
||||
* "Blonde, red, etc",
|
||||
* LDAPAttributeSchema.cis,
|
||||
* false );
|
||||
* // Add a custom qualifier
|
||||
* newObjClass.setQualifier( "X-OWNER", "John Jacobson" );
|
||||
*
|
||||
* // Add the new attribute type to the schema.
|
||||
* newAttrType.add( ld );
|
||||
*
|
||||
* // Fetch the schema again to verify that changes were made.
|
||||
* dirSchema.fetchSchema( ld );
|
||||
*
|
||||
* // Get and print the new attribute type.
|
||||
* newAttrType = dirSchema.getAttribute( "hairColor" );
|
||||
* if ( newAttrType != null ) {
|
||||
* System.out.println("hairColor := " + newAttrType.toString());
|
||||
* }
|
||||
*
|
||||
* // Get and print the new object class.
|
||||
* newObjClass = dirSchema.getObjectClass( "newInetOrgPerson" );
|
||||
* if ( newObjClass != null ) {
|
||||
* System.out.println("newInetOrgPerson := " +newObjClass.toString());
|
||||
* }
|
||||
*
|
||||
* ld.disconnect();
|
||||
*
|
||||
* } catch ( Exception e ) {
|
||||
* System.err.println( e.toString() );
|
||||
* System.exit( 1 );
|
||||
* }
|
||||
*
|
||||
* System.exit( 0 );
|
||||
* }
|
||||
* }
|
||||
* </PRE>
|
||||
*
|
||||
* If you are using the Netscape Directory Server 3.0, you can also
|
||||
* verify that the class and attribute type have been added through
|
||||
* the directory server manager (go to Schema | Edit or View Attributes
|
||||
* or Schema | Edit or View Object Classes).
|
||||
* <P>
|
||||
*
|
||||
* To remove the classes and attribute types added by the example,
|
||||
* see the examples under the <CODE>LDAPSchemaElement</CODE> class.
|
||||
* <P>
|
||||
*
|
||||
* @see netscape.ldap.LDAPAttributeSchema
|
||||
* @see netscape.ldap.LDAPObjectClassSchema
|
||||
* @see netscape.ldap.LDAPMatchingRuleSchema
|
||||
* @see netscape.ldap.LDAPSchemaElement
|
||||
* @version 1.0
|
||||
* @author Rob Weltman
|
||||
**/
|
||||
public class LDAPSchema {
|
||||
/**
|
||||
* Constructs a new <CODE>LDAPSchema</CODE> object.
|
||||
* Once you construct the object, you can get
|
||||
* the schema by calling <CODE>fetchSchema</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* You can also print out the schema by using the
|
||||
* <CODE>main</CODE> method. For example, you can enter
|
||||
* the following command:
|
||||
* <PRE>
|
||||
* java netscape.ldap.LDAPSchema myhost.mydomain.com 389
|
||||
* </PRE>
|
||||
*
|
||||
* Note that you need to call <CODE>fetchSchema</CODE>
|
||||
* to get the schema from the server. Constructing the
|
||||
* object does not fetch the schema.
|
||||
* <P>
|
||||
*
|
||||
* @see netscape.ldap.LDAPSchema#fetchSchema
|
||||
* @see netscape.ldap.LDAPSchema#main
|
||||
*/
|
||||
public LDAPSchema() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an object class schema definition to the current schema.
|
||||
* You can also add object class schema definitions by calling the
|
||||
* <CODE>add</CODE> method of your newly constructed
|
||||
* <CODE>LDAPObjectClassSchema</CODE> object.
|
||||
* <P>
|
||||
*
|
||||
* To remove an object class schema definition that you have added,
|
||||
* call the <CODE>getObjectClass</CODE> method to get the
|
||||
* <CODE>LDAPObjectClassSchema</CODE> object representing your
|
||||
* object class and call the <CODE>remove</CODE> method.
|
||||
* <P>
|
||||
*
|
||||
* <B>NOTE: </B>For information on the <CODE>add</CODE> and
|
||||
* <CODE>remove</CODE> methods of <CODE>LDAPObjectClassSchema</CODE>,
|
||||
* see the documentation for <CODE>LDAPSchemaElement</CODE>.
|
||||
* (These methods are inherited from <CODE>LDAPSchemaElement</CODE>.)
|
||||
* <P>
|
||||
*
|
||||
* @param objectSchema <CODE>LDAPObjectClassSchema</CODE> object
|
||||
* representing the object class schema definition that you want
|
||||
* to add.
|
||||
* @see netscape.ldap.LDAPObjectClassSchema
|
||||
* @see netscape.ldap.LDAPSchemaElement#add
|
||||
* @see netscape.ldap.LDAPSchemaElement#remove
|
||||
*/
|
||||
protected void addObjectClass( LDAPObjectClassSchema objectSchema ) {
|
||||
objectClasses.put( objectSchema.getName().toLowerCase(),
|
||||
objectSchema );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an attribute type schema definition to the current schema.
|
||||
* You can also add attribute type schema definitions by calling the
|
||||
* <CODE>add</CODE> method of your newly constructed
|
||||
* <CODE>LDAPAttributeSchema</CODE> object.
|
||||
* <P>
|
||||
*
|
||||
* To remove an attribute type schema definition that you have added,
|
||||
* call the <CODE>getAttribute</CODE> method to get the
|
||||
* <CODE>LDAPAttributeSchema</CODE> object representing your
|
||||
* attribute type and call the <CODE>remove</CODE> method.
|
||||
* <P>
|
||||
*
|
||||
* <B>NOTE: </B>For information on the <CODE>add</CODE> and
|
||||
* <CODE>remove</CODE> methods of <CODE>LDAPAttributeSchema</CODE>,
|
||||
* see the documentation for <CODE>LDAPSchemaElement</CODE>.
|
||||
* (These methods are inherited from <CODE>LDAPSchemaElement</CODE>.)
|
||||
* <P>
|
||||
*
|
||||
* @param attrSchema <CODE>LDAPAttributeSchema</CODE> object
|
||||
* representing the attribute type schema definition that you
|
||||
* want to add.
|
||||
* @see netscape.ldap.LDAPAttributeSchema
|
||||
* @see netscape.ldap.LDAPSchemaElement#add
|
||||
* @see netscape.ldap.LDAPSchemaElement#remove
|
||||
*/
|
||||
protected void addAttribute( LDAPAttributeSchema attrSchema ) {
|
||||
attributes.put( attrSchema.getName().toLowerCase(), attrSchema );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a matching rule schema definition to the current schema.
|
||||
* You can also add matching rule schema definitions by calling the
|
||||
* <CODE>add</CODE> method of your newly constructed
|
||||
* <CODE>LDAPMatchingRuleSchema</CODE> object.
|
||||
* <P>
|
||||
*
|
||||
* To remove an attribute type schema definition that you have added,
|
||||
* call the <CODE>getMatchingRule</CODE> method to get the
|
||||
* <CODE>LDAPMatchingRuleSchema</CODE> object representing your
|
||||
* matching rule and call the <CODE>remove</CODE> method.
|
||||
* <P>
|
||||
*
|
||||
* <B>NOTE: </B>For information on the <CODE>add</CODE> and
|
||||
* <CODE>remove</CODE> methods of <CODE>LDAPMatchingRuleSchema</CODE>,
|
||||
* see the documentation for <CODE>LDAPSchemaElement</CODE>.
|
||||
* (These methods are inherited from <CODE>LDAPSchemaElement</CODE>.)
|
||||
* <P>
|
||||
*
|
||||
* @param matchSchema <CODE>LDAPMatchingRuleSchema</CODE> object
|
||||
* representing the matching rule schema definition that you want
|
||||
* to add.
|
||||
* @see netscape.ldap.LDAPMatchingRuleSchema
|
||||
* @see netscape.ldap.LDAPSchemaElement#add
|
||||
* @see netscape.ldap.LDAPSchemaElement#remove
|
||||
*/
|
||||
protected void addMatchingRule( LDAPMatchingRuleSchema matchSchema ) {
|
||||
matchingRules.put( matchSchema.getName().toLowerCase(), matchSchema );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an enumeration ofthe object class definitions in this schema.
|
||||
* @return An enumeration ofobject class definitions.
|
||||
*/
|
||||
public Enumeration getObjectClasses() {
|
||||
return objectClasses.elements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an enumeration ofthe attribute type definitions in this schema.
|
||||
* @return An enumeration ofattribute type definitions.
|
||||
*/
|
||||
public Enumeration getAttributes() {
|
||||
return attributes.elements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an enumeration ofthe matching rule definitions in this schema.
|
||||
* @return An enumeration ofmatching rule definitions.
|
||||
*/
|
||||
public Enumeration getMatchingRules() {
|
||||
return matchingRules.elements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the definition of the object class with the specified name.
|
||||
* @param name Name of the object class that you want to find.
|
||||
* @return An <CODE>LDAPObjectClassSchema</CODE> object representing
|
||||
* the object class definition, or <CODE>null</CODE> if not found.
|
||||
*/
|
||||
public LDAPObjectClassSchema getObjectClass( String name ) {
|
||||
return (LDAPObjectClassSchema)objectClasses.get( name.toLowerCase() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the definition of the attribute type with the specified name.
|
||||
* @param name Name of the attribute type that you want to find.
|
||||
* @return An <CODE>LDAPAttributeSchema</CODE> object representing
|
||||
* the attribute type definition, or <CODE>null</CODE> if not found.
|
||||
*/
|
||||
public LDAPAttributeSchema getAttribute( String name ) {
|
||||
return (LDAPAttributeSchema)attributes.get( name.toLowerCase() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the definition of a matching rule with the specified name.
|
||||
* @param name Name of the matching rule that you want to find.
|
||||
* @return An <CODE>LDAPMatchingRuleSchema</CODE> object representing
|
||||
* the matching rule definition, or <CODE>null</CODE> if not found.
|
||||
*/
|
||||
public LDAPMatchingRuleSchema getMatchingRule( String name ) {
|
||||
return (LDAPMatchingRuleSchema)matchingRules.get( name.toLowerCase() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an enumeration of the names of the object classes in this schema.
|
||||
* @return An enumeration of object class names (all lower-case).
|
||||
*/
|
||||
public Enumeration getObjectClassNames() {
|
||||
return objectClasses.keys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an enumeration of the names of the attribute types in this schema.
|
||||
* @return An enumeration of attribute names (all lower-case).
|
||||
*/
|
||||
public Enumeration getAttributeNames() {
|
||||
return attributes.keys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an enumeration of the names of the matching rules in this schema.
|
||||
* @return An enumeration of matching rule names (all lower-case).
|
||||
*/
|
||||
public Enumeration getMatchingRuleNames() {
|
||||
return matchingRules.keys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the schema for a specific entry.
|
||||
* @param ld An active connection to a Directory Server.
|
||||
* @param dn The entry for which to fetch schema.
|
||||
* @exception LDAPException on failure.
|
||||
*/
|
||||
public void fetchSchema( LDAPConnection ld, String dn )
|
||||
throws LDAPException {
|
||||
/* Find the subschemasubentry value for this DN */
|
||||
String entryName = getSchemaDN( ld, dn );
|
||||
Enumeration en;
|
||||
|
||||
/* Get the entire schema definition entry */
|
||||
LDAPEntry entry = readSchema( ld, entryName );
|
||||
/* Get all object class definitions */
|
||||
LDAPAttribute attr = entry.getAttribute( "objectclasses" );
|
||||
if ( attr != null ) {
|
||||
en = attr.getStringValues();
|
||||
while( en.hasMoreElements() ) {
|
||||
LDAPObjectClassSchema sch =
|
||||
new LDAPObjectClassSchema( (String)en.nextElement() );
|
||||
addObjectClass( sch );
|
||||
}
|
||||
}
|
||||
|
||||
/* Get all attribute definitions */
|
||||
attr = entry.getAttribute( "attributetypes" );
|
||||
if ( attr != null ) {
|
||||
en = attr.getStringValues();
|
||||
while( en.hasMoreElements() ) {
|
||||
LDAPAttributeSchema sch =
|
||||
new LDAPAttributeSchema( (String)en.nextElement() );
|
||||
addAttribute( sch );
|
||||
}
|
||||
}
|
||||
|
||||
/* Matching rules are tricky, because we have to match up a
|
||||
rule with its use. First get all the uses. */
|
||||
Hashtable h = new Hashtable();
|
||||
attr = entry.getAttribute( "matchingruleuse" );
|
||||
if ( attr != null ) {
|
||||
en = attr.getStringValues();
|
||||
while( en.hasMoreElements() ) {
|
||||
String use = (String)en.nextElement();
|
||||
LDAPMatchingRuleSchema sch =
|
||||
new LDAPMatchingRuleSchema( null, use );
|
||||
h.put( sch.getOID(), use );
|
||||
}
|
||||
}
|
||||
/* Now get the rules, and assign uses to them */
|
||||
attr = entry.getAttribute( "matchingrules" );
|
||||
if ( attr != null ) {
|
||||
en = attr.getStringValues();
|
||||
while( en.hasMoreElements() ) {
|
||||
String raw = (String)en.nextElement();
|
||||
LDAPMatchingRuleSchema sch =
|
||||
new LDAPMatchingRuleSchema( raw, null );
|
||||
String use = (String)h.get( sch.getOID() );
|
||||
if ( use != null )
|
||||
sch = new LDAPMatchingRuleSchema( raw, use );
|
||||
addMatchingRule( sch );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the entire schema from the root of a Directory Server.
|
||||
* @param ld An active connection to a Directory Server.
|
||||
* @exception LDAPException on failure.
|
||||
*/
|
||||
public void fetchSchema( LDAPConnection ld ) throws LDAPException {
|
||||
fetchSchema( ld, "" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Read one attribute definition from a server to determine if
|
||||
* attribute syntaxes are quoted (a bug, present in Netscape
|
||||
* and Novell servers).
|
||||
* @param ld An active connection to a Directory Server.
|
||||
* @return <CODE>true</CODE> if standards-compliant
|
||||
* @exception LDAPException on failure.
|
||||
*/
|
||||
static boolean isAttributeSyntaxStandardsCompliant( LDAPConnection ld )
|
||||
throws LDAPException {
|
||||
|
||||
/* Check if this has already been investigated */
|
||||
String schemaBug = (String)ld.getProperty( ld.SCHEMA_BUG_PROPERTY );
|
||||
if ( schemaBug != null ) {
|
||||
return schemaBug.equalsIgnoreCase( "standard" );
|
||||
}
|
||||
|
||||
boolean compliant = true;
|
||||
/* Get the schema definitions for attributes */
|
||||
String entryName = getSchemaDN( ld, "" );
|
||||
String[] attrs = { "attributetypes" };
|
||||
LDAPEntry entry = readSchema( ld, entryName, attrs );
|
||||
/* Get all attribute definitions, and check the first one */
|
||||
LDAPAttribute attr = entry.getAttribute( "attributetypes" );
|
||||
if ( attr != null ) {
|
||||
Enumeration en = attr.getStringValues();
|
||||
if( en.hasMoreElements() ) {
|
||||
compliant = !LDAPAttributeSchema.isSyntaxQuoted(
|
||||
(String)en.nextElement() );
|
||||
}
|
||||
}
|
||||
ld.setProperty( ld.SCHEMA_BUG_PROPERTY, compliant ? "standard" :
|
||||
"NetscapeBug" );
|
||||
return compliant;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the schema (including the descriptions of its object
|
||||
* classes, attribute types, and matching rules) in an easily
|
||||
* readable format (not the same as the format expected by
|
||||
* an LDAP server).
|
||||
* @return A string containing the schema in printable format.
|
||||
*/
|
||||
public String toString() {
|
||||
String s = "Object classes:\n";
|
||||
Enumeration en = getObjectClasses();
|
||||
while( en.hasMoreElements() ) {
|
||||
s += en.nextElement().toString();
|
||||
s += '\n';
|
||||
}
|
||||
s += "Attributes:\n";
|
||||
en = getAttributes();
|
||||
while( en.hasMoreElements() ) {
|
||||
s += en.nextElement().toString();
|
||||
s += '\n';
|
||||
}
|
||||
s += "Matching rules:\n";
|
||||
en = getMatchingRules();
|
||||
while( en.hasMoreElements() ) {
|
||||
s += en.nextElement().toString();
|
||||
s += '\n';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the DN of the schema definitions for a specific entry.
|
||||
* @param ld An active connection to a Directory Server.
|
||||
* @param dn The entry for which to fetch schema.
|
||||
* @exception LDAPException on failure.
|
||||
*/
|
||||
static String getSchemaDN( LDAPConnection ld, String dn )
|
||||
throws LDAPException {
|
||||
if ( (ld == null) || !ld.isConnected() ) {
|
||||
throw new LDAPException( "No connection", LDAPException.OTHER );
|
||||
}
|
||||
String[] attrs = { "subschemasubentry" };
|
||||
LDAPEntry entry = readSchema( ld, dn, attrs );
|
||||
if ( entry == null ) {
|
||||
throw new LDAPException( "", LDAPException.NO_SUCH_OBJECT );
|
||||
}
|
||||
LDAPAttribute attr = entry.getAttribute( attrs[0] );
|
||||
String entryName = "cn=schema";
|
||||
if ( attr != null ) {
|
||||
Enumeration en = attr.getStringValues();
|
||||
if ( en.hasMoreElements() ) {
|
||||
entryName = (String)en.nextElement();
|
||||
}
|
||||
}
|
||||
return entryName;
|
||||
}
|
||||
|
||||
private static LDAPEntry readSchema( LDAPConnection ld, String dn,
|
||||
String[] attrs )
|
||||
throws LDAPException {
|
||||
LDAPSearchResults results = ld.search (dn, ld.SCOPE_BASE,
|
||||
"objectclass=subschema",
|
||||
attrs, false);
|
||||
if ( !results.hasMoreElements() ) {
|
||||
throw new LDAPException( "Cannot read schema",
|
||||
LDAPException.INSUFFICIENT_ACCESS_RIGHTS );
|
||||
}
|
||||
return results.next ();
|
||||
}
|
||||
|
||||
private static LDAPEntry readSchema( LDAPConnection ld, String dn )
|
||||
throws LDAPException {
|
||||
return readSchema( ld, dn, null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for "main" to print out schema elements.
|
||||
* @param en Enumeration of schema elements.
|
||||
*/
|
||||
private static void printEnum( Enumeration en ) {
|
||||
while( en.hasMoreElements() ) {
|
||||
LDAPSchemaElement s = (LDAPSchemaElement)en.nextElement();
|
||||
System.out.println( " " + s );
|
||||
// System.out.println( " " + s.getValue() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the schema from the LDAP server at the specified
|
||||
* host and port, and print out the schema (including descriptions
|
||||
* of its object classes, attribute types, and matching rules).
|
||||
* The schema is printed in an easily readable format (not the
|
||||
* same as the format expected by an LDAP server). For example,
|
||||
* you can enter the following command to print the schema:
|
||||
* <PRE>
|
||||
* java netscape.ldap.LDAPSchema myhost.mydomain.com 389
|
||||
* </PRE>
|
||||
*
|
||||
* @param args The host name and the port number of the LDAP server
|
||||
* (for example, <CODE>netscape.ldap.LDAPSchema directory.netscape.com
|
||||
* 389</CODE>).
|
||||
*/
|
||||
public static void main( String[] args ) {
|
||||
if ( args.length < 2 ) {
|
||||
System.err.println( "Usage: netscape.ldap.LDAPSchema HOST PORT" );
|
||||
System.exit(1 );
|
||||
}
|
||||
int port = Integer.parseInt( args[1] );
|
||||
LDAPConnection ld = new LDAPConnection();
|
||||
try {
|
||||
ld.connect( args[0], port );
|
||||
LDAPSchema schema = new LDAPSchema();
|
||||
schema.fetchSchema( ld );
|
||||
ld.disconnect();
|
||||
System.out.println( "Object classes: " );
|
||||
printEnum( schema.getObjectClasses() );
|
||||
System.out.println( "\nAttributes: " );
|
||||
printEnum( schema.getAttributes() );
|
||||
System.out.println( "\nMatching rules: " );
|
||||
printEnum( schema.getMatchingRules() );
|
||||
System.exit( 0 );
|
||||
} catch ( LDAPException e ) {
|
||||
System.err.println( e );
|
||||
}
|
||||
}
|
||||
|
||||
private Hashtable objectClasses = new Hashtable();
|
||||
private Hashtable attributes = new Hashtable();
|
||||
private Hashtable matchingRules = new Hashtable();
|
||||
}
|
||||
@@ -0,0 +1,675 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* Abstract class representing an element (such as an object class
|
||||
* definition, an attribute type definition, or a matching rule
|
||||
* definition) in the schema. The specific types of elements are
|
||||
* represented by the <CODE>LDAPObjectClassSchema</CODE>,
|
||||
* <CODE>LDAPAttributeSchema</CODE>, and <CODE>LDAPMatchingRuleSchema</CODE>
|
||||
* subclasses.
|
||||
* <P>
|
||||
*
|
||||
* <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
|
||||
* TARGET="_blank">RFC 2252, Lightweight Directory Access Protocol (v3):
|
||||
* Attribute Syntax Definitions</A> covers the types of information
|
||||
* that need to be specified in the definition of an object class,
|
||||
* attribute type, or matching rule. All of these schema elements
|
||||
* can specify the following information:
|
||||
* <P>
|
||||
*
|
||||
* <UL>
|
||||
* <LI>a name identifying the element
|
||||
* <LI>an OID identifying the element
|
||||
* <LI>a description of the element
|
||||
* <LI>a qualifier "OBSOLETE"
|
||||
* </UL>
|
||||
* <P>
|
||||
*
|
||||
* In addition, there are optional standard qualifiers for attribute
|
||||
* types (see LDAPAttributeSchema), and implementation-specific
|
||||
* qualifiers may be added. Non-standard qualifiers must have names
|
||||
* starting with X-, e.g. "X-OWNER 'John Jacobson'". Optional and
|
||||
* non-standard qualifiers can be accessed with <CODE>getQualifier</CODE> and
|
||||
* <CODE>setQualifier</CODE>, and enumerated with
|
||||
* <CODE>getQualifierNames</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* The <CODE>LDAPSchemaElement</CODE> class implements methods that
|
||||
* you can use with different types of schema elements (object class
|
||||
* definitions, attribute type definitions, and matching rule definitions).
|
||||
* You can do the following:
|
||||
* <UL>
|
||||
* <LI>get the name of a schema element
|
||||
* <LI>get the OID of a schema element
|
||||
* <LI>get the description of a schema element
|
||||
* <LI>add an element to the schema
|
||||
* <LI>remove an element from the schema
|
||||
* </UL>
|
||||
* <P>
|
||||
*
|
||||
* @see netscape.ldap.LDAPObjectClassSchema
|
||||
* @see netscape.ldap.LDAPAttributeSchema
|
||||
* @see netscape.ldap.LDAPMatchingRuleSchema
|
||||
* @version 1.0
|
||||
**/
|
||||
|
||||
public abstract class LDAPSchemaElement {
|
||||
/**
|
||||
* Construct a blank element.
|
||||
*/
|
||||
protected LDAPSchemaElement() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a definition explicitly.
|
||||
* @param name Name of element.
|
||||
* @param oid Dotted-string object identifier.
|
||||
* @param description Description of element.
|
||||
*/
|
||||
protected LDAPSchemaElement( String name, String oid,
|
||||
String description ) {
|
||||
this.name = name;
|
||||
this.oid = oid;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the object class, attribute type, or matching rule.
|
||||
* @return The name of the object class, attribute type, or
|
||||
* matching rule.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the object ID (OID) of the object class, attribute type,
|
||||
* or matching rule in dotted-string format (for example, "1.2.3.4").
|
||||
* @return The OID of the object class, attribute type,
|
||||
* or matching rule.
|
||||
*/
|
||||
public String getOID() {
|
||||
return oid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the description of the object class, attribute type,
|
||||
* or matching rule.
|
||||
* @return The description of the object class, attribute type,
|
||||
* or matching rule.
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add, remove or modify the definition from a Directory.
|
||||
* @param ld An open connection to a Directory Server. Typically the
|
||||
* connection must have been authenticated to add a definition.
|
||||
* @param op Type of modification to make.
|
||||
* @param atrr Attribute in the schema entry to modify.
|
||||
* @exception LDAPException if the definition can't be added/removed.
|
||||
*/
|
||||
protected void update( LDAPConnection ld, int op, LDAPAttribute attr,
|
||||
String dn )
|
||||
throws LDAPException {
|
||||
LDAPAttribute[] attrs = new LDAPAttribute[1];
|
||||
attrs[0] = attr;
|
||||
update( ld, op, attrs, dn );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add, remove or modify the definition from a Directory.
|
||||
* @param ld An open connection to a Directory Server. Typically the
|
||||
* connection must have been authenticated to add a definition.
|
||||
* @param op Type of modification to make.
|
||||
* @param attrs Attributes in the schema entry to modify.
|
||||
* @exception LDAPException if the definition can't be added/removed.
|
||||
*/
|
||||
protected void update( LDAPConnection ld, int op, LDAPAttribute[] attrs,
|
||||
String dn )
|
||||
throws LDAPException {
|
||||
LDAPModificationSet mods = new LDAPModificationSet();
|
||||
for( int i = 0; i < attrs.length; i++ ) {
|
||||
mods.add( op, attrs[i] );
|
||||
}
|
||||
String entryName = LDAPSchema.getSchemaDN( ld, dn );
|
||||
ld.modify( entryName, mods );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add, remove or modify the definition from a Directory.
|
||||
* @param ld An open connection to a Directory Server. Typically the
|
||||
* connection must have been authenticated to add a definition.
|
||||
* @param op Type of modification to make.
|
||||
* @param name Name of attribute in the schema entry to modify.
|
||||
* @exception LDAPException if the definition can't be added/removed.
|
||||
*/
|
||||
protected void update( LDAPConnection ld, int op, String name,
|
||||
String dn )
|
||||
throws LDAPException {
|
||||
boolean quotingBug =
|
||||
!LDAPSchema.isAttributeSyntaxStandardsCompliant( ld );
|
||||
LDAPAttribute attr = new LDAPAttribute( name,
|
||||
getValue( quotingBug ) );
|
||||
update( ld, op, attr, dn );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the current object class, attribute type, or matching rule
|
||||
* definition to the schema. Typically, most servers
|
||||
* will require you to authenticate before allowing you to
|
||||
* edit the schema.
|
||||
* @param ld The <CODE>LDAPConnection</CODE> object representing
|
||||
* a connection to an LDAP server.
|
||||
* @param dn The entry at which to add the schema definition.
|
||||
* @exception LDAPException The specified definition cannot be
|
||||
* added to the schema.
|
||||
*/
|
||||
public void add( LDAPConnection ld, String dn ) throws LDAPException {
|
||||
update( ld, LDAPModification.ADD, attrName, dn );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the current object class, attribute type, or matching rule
|
||||
* definition to the schema at the root DSE. Typically, most servers
|
||||
* will require you to authenticate before allowing you to
|
||||
* edit the schema.
|
||||
* @param ld The <CODE>LDAPConnection</CODE> object representing
|
||||
* a connection to an LDAP server.
|
||||
* @exception LDAPException The specified definition cannot be
|
||||
* added to the schema.
|
||||
*/
|
||||
public void add( LDAPConnection ld ) throws LDAPException {
|
||||
add( ld, "" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace a single value of the object class, attribute type,
|
||||
* or matching rule definition in the schema. Typically, most servers
|
||||
* will require you to authenticate before allowing you to
|
||||
* edit the schema.
|
||||
* @param ld The <CODE>LDAPConnection</CODE> object representing
|
||||
* a connection to an LDAP server.
|
||||
* @param newValue The new value
|
||||
* @param dn The entry at which to modify the schema definition.
|
||||
* @exception LDAPException The specified definition cannot be
|
||||
* modified.
|
||||
*/
|
||||
public void modify( LDAPConnection ld, LDAPSchemaElement newValue,
|
||||
String dn )
|
||||
throws LDAPException {
|
||||
boolean quotingBug =
|
||||
!LDAPSchema.isAttributeSyntaxStandardsCompliant( ld );
|
||||
LDAPModificationSet mods = new LDAPModificationSet();
|
||||
mods.add( LDAPModification.DELETE,
|
||||
new LDAPAttribute( attrName, getValue( quotingBug ) ) );
|
||||
mods.add( LDAPModification.ADD,
|
||||
new LDAPAttribute( attrName,
|
||||
newValue.getValue( quotingBug ) ) );
|
||||
String entryName = LDAPSchema.getSchemaDN( ld, dn );
|
||||
ld.modify( entryName, mods );
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace a single value of the object class, attribute type,
|
||||
* or matching rule definition in the schema at the root DSE.
|
||||
* Typically, most servers
|
||||
* will require you to authenticate before allowing you to
|
||||
* edit the schema.
|
||||
* @param ld The <CODE>LDAPConnection</CODE> object representing
|
||||
* a connection to an LDAP server.
|
||||
* @param newValue The new value
|
||||
* @exception LDAPException The specified definition cannot be
|
||||
* modified.
|
||||
*/
|
||||
public void modify( LDAPConnection ld, LDAPSchemaElement newValue )
|
||||
throws LDAPException {
|
||||
modify( ld, newValue, "" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the current object class, attribute type, or matching rule
|
||||
* definition from the schema. Typically, most servers
|
||||
* will require you to authenticate before allowing you to
|
||||
* edit the schema.
|
||||
* @param ld The <CODE>LDAPConnection</CODE> object representing
|
||||
* a connection to an LDAP server.
|
||||
* @param dn The entry at which to remove the schema definition.
|
||||
* @exception LDAPException The specified definition cannot be
|
||||
* removed from the schema.
|
||||
*/
|
||||
public void remove( LDAPConnection ld, String dn ) throws LDAPException {
|
||||
update( ld, LDAPModification.DELETE, attrName, dn );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the current object class, attribute type, or matching rule
|
||||
* definition from the schema at the root DSE. Typically, most servers
|
||||
* will require you to authenticate before allowing you to
|
||||
* edit the schema.
|
||||
* @param ld The <CODE>LDAPConnection</CODE> object representing
|
||||
* a connection to an LDAP server.
|
||||
* @exception LDAPException The specified definition cannot be
|
||||
* removed from the schema.
|
||||
*/
|
||||
public void remove( LDAPConnection ld ) throws LDAPException {
|
||||
remove( ld, "" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Report if the element is marked as obsolete.
|
||||
* @return <CODE>true<CODE> if the element is defined as obsolete.
|
||||
*/
|
||||
public boolean isObsolete() {
|
||||
return obsolete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a raw schema value into OID, name, description, and
|
||||
* a Hashtable of other qualifiers and values
|
||||
*
|
||||
* @param raw A raw schema definition
|
||||
*/
|
||||
protected void parseValue( String raw ) {
|
||||
if ( properties == null ) {
|
||||
properties = new Hashtable();
|
||||
}
|
||||
int l = raw.length();
|
||||
// Processing is faster in char array than in String
|
||||
char[] ch = new char[l];
|
||||
raw.getChars( 0, l, ch, 0 );
|
||||
// Trim leading and trailing space
|
||||
l--;
|
||||
while( ch[l] == ' ' ) {
|
||||
l--;
|
||||
}
|
||||
int start = 0;
|
||||
while( ch[start] == ' ' ) {
|
||||
start++;
|
||||
}
|
||||
// Skip past "( " and ")" to start of OID
|
||||
start += 2;
|
||||
// Find end of OID
|
||||
int ind = start + 1;
|
||||
while( ch[ind] != ' ' ) {
|
||||
ind++;
|
||||
}
|
||||
oid = new String( ch, start, ind - start );
|
||||
|
||||
ind = ind + 1;
|
||||
String s;
|
||||
String val;
|
||||
while ( ind < l ) {
|
||||
// Skip past blanks to start of next token
|
||||
while( ch[ind] == ' ' ) {
|
||||
ind++;
|
||||
}
|
||||
// Find end of token
|
||||
int last = ind + 1;
|
||||
while( (last < l) && (ch[last] != ' ') )
|
||||
last++;
|
||||
if ( last < l ) {
|
||||
// Found a token
|
||||
s = new String( ch, ind, last-ind );
|
||||
ind = last;
|
||||
if ( novalsTable.containsKey( s ) ) {
|
||||
properties.put( s, "" );
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Reached end of string with no end of token
|
||||
s = "";
|
||||
ind = l;
|
||||
break;
|
||||
}
|
||||
|
||||
// Find the start of the value of the token
|
||||
while( (ind < l) && (ch[ind] == ' ') ) {
|
||||
ind++;
|
||||
}
|
||||
last = ind + 1;
|
||||
if ( ind >= l ) {
|
||||
break;
|
||||
}
|
||||
|
||||
boolean quoted = false;
|
||||
boolean list = false;
|
||||
if ( ch[ind] == '\'' ) {
|
||||
// The value is quoted
|
||||
quoted = true;
|
||||
ind++;
|
||||
while( (last < l) && (ch[last] != '\'') ) {
|
||||
last++;
|
||||
}
|
||||
} else if ( ch[ind] == '(' ) {
|
||||
// The value is a list
|
||||
list = true;
|
||||
ind++;
|
||||
while( (last < l) && (ch[last] != ')') ) {
|
||||
last++;
|
||||
}
|
||||
} else {
|
||||
// The value is not quoted
|
||||
while( (last < l) && (ch[last] != ' ') ) {
|
||||
last++;
|
||||
}
|
||||
}
|
||||
if ( (ind < last) && (last < l) ) {
|
||||
if ( list ) {
|
||||
Vector v = new Vector();
|
||||
val = new String( ch, ind+1, last-ind-1 );
|
||||
StringTokenizer st = new StringTokenizer( val, " " );
|
||||
while ( st.hasMoreTokens() ) {
|
||||
String tok = st.nextToken();
|
||||
if ( !tok.equals( "$" ) ) {
|
||||
// Remove quotes, if any
|
||||
if ( tok.charAt( 0 ) == '\'' ) {
|
||||
tok = tok.substring( 1, tok.length()-1 );
|
||||
}
|
||||
v.addElement( tok );
|
||||
}
|
||||
}
|
||||
properties.put( s, v );
|
||||
} else {
|
||||
val = new String( ch, ind, last-ind );
|
||||
if ( s.equals( "NAME" ) ) {
|
||||
name = val;
|
||||
} else if ( s.equals( "DESC" ) ) {
|
||||
description = val;
|
||||
} else {
|
||||
properties.put( s, val );
|
||||
}
|
||||
if ( quoted ) {
|
||||
last++;
|
||||
}
|
||||
}
|
||||
}
|
||||
ind = last + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a String in the format defined in X.501 (see
|
||||
* <A HREF="http://ds.internic.net/rfc/rfc2252.txt"
|
||||
* >RFC 2252, Lightweight Directory Access Protocol
|
||||
* (v3): Attribute Syntax Definitions</A>
|
||||
* for a description of this format).
|
||||
* This is the format that LDAP servers and clients use to exchange
|
||||
* schema information. For example, when
|
||||
* you search an LDAP server for its schema, the server returns an entry
|
||||
* with the attributes "objectclasses" and "attributetypes". The
|
||||
* values of the "attributetypes" attribute are attribute type
|
||||
* descriptions in this format.
|
||||
* <P>
|
||||
* @param quotingBug <CODE>true</CODE> if single quotes are to be
|
||||
* supplied around the SYNTAX and SUP value
|
||||
* @return A formatted String for defining a schema element
|
||||
*/
|
||||
public String getValue() {
|
||||
return getValue( false );
|
||||
}
|
||||
|
||||
abstract String getValue( boolean quotingBug );
|
||||
|
||||
/**
|
||||
* Prepare the initial common part of a schema element value in
|
||||
* RFC 2252 format for submitting to a server
|
||||
*
|
||||
* @return The OID, name, description, and possibly OBSOLETE
|
||||
* fields of a schema element definition
|
||||
*/
|
||||
String getValuePrefix() {
|
||||
String s = "( " + oid + " NAME \'" + name + "\' DESC \'" +
|
||||
description + "\' ";
|
||||
if ( isObsolete() ) {
|
||||
s += OBSOLETE + ' ';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get qualifiers which may or may not be present
|
||||
*
|
||||
* @param names List of qualifiers to look up
|
||||
* @return String in RFC 2252 format containing any values
|
||||
* found, not terminated with ' '
|
||||
*/
|
||||
protected String getOptionalValues( String[] names ) {
|
||||
String s = "";
|
||||
for( int i = 0; i < names.length; i++ ) {
|
||||
String[] vals = getQualifier( names[i] );
|
||||
if ( (vals != null) && (vals.length > 0) ) {
|
||||
s += names[i] + ' ' + vals[0];
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any qualifiers marked as custom
|
||||
*
|
||||
* @return String in RFC 2252 format, without a terminating
|
||||
* ' '
|
||||
*/
|
||||
protected String getCustomValues() {
|
||||
String s = "";
|
||||
Enumeration en = properties.keys();
|
||||
while( en.hasMoreElements() ) {
|
||||
String key = (String)en.nextElement();
|
||||
if ( !key.startsWith( "X-" ) ) {
|
||||
continue;
|
||||
}
|
||||
s += getValue( key, true );
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a qualifier's value or values, if present, and format
|
||||
* the String according to RFC 2252
|
||||
*
|
||||
* @return String in RFC 2252 format, without a terminating
|
||||
* ' '
|
||||
*/
|
||||
String getValue( String key, boolean doQuote ) {
|
||||
String s = "";
|
||||
Object o = properties.get( key );
|
||||
if ( o == null ) {
|
||||
return s;
|
||||
}
|
||||
if ( o instanceof String ) {
|
||||
if ( ((String)o).length() > 0 ) {
|
||||
s += key + ' ';
|
||||
if ( doQuote ) {
|
||||
s += '\'';
|
||||
}
|
||||
s += (String)o;
|
||||
if ( doQuote ) {
|
||||
s += '\'';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s += key + " ( ";
|
||||
Vector v = (Vector)o;
|
||||
for( int i = 0; i < v.size(); i++ ) {
|
||||
if ( doQuote ) {
|
||||
s += '\'';
|
||||
}
|
||||
s += (String)v.elementAt(i);
|
||||
if ( doQuote ) {
|
||||
s += '\'';
|
||||
}
|
||||
s += ' ';
|
||||
if ( i < (v.size() - 1) ) {
|
||||
s += "$ ";
|
||||
}
|
||||
}
|
||||
s += ')';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep track of qualifiers which are not predefined.
|
||||
* @param name Name of qualifier
|
||||
* @param value Value of qualifier. "" for no value
|
||||
*/
|
||||
public void setQualifier( String name, String value ) {
|
||||
if ( properties == null ) {
|
||||
properties = new Hashtable();
|
||||
}
|
||||
if ( value != null ) {
|
||||
properties.put( name, value );
|
||||
} else {
|
||||
properties.remove( name );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep track of qualifiers which are not predefined.
|
||||
* @param name Name of qualifier
|
||||
* @param values Array of values
|
||||
*/
|
||||
public void setQualifier( String name, String[] values ) {
|
||||
if ( values == null ) {
|
||||
return;
|
||||
}
|
||||
if ( properties == null ) {
|
||||
properties = new Hashtable();
|
||||
}
|
||||
Vector v = new Vector();
|
||||
for( int i = 0; i < v.size(); i++ ) {
|
||||
v.addElement( values[i] );
|
||||
}
|
||||
properties.put( name, v );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of a qualifier which is not predefined.
|
||||
* @param name Name of qualifier
|
||||
* @return Value or values of qualifier. <CODE>null</CODE> if not
|
||||
* present, a zero-length array if present but with no value
|
||||
*/
|
||||
public String[] getQualifier( String name ) {
|
||||
if ( properties == null ) {
|
||||
return null;
|
||||
}
|
||||
Object o = properties.get( name );
|
||||
if ( o == null ) {
|
||||
return null;
|
||||
}
|
||||
if ( o instanceof Vector ) {
|
||||
Vector v = (Vector)o;
|
||||
String[] vals = new String[v.size()];
|
||||
v.copyInto( vals );
|
||||
return vals;
|
||||
}
|
||||
String s = (String)o;
|
||||
if ( s.length() < 1 ) {
|
||||
return new String[0];
|
||||
} else {
|
||||
return new String[] { s };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an enumeration of all qualifiers which are not predefined.
|
||||
* @return Enumeration of qualifiers.
|
||||
*/
|
||||
public Enumeration getQualifierNames() {
|
||||
return properties.keys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a string for use in toString with any qualifiers of the element.
|
||||
*
|
||||
* @param ignore Any qualifiers to NOT include
|
||||
* @return A String with any known qualifiers
|
||||
*/
|
||||
String getQualifierString( String[] ignore ) {
|
||||
Hashtable toIgnore = null;
|
||||
if ( ignore != null ) {
|
||||
toIgnore = new Hashtable();
|
||||
for( int i = 0; i < ignore.length; i++ ) {
|
||||
toIgnore.put( ignore[i], ignore[i] );
|
||||
}
|
||||
}
|
||||
String s = "";
|
||||
Enumeration en = getQualifierNames();
|
||||
while( en.hasMoreElements() ) {
|
||||
String qualifier = (String)en.nextElement();
|
||||
if ( (toIgnore != null) && toIgnore.containsKey( qualifier ) ) {
|
||||
continue;
|
||||
}
|
||||
s += "; " + qualifier;
|
||||
String[] vals = getQualifier( qualifier );
|
||||
if ( vals == null ) {
|
||||
s += ' ';
|
||||
continue;
|
||||
}
|
||||
s += ": ";
|
||||
for( int i = 0; i < vals.length; i++ ) {
|
||||
s += vals[i] + ' ';
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// Constants for known syntax types
|
||||
public static final int unknown = 0;
|
||||
public static final int cis = 1;
|
||||
public static final int binary = 2;
|
||||
public static final int telephone = 3;
|
||||
public static final int ces = 4;
|
||||
public static final int dn = 5;
|
||||
public static final int integer = 6;
|
||||
|
||||
protected static final String cisString =
|
||||
"1.3.6.1.4.1.1466.115.121.1.15";
|
||||
protected static final String binaryString =
|
||||
"1.3.6.1.4.1.1466.115.121.1.5";
|
||||
protected static final String telephoneString =
|
||||
"1.3.6.1.4.1.1466.115.121.1.50";
|
||||
protected static final String cesString =
|
||||
"1.3.6.1.4.1.1466.115.121.1.26";
|
||||
protected static final String intString =
|
||||
"1.3.6.1.4.1.1466.115.121.1.27";
|
||||
protected static final String dnString =
|
||||
"1.3.6.1.4.1.1466.115.121.1.12";
|
||||
// Predefined qualifiers which apply to any schema element type
|
||||
public static final String OBSOLETE = "OBSOLETE";
|
||||
public static final String SUPERIOR = "SUP";
|
||||
|
||||
// Properties which are common to all schema elements
|
||||
protected String oid = null;
|
||||
protected String name = "";
|
||||
protected String description = "";
|
||||
protected String attrName = null;
|
||||
protected boolean obsolete = false;
|
||||
protected String rawValue = null;
|
||||
// Additional qualifiers
|
||||
protected Hashtable properties = null;
|
||||
// Qualifiers known to not have values
|
||||
static protected Hashtable novalsTable = new Hashtable();
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
/**
|
||||
* Represents a set of search preferences.
|
||||
* You can set these preferences for a particular search
|
||||
* by creating an <CODE>LDAPSearchConstraints</CODE> object,
|
||||
* specifying your preferences, and passing the object to
|
||||
* the <CODE>LDAPConnection.search</CODE> method.
|
||||
* <P>
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LDAPSearchConstraints extends LDAPConstraints
|
||||
implements Cloneable {
|
||||
|
||||
private int deref;
|
||||
private int maxRes;
|
||||
private int batch;
|
||||
private int serverTimeLimit;
|
||||
transient private int m_maxBacklog = 100;
|
||||
|
||||
/**
|
||||
* Constructs an <CODE>LDAPSearchConstraints</CODE> object that specifies
|
||||
* the default set of search constraints.
|
||||
*/
|
||||
public LDAPSearchConstraints() {
|
||||
super();
|
||||
deref = 0;
|
||||
maxRes = 1000;
|
||||
batch = 1;
|
||||
serverTimeLimit = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <CODE>LDAPSearchConstraints</CODE> object and allows you
|
||||
* to specify the search constraints in that object.
|
||||
* <P>
|
||||
* @param msLimit Maximum time in milliseconds to wait for results (0
|
||||
* by default, which means that there is no maximum time limit)
|
||||
* @param dereference Either <CODE>LDAPv2.DEREF_NEVER</CODE>,
|
||||
* <CODE>LDAPv2.DEREF_FINDING</CODE>,
|
||||
* <CODE>LDAPv2.DEREF_SEARCHING</CODE>, or
|
||||
* <CODE>LDAPv2.DEREF_ALWAYS</CODE> (see LDAPConnection.setOption).
|
||||
* <CODE>LDAPv2.DEREF_NEVER</CODE> is the default.
|
||||
* @param maxResults Maximum number of search results to return
|
||||
* (1000 by default)
|
||||
* @param doReferrals Specify <CODE>true</CODE> to follow referrals
|
||||
* automatically, or <CODE>False</CODE> to throw an
|
||||
* <CODE>LDAPReferralException</CODE> error if the server sends back
|
||||
* a referral (<CODE>False</CODE> by default)
|
||||
* @param batchSize Specify the number of results to return at a time
|
||||
* (1 by default)
|
||||
* @param rebind_proc Specifies the object of the class that
|
||||
* implements the <CODE>LDAPRebind</CODE> interface (you need to
|
||||
* define this class). The object will be used when the client
|
||||
* follows referrals automatically. The object provides the client
|
||||
* with a method for getting the distinguished name and password
|
||||
* used to authenticate to another LDAP server during a referral.
|
||||
* (This field is <CODE>null</CODE> by default.)
|
||||
* @param hop_limit Maximum number of referrals to follow in a
|
||||
* sequence when attempting to resolve a request.
|
||||
* @see netscape.ldap.LDAPConnection#setOption(int, java.lang.Object)
|
||||
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl, netscape.ldap.LDAPSearchConstraints)
|
||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
|
||||
*/
|
||||
public LDAPSearchConstraints( int msLimit, int dereference,
|
||||
int maxResults, boolean doReferrals, int batchSize,
|
||||
LDAPRebind rebind_proc, int hop_limit) {
|
||||
super(msLimit, doReferrals, rebind_proc, hop_limit);
|
||||
deref = dereference;
|
||||
maxRes = maxResults;
|
||||
batch = batchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <CODE>LDAPSearchConstraints</CODE> object and allows you
|
||||
* to specify the search constraints in that object.
|
||||
* <P>
|
||||
* @param msLimit Maximum time in milliseconds to wait for results (0
|
||||
* by default, which means that there is no maximum time limit)
|
||||
* @param timeLimit Maximum time in seconds for the server to spend
|
||||
* processing a search request (0 by default for no limit)
|
||||
* @param dereference Either <CODE>LDAPv2.DEREF_NEVER</CODE>,
|
||||
* <CODE>LDAPv2.DEREF_FINDING</CODE>,
|
||||
* <CODE>LDAPv2.DEREF_SEARCHING</CODE>, or
|
||||
* <CODE>LDAPv2.DEREF_ALWAYS</CODE> (see LDAPConnection.setOption).
|
||||
* <CODE>LDAPv2.DEREF_NEVER</CODE> is the default.
|
||||
* @param maxResults Maximum number of search results to return
|
||||
* (1000 by default)
|
||||
* @param doReferrals Specify <CODE>true</CODE> to follow referrals
|
||||
* automatically, or <CODE>False</CODE> to throw an
|
||||
* <CODE>LDAPReferralException</CODE> error if the server sends back
|
||||
* a referral (<CODE>False</CODE> by default)
|
||||
* @param batchSize Specify the number of results to return at a time
|
||||
* (1 by default)
|
||||
* @param rebind_proc Specifies the object that
|
||||
* implements the <CODE>LDAPRebind</CODE> interface.
|
||||
* The object will be used when the client
|
||||
* follows referrals automatically. The object provides the client
|
||||
* with a method for getting the distinguished name and password
|
||||
* used to authenticate to another LDAP server during a referral.
|
||||
* (This field is <CODE>null</CODE> by default.)
|
||||
* @param hop_limit Maximum number of referrals to follow in a
|
||||
* sequence when attempting to resolve a request.
|
||||
* @see netscape.ldap.LDAPConnection#setOption(int, java.lang.Object)
|
||||
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl, netscape.ldap.LDAPSearchConstraints)
|
||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
|
||||
*/
|
||||
public LDAPSearchConstraints( int msLimit, int timeLimit,
|
||||
int dereference,
|
||||
int maxResults, boolean doReferrals,
|
||||
int batchSize,
|
||||
LDAPRebind rebind_proc,
|
||||
int hop_limit) {
|
||||
super(msLimit, doReferrals, rebind_proc, hop_limit);
|
||||
serverTimeLimit = timeLimit;
|
||||
deref = dereference;
|
||||
maxRes = maxResults;
|
||||
batch = batchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <CODE>LDAPSearchConstraints</CODE> object and allows you
|
||||
* to specify the search constraints in that object.
|
||||
* <P>
|
||||
* @param msLimit Maximum time in milliseconds to wait for results (0
|
||||
* by default, which means that there is no maximum time limit)
|
||||
* @param timeLimit Maximum time in seconds for the server to spend
|
||||
* processing a search request (0 by default for no limit)
|
||||
* @param dereference Either <CODE>LDAPv2.DEREF_NEVER</CODE>,
|
||||
* <CODE>LDAPv2.DEREF_FINDING</CODE>,
|
||||
* <CODE>LDAPv2.DEREF_SEARCHING</CODE>, or
|
||||
* <CODE>LDAPv2.DEREF_ALWAYS</CODE> (see LDAPConnection.setOption).
|
||||
* <CODE>LDAPv2.DEREF_NEVER</CODE> is the default.
|
||||
* @param maxResults Maximum number of search results to return
|
||||
* (1000 by default)
|
||||
* @param doReferrals Specify <CODE>true</CODE> to follow referrals
|
||||
* automatically, or <CODE>False</CODE> to throw an
|
||||
* <CODE>LDAPReferralException</CODE> error if the server sends back
|
||||
* a referral (<CODE>False</CODE> by default)
|
||||
* @param batchSize Specify the number of results to return at a time
|
||||
* (1 by default)
|
||||
* @param bind_proc Specifies the object that
|
||||
* implements the <CODE>LDAPBind</CODE> interface (you need to
|
||||
* define this class). The object will be used to authenticate
|
||||
* to the server on referrals.
|
||||
* (This field is <CODE>null</CODE> by default.)
|
||||
* @param hop_limit Maximum number of referrals to follow in a
|
||||
* sequence when attempting to resolve a request.
|
||||
* @see netscape.ldap.LDAPConnection#setOption(int, java.lang.Object)
|
||||
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl, netscape.ldap.LDAPSearchConstraints)
|
||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
|
||||
*/
|
||||
public LDAPSearchConstraints( int msLimit, int timeLimit,
|
||||
int dereference,
|
||||
int maxResults, boolean doReferrals,
|
||||
int batchSize,
|
||||
LDAPBind bind_proc,
|
||||
int hop_limit) {
|
||||
super(msLimit, doReferrals, bind_proc, hop_limit);
|
||||
serverTimeLimit = timeLimit;
|
||||
deref = dereference;
|
||||
maxRes = maxResults;
|
||||
batch = batchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum number of seconds to wait for the server to
|
||||
* spend on a search operation.If 0, there is no time limit.
|
||||
* @return Maximum number of seconds for the server to spend.
|
||||
*/
|
||||
public int getServerTimeLimit() {
|
||||
return serverTimeLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies how aliases should be dereferenced.
|
||||
* @return <CODE>LDAPv2.DEREF_NEVER</CODE> to
|
||||
* never follow ("dereference") aliases,
|
||||
* <CODE>LDAPv2.DEREF_FINDING</CODE> to dereference when finding
|
||||
* the starting point for the search (but not when searching
|
||||
* under that starting entry), <CODE>LDAPv2.DEREF_SEARCHING</CODE>
|
||||
* to dereference when searching the entries beneath the
|
||||
* starting point of the search (but not when finding the starting
|
||||
* entry), or <CODE>LDAPv2.DEREF_ALWAYS</CODE> to always
|
||||
* dereference aliases.
|
||||
*/
|
||||
public int getDereference() {
|
||||
return deref;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum number of search results to be returned; 0 means
|
||||
* no limit.
|
||||
* @return Maximum number of search results to be returned.
|
||||
*/
|
||||
public int getMaxResults() {
|
||||
return maxRes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the suggested number of results to return at a time during
|
||||
* search. This should be 0 if intermediate results are not needed, and
|
||||
* 1 if results are to be processed as they come in.
|
||||
* @return Number of results to return at a time.
|
||||
*/
|
||||
public int getBatchSize() {
|
||||
return batch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum number of seconds for the server to spend
|
||||
* returning search results. If 0, there is no time limit.
|
||||
* @param limit Maximum number of seconds for the server to spend.
|
||||
* (0 by default, which means that there is no maximum time limit.)
|
||||
*/
|
||||
public void setServerTimeLimit( int limit ) {
|
||||
serverTimeLimit = limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a preference indicating how aliases should be dereferenced.
|
||||
* @param dereference <CODE>LDAPv2.DEREF_NEVER</CODE> to
|
||||
* never follow ("dereference") aliases,
|
||||
* <CODE>LDAPv2.DEREF_FINDING</CODE> to dereference when finding
|
||||
* the starting point for the search (but not when searching
|
||||
* under that starting entry), <CODE>LDAPv2.DEREF_SEARCHING</CODE>
|
||||
* to dereference when searching the entries beneath the
|
||||
* starting point of the search (but not when finding the starting
|
||||
* entry), or <CODE>LDAPv2.DEREF_ALWAYS</CODE> to always
|
||||
* dereference aliases.
|
||||
*/
|
||||
public void setDereference( int dereference ) {
|
||||
deref = dereference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum number of search results to be returned; 0 means
|
||||
* no limit. (By default, this is set to 1000.)
|
||||
* @param maxResults Maximum number of search results to be returned.
|
||||
*/
|
||||
public void setMaxResults( int maxResults ) {
|
||||
maxRes = maxResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the suggested number of results to return at a time during search.
|
||||
* This should be 0 if intermediate results are not needed, and 1 if
|
||||
* results are to be processed as they come in. (By default, this is 1.)
|
||||
* @param batchSize Number of results to return at a time.
|
||||
*/
|
||||
public void setBatchSize( int batchSize ) {
|
||||
batch = batchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of unread entries any search listener can
|
||||
* have before we stop reading from the server.
|
||||
* @param backlog The maximum number of unread entries per listener
|
||||
* @deprecated Use <CODE>LDAPConnection.getOption()</CODE>
|
||||
*/
|
||||
public void setMaxBacklog( int backlog ) {
|
||||
m_maxBacklog = backlog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum number of unread entries any search listener can
|
||||
* have before we stop reading from the server.
|
||||
* @return The maximum number of unread entries per listener
|
||||
* @deprecated Use <CODE>LDAPConnection.setOption()</CODE>
|
||||
*/
|
||||
public int getMaxBacklog() {
|
||||
return m_maxBacklog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a copy of an existing set of search constraints.
|
||||
* @returns A copy of an existing set of search constraints.
|
||||
*/
|
||||
public Object clone() {
|
||||
LDAPSearchConstraints o = new LDAPSearchConstraints();
|
||||
|
||||
o.serverTimeLimit = this.serverTimeLimit;
|
||||
o.deref = this.deref;
|
||||
o.maxRes = this.maxRes;
|
||||
o.batch = this.batch;
|
||||
|
||||
o.setHopLimit(this.getTimeLimit());
|
||||
o.setReferrals(this.getReferrals());
|
||||
o.setTimeLimit(this.getTimeLimit());
|
||||
|
||||
if (this.getBindProc() != null) {
|
||||
o.setBindProc(this.getBindProc());
|
||||
} else {
|
||||
o.setRebindProc(this.getRebindProc());
|
||||
}
|
||||
|
||||
LDAPControl[] tClientControls = this.getClientControls();
|
||||
LDAPControl[] oClientControls;
|
||||
|
||||
if ( (tClientControls != null) &&
|
||||
(tClientControls.length > 0) ) {
|
||||
oClientControls = new LDAPControl[tClientControls.length];
|
||||
for( int i = 0; i < tClientControls.length; i++ )
|
||||
oClientControls[i] = (LDAPControl)tClientControls[i].clone();
|
||||
o.setClientControls(oClientControls);
|
||||
}
|
||||
|
||||
LDAPControl[] tServerControls = this.getServerControls();
|
||||
LDAPControl[] oServerControls;
|
||||
|
||||
if ( (tServerControls != null) &&
|
||||
(tServerControls.length > 0) ) {
|
||||
oServerControls = new LDAPControl[tServerControls.length];
|
||||
for( int i = 0; i < tServerControls.length; i++ )
|
||||
oServerControls[i] = (LDAPControl)tServerControls[i].clone();
|
||||
o.setServerControls(oServerControls);
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import netscape.ldap.client.*;
|
||||
|
||||
/**
|
||||
* Manages search results, references and responses returned on one or
|
||||
* more search requests
|
||||
*
|
||||
*/
|
||||
public class LDAPSearchListener extends LDAPMessageQueue {
|
||||
|
||||
// this instance variable is only for cache purpose
|
||||
private Long m_key = null;
|
||||
private LDAPSearchConstraints m_constraints;
|
||||
|
||||
/**
|
||||
* Constructs a LDAP search listener.
|
||||
* @param asynchOp A flag whether the object is used for asynchronous
|
||||
* LDAP operations
|
||||
* @param cons LDAP Search Constraints
|
||||
* @see netscape.ldap.LDAPAsynchronousConnection
|
||||
*/
|
||||
LDAPSearchListener ( boolean asynchOp,
|
||||
LDAPSearchConstraints cons ) {
|
||||
super ( asynchOp );
|
||||
m_constraints = cons;
|
||||
}
|
||||
|
||||
/**
|
||||
* Block until all results are in. Used for synchronous search with
|
||||
* batch size of zero.
|
||||
* @return search response message
|
||||
* @exception Network exception error
|
||||
*/
|
||||
LDAPResponse completeSearchOperation () throws LDAPException{
|
||||
return completeRequest();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Blocks until a search result, reference or response is available,
|
||||
* or until all operations associated with the object have completed
|
||||
* or been canceled.
|
||||
*
|
||||
* @return A search result, search reference, or search response message
|
||||
* or null if there is no more outstanding requests
|
||||
* @exception LDAPException Network error exception
|
||||
* @exception LDAPInterruptedException The invoking thread was interrupted
|
||||
* @see LDAPResponse
|
||||
* @see LDAPSearchResult
|
||||
* @see LDAPSearchResultReference
|
||||
*/
|
||||
public LDAPMessage getResponse () throws LDAPException{
|
||||
LDAPMessage result = nextMessage();
|
||||
|
||||
// Notify LDAPConnThread to wake up if backlog limit has been reached
|
||||
if (result instanceof LDAPSearchResult || result instanceof LDAPSearchResultReference) {
|
||||
LDAPConnection ld = getConnection(result.getId());
|
||||
if (ld != null) {
|
||||
ld.resultRetrieved();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge two search listeners
|
||||
* Move/append the content from another search listener to this one.
|
||||
*
|
||||
* To be used for synchronization of asynchronous LDAP operations where
|
||||
* requests are sent by one thread but processed by another one
|
||||
*
|
||||
* A client may be implemented in such a way that one thread makes LDAP
|
||||
* requests and calls l.getIDs(), while another thread is responsible for
|
||||
* processing of responses (call l.getResponse()). Both threads are using
|
||||
* the same listener objects. In such a case, a race
|
||||
* condition may occur, where a LDAP response message is retrieved and
|
||||
* the request terminated (request ID removed) before the first thread
|
||||
* has a chance to execute l.getIDs().
|
||||
* The proper way to handle this scenario is to create a separate listener
|
||||
* for each new request, and after l.getIDs() has been invoked, merge the
|
||||
* new request with the existing one.
|
||||
* @param listener2 The listener to be merged with.
|
||||
*/
|
||||
public void merge(LDAPSearchListener listener2) {
|
||||
super.merge(listener2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns message ids for all outstanding requests
|
||||
* @return Message id array
|
||||
*/
|
||||
public int[] getIDs() {
|
||||
return super.getIDs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the search constraints used to create this object
|
||||
* @return the search constraints used to create this object
|
||||
*/
|
||||
LDAPSearchConstraints getConstraints() {
|
||||
return m_constraints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the key of the cache entry. The listener needs to know this value
|
||||
* when the results get processed in the queue. After the results have been
|
||||
* saved in the vector, then the key and a vector of results are put in
|
||||
* the cache.
|
||||
* @param key The key of the cache entry
|
||||
*/
|
||||
void setKey(Long key) {
|
||||
m_key = key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key of the cache entry.
|
||||
* @return The key of the cache entry
|
||||
*/
|
||||
Long getKey() {
|
||||
return m_key;
|
||||
@@ -0,0 +1,68 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import netscape.ldap.client.opers.JDAPSearchResponse;
|
||||
|
||||
/**
|
||||
* A LDAPSearchResult object encapsulates a single search result.
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LDAPSearchResult extends LDAPMessage {
|
||||
|
||||
/**
|
||||
* LDAPEntry
|
||||
*/
|
||||
private LDAPEntry m_entry;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param msgid message identifier
|
||||
* @param rsp Search operation response
|
||||
* @param controls Array of controls of null
|
||||
* @see netscape.ldap.LDAPEntry
|
||||
*/
|
||||
LDAPSearchResult(int msgid, JDAPSearchResponse rsp, LDAPControl[]controls) {
|
||||
super(msgid, rsp, controls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entry of a server search response.
|
||||
* @return An entry returned by the server in response to a search
|
||||
* request
|
||||
* @see netscape.ldap.LDAPEntry
|
||||
*/
|
||||
public LDAPEntry getEntry() {
|
||||
if (m_entry == null) {
|
||||
JDAPSearchResponse rsp = (JDAPSearchResponse)getProtocolOp();
|
||||
LDAPAttribute[] lattrs = rsp.getAttributes();
|
||||
LDAPAttributeSet attrs;
|
||||
if ( lattrs != null ) {
|
||||
attrs = new LDAPAttributeSet( lattrs );
|
||||
}
|
||||
else {
|
||||
attrs = new LDAPAttributeSet();
|
||||
}
|
||||
String dn = rsp.getObjectName();
|
||||
m_entry = new LDAPEntry( dn, attrs );
|
||||
}
|
||||
return m_entry;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import netscape.ldap.client.opers.JDAPSearchResultReference;
|
||||
/**
|
||||
* An LDAPSearchResultReference object encapsulates a continuation
|
||||
* reference from a search operation.
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LDAPSearchResultReference extends LDAPMessage {
|
||||
|
||||
/**
|
||||
* A lists of referred to Ldap URLs
|
||||
*/
|
||||
private String m_URLs[];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param msgid message identifier
|
||||
* @param resRef Search result reference response
|
||||
* @param controls Array of controls of null
|
||||
* @see netscape.ldap.LDAPEntry
|
||||
*/
|
||||
LDAPSearchResultReference(int msgid, JDAPSearchResultReference resRef, LDAPControl[]controls) {
|
||||
super(msgid, resRef, controls);
|
||||
m_URLs = resRef.getUrls();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of referred to LDAP URLs
|
||||
* @return A list of URLs
|
||||
*/
|
||||
public String[] getUrls() {
|
||||
return m_URLs;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,546 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import netscape.ldap.client.*;
|
||||
import netscape.ldap.client.opers.*;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* The results of an LDAP search operation, represented as an enumeration.
|
||||
* Note that you can only iterate through this enumeration once: if you
|
||||
* need to use these results more than once, make sure to save the
|
||||
* results in a separate location.
|
||||
* <P>
|
||||
*
|
||||
* You can also use the results of a search in progress to abandon that search
|
||||
* operation.
|
||||
* <P>
|
||||
*
|
||||
* @version 1.0
|
||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean)
|
||||
* @see netscape.ldap.LDAPConnection#abandon(netscape.ldap.LDAPSearchResults)
|
||||
*/
|
||||
public class LDAPSearchResults implements Enumeration {
|
||||
|
||||
private Vector entries = null;
|
||||
private LDAPSearchListener resultSource;
|
||||
private boolean searchComplete = false;
|
||||
private LDAPConnection connectionToClose;
|
||||
private LDAPConnection currConn;
|
||||
private boolean persistentSearch = false;
|
||||
private LDAPSearchConstraints currCons;
|
||||
private String currBase;
|
||||
private int currScope;
|
||||
private String currFilter;
|
||||
private String[] currAttrs;
|
||||
private boolean currAttrsOnly;
|
||||
private Vector referralResults = new Vector();
|
||||
private Vector exceptions;
|
||||
private LDAPControl[] responseControls = null;
|
||||
|
||||
// only used for the persistent search
|
||||
private boolean firstResult = false;
|
||||
|
||||
/**
|
||||
* Constructs an enumeration of search results.
|
||||
* Note that this does not actually generate the results;
|
||||
* you need to call <CODE>LDAPConnection.search</CODE> to
|
||||
* perform the search and get the results.
|
||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean)
|
||||
*/
|
||||
public LDAPSearchResults() {
|
||||
entries = new Vector();
|
||||
connectionToClose = null;
|
||||
searchComplete = true;
|
||||
}
|
||||
|
||||
LDAPSearchResults(LDAPConnection conn, LDAPSearchConstraints cons,
|
||||
String base, int scope, String filter, String[] attrs, boolean attrsOnly) {
|
||||
this();
|
||||
currConn = conn;
|
||||
currCons = cons;
|
||||
currBase = base;
|
||||
currScope = scope;
|
||||
currFilter = filter;
|
||||
currAttrs = attrs;
|
||||
currAttrsOnly = attrsOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an enumeration of search results. Used when returning results
|
||||
* from a cache.
|
||||
* @param v The vector containing LDAPEntries.
|
||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean)
|
||||
*/
|
||||
LDAPSearchResults(Vector v) {
|
||||
this();
|
||||
entries = (Vector)v.clone();
|
||||
|
||||
if ((entries != null) && (entries.size() >= 1)) {
|
||||
// Each cache value is represented by a vector. The first element
|
||||
// represents the size of all the LDAPEntries. This needs to be
|
||||
// removed before we iterate through each LDAPEntry.
|
||||
entries.removeElementAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
LDAPSearchResults(Vector v, LDAPConnection conn, LDAPSearchConstraints cons,
|
||||
String base, int scope, String filter, String[] attrs, boolean attrsOnly) {
|
||||
this(v);
|
||||
currConn = conn;
|
||||
currCons = cons;
|
||||
currBase = base;
|
||||
currScope = scope;
|
||||
currFilter = filter;
|
||||
currAttrs = attrs;
|
||||
currAttrsOnly = attrsOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add search entry of referral
|
||||
* @param msg LDAPSearchResult or LDAPsearchResultReference
|
||||
*/
|
||||
void add( LDAPMessage msg ) {
|
||||
if (msg instanceof LDAPSearchResult) {
|
||||
entries.addElement( ((LDAPSearchResult)msg).getEntry());
|
||||
}
|
||||
else if (msg instanceof LDAPSearchResultReference) {
|
||||
/* convert to LDAPReferralException */
|
||||
String urls[] = ((LDAPSearchResultReference)msg).getUrls();
|
||||
if (urls != null) {
|
||||
if (exceptions == null) {
|
||||
exceptions = new Vector();
|
||||
}
|
||||
exceptions.addElement(new LDAPReferralException(null, 0, urls));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add exception
|
||||
* @param e exception
|
||||
*/
|
||||
void add(LDAPException e) {
|
||||
if (exceptions == null) {
|
||||
exceptions = new Vector();
|
||||
}
|
||||
exceptions.addElement(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares to return asynchronous results from a search
|
||||
* @param l Listener which will provide results
|
||||
*/
|
||||
void associate( LDAPSearchListener l) {
|
||||
resultSource = l;
|
||||
searchComplete = false;
|
||||
}
|
||||
|
||||
void associatePersistentSearch( LDAPSearchListener l) {
|
||||
resultSource = l;
|
||||
persistentSearch = true;
|
||||
searchComplete = false;
|
||||
firstResult = true;
|
||||
}
|
||||
|
||||
void addReferralEntries(LDAPSearchResults res) {
|
||||
referralResults.addElement(res);
|
||||
}
|
||||
|
||||
/**
|
||||
* For asynchronous search, this mechanism allows the programmer to
|
||||
* close a connection whenever the search completes.
|
||||
* @param toClose Connection to close when the search terminates
|
||||
*/
|
||||
void closeOnCompletion (LDAPConnection toClose) {
|
||||
if (searchComplete) {
|
||||
try {
|
||||
toClose.disconnect();
|
||||
} catch (LDAPException e) {
|
||||
}
|
||||
} else {
|
||||
connectionToClose = toClose;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Basic quicksort algorithm.
|
||||
*/
|
||||
void quicksort (LDAPEntry[] toSort, LDAPEntryComparator compare,
|
||||
int low, int high) {
|
||||
if (low >= high)
|
||||
return;
|
||||
|
||||
LDAPEntry pivot = toSort[low];
|
||||
int slow = low-1, shigh = high+1;
|
||||
|
||||
while (true) {
|
||||
do
|
||||
shigh--;
|
||||
while (compare.isGreater (toSort[shigh], pivot));
|
||||
do
|
||||
slow++;
|
||||
while (compare.isGreater (pivot, toSort[slow]));
|
||||
|
||||
if (slow >= shigh)
|
||||
break;
|
||||
|
||||
LDAPEntry temp = toSort[slow];
|
||||
toSort[slow] = toSort[shigh];
|
||||
toSort[shigh] = temp;
|
||||
}
|
||||
|
||||
quicksort (toSort, compare, low, shigh);
|
||||
quicksort (toSort, compare, shigh+1, high);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the response controls for this search result.
|
||||
* @param controls The controls to be stored.
|
||||
*/
|
||||
protected void setResponseControls(LDAPControl[] controls) {
|
||||
responseControls = controls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the controls returned with this search result. If any control
|
||||
* is registered with <CODE>LDAPControl</CODE>, an attempt is made to
|
||||
* instantiate the control. If the instantiation fails, the control is
|
||||
* returned as a basic <CODE>LDAPControl</CODE>.
|
||||
* @return An array of type <CODE>LDAPControl</CODE>
|
||||
* @see netscape.ldap.LDAPControl#register
|
||||
*/
|
||||
public LDAPControl[] getResponseControls() {
|
||||
return responseControls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the search results.
|
||||
* <P>
|
||||
*
|
||||
* The comparator (<CODE>LDAPEntryComparator</CODE>) determines the
|
||||
* sort order used. For example, if the comparator uses the <CODE>uid</CODE>
|
||||
* attribute for comparison, the search results are sorted according to
|
||||
* <CODE>uid</CODE>.
|
||||
* <P>
|
||||
*
|
||||
* The following section of code sorts results in ascending order,
|
||||
* first by surname and then by common name.
|
||||
*
|
||||
* <PRE>
|
||||
* String[] sortAttrs = {"sn", "cn"};
|
||||
* boolean[] ascending = {true, true};
|
||||
*
|
||||
* LDAPConnection ld = new LDAPConnection();
|
||||
* ld.connect( ... );
|
||||
* LDAPSearchResults res = ld.search( ... );
|
||||
* res.sort( new LDAPCompareAttrNames(sortAttrs, ascending) );
|
||||
* </PRE>
|
||||
* NOTE: If the search results arrive asynchronously, the <CODE>sort</CODE>
|
||||
* method blocks until all the results are returned.
|
||||
* <P>
|
||||
*
|
||||
* If some of the elements of the Enumeration have already been fetched,
|
||||
* the cursor is reset to the (new) first element.
|
||||
* <P>
|
||||
*
|
||||
* @param compare Comparator used to determine the sort order of the results.
|
||||
* @see LDAPEntryComparator
|
||||
*/
|
||||
public synchronized void sort(LDAPEntryComparator compare) {
|
||||
while (!searchComplete) {
|
||||
fetchResult();
|
||||
}
|
||||
|
||||
// if automatic referral, then add to the entries, otherwise, dont do it
|
||||
// since the elements in referralResults are LDAPReferralException.
|
||||
if (currCons.getReferrals())
|
||||
while (referralResults.size() > 0) {
|
||||
Object obj = null;
|
||||
if ((obj=nextReferralElement()) != null)
|
||||
entries.addElement(obj);
|
||||
}
|
||||
|
||||
int numEntries = entries.size();
|
||||
if (numEntries <= 0)
|
||||
return;
|
||||
|
||||
LDAPEntry[] toSort = new LDAPEntry[numEntries];
|
||||
entries.copyInto (toSort);
|
||||
|
||||
if (toSort.length > 1)
|
||||
quicksort (toSort, compare, 0, numEntries-1);
|
||||
|
||||
entries.removeAllElements();
|
||||
for (int i = 0; i < numEntries; i++)
|
||||
entries.addElement (toSort[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next LDAP entry from the search results
|
||||
* and throws an exception if the next result is a referral, or
|
||||
* if a sizelimit or timelimit error occurred.
|
||||
* <P>
|
||||
*
|
||||
* You can use this method in conjunction with the
|
||||
* <CODE>hasMoreElements</CODE> method to iterate through
|
||||
* each entry in the search results. For example:
|
||||
* <PRE>
|
||||
* LDAPSearchResults res = ld.search( MY_SEARCHBASE,
|
||||
* LDAPConnection.SCOPE_BASE, MY_FILTER,
|
||||
* null, false );
|
||||
* while ( res.hasMoreElements() ) {
|
||||
* try {
|
||||
* LDAPEntry findEntry = res.next();
|
||||
* } catch ( LDAPReferralException e ) {
|
||||
* LDAPUrl refUrls[] = e.getURLs();
|
||||
* for ( int i = 0; i < refUrls.length; i++ ) {
|
||||
* // Your code for handling referrals
|
||||
* }
|
||||
* continue;
|
||||
* } catch ( LDAPException e ) {
|
||||
* // Your code for handling errors on limits exceeded
|
||||
* continue;
|
||||
* }
|
||||
* ...
|
||||
* }
|
||||
* </PRE>
|
||||
* @return The next LDAP entry in the search results.
|
||||
* @exception LDAPReferralException A referral (thrown
|
||||
* if the next result is a referral), or LDAPException
|
||||
* if a limit on the number of entries or the time was
|
||||
* exceeded.
|
||||
* @see netscape.ldap.LDAPSearchResults#hasMoreElements()
|
||||
*/
|
||||
public LDAPEntry next() throws LDAPException {
|
||||
Object o = nextElement();
|
||||
if ((o instanceof LDAPReferralException) ||
|
||||
(o instanceof LDAPException))
|
||||
throw (LDAPException)o;
|
||||
if (o instanceof LDAPEntry)
|
||||
return (LDAPEntry)o;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next result from a search. You can use this method
|
||||
* in conjunction with the <CODE>hasMoreElements</CODE> method to
|
||||
* iterate through all elements in the search results.
|
||||
* <P>
|
||||
*
|
||||
* Make sure to cast the
|
||||
* returned element as the correct type. For example:
|
||||
* <PRE>
|
||||
* LDAPSearchResults res = ld.search( MY_SEARCHBASE,
|
||||
* LDAPConnection.SCOPE_BASE, MY_FILTER,
|
||||
* null, false );
|
||||
* while ( res.hasMoreElements() ) {
|
||||
* Object o = res.nextElement();
|
||||
* if ( o instanceof LDAPEntry ) {
|
||||
* LDAPEntry findEntry = (LDAPEntry)o;
|
||||
* ...
|
||||
* } else if ( o instanceof LDAPReferralException ) {
|
||||
* LDAPReferralException e = (LDAPReferralException)o;
|
||||
* LDAPUrl refUrls[] = e.getURLs();
|
||||
* ...
|
||||
* } else if ( o instanceof LDAPException ) {
|
||||
* LDAPException e = (LDAPException)o;
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
* </PRE>
|
||||
* @return The next element in the search results.
|
||||
* @see netscape.ldap.LDAPSearchResults#hasMoreElements()
|
||||
*/
|
||||
public Object nextElement() {
|
||||
if ( entries.size() > 0 ) {
|
||||
Object obj = entries.elementAt(0);
|
||||
entries.removeElementAt(0);
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (referralResults.size() > 0) {
|
||||
return nextReferralElement();
|
||||
}
|
||||
|
||||
if ((exceptions != null) && (exceptions.size() > 0)) {
|
||||
Object obj = exceptions.elementAt(0);
|
||||
exceptions.removeElementAt(0);
|
||||
return obj;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Object nextReferralElement() {
|
||||
LDAPSearchResults res =
|
||||
(LDAPSearchResults)referralResults.elementAt(0);
|
||||
if ((!res.persistentSearch && res.hasMoreElements()) ||
|
||||
(res.persistentSearch)) {
|
||||
Object obj = res.nextElement();
|
||||
if (obj != null) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
if ((obj == null) || (!res.hasMoreElements()))
|
||||
referralResults.removeElementAt(0);
|
||||
}
|
||||
else
|
||||
referralResults.removeElementAt(0);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <CODE>true</CODE> if there are more search results
|
||||
* to be returned. You can use this method in conjunction with the
|
||||
* <CODE>nextElement</CODE> or <CODE>next</CODE> methods to iterate
|
||||
* through each entry in the results. For example:
|
||||
* <PRE>
|
||||
* LDAPSearchResults res = ld.search( MY_SEARCHBASE,
|
||||
* LDAPConnection.SCOPE_BASE, MY_FILTER,
|
||||
* null, false );
|
||||
* while ( res.hasMoreElements() ) {
|
||||
* LDAPEntry findEntry = (LDAPEntry)res.nextElement();
|
||||
* ...
|
||||
* }
|
||||
* </PRE>
|
||||
* @return <CODE>true</CODE> if there are more search results
|
||||
* @see netscape.ldap.LDAPSearchResults#nextElement()
|
||||
* @see netscape.ldap.LDAPSearchResults#next()
|
||||
*/
|
||||
public boolean hasMoreElements() {
|
||||
|
||||
while ((entries.size() == 0) && (!searchComplete))
|
||||
fetchResult();
|
||||
|
||||
if ((entries.size() == 0) &&
|
||||
((exceptions == null) || (exceptions.size() == 0))) {
|
||||
while (referralResults.size() > 0) {
|
||||
LDAPSearchResults res =
|
||||
(LDAPSearchResults)referralResults.elementAt(0);
|
||||
if (res.hasMoreElements())
|
||||
return true;
|
||||
else
|
||||
referralResults.removeElementAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
return ((entries.size() > 0) ||
|
||||
((exceptions != null) && (exceptions.size() > 0)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a count of the entries in the search results.
|
||||
* @return Count of entries found by the search.
|
||||
*/
|
||||
public int getCount() {
|
||||
int totalReferralEntries = 0;
|
||||
int count = 0;
|
||||
for (int i=0; i<referralResults.size(); i++) {
|
||||
LDAPSearchResults res =
|
||||
(LDAPSearchResults)referralResults.elementAt(i);
|
||||
totalReferralEntries = totalReferralEntries+res.getCount();
|
||||
}
|
||||
if (resultSource != null) {
|
||||
count = resultSource.getMessageCount();
|
||||
} else {
|
||||
count = entries.size();
|
||||
}
|
||||
if (exceptions != null)
|
||||
return (count + exceptions.size() + totalReferralEntries);
|
||||
return (count + totalReferralEntries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns message id.
|
||||
* @return Message id.
|
||||
*/
|
||||
int getID() {
|
||||
if ( resultSource == null )
|
||||
return -1;
|
||||
return resultSource.getID();
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminates the iteration; called on LDAPConnection.abandon().
|
||||
*/
|
||||
void abandon() {
|
||||
synchronized( this ) {
|
||||
searchComplete = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetchs the next result, for asynchronous searches.
|
||||
*/
|
||||
private synchronized void fetchResult() {
|
||||
|
||||
/* Asynchronous case */
|
||||
if ( resultSource != null ) {
|
||||
synchronized( this ) {
|
||||
if (searchComplete || firstResult)
|
||||
{
|
||||
firstResult = false;
|
||||
return;
|
||||
}
|
||||
|
||||
LDAPMessage msg = null;
|
||||
try {
|
||||
msg = resultSource.nextMessage();
|
||||
} catch (LDAPException e) {
|
||||
add(e);
|
||||
currConn.releaseSearchListener(resultSource);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg instanceof LDAPResponse) {
|
||||
try {
|
||||
// check response and see if we need to do referral
|
||||
// v2: referral stored in the JDAPResult
|
||||
currConn.checkSearchMsg(this, msg, currCons,
|
||||
currBase, currScope, currFilter, currAttrs, currAttrsOnly);
|
||||
} catch (LDAPException e) {
|
||||
System.err.println("Exception: "+e);
|
||||
} finally {
|
||||
currConn.releaseSearchListener(resultSource);
|
||||
}
|
||||
searchComplete = true;
|
||||
if (connectionToClose != null) {
|
||||
try {
|
||||
connectionToClose.disconnect ();
|
||||
} catch (LDAPException e) {
|
||||
}
|
||||
connectionToClose = null;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
try {
|
||||
currConn.checkSearchMsg(this, msg, currCons,
|
||||
currBase, currScope, currFilter, currAttrs, currAttrsOnly);
|
||||
} catch (LDAPException e) {
|
||||
System.err.println("Exception: "+e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
/**
|
||||
* Represents a socket connection that you can use to connect to an
|
||||
* LDAP server. You can write a class that implements this interface
|
||||
* if you want to use a TLS socket to connect to a secure server.
|
||||
* (The <CODE>LDAPSSLSocketFactory class</CODE>, which is included
|
||||
* in the <CODE>netscape.ldap</CODE> package, implements this
|
||||
* interface for SSL connections.)
|
||||
* <P>
|
||||
*
|
||||
* When you construct a new <CODE>LDAPConnection</CODE>
|
||||
* object, you can specify that the connection uses his socket by
|
||||
* passing the constructor an object of the class that implements
|
||||
* this interface.
|
||||
* <P>
|
||||
*
|
||||
* @version 1.0
|
||||
* @see LDAPConnection#LDAPConnection(netscape.ldap.LDAPSocketFactory)
|
||||
* @see LDAPSSLSocketFactory
|
||||
*/
|
||||
public interface LDAPSocketFactory {
|
||||
/**
|
||||
* Returns a socket to the specified host name and port number.
|
||||
* <P>
|
||||
*
|
||||
* @param host Name of the host that you want to connect to.
|
||||
* @param port Port number that you want to connect to.
|
||||
* @exception LDAPException Failed to create the socket.
|
||||
* @see LDAPSSLSocketFactory#makeSocket(java.lang.String,int)
|
||||
*/
|
||||
public Socket makeSocket(String host, int port)
|
||||
throws LDAPException;
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
/**
|
||||
* Represents sorting instructions for a particular attribute.
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LDAPSortKey {
|
||||
public final static int REVERSE = 0x81;
|
||||
|
||||
/**
|
||||
* Constructs a new <CODE>LDAPSortKey</CODE> object that will
|
||||
* sort based on the specified instructions.
|
||||
* @param keyDescription A single attribute specification to sort by.
|
||||
* If preceded by a hyphen ("-"), the attribute is sorted in reverse order.
|
||||
* You can also specify the object ID (OID) of a matching rule after
|
||||
* a colon (":"). For example:
|
||||
* <P>
|
||||
* <UL>
|
||||
* <LI><CODE>"cn"</CODE> (sort by the <CODE>cn</CODE> attribute) <P>
|
||||
* <LI><CODE>"-cn"</CODE> (sort by the <CODE>cn</CODE> attribute in
|
||||
* reverse order) <P>
|
||||
* <LI><CODE>"-cn:1.2.3.4"</CODE> (sort by the <CODE>cn</CODE>
|
||||
* attribute in reverse order and use the matching rule identified
|
||||
* by the OID 1.2.3.4) <P>
|
||||
*</UL>
|
||||
* @see netscape.ldap.controls.LDAPSortControl
|
||||
* @see netscape.ldap.controls.LDAPVirtualListControl
|
||||
*/
|
||||
public LDAPSortKey( String keyDescription ) {
|
||||
if ( (keyDescription != null) && (keyDescription.length() > 0) ) {
|
||||
if ( keyDescription.charAt( 0 ) == '-' ) {
|
||||
m_reverse = true;
|
||||
m_key = keyDescription.substring( 1 );
|
||||
} else {
|
||||
m_reverse = false;
|
||||
m_key = keyDescription;
|
||||
}
|
||||
int colonIndex = m_key.indexOf( ':' );
|
||||
if ( colonIndex == 0 )
|
||||
m_key = null;
|
||||
else if ( colonIndex > 0 ) {
|
||||
m_matchRule = m_key.substring( colonIndex+1 );
|
||||
m_key = m_key.substring( 0, colonIndex );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <CODE>LDAPSortKey</CODE> object that will
|
||||
* sort based on the specified attribute and sort order.
|
||||
* @param key A single attribute to sort by. For example:
|
||||
* <P>
|
||||
* <UL>
|
||||
* <LI><CODE>"cn"</CODE> (sort by the <CODE>cn</CODE> attribute)
|
||||
* <LI><CODE>"givenname"</CODE> (sort by the <CODE>givenname</CODE>
|
||||
* attribute)
|
||||
* </UL>
|
||||
* @param reverse If <CODE>true</CODE>, the sorting is done in
|
||||
* descending order.
|
||||
* @see netscape.ldap.controls.LDAPSortControl
|
||||
* @see netscape.ldap.controls.LDAPVirtualListControl
|
||||
*/
|
||||
public LDAPSortKey( String key,
|
||||
boolean reverse) {
|
||||
m_key = key;
|
||||
m_reverse = reverse;
|
||||
m_matchRule = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <CODE>LDAPSortKey</CODE> object that will
|
||||
* sort based on the specified attribute, sort order, and matching
|
||||
* rule.
|
||||
* @param key A single attribute to sort by. For example:
|
||||
* <P>
|
||||
* <UL>
|
||||
* <LI><CODE>"cn"</CODE> (sort by the <CODE>cn</CODE> attribute)
|
||||
* <LI><CODE>"givenname"</CODE> (sort by the <CODE>givenname</CODE>
|
||||
* attribute)
|
||||
* </UL>
|
||||
* @param reverse If <CODE>true</CODE>, the sorting is done in
|
||||
* descending order.
|
||||
* @param matchRule Object ID (OID) of the matching rule for
|
||||
* the attribute (for example, <CODE>1.2.3.4</CODE>).
|
||||
* @see netscape.ldap.controls.LDAPSortControl
|
||||
* @see netscape.ldap.controls.LDAPVirtualListControl
|
||||
*/
|
||||
public LDAPSortKey( String key,
|
||||
boolean reverse,
|
||||
String matchRule) {
|
||||
m_key = key;
|
||||
m_reverse = reverse;
|
||||
m_matchRule = matchRule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute to sort by.
|
||||
* @return A single attribute to sort by.
|
||||
*/
|
||||
public String getKey() {
|
||||
return m_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <CODE>true</CODE> if sorting is to be done in descending order.
|
||||
* @return <CODE>true</CODE> if sorting is to be done in descending order.
|
||||
*/
|
||||
public boolean getReverse() {
|
||||
return m_reverse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object ID (OID) of the matching rule used for sorting.
|
||||
* If no matching rule is specified, <CODE>null</CODE> is returned.
|
||||
* @return The object ID (OID) of the matching rule, or <CODE>null</CODE>
|
||||
* if the sorting instructions specify no matching rule.
|
||||
*/
|
||||
public String getMatchRule() {
|
||||
return m_matchRule;
|
||||
}
|
||||
|
||||
private String m_key;
|
||||
private boolean m_reverse;
|
||||
private String m_matchRule;
|
||||
}
|
||||
|
||||
581
mozilla/directory/java-sdk/ldapjdk/netscape/ldap/LDAPUrl.java
Normal file
581
mozilla/directory/java-sdk/ldapjdk/netscape/ldap/LDAPUrl.java
Normal file
@@ -0,0 +1,581 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
/**
|
||||
* Represents an LDAP URL. The complete specification for LDAP URLs is in
|
||||
* <A HREF="http://ds.internic.net/rfc/rfc1959.txt"
|
||||
* TARGET="_blank">RFC 1959</A>. LDAP URLs have the following format:
|
||||
*
|
||||
* <PRE>
|
||||
* "ldap://" [ <I>hostName</I> [":" <I>portNumber</I>] ] "//"
|
||||
* <I>distinguishedName</I>
|
||||
* ["?" <I>attributeList</I> ["?" <I>scope</I>
|
||||
* "?" <I>filterString</I> ] ]
|
||||
* </PRE>
|
||||
* where
|
||||
* <P>
|
||||
* <UL>
|
||||
* <LI>all text within double-quotes are literal<P>
|
||||
* <LI><CODE><I>hostName</I></CODE> and <CODE><I>portNumber</I></CODE>
|
||||
* identify the location of the LDAP server.<P>
|
||||
* <LI><CODE><I>distinguishedName</I></CODE> is the name of an entry
|
||||
* within the given directory (the entry represents the starting point
|
||||
* of the search)<P>
|
||||
* <LI><CODE><I>attributeList</I></CODE> contains a list of attributes
|
||||
* to retrieve (if null, fetch all attributes). This is a comma-delimited
|
||||
* list of attribute names.<P>
|
||||
* <LI><CODE><I>scope</I></CODE> is one of the following:
|
||||
* <UL>
|
||||
* <LI><CODE>base</CODE> indicates that this is a search only for the
|
||||
* specified entry
|
||||
* <LI><CODE>one</CODE> indicates that this is a search for matching entries
|
||||
* one level under the specified entry (and not including the entry itself)
|
||||
* <LI><CODE>sub</CODE> indicates that this is a search for matching entries
|
||||
* at all levels under the specified entry (including the entry itself)
|
||||
* </UL>
|
||||
* <P>
|
||||
* If not specified, <CODE><I>scope</I></CODE> is <CODE>base</CODE> by
|
||||
* default. <P>
|
||||
* <LI><CODE><I>filterString</I></CODE> is a human-readable representation
|
||||
* of the search criteria. This value is used only for one-level or subtree
|
||||
* searches.<P>
|
||||
* </UL>
|
||||
* <P>
|
||||
* Note that if <CODE><I>scope</I></CODE> and <CODE><I>filterString</I></CODE>
|
||||
* are not specified, an LDAP URL identifies exactly one entry in the
|
||||
* directory. <P>
|
||||
* The same encoding rules for other URLs (e.g. HTTP) apply for LDAP
|
||||
* URLs. Specifically, any "illegal" characters are escaped with
|
||||
* <CODE>%<I>HH</I></CODE>, where <CODE><I>HH</I></CODE> represent the
|
||||
* two hex digits which correspond to the ASCII value of the character.
|
||||
* This encoding is only legal (or necessary) on the DN and filter portions
|
||||
* of the URL.
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LDAPUrl {
|
||||
|
||||
public static String defaultFilter = "(objectClass=*)";
|
||||
|
||||
private String hostName;
|
||||
private int portNumber;
|
||||
private String DN;
|
||||
private Vector attributes;
|
||||
private int scope;
|
||||
private String filter;
|
||||
private String URL;
|
||||
|
||||
/**
|
||||
* Constructs a URL object with the specified string as URL.
|
||||
* @param url LDAP search expression in URL form
|
||||
* @exception MalformedURLException failed to parse URL
|
||||
*/
|
||||
public LDAPUrl (String url) throws java.net.MalformedURLException {
|
||||
StringTokenizer urlParser = new StringTokenizer (url, ":/?", true);
|
||||
String currentToken;
|
||||
String attributeList = null;
|
||||
attributes = null;
|
||||
scope = LDAPv2.SCOPE_BASE;
|
||||
filter = defaultFilter;
|
||||
URL = url;
|
||||
|
||||
try {
|
||||
currentToken = urlParser.nextToken();
|
||||
if (!currentToken.equalsIgnoreCase ("LDAP"))
|
||||
throw new MalformedURLException ();
|
||||
|
||||
urlParser.nextToken(); // ":"
|
||||
urlParser.nextToken(); // "/"
|
||||
urlParser.nextToken(); // "/"
|
||||
|
||||
currentToken = urlParser.nextToken();
|
||||
|
||||
if (currentToken.equals ("/")) {
|
||||
hostName = null;
|
||||
portNumber = LDAPv2.DEFAULT_PORT;
|
||||
} else {
|
||||
hostName = currentToken;
|
||||
if (urlParser.countTokens() == 0) {
|
||||
portNumber = LDAPv2.DEFAULT_PORT;
|
||||
return;
|
||||
}
|
||||
currentToken = urlParser.nextToken (); // either ":" or "/"
|
||||
|
||||
if (currentToken.equals (":")) {
|
||||
portNumber = Integer.parseInt (urlParser.nextToken());
|
||||
if (urlParser.countTokens() == 0) {
|
||||
return;
|
||||
}
|
||||
urlParser.nextToken (); // "/"
|
||||
} else
|
||||
portNumber = LDAPv2.DEFAULT_PORT;
|
||||
}
|
||||
|
||||
if (urlParser.countTokens() == 0)
|
||||
return;
|
||||
|
||||
DN = decode (urlParser.nextToken ());
|
||||
|
||||
// it retrieves the ? token, meaning no DN is supplied
|
||||
if (DN.equals("?"))
|
||||
DN = "";
|
||||
else if (DN.equals("/"))
|
||||
throw new MalformedURLException ();
|
||||
|
||||
if (urlParser.hasMoreTokens ()) {
|
||||
// we have a "?attributeList" portion
|
||||
String str = null;
|
||||
str = readNextConstruct(urlParser);
|
||||
|
||||
// if attribute
|
||||
if ((str != null) && (isAttribute(str))) {
|
||||
// it retrieves the ? token, meaning no attribute is supplied
|
||||
if (str.equals("?")) {
|
||||
attributeList = null;
|
||||
str = urlParser.nextToken();
|
||||
}
|
||||
else {
|
||||
attributeList = decode(str);
|
||||
str = readNextConstruct(urlParser);
|
||||
}
|
||||
}
|
||||
|
||||
// if scope
|
||||
if ((str != null) && ((scope = getScope(str)) != -1))
|
||||
str = readNextConstruct(urlParser);
|
||||
// no scope is supplied
|
||||
else if ((str != null) && (str.equals("?"))) {
|
||||
scope = LDAPv2.SCOPE_BASE;
|
||||
str = urlParser.nextToken();
|
||||
} else {
|
||||
scope = LDAPv2.SCOPE_BASE;
|
||||
}
|
||||
|
||||
// if filter
|
||||
if ((str != null) && (isFilter(str))) {
|
||||
filter = decode(str);
|
||||
str = readNextConstruct(urlParser);
|
||||
}
|
||||
}
|
||||
} catch (NumberFormatException nf) {
|
||||
throw new MalformedURLException ();
|
||||
}
|
||||
|
||||
if (attributeList != null) {
|
||||
StringTokenizer attributeParser = new
|
||||
StringTokenizer (attributeList, ", ");
|
||||
attributes = new Vector ();
|
||||
|
||||
while (attributeParser.hasMoreTokens())
|
||||
attributes.addElement (attributeParser.nextToken());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs with the specified host, port, and DN. This form is used to
|
||||
* create URL references to a particular object in the directory.
|
||||
* @param host Host name of LDAP server, or null for "nearest X.500/LDAP"
|
||||
* @param port Port number for LDAP server (use LDAPv2.DEFAULT_PORT for
|
||||
* default port)
|
||||
* @param DN Distinguished name of object
|
||||
*/
|
||||
public LDAPUrl (String host, int port, String DN) {
|
||||
if (host != null) {
|
||||
if (port != LDAPv2.DEFAULT_PORT)
|
||||
URL = "LDAP://" + host + ":" + String.valueOf (port) +
|
||||
"/" + encode (DN);
|
||||
else
|
||||
URL = "LDAP://" + host + "/" + encode (DN);
|
||||
} else
|
||||
URL = "LDAP:///" + encode (DN);
|
||||
|
||||
this.hostName = host;
|
||||
this.DN = DN;
|
||||
portNumber = port;
|
||||
filter = defaultFilter;
|
||||
attributes = null;
|
||||
scope = LDAPv2.SCOPE_BASE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a full-blown LDAP URL to specify an LDAP search operation.
|
||||
* @param host Host name of LDAP server, or null for "nearest X.500/LDAP"
|
||||
* @param port Port number for LDAP server (use LDAPv2.DEFAULT_PORT for
|
||||
* default port)
|
||||
* @param DN Distinguished name of object
|
||||
* @param attributes List of attributes to return. Use null for "all
|
||||
* attributes"
|
||||
* @param scope Depth of search (in DN namespace). Use one of SCOPE_BASE,
|
||||
* SCOPE_ONE, SCOPE_SUB from LDAPv2
|
||||
* @param filter LDAP fitler string (as defined in RFC 1558) use null for
|
||||
* no filter (this effectively makes the URL reference a single object)
|
||||
*/
|
||||
public LDAPUrl (String host, int port, String DN,
|
||||
String attributes[], int scope, String filter) {
|
||||
|
||||
if (attributes != null) {
|
||||
Vector list = new Vector();
|
||||
for (int k = 0; k < attributes.length; k++) {
|
||||
list.addElement(attributes[k]);
|
||||
}
|
||||
initialize(host, port, DN, list.elements(), scope, filter);
|
||||
} else {
|
||||
initialize(host, port, DN, null, scope, filter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a full-blown LDAP URL to specify an LDAP search operation.
|
||||
* @param host Host name of LDAP server, or null for "nearest X.500/LDAP"
|
||||
* @param port Port number for LDAP server (use LDAPv2.DEFAULT_PORT for
|
||||
* default port)
|
||||
* @param DN Distinguished name of object
|
||||
* @param attributes List of attributes to return. Use null for "all
|
||||
* attributes"
|
||||
* @param scope Depth of search (in DN namespace). Use one of SCOPE_BASE,
|
||||
* SCOPE_ONE, SCOPE_SUB from LDAPv2
|
||||
* @param filter LDAP fitler string (as defined in RFC 1558) use null for
|
||||
* no filter (this effectively makes the URL reference a single object)
|
||||
*/
|
||||
public LDAPUrl (String host, int port, String DN,
|
||||
Enumeration attributes, int scope, String filter) {
|
||||
|
||||
initialize(host, port, DN, attributes, scope, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes URL object.
|
||||
*/
|
||||
private void initialize (String host, int port, String DN,
|
||||
Enumeration attributes, int scope, String filter) {
|
||||
|
||||
this.hostName = host;
|
||||
this.DN = DN;
|
||||
portNumber = port;
|
||||
this.filter = (filter != null) ? filter : defaultFilter;
|
||||
this.scope = scope;
|
||||
|
||||
if (attributes != null) {
|
||||
this.attributes = new Vector ();
|
||||
while (attributes.hasMoreElements()) {
|
||||
this.attributes.addElement (attributes.nextElement());
|
||||
}
|
||||
} else
|
||||
this.attributes = null;
|
||||
|
||||
StringBuffer url = new StringBuffer ("LDAP://");
|
||||
|
||||
if (host != null) {
|
||||
url.append (host);
|
||||
if (port != LDAPv2.DEFAULT_PORT) {
|
||||
url.append (':');
|
||||
url.append (String.valueOf (port));
|
||||
}
|
||||
}
|
||||
|
||||
url.append ('/');
|
||||
url.append (encode (DN));
|
||||
|
||||
if (attributes != null) {
|
||||
url.append ('?');
|
||||
Enumeration attrList = this.attributes.elements();
|
||||
boolean firstElement = true;
|
||||
|
||||
while (attrList.hasMoreElements()) {
|
||||
if (!firstElement)
|
||||
url.append (',');
|
||||
else
|
||||
firstElement = false;
|
||||
|
||||
url.append ((String)attrList.nextElement());
|
||||
}
|
||||
}
|
||||
|
||||
if (filter != null) {
|
||||
if (attributes == null)
|
||||
url.append ('?');
|
||||
|
||||
url.append ('?');
|
||||
|
||||
switch (scope) {
|
||||
default:
|
||||
case LDAPv2.SCOPE_BASE:
|
||||
url.append ("base"); break;
|
||||
case LDAPv2.SCOPE_ONE:
|
||||
url.append ("one"); break;
|
||||
case LDAPv2.SCOPE_SUB:
|
||||
url.append ("sub"); break;
|
||||
}
|
||||
|
||||
url.append ('?');
|
||||
url.append (filter);
|
||||
}
|
||||
|
||||
URL = url.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the host name of the LDAP server
|
||||
* @return LDAP host
|
||||
*/
|
||||
public String getHost () {
|
||||
return hostName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the port number for the LDAP server
|
||||
* @return port number
|
||||
*/
|
||||
public int getPort () {
|
||||
return portNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the distinguished name encapsulated in the URL
|
||||
* @return target distinguished name
|
||||
*/
|
||||
public String getDN () {
|
||||
return DN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the collection of attributes specified in the URL, or null
|
||||
* for "every attribute"
|
||||
* @return enumeration of attributes
|
||||
*/
|
||||
public Enumeration getAttributes () {
|
||||
if (attributes == null)
|
||||
return null;
|
||||
else
|
||||
return attributes.elements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the collection of attributes specified in the URL, or null
|
||||
* for "every attribute"
|
||||
* @return string array of attribute
|
||||
*/
|
||||
public String[] getAttributeArray () {
|
||||
if (attributes == null)
|
||||
return null;
|
||||
else {
|
||||
String[] attrNames = new String[attributes.size()];
|
||||
Enumeration attrs = getAttributes();
|
||||
int i = 0;
|
||||
|
||||
while (attrs.hasMoreElements())
|
||||
attrNames[i++] = (String)attrs.nextElement();
|
||||
|
||||
return attrNames;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scope of the search, according to the values
|
||||
* SCOPE_BASE, SCOPE_ONE, SCOPE_SUB defined in LDAPv2. This refers
|
||||
* to how deep in the directory namespace the search will look
|
||||
* @return search scope
|
||||
*/
|
||||
public int getScope () {
|
||||
return scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scope of the search. If the scope returned is -1, then
|
||||
* the given string is not for the scope.
|
||||
* @param str The string which compares with the scope type.
|
||||
* @returns The scope of the search, -1 returns if the given string is
|
||||
* not one of the values: sub, one or base.
|
||||
*/
|
||||
private int getScope(String str) {
|
||||
|
||||
int s = -1;
|
||||
if (str.equalsIgnoreCase("base"))
|
||||
s = LDAPv2.SCOPE_BASE;
|
||||
else if (str.equalsIgnoreCase("one"))
|
||||
s = LDAPv2.SCOPE_ONE;
|
||||
else if (str.equalsIgnoreCase("sub"))
|
||||
s = LDAPv2.SCOPE_SUB;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the search filter (RFC 1558), or the default if none was
|
||||
* specified.
|
||||
* @return filter
|
||||
*/
|
||||
public String getFilter () {
|
||||
return filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a valid string representation of this LDAP URL.
|
||||
* @return LDAP search expression in URL form
|
||||
*/
|
||||
public String getUrl () {
|
||||
return URL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given string is a filter expression.
|
||||
* @param The string which is checked if it is filter expression.
|
||||
* @return true if the given string is a filter expression; otherwise,
|
||||
* return false;
|
||||
*/
|
||||
private boolean isFilter(String str) {
|
||||
if (str.startsWith("("))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the given string is an attribute expression.
|
||||
* @param The string which is checked if it is attribute expression.
|
||||
* @return true if the given string is an attribute expression; otherwise,
|
||||
* return false;
|
||||
*/
|
||||
private boolean isAttribute(String str) {
|
||||
if ((!str.startsWith("(")) && (!str.equalsIgnoreCase("base")) &&
|
||||
(!str.equalsIgnoreCase("one")) && (!str.equalsIgnoreCase("sub")))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads next construct from the given string parser.
|
||||
* @param parser The string parser
|
||||
* @return The next construct which can be attribute, scope or filter.
|
||||
* @exception java.net.MalformedURLException Get thrown when the url format
|
||||
* is incorrect.
|
||||
*/
|
||||
private String readNextConstruct(StringTokenizer parser) throws
|
||||
MalformedURLException {
|
||||
|
||||
try {
|
||||
if (parser.hasMoreTokens()) {
|
||||
parser.nextToken(); // "?"
|
||||
return parser.nextToken();
|
||||
}
|
||||
} catch (NoSuchElementException e) {
|
||||
throw new MalformedURLException();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses hex character into integer.
|
||||
*/
|
||||
private static int hexValue (char hexChar) throws MalformedURLException {
|
||||
if (hexChar >= '0' && hexChar <= '9')
|
||||
return hexChar - '0';
|
||||
if (hexChar >= 'A' && hexChar <= 'F')
|
||||
return hexChar - 'A' + 10;
|
||||
if (hexChar >= 'a' && hexChar <= 'f')
|
||||
return hexChar - 'a' + 10;
|
||||
|
||||
throw new MalformedURLException ();
|
||||
}
|
||||
|
||||
private static char hexChar (int hexValue) {
|
||||
if (hexValue < 0 || hexValue > 0xF)
|
||||
return 'x';
|
||||
|
||||
if (hexValue < 10)
|
||||
return (char)(hexValue + '0');
|
||||
|
||||
return (char)((hexValue - 10) + 'a');
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a URL-encoded string. Any occurences of %HH are decoded to the
|
||||
* hex value represented. However, this routine does NOT decode "+"
|
||||
* into " ". See RFC 1738 for full details about URL encoding/decoding.
|
||||
* @param URLEncoded A segment of a URL which was encoded via the URL
|
||||
* encoding rules
|
||||
* @exception MalformedURLException failed to parse URL
|
||||
*/
|
||||
public static String decode (String URLEncoded) throws
|
||||
MalformedURLException {
|
||||
StringBuffer decoded = new StringBuffer (URLEncoded);
|
||||
int srcPos = 0, dstPos = 0;
|
||||
|
||||
try {
|
||||
while (srcPos < decoded.length()) {
|
||||
if (decoded.charAt (srcPos) != '%') {
|
||||
if (srcPos != dstPos)
|
||||
decoded.setCharAt (dstPos, decoded.charAt (srcPos));
|
||||
srcPos++;
|
||||
dstPos++;
|
||||
continue;
|
||||
}
|
||||
decoded.setCharAt (dstPos, (char)
|
||||
((hexValue(decoded.charAt (srcPos+1))<<4) |
|
||||
(hexValue(decoded.charAt (srcPos+2)))));
|
||||
dstPos++;
|
||||
srcPos += 3;
|
||||
}
|
||||
} catch (StringIndexOutOfBoundsException sioob) {
|
||||
// Indicates that a "%" character occured without the following HH
|
||||
throw new MalformedURLException ();
|
||||
}
|
||||
|
||||
/* 070497 Url problems submitted by Netscape */
|
||||
/* decoded.setLength (dstPos+1); */
|
||||
decoded.setLength (dstPos);
|
||||
return decoded.toString ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes an arbitrary string. Any illegal characters are encoded as
|
||||
* %HH. However, this routine does NOT decode "+" into " " (this is a HTTP
|
||||
* thing, not a general URL thing). Note that, because Sun's URLEncoder
|
||||
* does do this encoding, we can't use it.
|
||||
* See RFC 1738 for full details about URL encoding/decoding.
|
||||
* @param toEncode An arbitrary string to encode for embedding in a URL
|
||||
*/
|
||||
public static String encode (String toEncode) {
|
||||
StringBuffer encoded = new StringBuffer (toEncode.length()+10);
|
||||
|
||||
for (int currPos = 0; currPos < toEncode.length(); currPos++) {
|
||||
char currChar = toEncode.charAt (currPos);
|
||||
if ((currChar >= 'a' && currChar <= 'z') ||
|
||||
(currChar >= 'A' && currChar <= 'Z') ||
|
||||
(currChar >= '0' && currChar <= '9') ||
|
||||
("$-_.+!*'(),".indexOf (currChar) > 0)) {
|
||||
// this is the criteria for "doesn't need to be encoded" (whew!)
|
||||
encoded.append (currChar);
|
||||
} else {
|
||||
encoded.append ("%");
|
||||
encoded.append (hexChar ((currChar & 0xF0) >> 4));
|
||||
encoded.append (hexChar (currChar & 0x0F));
|
||||
}
|
||||
}
|
||||
|
||||
return encoded.toString();
|
||||
}
|
||||
}
|
||||
479
mozilla/directory/java-sdk/ldapjdk/netscape/ldap/LDAPv2.java
Normal file
479
mozilla/directory/java-sdk/ldapjdk/netscape/ldap/LDAPv2.java
Normal file
@@ -0,0 +1,479 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* This interface summarizes the basic functionality available in the
|
||||
* Lightweight Directory Access Protocol (LDAP) version 2. (See
|
||||
* <A HREF="http://www.cis.ohio-state.edu/htbin/rfc/rfc1777.html" TARGET="_blank">RFC 1777</A>
|
||||
* for the definition of the protocol.)
|
||||
* <P>
|
||||
*
|
||||
* In the general model for this protocol, objects exist under a directory
|
||||
* in a particular server. Objects are identified by unique, hierarchical names
|
||||
* called Distinguished Names, commonly abreviated "DN". An example of a DN:
|
||||
* <pre>
|
||||
* cn=Barbara Jensen,ou=Product Development,o=Ace Industry,c=us
|
||||
* </pre>
|
||||
* Objects have attributes, of the form
|
||||
* <pre>
|
||||
* attributeName = attributeValue(s)
|
||||
* </pre>
|
||||
* Attribute names must be Strings, and attribute values can be any 8-bit
|
||||
* sequence (Strings or binary values).
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public interface LDAPv2 {
|
||||
/**
|
||||
* The default port number for LDAP servers. You can specify
|
||||
* this identifier when calling the <CODE>LDAPConnection.connect</CODE>
|
||||
* method to connect to an LDAP server.
|
||||
* @see netscape.ldap.LDAPConnection#connect
|
||||
*/
|
||||
public final static int DEFAULT_PORT = 389;
|
||||
|
||||
/**
|
||||
* Option specifying how aliases are dereferenced.
|
||||
* <P>
|
||||
*
|
||||
* This option can have one of the following values:
|
||||
* <UL>
|
||||
* <LI><A HREF="#DEREF_NEVER"><CODE>DEREF_NEVER</CODE></A>
|
||||
* <LI><A HREF="#DEREF_FINDING"><CODE>DEREF_FINDING</CODE></A>
|
||||
* <LI><A HREF="#DEREF_SEARCHING"><CODE>DEREF_SEARCHING</CODE></A>
|
||||
* <LI><A HREF="#DEREF_ALWAYS"><CODE>DEREF_ALWAYS</CODE></A>
|
||||
* </UL>
|
||||
* <P>
|
||||
*
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
*/
|
||||
public static final int DEREF = 2;
|
||||
|
||||
/**
|
||||
* Option specifying the maximum number of search results that
|
||||
* can be returned.
|
||||
* <P>
|
||||
*
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
*/
|
||||
public static final int SIZELIMIT = 3;
|
||||
|
||||
/**
|
||||
* Option specifying the maximum number of milliseconds to
|
||||
* wait for an operation to be completed.
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
*/
|
||||
public static final int TIMELIMIT = 4;
|
||||
|
||||
/**
|
||||
* Option specifying the maximum number of milliseconds the
|
||||
* server should wait when returning search results.
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
*/
|
||||
public static final int SERVER_TIMELIMIT = 5;
|
||||
|
||||
/**
|
||||
* Option specifying whether or not referrals to other LDAP
|
||||
* servers are followed automatically.
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
* @see netscape.ldap.LDAPRebind
|
||||
* @see netscape.ldap.LDAPRebindAuth
|
||||
*/
|
||||
public static final int REFERRALS = 8;
|
||||
|
||||
/**
|
||||
* Option specifying the object containing the method for
|
||||
* getting authentication information (the distinguished name
|
||||
* and password) used during a referral. For example, when
|
||||
* referred to another LDAP server, your client uses this object
|
||||
* to obtain the DN and password. Your client authenticates to
|
||||
* the LDAP server using this DN and password.
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
* @see netscape.ldap.LDAPRebind
|
||||
* @see netscape.ldap.LDAPRebindAuth
|
||||
*/
|
||||
public static final int REFERRALS_REBIND_PROC = 9;
|
||||
|
||||
/**
|
||||
* Option specifying the maximum number of referrals to follow
|
||||
* in a sequence when requesting an LDAP operation.
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
*/
|
||||
public static final int REFERRALS_HOP_LIMIT = 10;
|
||||
|
||||
/**
|
||||
* Option specifying the object containing the method for
|
||||
* authenticating to the server.
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
* @see netscape.ldap.LDAPBind
|
||||
*/
|
||||
public static final int BIND = 13;
|
||||
|
||||
/**
|
||||
* Option specifying the version of the LDAP protocol
|
||||
* used by your client when interacting with the LDAP server.
|
||||
* If no version is set, the default version is 2. If you
|
||||
* are planning to use LDAP v3 features (such as controls
|
||||
* or extended operations), you should set this version to 3
|
||||
* or specify version 3 as an argument to the <CODE>authenticate</CODE>
|
||||
* method of the <CODE>LDAPConnection</CODE> object.
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
* @see netscape.ldap.LDAPConnection#authenticate(int, java.lang.String, java.lang.String)
|
||||
*/
|
||||
public static final int PROTOCOL_VERSION = 17;
|
||||
|
||||
/**
|
||||
* Option specifying the number of results to return at a time.
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
*/
|
||||
public static final int BATCHSIZE = 20;
|
||||
|
||||
|
||||
/*
|
||||
* Valid options for Scope
|
||||
*/
|
||||
|
||||
/**
|
||||
* Specifies that the scope of a search includes
|
||||
* only the base DN (distinguished name).
|
||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
|
||||
*/
|
||||
public static final int SCOPE_BASE = 0;
|
||||
|
||||
/**
|
||||
* Specifies that the scope of a search includes
|
||||
* only the entries one level below the base DN (distinguished name).
|
||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints) */
|
||||
public static final int SCOPE_ONE = 1;
|
||||
|
||||
/**
|
||||
* Specifies that the scope of a search includes
|
||||
* the base DN (distinguished name) and all entries at all levels
|
||||
* beneath that base.
|
||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints) */
|
||||
public static final int SCOPE_SUB = 2;
|
||||
|
||||
|
||||
/*
|
||||
* Valid options for Dereference
|
||||
*/
|
||||
|
||||
/**
|
||||
* Specifies that aliases are never dereferenced.
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
*/
|
||||
public static final int DEREF_NEVER = 0;
|
||||
|
||||
/**
|
||||
* Specifies that aliases are dereferenced when searching the
|
||||
* entries beneath the starting point of the search (but
|
||||
* not when finding the starting entry).
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
*/
|
||||
public static final int DEREF_SEARCHING = 1;
|
||||
|
||||
/**
|
||||
* Specifies that aliases are dereferenced when finding the
|
||||
* starting point for the search (but not when searching
|
||||
* under that starting entry).
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
*/
|
||||
public static final int DEREF_FINDING = 2;
|
||||
|
||||
/**
|
||||
* Specifies that aliases are always dereferenced.
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
*/
|
||||
public static final int DEREF_ALWAYS = 3;
|
||||
|
||||
/**
|
||||
* Connects to the LDAP server.
|
||||
* @param host Hostname of the LDAP server.
|
||||
* @param port Port number of the LDAP server. To specify the
|
||||
* default, well-known port, use <CODE>DEFAULT_PORT</CODE>.
|
||||
* @exception LDAPException Failed to connect to the server.
|
||||
*/
|
||||
public void connect (String host, int port) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Connects and authenticates to the LDAP server.
|
||||
* @param host Hostname of the LDAP server.
|
||||
* @param port Port number of the LDAP server. To specify the
|
||||
* default, well-known port, use <CODE>DEFAULT_PORT</CODE>.
|
||||
* @param dn Distinguished name to use for authentication.
|
||||
* @param passwd Password for authentication.
|
||||
* @exception LDAPException Failed to connect and authenticate to the server.
|
||||
*/
|
||||
public void connect (String host, int port, String dn, String passwd)
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Disconnects from the LDAP server. Subsequent operational calls
|
||||
* will first try to re-establish the connection to the same LDAP server.
|
||||
* @exception LDAPException Failed to disconnect from the server.
|
||||
*/
|
||||
public void disconnect() throws LDAPException;
|
||||
|
||||
/**
|
||||
* Notifies the server to not send additional results associated with this
|
||||
* <CODE>LDAPSearchResults</CODE> object, and discards any results already
|
||||
* received.
|
||||
* @param results LDAPSearchResults object returned from a search.
|
||||
* @exception LDAPException Failed to notify the server.
|
||||
*/
|
||||
public void abandon(LDAPSearchResults results) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Authenticates user with the LDAP server.
|
||||
* @param Dn Distinguished name to use for authentication.
|
||||
* @param passwd Password for authentication.
|
||||
* @exception LDAPException Failed to authenticate to the server.
|
||||
*/
|
||||
public void authenticate (String DN, String passwd) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Authenticates user with the LDAP server.
|
||||
* @param Dn Distinguished name to use for authentication.
|
||||
* @param passwd Password for authentication.
|
||||
* @exception LDAPException Failed to authenticate to the server.
|
||||
*/
|
||||
public void bind (String DN, String passwd) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Read the entry corresponding to the specified distinguished name (DN).
|
||||
* @param DN Distinguished name of the entry to retrieve.
|
||||
* @exception LDAPException Failed to retrieve the specified entry.
|
||||
*/
|
||||
public LDAPEntry read (String DN) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Read the entry corresponding to the specified distinguished name (DN),
|
||||
* and retrieve only the specified attributes.
|
||||
* @param DN Distinguished name of the entry to retrieve.
|
||||
* @param attrs Names of attributes to retrieve.
|
||||
* @exception LDAPException Failed to retrieve the specified entry.
|
||||
*/
|
||||
public LDAPEntry read (String DN, String attrs[]) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Read the entry corresponding to the specified distinguished name (DN),
|
||||
* and retrieve only the specified attributes.
|
||||
* @param DN Distinguished name of the entry to retrieve.
|
||||
* @param attrs Names of attributes to retrieve.
|
||||
* @param cons The constraints set for the read operation.
|
||||
* @exception LDAPException Failed to retrieve the specified entry.
|
||||
*/
|
||||
public LDAPEntry read (String DN, String attrs[], LDAPSearchConstraints cons)
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Searches for entries in the directory.
|
||||
* @param base Starting point for the search in the directory
|
||||
* (distinguished name).
|
||||
* @param scope Indicates whether the scope of the search includes
|
||||
* only the base DN (equivalent to a read operation), only the entries
|
||||
* one level below the base DN, or all entries at all levels beneath
|
||||
* the base DN (including the base DN itself).
|
||||
* @param filter String which describes the search criteria. The format
|
||||
* of the string is described fully in
|
||||
* <A HREF="http://www.cis.ohio-state.edu/htbin/rfc/rfc1558.html" TARGET="_blank">RFC 1558</A>.
|
||||
* @param attrs Names of the attributes to return for each matching
|
||||
* directory entry. If <CODE>null</CODE>, all attributes are returned.
|
||||
* @param attrsOnly If <CODE>true</CODE>, the search will return only the names of
|
||||
* the attributes (and not their values).
|
||||
* @exception LDAPException Failed to complete the requested search.
|
||||
*/
|
||||
public LDAPSearchResults search (String base, int scope, String filter,
|
||||
String[] attrs, boolean attrsOnly) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Searches for entries in the directory.
|
||||
* @param base Starting point for the search in the directory
|
||||
* (distinguished name).
|
||||
* @param scope Indicates whether the scope of the search includes
|
||||
* only the base DN (equivalent to a read operation), only the entries
|
||||
* one level below the base DN, or all entries at all levels beneath
|
||||
* the base DN (including the base DN itself).
|
||||
* @param filter String which describes the search criteria. The format
|
||||
* of the string is described fully in
|
||||
* <A HREF="http://www.cis.ohio-state.edu/htbin/rfc/rfc1558.html" TARGET="_blank">RFC 1558</A>.
|
||||
* @param attrs Names of the attributes to return for each matching
|
||||
* directory entry. If <CODE>null</CODE>, all attributes are returned.
|
||||
* @param attrsOnly If <CODE>true</CODE>, the search will return only the names of
|
||||
* the attributes (and not their values).
|
||||
* @param cons Constraints specific to the search (for example, the maximum number
|
||||
* of entries to return or the maximum time to wait for the search operation to complete).
|
||||
* @exception LDAPException Failed to complete the requested search.
|
||||
*/
|
||||
public LDAPSearchResults search (String base, int scope, String filter,
|
||||
String[] attrs, boolean attrsOnly, LDAPSearchConstraints cons)
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Compares the given entry's attribute value to the specified
|
||||
* attribute value.
|
||||
* @param DN Distinguished name of the entry that you want compared
|
||||
* against the specified attribute value.
|
||||
* @param attr Attribute name and value to use in the comparison.
|
||||
* @exception LDAPException Failed to perform the comparison.
|
||||
*/
|
||||
public boolean compare (String DN, LDAPAttribute attr) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Compares the given entry's attribute value to the specified
|
||||
* attribute value.
|
||||
* @param DN Distinguished name of the entry that you want compared
|
||||
* against the specified attribute value.
|
||||
* @param attr Attribute name and value to use in the comparison.
|
||||
* @param cons The constraints set for the compare operation.
|
||||
* @exception LDAPException Failed to perform the comparison.
|
||||
*/
|
||||
public boolean compare (String DN, LDAPAttribute attr,
|
||||
LDAPConstraints cons) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Adds an entry to the directory.
|
||||
* @param entry New entry to add to the directory.
|
||||
* @exception LDAPException Failed to add the entry to the directory.
|
||||
*/
|
||||
public void add (LDAPEntry entry) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Adds an entry to the directory.
|
||||
* @param entry New entry to add to the directory.
|
||||
* @param cons The constraints set for the add operation.
|
||||
* @exception LDAPException Failed to add the entry to the directory.
|
||||
*/
|
||||
public void add (LDAPEntry entry, LDAPConstraints cons)
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Modifies an attribute of a directory entry.
|
||||
* @param DN Distinguished name identifying the entry to be modified.
|
||||
* @param mod The modification to be made.
|
||||
* @exception LDAPException Failed to modify the specified entry.
|
||||
*/
|
||||
public void modify (String DN, LDAPModification mod) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Modifies an attribute of a directory entry.
|
||||
* @param DN Distinguished name identifying the entry to be modified.
|
||||
* @param mod The modification to be made.
|
||||
* @param cons The constraints set for the modify operation.
|
||||
* @exception LDAPException Failed to modify the specified entry.
|
||||
*/
|
||||
public void modify (String DN, LDAPModification mod,
|
||||
LDAPConstraints cons) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Modifies the attributes of a directory entry.
|
||||
* @param DN Distinguished name identifying the entry to be modified.
|
||||
* @param mod List of the modifications to be made.
|
||||
* @exception LDAPException Failed to modify the specified entry.
|
||||
*/
|
||||
public void modify (String DN, LDAPModificationSet mods ) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Modifies the attributes of a directory entry.
|
||||
* @param DN Distinguished name identifying the entry to be modified.
|
||||
* @param mod List of the modifications to be made.
|
||||
* @param cons The constraints set for the modify operation.
|
||||
* @exception LDAPException Failed to modify the specified entry.
|
||||
*/
|
||||
public void modify (String DN, LDAPModificationSet mods,
|
||||
LDAPConstraints cons ) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Removes an entry from the directory.
|
||||
* @param DN Distinguished name identifying the entry to remove.
|
||||
* @exception LDAPException Failed to remove the entry from the directory.
|
||||
*/
|
||||
public void delete( String DN ) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Removes an entry from the directory.
|
||||
* @param DN Distinguished name identifying the entry to remove.
|
||||
* @param cons The constraints set for the delete operation.
|
||||
* @exception LDAPException Failed to remove the entry from the directory.
|
||||
*/
|
||||
public void delete( String DN, LDAPConstraints cons )
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Changes the name of an entry in the directory.
|
||||
* @param DN Original distinguished name (DN) of entry.
|
||||
* @param newRDN New relative distinguished name (RDN) of the entry.
|
||||
* @param deleteOldRDN Specifies whether or not the original RDN remains
|
||||
* as an attribute of the entry. If <CODE>true</CODE>, the original RDN
|
||||
* is no longer an attribute of the entry.
|
||||
* @exception LDAPException Failed to rename the entry in the directory.
|
||||
*/
|
||||
public void rename ( String DN, String newRDN, boolean deleteOldRDN )
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Changes the name of an entry in the directory.
|
||||
* @param DN Original distinguished name (DN) of entry.
|
||||
* @param newRDN New relative distinguished name (RDN) of the entry.
|
||||
* @param deleteOldRDN Specifies whether or not the original RDN remains
|
||||
* as an attribute of the entry. If <CODE>true</CODE>, the original RDN
|
||||
* is no longer an attribute of the entry.
|
||||
* @param cons The constraints set for the rename operation.
|
||||
* @exception LDAPException Failed to rename the entry in the directory.
|
||||
*/
|
||||
public void rename ( String DN, String newRDN, boolean deleteOldRDN,
|
||||
LDAPConstraints cons ) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Retrieves an option that applies to the connection.
|
||||
* The particular meaning may be implementation-dependent.
|
||||
* The standard options are the options described by
|
||||
* the <CODE>LDAPSearchConstraints</CODE> and <CODE>LDAPConstraints</CODE>
|
||||
* classes.
|
||||
* @exception LDAPException Failed to retrieve the value of the specified option.
|
||||
*/
|
||||
public Object getOption( int option ) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Sets an option that applies to the connection.
|
||||
* The particular meaning may be implementation-dependent.
|
||||
* The standard options are the options described by
|
||||
* the <CODE>LDAPSearchConstraints</CODE> and <CODE>LDAPConstraints</CODE>
|
||||
* classes.
|
||||
* @exception LDAPException Failed to set the specified option.
|
||||
*/
|
||||
public void setOption( int option, Object value ) throws LDAPException;
|
||||
}
|
||||
189
mozilla/directory/java-sdk/ldapjdk/netscape/ldap/LDAPv3.java
Normal file
189
mozilla/directory/java-sdk/ldapjdk/netscape/ldap/LDAPv3.java
Normal file
@@ -0,0 +1,189 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import netscape.ldap.client.*;
|
||||
import netscape.ldap.client.opers.*;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Specifies additional features available in version 3 of the
|
||||
* LDAP protocol. (To view preliminary information on this work
|
||||
* in progress, see the LDAP v3 internet draft. You can find the
|
||||
* latest version of this document listed under the Internet-Drafts
|
||||
* section of the
|
||||
* <A HREF="http://www.ietf.cnri.reston.va.us/html.charters/asid-charter.html"
|
||||
* TARGET=_blank">ASID home page</A>.)
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public interface LDAPv3 extends LDAPv2 {
|
||||
|
||||
/**
|
||||
* Connects and authenticates to the LDAP server with the specified LDAP
|
||||
* protocol version.
|
||||
* @param version LDAP protocol version requested: currently 2 or 3
|
||||
* @param host Hostname of the LDAP server.
|
||||
* @param port Port number of the LDAP server. To specify the
|
||||
* default, well-known port, use <CODE>DEFAULT_PORT</CODE>.
|
||||
* @param dn Distinguished name to use for authentication.
|
||||
* @param passwd Password for authentication.
|
||||
* @exception LDAPException Failed to connect and authenticate to the server.
|
||||
*/
|
||||
public void connect(int version, String host, int port, String dn,
|
||||
String passwd) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Authenticates to the LDAP server (that the object is currently
|
||||
* connected to) using the specified name and password, with the
|
||||
* specified LDAP protocol version. If the server does not support
|
||||
* the requested protocol version, an exception is thrown. If the
|
||||
* object has been disconnected from an LDAP server, this method
|
||||
* attempts to reconnect to the server. If the object had already
|
||||
* authenticated, the old authentication is discarded.
|
||||
* @param version LDAP protocol version requested: currently 2 or 3.
|
||||
* @param dn If non-null and non-empty, specifies that the
|
||||
* connection and all operations through it should be
|
||||
* authenticated with dn as the distinguished name.
|
||||
* @param passwd If non-null and non-empty, specifies that the
|
||||
* connection and all operations through it should be
|
||||
* authenticated with passwd as password.
|
||||
* @exception LDAPException Failed to authenticate to the LDAP server.
|
||||
*/
|
||||
public void authenticate(int version,
|
||||
String dn,
|
||||
String passwd)
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Authenticates to the LDAP server (that the object is currently
|
||||
* connected to) using the specified name and password, with the
|
||||
* specified LDAP protocol version. If the server does not support
|
||||
* the requested protocol version, an exception is thrown. If the
|
||||
* object has been disconnected from an LDAP server, this method
|
||||
* attempts to reconnect to the server. If the object had already
|
||||
* authenticated, the old authentication is discarded.
|
||||
* @param version LDAP protocol version requested: currently 2 or 3.
|
||||
* @param dn If non-null and non-empty, specifies that the
|
||||
* connection and all operations through it should be
|
||||
* authenticated with dn as the distinguished name.
|
||||
* @param passwd If non-null and non-empty, specifies that the
|
||||
* connection and all operations through it should be
|
||||
* authenticated with passwd as password.
|
||||
* @exception LDAPException Failed to authenticate to the LDAP server.
|
||||
*/
|
||||
public void bind(int version,
|
||||
String dn,
|
||||
String passwd)
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Performs an extended operation on the directory. Extended operations
|
||||
* are part of version 3 of the LDAP protocol.
|
||||
* <P>
|
||||
*
|
||||
* @param op LDAPExtendedOperation object specifying the OID of the
|
||||
* extended operation and the data to be used in the operation.
|
||||
* @exception LDAPException Failed to execute the operation
|
||||
* @return LDAPExtendedOperation object representing the extended response
|
||||
* returned by the server.
|
||||
* @see LDAPExtendedOperation
|
||||
*/
|
||||
public LDAPExtendedOperation extendedOperation( LDAPExtendedOperation op )
|
||||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Renames and moves an entry in the directory.
|
||||
* @param DN Original distinguished name (DN) for the entry.
|
||||
* @param newRDN New relative distinguished name (RDN) for the entry.
|
||||
* @param newParentDN Distinguished name of the new parent entry of the
|
||||
* specified entry.
|
||||
* @exception LDAPException Failed to rename the specified entry.
|
||||
*/
|
||||
public void rename( String DN, String newRDN, String newParentDN,
|
||||
boolean deleteOldRDN ) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Renames and moves an entry in the directory.
|
||||
* @param DN Original distinguished name (DN) for the entry.
|
||||
* @param newRDN New relative distinguished name (RDN) for the entry.
|
||||
* @param newParentDN Distinguished name of the new parent entry of the
|
||||
* specified entry.
|
||||
* @param cons The constraints set for the rename operation.
|
||||
* @exception LDAPException Failed to rename the specified entry.
|
||||
*/
|
||||
public void rename( String DN, String newRDN, String newParentDN,
|
||||
boolean deleteOldRDN, LDAPConstraints cons ) throws LDAPException;
|
||||
|
||||
/**
|
||||
* Returns an array of the latest controls (if any) from server.
|
||||
* @return An array of the controls returned by an operation,
|
||||
* or <CODE>null</CODE> if none.
|
||||
* @see netscape.ldap.LDAPControl
|
||||
*/
|
||||
public LDAPControl[] getResponseControls();
|
||||
|
||||
/**
|
||||
* Option specifying client controls for LDAP operations. These
|
||||
* controls are interpreted by the client and are not passed
|
||||
* to the LDAP server.
|
||||
* @see netscape.ldap.LDAPControl
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
*/
|
||||
public static final int CLIENTCONTROLS = 11;
|
||||
|
||||
/**
|
||||
* Option specifying server controls for LDAP operations. These
|
||||
* controls are passed to the LDAP server. They may also be returned by
|
||||
* the server.
|
||||
* @see netscape.ldap.LDAPControl
|
||||
* @see netscape.ldap.LDAPConnection#getOption
|
||||
* @see netscape.ldap.LDAPConnection#setOption
|
||||
*/
|
||||
public static final int SERVERCONTROLS = 12;
|
||||
|
||||
/**
|
||||
* Attribute type that you can specify in the LDAPConnection
|
||||
* search method if you don't want to retrieve any of the
|
||||
* attribute types for entries found by the search.
|
||||
* @see netscape.ldap.LDAPConnection#search
|
||||
*/
|
||||
public static final String NO_ATTRS = "1.1";
|
||||
|
||||
/**
|
||||
* Attribute type that you can specify in the LDAPConnection
|
||||
* search method if you want to retrieve all attribute types.
|
||||
* You can use this if you want to retrieve all attributes in
|
||||
* addition to an operational attribute. For example:
|
||||
* <P>
|
||||
*
|
||||
* <PRE>
|
||||
* ...
|
||||
* String [] MY_ATTRS = { LDAPv3.ALL_USER_ATTRS, "modifiersName",
|
||||
* "modifyTimestamp" };
|
||||
* LDAPSearchResults res = ld.search( MY_SEARCHBASE,
|
||||
* LDAPConnection.SCOPE_SUB, MY_FILTER, MY_ATTRS, false, cons );
|
||||
* ...
|
||||
* </PRE>
|
||||
* @see netscape.ldap.LDAPConnection#search
|
||||
*/
|
||||
public static final String ALL_USER_ATTRS = "*";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.ber.stream;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* This class is for the "any" object that is unknown to the
|
||||
* BER package but conforms to BER rules.
|
||||
*
|
||||
* <pre>
|
||||
* Encoding Rule:
|
||||
* The encoding is that of the particular implementation.
|
||||
* </pre>
|
||||
*
|
||||
* @version 1.0
|
||||
* @seeAlso CCITT X.209
|
||||
*/
|
||||
public class BERAny extends BERElement {
|
||||
/**
|
||||
* Internal variables
|
||||
*/
|
||||
private BERElement m_value = null;
|
||||
|
||||
/**
|
||||
* Constructs an "any" element.
|
||||
* @param value BERElement value
|
||||
*/
|
||||
public BERAny(BERElement value) {
|
||||
m_value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an "any" element from an input stream.
|
||||
* Note that with the current decoding architecture "any" types
|
||||
* will not be decoded as any's but rather as the particular
|
||||
* implementation. The following method will never be called.
|
||||
* @param stream input stream
|
||||
* @param bytes_read array of 1 int; value incremented by
|
||||
* number of bytes read from stream.
|
||||
* @exception IOException failed to construct
|
||||
*/
|
||||
public BERAny(BERTagDecoder decoder, InputStream stream,
|
||||
int[] bytes_read) throws IOException {
|
||||
m_value = getElement(decoder, stream, bytes_read);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the BER encoding directly to an output stream.
|
||||
* @param stream output stream
|
||||
*/
|
||||
public void write(OutputStream stream) throws IOException {
|
||||
m_value.write(stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the element type.
|
||||
* @param element type
|
||||
*/
|
||||
public int getType() {
|
||||
return BERElement.ANY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string representation.
|
||||
* @return string representation of tag
|
||||
*/
|
||||
public String toString() {
|
||||
return "ANY {" + m_value + "}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
package netscape.ldap.ber.stream;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.BitSet;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* This class is for the BitString object. Note that the BitSet class
|
||||
* has a bug: size() returns the size of the internal allocated memory
|
||||
* rather than the number of bits. Current work-around is to maintain
|
||||
* the number of bits ourselves in m_value_num_bits.
|
||||
* Change is required when BitSet is fixed.
|
||||
*
|
||||
* <pre>
|
||||
* ENCODING RULE:
|
||||
* Primitive Definite length.
|
||||
* tag = 0x03
|
||||
* </pre>
|
||||
*
|
||||
* @version 1.0
|
||||
* @seeAlso CCITT X.209
|
||||
*/
|
||||
public class BERBitString extends BERElement {
|
||||
/**
|
||||
* Internal variables
|
||||
*/
|
||||
private BitSet m_value;
|
||||
private int m_value_num_bits;
|
||||
|
||||
/**
|
||||
* Constructs a boolean element.
|
||||
* @param value boolean value
|
||||
*/
|
||||
public BERBitString(BitSet value) {
|
||||
m_value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a bitstring element from an input stream
|
||||
* (for constructed encodings).
|
||||
* @param stream source
|
||||
* @param bytes_read array of 1 int; value incremented by
|
||||
* number of bytes read from stream.
|
||||
* @exception IOException failed to construct
|
||||
*/
|
||||
public BERBitString(BERTagDecoder decoder, InputStream stream,
|
||||
int[] bytes_read) throws IOException {
|
||||
int octet;
|
||||
int contents_length = super.readLengthOctets(stream, bytes_read);
|
||||
int[] component_length = new int[1];
|
||||
BERElement element = null;
|
||||
|
||||
if (contents_length == -1) {
|
||||
/* Constructed - indefinite length. */
|
||||
{
|
||||
component_length[0] = 0;
|
||||
element = getElement(decoder,stream,component_length);
|
||||
if (element != null) {
|
||||
/* element is a bitstring - add it to the existing BitSet */
|
||||
BERBitString bit_string_element = (BERBitString)element;
|
||||
|
||||
BitSet new_bit_set = new BitSet(m_value_num_bits +
|
||||
bit_string_element.getSize());
|
||||
|
||||
for (int i = 0; i<m_value_num_bits; i++)
|
||||
if (m_value.get(i))
|
||||
new_bit_set.set(i);
|
||||
for (int j = 0; j<bit_string_element.getSize(); j++)
|
||||
if (bit_string_element.getValue().get(j))
|
||||
new_bit_set.set(m_value_num_bits+j);
|
||||
m_value = new_bit_set;
|
||||
m_value_num_bits += bit_string_element.getSize();
|
||||
}
|
||||
} while (element != null);
|
||||
} else {
|
||||
/* Constructed - definite length */
|
||||
bytes_read[0] += contents_length;
|
||||
while (contents_length > 0) {
|
||||
component_length[0] = 0;
|
||||
element = getElement(decoder,stream,component_length);
|
||||
if (element != null) {
|
||||
/* element is a bitstring - add it to the existing BitSet */
|
||||
BERBitString bit_string_element = (BERBitString)element;
|
||||
|
||||
BitSet new_bit_set = new BitSet(m_value_num_bits +
|
||||
bit_string_element.getSize());
|
||||
for (int i = 0; i<m_value_num_bits; i++)
|
||||
if (m_value.get(i))
|
||||
new_bit_set.set(i);
|
||||
for (int j = 0; j<bit_string_element.getSize(); j++)
|
||||
if (bit_string_element.getValue().get(j))
|
||||
new_bit_set.set(m_value_num_bits+j);
|
||||
m_value = new_bit_set;
|
||||
m_value_num_bits += bit_string_element.getSize();
|
||||
}
|
||||
contents_length -= component_length[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a bitstring element from an input stream
|
||||
* (for primitive encodings).
|
||||
* @param stream source
|
||||
* @param bytes_read array of 1 int; value incremented by
|
||||
* number of bytes read from stream.
|
||||
* @exception IOException failed to construct
|
||||
*/
|
||||
public BERBitString(InputStream stream, int[] bytes_read)
|
||||
throws IOException {
|
||||
/* Primitive - definite length content octets string. */
|
||||
|
||||
int octet;
|
||||
int contents_length = super.readLengthOctets(stream, bytes_read);
|
||||
|
||||
|
||||
/* First content octect doesn't encode any of
|
||||
* the string - it encodes the number of unused
|
||||
* bits in the final content octet.
|
||||
*/
|
||||
int last_unused_bits = stream.read();
|
||||
bytes_read[0]++;
|
||||
contents_length--;
|
||||
|
||||
m_value_num_bits = ((contents_length-1)*8) + (8-last_unused_bits);
|
||||
m_value = new BitSet();
|
||||
|
||||
int bit_num = 0;
|
||||
for (int i = 0; i < contents_length-1; i++) {
|
||||
octet = stream.read();
|
||||
int mask = 0x80;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if ((octet & mask) > 0) {
|
||||
m_value.set(bit_num);
|
||||
}
|
||||
else
|
||||
m_value.clear(bit_num);
|
||||
bit_num++;
|
||||
mask = mask / 2;
|
||||
}
|
||||
}
|
||||
|
||||
octet = stream.read(); /* last content octet */
|
||||
int mask = 0x80;
|
||||
for (int j = 0; j < 8-last_unused_bits; j++) {
|
||||
if ((octet & mask) > 0)
|
||||
m_value.set(bit_num);
|
||||
else
|
||||
m_value.clear(bit_num);
|
||||
bit_num++;
|
||||
mask = mask / 2;
|
||||
}
|
||||
|
||||
bytes_read[0] += contents_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the BER encoding directly to a stream.
|
||||
* Always sends in primitive form.
|
||||
* @param stream output stream
|
||||
*/
|
||||
public void write(OutputStream stream) throws IOException {
|
||||
stream.write(BERElement.BITSTRING);
|
||||
|
||||
//int num_bits = m_value.size(); /* number of bits to send */
|
||||
int num_bits = m_value_num_bits;
|
||||
|
||||
/* Number of bits unused int the last contents octet */
|
||||
int last_unused_bits = 8 - (num_bits % 8);
|
||||
|
||||
/* Figure out the number of content octets */
|
||||
int num_content_octets = (int)(num_bits/8) + 1;
|
||||
if (last_unused_bits > 0)
|
||||
num_content_octets += 1;
|
||||
stream.write(num_content_octets); /* length octet */
|
||||
|
||||
stream.write(last_unused_bits); /* first content octet */
|
||||
|
||||
for (int i = 0; i < (int)(num_bits/8); i++) {
|
||||
int new_octet = 0;
|
||||
int bit = 0x80;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if (m_value.get(i*8+j))
|
||||
new_octet += bit;
|
||||
bit = bit/2;
|
||||
}
|
||||
stream.write(new_octet);
|
||||
}
|
||||
|
||||
/*
|
||||
* Last octet may not use all bits. If last octet DOES use all
|
||||
* bits then it has already been written above.
|
||||
*/
|
||||
if (last_unused_bits > 0) {
|
||||
int new_octet = 0;
|
||||
int bit = 0x80;
|
||||
for (int j = 0; j < last_unused_bits; j++) {
|
||||
if (m_value.get(((int)(num_bits/8))*8+j))
|
||||
new_octet += bit;
|
||||
bit = bit/2;
|
||||
}
|
||||
stream.write(new_octet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bitstring value.
|
||||
* @param element type
|
||||
*/
|
||||
public BitSet getValue() {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of bits.
|
||||
* @return bit numbers
|
||||
*/
|
||||
public int getSize() {
|
||||
return m_value_num_bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the element type.
|
||||
* @param element type
|
||||
*/
|
||||
public int getType() {
|
||||
return BERElement.BITSTRING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string representation.
|
||||
* @return string representation of tag
|
||||
*/
|
||||
public String toString() {
|
||||
String hex_string = "";
|
||||
int octet;
|
||||
|
||||
//int num_bits = m_value.size();
|
||||
int num_bits = m_value_num_bits;
|
||||
for (int i = 0; i < (int)(num_bits/8); i++) {
|
||||
octet = 0;
|
||||
int bit = 0x80;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if (m_value.get(i*8+j))
|
||||
octet += bit;
|
||||
bit = bit/2;
|
||||
}
|
||||
hex_string += " " + (byte)octet;
|
||||
}
|
||||
|
||||
int bit = 0x80;
|
||||
octet = 0;
|
||||
for (int k = 0; k < num_bits-(int)(num_bits/8); k++) {
|
||||
if (m_value.get(((int)(num_bits/8))*8+k))
|
||||
octet += bit;
|
||||
bit = bit/2;
|
||||
}
|
||||
hex_string += " " + (byte)octet;
|
||||
|
||||
return "Bitstring {" + hex_string + " }";
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user