001: /*
002: * Copyright 2006-2007 The Scriptella Project Team.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package scriptella.driver.ldap;
017:
018: import scriptella.spi.AbstractConnection;
019: import scriptella.spi.ConnectionParameters;
020: import scriptella.spi.DriverContext;
021: import scriptella.spi.ParametersCallback;
022: import scriptella.spi.ProviderException;
023: import scriptella.spi.QueryCallback;
024: import scriptella.spi.Resource;
025: import scriptella.util.IOUtils;
026:
027: import javax.naming.Context;
028: import javax.naming.NamingException;
029: import javax.naming.directory.DirContext;
030: import javax.naming.directory.InitialDirContext;
031: import javax.naming.directory.SearchControls;
032: import java.io.IOException;
033: import java.io.Reader;
034: import java.util.Hashtable;
035: import java.util.logging.Level;
036: import java.util.logging.Logger;
037:
038: /**
039: * Represents a connection to a directory context.
040: * <p>For configuration details and examples see <a href="package-summary.html">overview page</a>.
041: *
042: * @author Fyodor Kupolov
043: * @version 1.0
044: */
045: public class LdapConnection extends AbstractConnection {
046: private static final Logger LOG = Logger
047: .getLogger(LdapConnection.class.getName());
048: private DirContext ctx;
049: private final SearchControls searchControls; //default search controls
050: private final Long maxFileLength;
051: private final String baseDn;
052: private final DriverContext driverContext;
053:
054: /**
055: * Name of the <em>Search scope</em> connection property.
056: * <p>The value must be one of the: object, onelevel, subtree
057: *
058: * @see SearchControls#setSearchScope(int)
059: */
060: public static final String SEARCH_SCOPE_KEY = "search.scope";
061:
062: /**
063: * Name of the <em>Search base DN</em> connection property.
064: *
065: * @see DirContext#search(String,javax.naming.directory.Attributes)
066: */
067: public static final String SEARCH_BASEDN_KEY = "search.basedn";
068:
069: /**
070: * Name of the <em>Time Limit</em> connection property.
071: * <p>The value must be integer.
072: *
073: * @see SearchControls#setTimeLimit(int)
074: */
075: public static final String SEARCH_TIMELIMIT_KEY = "search.timelimit";
076:
077: /**
078: * Name of the <em>Count Limit</em>(maximum number of entries to be returned)
079: * connection property.
080: * <p>The value must be integer.
081: *
082: * @see SearchControls#setCountLimit(long)
083: */
084: public static final String SEARCH_COUNTLIMIT_KEY = "search.countlimit";
085:
086: /**
087: * Names of the Max File Length connection property.
088: * <p>This property specifies the maximum size in Kb of the external files referenced from LDIFs.
089: * The default value is 10000 (10MB)
090: */
091: public static final String FILE_MAXLENGTH_KEY = "file.maxlength";
092:
093: public LdapConnection() {
094: this .searchControls = null;
095: this .maxFileLength = null;
096: this .baseDn = null;
097: this .driverContext = null;
098: }
099:
100: /**
101: * Creates a connnection to a directory.
102: *
103: * @param parameters parameters to establish connection.
104: */
105: public LdapConnection(ConnectionParameters parameters) {
106: super (Driver.DIALECT, parameters);
107: Hashtable<String, Object> env = new Hashtable<String, Object>();
108: //Put default settings
109: env.put(Context.INITIAL_CONTEXT_FACTORY,
110: "com.sun.jndi.ldap.LdapCtxFactory");
111: //Put connection settings
112: if (parameters.getUrl() == null) {
113: throw new LdapProviderException(
114: "Connection URL is required");
115: }
116: env.put(Context.PROVIDER_URL, parameters.getUrl());
117: if (parameters.getUser() != null) {
118: env.put(Context.SECURITY_PRINCIPAL, parameters.getUser());
119: }
120: if (parameters.getPassword() != null) {
121: env.put(Context.SECURITY_CREDENTIALS, parameters
122: .getPassword());
123: }
124: //Override env with user specified connection properties
125: env.putAll(parameters.getProperties());
126: //Set the search controls used for queries
127: searchControls = new SearchControls();
128: String scope = parameters.getStringProperty(SEARCH_SCOPE_KEY);
129: if (scope != null) {
130: if ("object".equalsIgnoreCase(scope)) {
131: searchControls
132: .setSearchScope(SearchControls.OBJECT_SCOPE);
133: } else if ("onelevel".equalsIgnoreCase(scope)) {
134: searchControls
135: .setSearchScope(SearchControls.ONELEVEL_SCOPE);
136: } else if ("subtree".equalsIgnoreCase(scope)) {
137: searchControls
138: .setSearchScope(SearchControls.SUBTREE_SCOPE);
139: } else {
140: throw new LdapProviderException("Unsupported "
141: + SEARCH_SCOPE_KEY + "=" + scope);
142: }
143: }
144: String baseDn = parameters.getStringProperty(SEARCH_BASEDN_KEY);
145: this .baseDn = baseDn == null ? "" : baseDn;
146:
147: Integer tl = parameters
148: .getIntegerProperty(SEARCH_TIMELIMIT_KEY);
149: if (tl != null) {
150: searchControls.setTimeLimit(tl);
151: }
152: Integer cl = parameters
153: .getIntegerProperty(SEARCH_COUNTLIMIT_KEY);
154: if (cl != null) {
155: searchControls.setCountLimit(cl);
156: }
157: Number mfl = parameters.getNumberProperty(FILE_MAXLENGTH_KEY,
158: null);
159: maxFileLength = mfl == null ? null : mfl.longValue();
160:
161: driverContext = parameters.getContext();
162: initializeContext(env); //Initializing context
163: }
164:
165: /**
166: * Creates a directory context.
167: *
168: * @param env environment to create initial context.
169: */
170: protected void initializeContext(Hashtable<String, Object> env) {
171: if (LOG.isLoggable(Level.FINE)) {
172: LOG.fine("Creating initial context, environment: " + env);
173: }
174: try {
175: ctx = new InitialDirContext(env);
176: } catch (NamingException e) {
177: throw new LdapProviderException(
178: "Unable to establish directory connection", e);
179: }
180: }
181:
182: DirContext getCtx() {
183: return ctx;
184: }
185:
186: SearchControls getSearchControls() {
187: return searchControls;
188: }
189:
190: Long getMaxFileLength() {
191: return maxFileLength;
192: }
193:
194: DriverContext getDriversContext() {
195: return driverContext;
196: }
197:
198: String getBaseDn() {
199: return baseDn;
200: }
201:
202: StatementCounter getStatementCounter() {
203: return counter;
204: }
205:
206: public void executeScript(final Resource scriptContent,
207: final ParametersCallback parametersCallback)
208: throws ProviderException {
209: Reader in;
210: try {
211: in = scriptContent.open();
212: } catch (IOException e) {
213: throw new LdapProviderException("Failed to read script", e);
214: }
215: new LdifScript(this ).execute(in, ctx, parametersCallback);
216: }
217:
218: public void executeQuery(final Resource queryContent,
219: final ParametersCallback parametersCallback,
220: final QueryCallback queryCallback) throws ProviderException {
221: String filter;
222: try {
223: filter = IOUtils.toString(queryContent.open()).trim();
224: } catch (IOException e) {
225: throw new LdapProviderException(
226: "Failed to read query filter", e);
227: }
228: SearchFilterQuery q = new SearchFilterQuery(this ,
229: parametersCallback, queryCallback);
230: q.execute(filter);
231: }
232:
233: public void close() throws ProviderException {
234: if (ctx != null) {
235: try {
236: ctx.close();
237: ctx = null;
238: } catch (NamingException e) {
239: throw new LdapProviderException(
240: "Unable to close directory context", e);
241: }
242: }
243: }
244:
245: }
|