Categories:
Audio (13)
Biotech (29)
Bytecode (36)
Database (77)
Framework (7)
Game (7)
General (507)
Graphics (53)
I/O (35)
IDE (2)
JAR Tools (101)
JavaBeans (21)
JDBC (121)
JDK (426)
JSP (20)
Logging (108)
Mail (58)
Messaging (8)
Network (84)
PDF (97)
Report (7)
Scripting (84)
Security (32)
Server (121)
Servlet (26)
SOAP (24)
Testing (54)
Web (15)
XML (309)
Collections:
Other Resources:
JDK 11 java.naming.jmod - Naming Module
JDK 11 java.naming.jmod is the JMOD file for JDK 11 Naming module.
JDK 11 Naming module compiled class files are stored in \fyicenter\jdk-11.0.1\jmods\java.naming.jmod.
JDK 11 Naming module compiled class files are also linked and stored in the \fyicenter\jdk-11.0.1\lib\modules JImage file.
JDK 11 Naming module source code files are stored in \fyicenter\jdk-11.0.1\lib\src.zip\java.naming.
You can click and view the content of each source code file in the list below.
✍: FYIcenter
⏎ com/sun/jndi/ldap/LdapClient.java
/* * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * * * * * * * * * * * * * * * * * * * */ package com.sun.jndi.ldap; import java.io.*; import java.util.Locale; import java.util.Vector; import java.util.Hashtable; import javax.naming.*; import javax.naming.directory.*; import javax.naming.ldap.*; import com.sun.jndi.ldap.pool.PooledConnection; import com.sun.jndi.ldap.pool.PoolCallback; import com.sun.jndi.ldap.sasl.LdapSasl; import com.sun.jndi.ldap.sasl.SaslInputStream; /** * LDAP (RFC-1777) and LDAPv3 (RFC-2251) compliant client * * This class represents a connection to an LDAP client. * Callers interact with this class at an LDAP operation level. * That is, the caller invokes a method to do a SEARCH or MODRDN * operation and gets back the result. * The caller uses the constructor to create a connection to the server. * It then needs to use authenticate() to perform an LDAP BIND. * Note that for v3, BIND is optional so authenticate() might not * actually send a BIND. authenticate() can be used later on to issue * a BIND, for example, for a v3 client that wants to change the connection's * credentials. *<p> * Multiple LdapCtx might share the same LdapClient. For example, contexts * derived from the same initial context would share the same LdapClient * until changes to a context's properties necessitates its own LdapClient. * LdapClient methods that access shared data are thread-safe (i.e., caller * does not have to sync). *<p> * Fields: * isLdapv3 - no sync; initialized and updated within sync authenticate(); * always updated when connection is "quiet" and not shared; * read access from outside LdapClient not sync * referenceCount - sync within LdapClient; exception is forceClose() which * is used by Connection thread to close connection upon receiving * an Unsolicited Notification. * access from outside LdapClient must sync; * conn - no sync; Connection takes care of its own sync * unsolicited - sync Vector; multiple operations sync'ed * * @author Vincent Ryan * @author Jagane Sundar * @author Rosanna Lee */ public final class LdapClient implements PooledConnection { // ---------------------- Constants ---------------------------------- private static final int debug = 0; static final boolean caseIgnore = true; // Default list of binary attributes private static final Hashtable<String, Boolean> defaultBinaryAttrs = new Hashtable<>(23,0.75f); static { defaultBinaryAttrs.put("userpassword", Boolean.TRUE); //2.5.4.35 defaultBinaryAttrs.put("javaserializeddata", Boolean.TRUE); //1.3.6.1.4.1.42.2.27.4.1.8 defaultBinaryAttrs.put("javaserializedobject", Boolean.TRUE); // 1.3.6.1.4.1.42.2.27.4.1.2 defaultBinaryAttrs.put("jpegphoto", Boolean.TRUE); //0.9.2342.19200300.100.1.60 defaultBinaryAttrs.put("audio", Boolean.TRUE); //0.9.2342.19200300.100.1.55 defaultBinaryAttrs.put("thumbnailphoto", Boolean.TRUE); //1.3.6.1.4.1.1466.101.120.35 defaultBinaryAttrs.put("thumbnaillogo", Boolean.TRUE); //1.3.6.1.4.1.1466.101.120.36 defaultBinaryAttrs.put("usercertificate", Boolean.TRUE); //2.5.4.36 defaultBinaryAttrs.put("cacertificate", Boolean.TRUE); //2.5.4.37 defaultBinaryAttrs.put("certificaterevocationlist", Boolean.TRUE); //2.5.4.39 defaultBinaryAttrs.put("authorityrevocationlist", Boolean.TRUE); //2.5.4.38 defaultBinaryAttrs.put("crosscertificatepair", Boolean.TRUE); //2.5.4.40 defaultBinaryAttrs.put("photo", Boolean.TRUE); //0.9.2342.19200300.100.1.7 defaultBinaryAttrs.put("personalsignature", Boolean.TRUE); //0.9.2342.19200300.100.1.53 defaultBinaryAttrs.put("x500uniqueidentifier", Boolean.TRUE); //2.5.4.45 } private static final String DISCONNECT_OID = "1.3.6.1.4.1.1466.20036"; // ----------------------- instance fields ------------------------ boolean isLdapv3; // Used by LdapCtx int referenceCount = 1; // Used by LdapCtx for check for sharing Connection conn; // Connection to server; has reader thread // used by LdapCtx for StartTLS final private PoolCallback pcb; final private boolean pooled; private boolean authenticateCalled = false; //////////////////////////////////////////////////////////////////////////// // // constructor: Create an authenticated connection to server // //////////////////////////////////////////////////////////////////////////// LdapClient(String host, int port, String socketFactory, int connectTimeout, int readTimeout, OutputStream trace, PoolCallback pcb) throws NamingException { if (debug > 0) System.err.println("LdapClient: constructor called " + host + ":" + port ); conn = new Connection(this, host, port, socketFactory, connectTimeout, readTimeout, trace); this.pcb = pcb; pooled = (pcb != null); } synchronized boolean authenticateCalled() { return authenticateCalled; } synchronized LdapResult authenticate(boolean initial, String name, Object pw, int version, String authMechanism, Control[] ctls, Hashtable<?,?> env) throws NamingException { int readTimeout = conn.readTimeout; conn.readTimeout = conn.connectTimeout; LdapResult res = null; try { authenticateCalled = true; try { ensureOpen(); } catch (IOException e) { NamingException ne = new CommunicationException(); ne.setRootCause(e); throw ne; } switch (version) { case LDAP_VERSION3_VERSION2: case LDAP_VERSION3: isLdapv3 = true; break; case LDAP_VERSION2: isLdapv3 = false; break; default: throw new CommunicationException("Protocol version " + version + " not supported"); } if (authMechanism.equalsIgnoreCase("none") || authMechanism.equalsIgnoreCase("anonymous")) { // Perform LDAP bind if we are reauthenticating, using LDAPv2, // supporting failover to LDAPv2, or controls have been supplied. if (!initial || (version == LDAP_VERSION2) || (version == LDAP_VERSION3_VERSION2) || ((ctls != null) && (ctls.length > 0))) { try { // anonymous bind; update name/pw for LDAPv2 retry res = ldapBind(name=null, (byte[])(pw=null), ctls, null, false); if (res.status == LdapClient.LDAP_SUCCESS) { conn.setBound(); } } catch (IOException e) { NamingException ne = new CommunicationException("anonymous bind failed: " + conn.host + ":" + conn.port); ne.setRootCause(e); throw ne; } } else { // Skip LDAP bind for LDAPv3 anonymous bind res = new LdapResult(); res.status = LdapClient.LDAP_SUCCESS; } } else if (authMechanism.equalsIgnoreCase("simple")) { // simple authentication byte[] encodedPw = null; try { encodedPw = encodePassword(pw, isLdapv3); res = ldapBind(name, encodedPw, ctls, null, false); if (res.status == LdapClient.LDAP_SUCCESS) { conn.setBound(); } } catch (IOException e) { NamingException ne = new CommunicationException("simple bind failed: " + conn.host + ":" + conn.port); ne.setRootCause(e); throw ne; } finally { // If pw was copied to a new array, clear that array as // a security precaution. if (encodedPw != pw && encodedPw != null) { for (int i = 0; i < encodedPw.length; i++) { encodedPw[i] = 0; } } } } else if (isLdapv3) { // SASL authentication try { res = LdapSasl.saslBind(this, conn, conn.host, name, pw, authMechanism, env, ctls); if (res.status == LdapClient.LDAP_SUCCESS) { conn.setBound(); } } catch (IOException e) { NamingException ne = new CommunicationException("SASL bind failed: " + conn.host + ":" + conn.port); ne.setRootCause(e); throw ne; } } else { throw new AuthenticationNotSupportedException(authMechanism); } // // re-try login using v2 if failing over // if (initial && (res.status == LdapClient.LDAP_PROTOCOL_ERROR) && (version == LdapClient.LDAP_VERSION3_VERSION2) && (authMechanism.equalsIgnoreCase("none") || authMechanism.equalsIgnoreCase("anonymous") || authMechanism.equalsIgnoreCase("simple"))) { byte[] encodedPw = null; try { isLdapv3 = false; encodedPw = encodePassword(pw, false); res = ldapBind(name, encodedPw, ctls, null, false); if (res.status == LdapClient.LDAP_SUCCESS) { conn.setBound(); } } catch (IOException e) { NamingException ne = new CommunicationException(authMechanism + ":" + conn.host + ":" + conn.port); ne.setRootCause(e); throw ne; } finally { // If pw was copied to a new array, clear that array as // a security precaution. if (encodedPw != pw && encodedPw != null) { for (int i = 0; i < encodedPw.length; i++) { encodedPw[i] = 0; } } } } // principal name not found // (map NameNotFoundException to AuthenticationException) // %%% This is a workaround for Netscape servers returning // %%% no such object when the principal name is not found // %%% Note that when this workaround is applied, it does not allow // %%% response controls to be recorded by the calling context if (res.status == LdapClient.LDAP_NO_SUCH_OBJECT) { throw new AuthenticationException( getErrorMessage(res.status, res.errorMessage)); } conn.setV3(isLdapv3); return res; } finally { conn.readTimeout = readTimeout; } } /** * Sends an LDAP Bind request. * Cannot be private; called by LdapSasl * @param dn The possibly null DN to use in the BIND request. null if anonymous. * @param toServer The possibly null array of bytes to send to the server. * @param auth The authentication mechanism * */ synchronized public LdapResult ldapBind(String dn, byte[]toServer, Control[] bindCtls, String auth, boolean pauseAfterReceipt) throws java.io.IOException, NamingException { ensureOpen(); // flush outstanding requests conn.abandonOutstandingReqs(null); BerEncoder ber = new BerEncoder(); int curMsgId = conn.getMsgId(); LdapResult res = new LdapResult(); res.status = LDAP_OPERATIONS_ERROR; // // build the bind request. // ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); ber.encodeInt(curMsgId); ber.beginSeq(LdapClient.LDAP_REQ_BIND); ber.encodeInt(isLdapv3 ? LDAP_VERSION3 : LDAP_VERSION2); ber.encodeString(dn, isLdapv3); // if authentication mechanism specified, it is SASL if (auth != null) { ber.beginSeq(Ber.ASN_CONTEXT | Ber.ASN_CONSTRUCTOR | 3); ber.encodeString(auth, isLdapv3); // SASL mechanism if (toServer != null) { ber.encodeOctetString(toServer, Ber.ASN_OCTET_STR); } ber.endSeq(); } else { if (toServer != null) { ber.encodeOctetString(toServer, Ber.ASN_CONTEXT); } else { ber.encodeOctetString(null, Ber.ASN_CONTEXT, 0, 0); } } ber.endSeq(); // Encode controls if (isLdapv3) { encodeControls(ber, bindCtls); } ber.endSeq(); LdapRequest req = conn.writeRequest(ber, curMsgId, pauseAfterReceipt); if (toServer != null) { ber.reset(); // clear internally-stored password } // Read reply BerDecoder rber = conn.readReply(req); rber.parseSeq(null); // init seq rber.parseInt(); // msg id if (rber.parseByte() != LDAP_REP_BIND) { return res; } rber.parseLength(); parseResult(rber, res, isLdapv3); // handle server's credentials (if present) if (isLdapv3 && (rber.bytesLeft() > 0) && (rber.peekByte() == (Ber.ASN_CONTEXT | 7))) { res.serverCreds = rber.parseOctetString((Ber.ASN_CONTEXT | 7), null); } res.resControls = isLdapv3 ? parseControls(rber) : null; conn.removeRequest(req); return res; } /** * Determines whether SASL encryption/integrity is in progress. * This check is made prior to reauthentication. You cannot reauthenticate * over an encrypted/integrity-protected SASL channel. You must * close the channel and open a new one. */ boolean usingSaslStreams() { return (conn.inStream instanceof SaslInputStream); } synchronized void incRefCount() { ++referenceCount; if (debug > 1) { System.err.println("LdapClient.incRefCount: " + referenceCount + " " + this); } } /** * Returns the encoded password. */ private static byte[] encodePassword(Object pw, boolean v3) throws IOException { if (pw instanceof char[]) { pw = new String((char[])pw); } if (pw instanceof String) { if (v3) { return ((String)pw).getBytes("UTF8"); } else { return ((String)pw).getBytes("8859_1"); } } else { return (byte[])pw; } } synchronized void close(Control[] reqCtls, boolean hardClose) { --referenceCount; if (debug > 1) { System.err.println("LdapClient: " + this); System.err.println("LdapClient: close() called: " + referenceCount); (new Throwable()).printStackTrace(); } if (referenceCount <= 0 && conn != null) { if (debug > 0) System.err.println("LdapClient: closed connection " + this); if (!pooled) { // Not being pooled; continue with closing conn.cleanup(reqCtls, false); conn = null; } else { // Pooled // Is this a real close or a request to return conn to pool if (hardClose) { conn.cleanup(reqCtls, false); conn = null; pcb.removePooledConnection(this); } else { pcb.releasePooledConnection(this); } } } } // NOTE: Should NOT be synchronized otherwise won't be able to close private void forceClose(boolean cleanPool) { referenceCount = 0; // force closing of connection if (debug > 1) { System.err.println("LdapClient: forceClose() of " + this); } if (conn != null) { if (debug > 0) System.err.println( "LdapClient: forced close of connection " + this); conn.cleanup(null, false); conn = null; if (cleanPool) { pcb.removePooledConnection(this); } } } @SuppressWarnings("deprecation") protected void finalize() { if (debug > 0) System.err.println("LdapClient: finalize " + this); forceClose(pooled); } /* * Used by connection pooling to close physical connection. */ synchronized public void closeConnection() { forceClose(false); // this is a pool callback so no need to clean pool } /** * Called by Connection.cleanup(). LdapClient should * notify any unsolicited listeners and removing itself from any pool. * This is almost like forceClose(), except it doesn't call * Connection.cleanup() (because this is called from cleanup()). */ void processConnectionClosure() { // Notify listeners if (unsolicited.size() > 0) { String msg; if (conn != null) { msg = conn.host + ":" + conn.port + " connection closed"; } else { msg = "Connection closed"; } notifyUnsolicited(new CommunicationException(msg)); } // Remove from pool if (pooled) { pcb.removePooledConnection(this); } } //////////////////////////////////////////////////////////////////////////// // // LDAP search. also includes methods to encode rfc 1558 compliant filters // //////////////////////////////////////////////////////////////////////////// static final int SCOPE_BASE_OBJECT = 0; static final int SCOPE_ONE_LEVEL = 1; static final int SCOPE_SUBTREE = 2; LdapResult search(String dn, int scope, int deref, int sizeLimit, int timeLimit, boolean attrsOnly, String attrs[], String filter, int batchSize, Control[] reqCtls, Hashtable<String, Boolean> binaryAttrs, boolean waitFirstReply, int replyQueueCapacity) throws IOException, NamingException { ensureOpen(); LdapResult res = new LdapResult(); BerEncoder ber = new BerEncoder(); int curMsgId = conn.getMsgId(); ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); ber.encodeInt(curMsgId); ber.beginSeq(LDAP_REQ_SEARCH); ber.encodeString(dn == null ? "" : dn, isLdapv3); ber.encodeInt(scope, LBER_ENUMERATED); ber.encodeInt(deref, LBER_ENUMERATED); ber.encodeInt(sizeLimit); ber.encodeInt(timeLimit); ber.encodeBoolean(attrsOnly); Filter.encodeFilterString(ber, filter, isLdapv3); ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); ber.encodeStringArray(attrs, isLdapv3); ber.endSeq(); ber.endSeq(); if (isLdapv3) encodeControls(ber, reqCtls); ber.endSeq(); LdapRequest req = conn.writeRequest(ber, curMsgId, false, replyQueueCapacity); res.msgId = curMsgId; res.status = LdapClient.LDAP_SUCCESS; //optimistic if (waitFirstReply) { // get first reply res = getSearchReply(req, batchSize, res, binaryAttrs); } return res; } /* * Abandon the search operation and remove it from the message queue. */ void clearSearchReply(LdapResult res, Control[] ctls) { if (res != null && conn != null) { // Only send an LDAP abandon operation when clearing the search // reply from a one-level or subtree search. LdapRequest req = conn.findRequest(res.msgId); if (req == null) { return; } // OK if req got removed after check; double removal attempt // but otherwise no harm done // Send an LDAP abandon only if the search operation has not yet // completed. if (req.hasSearchCompleted()) { conn.removeRequest(req); } else { conn.abandonRequest(req, ctls); } } } /* * Retrieve the next batch of entries and/or referrals. */ LdapResult getSearchReply(int batchSize, LdapResult res, Hashtable<String, Boolean> binaryAttrs) throws IOException, NamingException { ensureOpen(); LdapRequest req; if ((req = conn.findRequest(res.msgId)) == null) { return null; } return getSearchReply(req, batchSize, res, binaryAttrs); } private LdapResult getSearchReply(LdapRequest req, int batchSize, LdapResult res, Hashtable<String, Boolean> binaryAttrs) throws IOException, NamingException { if (batchSize == 0) batchSize = Integer.MAX_VALUE; if (res.entries != null) { res.entries.setSize(0); // clear the (previous) set of entries } else { res.entries = new Vector<>(batchSize == Integer.MAX_VALUE ? 32 : batchSize); } if (res.referrals != null) { res.referrals.setSize(0); // clear the (previous) set of referrals } BerDecoder replyBer; // Decoder for response int seq; // Request id Attributes lattrs; // Attribute set read from response Attribute la; // Attribute read from response String DN; // DN read from response LdapEntry le; // LDAP entry representing response int[] seqlen; // Holder for response length int endseq; // Position of end of response for (int i = 0; i < batchSize;) { replyBer = conn.readReply(req); // // process search reply // replyBer.parseSeq(null); // init seq replyBer.parseInt(); // req id seq = replyBer.parseSeq(null); if (seq == LDAP_REP_SEARCH) { // handle LDAPv3 search entries lattrs = new BasicAttributes(caseIgnore); DN = replyBer.parseString(isLdapv3); le = new LdapEntry(DN, lattrs); seqlen = new int[1]; replyBer.parseSeq(seqlen); endseq = replyBer.getParsePosition() + seqlen[0]; while ((replyBer.getParsePosition() < endseq) && (replyBer.bytesLeft() > 0)) { la = parseAttribute(replyBer, binaryAttrs); lattrs.put(la); } le.respCtls = isLdapv3 ? parseControls(replyBer) : null; res.entries.addElement(le); i++; } else if ((seq == LDAP_REP_SEARCH_REF) && isLdapv3) { // handle LDAPv3 search reference Vector<String> URLs = new Vector<>(4); // %%% Although not strictly correct, some LDAP servers // encode the SEQUENCE OF tag in the SearchResultRef if (replyBer.peekByte() == (Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR)) { replyBer.parseSeq(null); } while ((replyBer.bytesLeft() > 0) && (replyBer.peekByte() == Ber.ASN_OCTET_STR)) { URLs.addElement(replyBer.parseString(isLdapv3)); } if (res.referrals == null) { res.referrals = new Vector<>(4); } res.referrals.addElement(URLs); res.resControls = isLdapv3 ? parseControls(replyBer) : null; // Save referral and continue to get next search result } else if (seq == LDAP_REP_EXTENSION) { parseExtResponse(replyBer, res); //%%% ignore for now } else if (seq == LDAP_REP_RESULT) { parseResult(replyBer, res, isLdapv3); res.resControls = isLdapv3 ? parseControls(replyBer) : null; conn.removeRequest(req); return res; // Done with search } } return res; } private Attribute parseAttribute(BerDecoder ber, Hashtable<String, Boolean> binaryAttrs) throws IOException { int len[] = new int[1]; int seq = ber.parseSeq(null); String attrid = ber.parseString(isLdapv3); boolean hasBinaryValues = isBinaryValued(attrid, binaryAttrs); Attribute la = new LdapAttribute(attrid); if ((seq = ber.parseSeq(len)) == LBER_SET) { int attrlen = len[0]; while (ber.bytesLeft() > 0 && attrlen > 0) { try { attrlen -= parseAttributeValue(ber, la, hasBinaryValues); } catch (IOException ex) { ber.seek(attrlen); break; } } } else { // Skip the rest of the sequence because it is not what we want ber.seek(len[0]); } return la; } // // returns number of bytes that were parsed. Adds the values to attr // private int parseAttributeValue(BerDecoder ber, Attribute la, boolean hasBinaryValues) throws IOException { int len[] = new int[1]; if (hasBinaryValues) { la.add(ber.parseOctetString(ber.peekByte(), len)); } else { la.add(ber.parseStringWithTag( Ber.ASN_SIMPLE_STRING, isLdapv3, len)); } return len[0]; } private boolean isBinaryValued(String attrid, Hashtable<String, Boolean> binaryAttrs) { String id = attrid.toLowerCase(Locale.ENGLISH); return ((id.indexOf(";binary") != -1) || defaultBinaryAttrs.containsKey(id) || ((binaryAttrs != null) && (binaryAttrs.containsKey(id)))); } // package entry point; used by Connection static void parseResult(BerDecoder replyBer, LdapResult res, boolean isLdapv3) throws IOException { res.status = replyBer.parseEnumeration(); res.matchedDN = replyBer.parseString(isLdapv3); res.errorMessage = replyBer.parseString(isLdapv3); // handle LDAPv3 referrals (if present) if (isLdapv3 && (replyBer.bytesLeft() > 0) && (replyBer.peekByte() == LDAP_REP_REFERRAL)) { Vector<String> URLs = new Vector<>(4); int[] seqlen = new int[1]; replyBer.parseSeq(seqlen); int endseq = replyBer.getParsePosition() + seqlen[0]; while ((replyBer.getParsePosition() < endseq) && (replyBer.bytesLeft() > 0)) { URLs.addElement(replyBer.parseString(isLdapv3)); } if (res.referrals == null) { res.referrals = new Vector<>(4); } res.referrals.addElement(URLs); } } // package entry point; used by Connection static Vector<Control> parseControls(BerDecoder replyBer) throws IOException { // handle LDAPv3 controls (if present) if ((replyBer.bytesLeft() > 0) && (replyBer.peekByte() == LDAP_CONTROLS)) { Vector<Control> ctls = new Vector<>(4); String controlOID; boolean criticality = false; // default byte[] controlValue = null; // optional int[] seqlen = new int[1]; replyBer.parseSeq(seqlen); int endseq = replyBer.getParsePosition() + seqlen[0]; while ((replyBer.getParsePosition() < endseq) && (replyBer.bytesLeft() > 0)) { replyBer.parseSeq(null); controlOID = replyBer.parseString(true); if ((replyBer.bytesLeft() > 0) && (replyBer.peekByte() == Ber.ASN_BOOLEAN)) { criticality = replyBer.parseBoolean(); } if ((replyBer.bytesLeft() > 0) && (replyBer.peekByte() == Ber.ASN_OCTET_STR)) { controlValue = replyBer.parseOctetString(Ber.ASN_OCTET_STR, null); } if (controlOID != null) { ctls.addElement( new BasicControl(controlOID, criticality, controlValue)); } } return ctls; } else { return null; } } private void parseExtResponse(BerDecoder replyBer, LdapResult res) throws IOException { parseResult(replyBer, res, isLdapv3); if ((replyBer.bytesLeft() > 0) && (replyBer.peekByte() == LDAP_REP_EXT_OID)) { res.extensionId = replyBer.parseStringWithTag(LDAP_REP_EXT_OID, isLdapv3, null); } if ((replyBer.bytesLeft() > 0) && (replyBer.peekByte() == LDAP_REP_EXT_VAL)) { res.extensionValue = replyBer.parseOctetString(LDAP_REP_EXT_VAL, null); } res.resControls = parseControls(replyBer); } // // Encode LDAPv3 controls // static void encodeControls(BerEncoder ber, Control[] reqCtls) throws IOException { if ((reqCtls == null) || (reqCtls.length == 0)) { return; } byte[] controlVal; ber.beginSeq(LdapClient.LDAP_CONTROLS); for (int i = 0; i < reqCtls.length; i++) { ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); ber.encodeString(reqCtls[i].getID(), true); // control OID if (reqCtls[i].isCritical()) { ber.encodeBoolean(true); // critical control } if ((controlVal = reqCtls[i].getEncodedValue()) != null) { ber.encodeOctetString(controlVal, Ber.ASN_OCTET_STR); } ber.endSeq(); } ber.endSeq(); } /** * Reads the next reply corresponding to msgId, outstanding on requestBer. * Processes the result and any controls. */ private LdapResult processReply(LdapRequest req, LdapResult res, int responseType) throws IOException, NamingException { BerDecoder rber = conn.readReply(req); rber.parseSeq(null); // init seq rber.parseInt(); // msg id if (rber.parseByte() != responseType) { return res; } rber.parseLength(); parseResult(rber, res, isLdapv3); res.resControls = isLdapv3 ? parseControls(rber) : null; conn.removeRequest(req); return res; // Done with operation } //////////////////////////////////////////////////////////////////////////// // // LDAP modify: // Modify the DN dn with the operations on attributes attrs. // ie, operations[0] is the operation to be performed on // attrs[0]; // dn - DN to modify // operations - add, delete or replace // attrs - array of Attribute // reqCtls - array of request controls // //////////////////////////////////////////////////////////////////////////// static final int ADD = 0; static final int DELETE = 1; static final int REPLACE = 2; LdapResult modify(String dn, int operations[], Attribute attrs[], Control[] reqCtls) throws IOException, NamingException { ensureOpen(); LdapResult res = new LdapResult(); res.status = LDAP_OPERATIONS_ERROR; if (dn == null || operations.length != attrs.length) return res; BerEncoder ber = new BerEncoder(); int curMsgId = conn.getMsgId(); ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); ber.encodeInt(curMsgId); ber.beginSeq(LDAP_REQ_MODIFY); ber.encodeString(dn, isLdapv3); ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); for (int i = 0; i < operations.length; i++) { ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); ber.encodeInt(operations[i], LBER_ENUMERATED); // zero values is not permitted for the add op. if ((operations[i] == ADD) && hasNoValue(attrs[i])) { throw new InvalidAttributeValueException( "'" + attrs[i].getID() + "' has no values."); } else { encodeAttribute(ber, attrs[i]); } ber.endSeq(); } ber.endSeq(); ber.endSeq(); if (isLdapv3) encodeControls(ber, reqCtls); ber.endSeq(); LdapRequest req = conn.writeRequest(ber, curMsgId); return processReply(req, res, LDAP_REP_MODIFY); } private void encodeAttribute(BerEncoder ber, Attribute attr) throws IOException, NamingException { ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); ber.encodeString(attr.getID(), isLdapv3); ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR | 1); NamingEnumeration<?> enum_ = attr.getAll(); Object val; while (enum_.hasMore()) { val = enum_.next(); if (val instanceof String) { ber.encodeString((String)val, isLdapv3); } else if (val instanceof byte[]) { ber.encodeOctetString((byte[])val, Ber.ASN_OCTET_STR); } else if (val == null) { // no attribute value } else { throw new InvalidAttributeValueException( "Malformed '" + attr.getID() + "' attribute value"); } } ber.endSeq(); ber.endSeq(); } private static boolean hasNoValue(Attribute attr) throws NamingException { return attr.size() == 0 || (attr.size() == 1 && attr.get() == null); } //////////////////////////////////////////////////////////////////////////// // // LDAP add // Adds entry to the Directory // //////////////////////////////////////////////////////////////////////////// LdapResult add(LdapEntry entry, Control[] reqCtls) throws IOException, NamingException { ensureOpen(); LdapResult res = new LdapResult(); res.status = LDAP_OPERATIONS_ERROR; if (entry == null || entry.DN == null) return res; BerEncoder ber = new BerEncoder(); int curMsgId = conn.getMsgId(); Attribute attr; ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); ber.encodeInt(curMsgId); ber.beginSeq(LDAP_REQ_ADD); ber.encodeString(entry.DN, isLdapv3); ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); NamingEnumeration<? extends Attribute> enum_ = entry.attributes.getAll(); while (enum_.hasMore()) { attr = enum_.next(); // zero values is not permitted if (hasNoValue(attr)) { throw new InvalidAttributeValueException( "'" + attr.getID() + "' has no values."); } else { encodeAttribute(ber, attr); } } ber.endSeq(); ber.endSeq(); if (isLdapv3) encodeControls(ber, reqCtls); ber.endSeq(); LdapRequest req = conn.writeRequest(ber, curMsgId); return processReply(req, res, LDAP_REP_ADD); } //////////////////////////////////////////////////////////////////////////// // // LDAP delete // deletes entry from the Directory // //////////////////////////////////////////////////////////////////////////// LdapResult delete(String DN, Control[] reqCtls) throws IOException, NamingException { ensureOpen(); LdapResult res = new LdapResult(); res.status = LDAP_OPERATIONS_ERROR; if (DN == null) return res; BerEncoder ber = new BerEncoder(); int curMsgId = conn.getMsgId(); ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); ber.encodeInt(curMsgId); ber.encodeString(DN, LDAP_REQ_DELETE, isLdapv3); if (isLdapv3) encodeControls(ber, reqCtls); ber.endSeq(); LdapRequest req = conn.writeRequest(ber, curMsgId); return processReply(req, res, LDAP_REP_DELETE); } //////////////////////////////////////////////////////////////////////////// // // LDAP modrdn // Changes the last element of DN to newrdn // dn - DN to change // newrdn - new RDN to rename to // deleteoldrdn - boolean whether to delete old attrs or not // newSuperior - new place to put the entry in the tree // (ignored if server is LDAPv2) // reqCtls - array of request controls // //////////////////////////////////////////////////////////////////////////// LdapResult moddn(String DN, String newrdn, boolean deleteOldRdn, String newSuperior, Control[] reqCtls) throws IOException, NamingException { ensureOpen(); boolean changeSuperior = (newSuperior != null && newSuperior.length() > 0); LdapResult res = new LdapResult(); res.status = LDAP_OPERATIONS_ERROR; if (DN == null || newrdn == null) return res; BerEncoder ber = new BerEncoder(); int curMsgId = conn.getMsgId(); ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); ber.encodeInt(curMsgId); ber.beginSeq(LDAP_REQ_MODRDN); ber.encodeString(DN, isLdapv3); ber.encodeString(newrdn, isLdapv3); ber.encodeBoolean(deleteOldRdn); if(isLdapv3 && changeSuperior) { //System.err.println("changin superior"); ber.encodeString(newSuperior, LDAP_SUPERIOR_DN, isLdapv3); } ber.endSeq(); if (isLdapv3) encodeControls(ber, reqCtls); ber.endSeq(); LdapRequest req = conn.writeRequest(ber, curMsgId); return processReply(req, res, LDAP_REP_MODRDN); } //////////////////////////////////////////////////////////////////////////// // // LDAP compare // Compare attribute->value pairs in dn // //////////////////////////////////////////////////////////////////////////// LdapResult compare(String DN, String type, String value, Control[] reqCtls) throws IOException, NamingException { ensureOpen(); LdapResult res = new LdapResult(); res.status = LDAP_OPERATIONS_ERROR; if (DN == null || type == null || value == null) return res; BerEncoder ber = new BerEncoder(); int curMsgId = conn.getMsgId(); ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); ber.encodeInt(curMsgId); ber.beginSeq(LDAP_REQ_COMPARE); ber.encodeString(DN, isLdapv3); ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); ber.encodeString(type, isLdapv3); // replace any escaped characters in the value byte[] val = isLdapv3 ? value.getBytes("UTF8") : value.getBytes("8859_1"); ber.encodeOctetString( Filter.unescapeFilterValue(val, 0, val.length), Ber.ASN_OCTET_STR); ber.endSeq(); ber.endSeq(); if (isLdapv3) encodeControls(ber, reqCtls); ber.endSeq(); LdapRequest req = conn.writeRequest(ber, curMsgId); return processReply(req, res, LDAP_REP_COMPARE); } //////////////////////////////////////////////////////////////////////////// // // LDAP extended operation // //////////////////////////////////////////////////////////////////////////// LdapResult extendedOp(String id, byte[] request, Control[] reqCtls, boolean pauseAfterReceipt) throws IOException, NamingException { ensureOpen(); LdapResult res = new LdapResult(); res.status = LDAP_OPERATIONS_ERROR; if (id == null) return res; BerEncoder ber = new BerEncoder(); int curMsgId = conn.getMsgId(); ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); ber.encodeInt(curMsgId); ber.beginSeq(LDAP_REQ_EXTENSION); ber.encodeString(id, Ber.ASN_CONTEXT | 0, isLdapv3);//[0] if (request != null) { ber.encodeOctetString(request, Ber.ASN_CONTEXT | 1);//[1] } ber.endSeq(); encodeControls(ber, reqCtls); // always v3 ber.endSeq(); LdapRequest req = conn.writeRequest(ber, curMsgId, pauseAfterReceipt); BerDecoder rber = conn.readReply(req); rber.parseSeq(null); // init seq rber.parseInt(); // msg id if (rber.parseByte() != LDAP_REP_EXTENSION) { return res; } rber.parseLength(); parseExtResponse(rber, res); conn.removeRequest(req); return res; // Done with operation } //////////////////////////////////////////////////////////////////////////// // // Some BER definitions convenient for LDAP // //////////////////////////////////////////////////////////////////////////// static final int LDAP_VERSION3_VERSION2 = 32; static final int LDAP_VERSION2 = 0x02; static final int LDAP_VERSION3 = 0x03; // LDAPv3 static final int LDAP_VERSION = LDAP_VERSION3; static final int LDAP_REF_FOLLOW = 0x01; // follow referrals static final int LDAP_REF_THROW = 0x02; // throw referral ex. static final int LDAP_REF_IGNORE = 0x03; // ignore referrals static final int LDAP_REF_FOLLOW_SCHEME = 0x04; // follow referrals of the same scheme static final String LDAP_URL = "ldap://"; // LDAPv3 static final String LDAPS_URL = "ldaps://"; // LDAPv3 static final int LBER_BOOLEAN = 0x01; static final int LBER_INTEGER = 0x02; static final int LBER_BITSTRING = 0x03; static final int LBER_OCTETSTRING = 0x04; static final int LBER_NULL = 0x05; static final int LBER_ENUMERATED = 0x0a; static final int LBER_SEQUENCE = 0x30; static final int LBER_SET = 0x31; static final int LDAP_SUPERIOR_DN = 0x80; static final int LDAP_REQ_BIND = 0x60; // app + constructed static final int LDAP_REQ_UNBIND = 0x42; // app + primitive static final int LDAP_REQ_SEARCH = 0x63; // app + constructed static final int LDAP_REQ_MODIFY = 0x66; // app + constructed static final int LDAP_REQ_ADD = 0x68; // app + constructed static final int LDAP_REQ_DELETE = 0x4a; // app + primitive static final int LDAP_REQ_MODRDN = 0x6c; // app + constructed static final int LDAP_REQ_COMPARE = 0x6e; // app + constructed static final int LDAP_REQ_ABANDON = 0x50; // app + primitive static final int LDAP_REQ_EXTENSION = 0x77; // app + constructed (LDAPv3) static final int LDAP_REP_BIND = 0x61; // app + constructed | 1 static final int LDAP_REP_SEARCH = 0x64; // app + constructed | 4 static final int LDAP_REP_SEARCH_REF = 0x73;// app + constructed (LDAPv3) static final int LDAP_REP_RESULT = 0x65; // app + constructed | 5 static final int LDAP_REP_MODIFY = 0x67; // app + constructed | 7 static final int LDAP_REP_ADD = 0x69; // app + constructed | 9 static final int LDAP_REP_DELETE = 0x6b; // app + primitive | b static final int LDAP_REP_MODRDN = 0x6d; // app + primitive | d static final int LDAP_REP_COMPARE = 0x6f; // app + primitive | f static final int LDAP_REP_EXTENSION = 0x78; // app + constructed (LDAPv3) static final int LDAP_REP_REFERRAL = 0xa3; // ctx + constructed (LDAPv3) static final int LDAP_REP_EXT_OID = 0x8a; // ctx + primitive (LDAPv3) static final int LDAP_REP_EXT_VAL = 0x8b; // ctx + primitive (LDAPv3) // LDAPv3 Controls static final int LDAP_CONTROLS = 0xa0; // ctx + constructed (LDAPv3) static final String LDAP_CONTROL_MANAGE_DSA_IT = "2.16.840.1.113730.3.4.2"; static final String LDAP_CONTROL_PREFERRED_LANG = "1.3.6.1.4.1.1466.20035"; static final String LDAP_CONTROL_PAGED_RESULTS = "1.2.840.113556.1.4.319"; static final String LDAP_CONTROL_SERVER_SORT_REQ = "1.2.840.113556.1.4.473"; static final String LDAP_CONTROL_SERVER_SORT_RES = "1.2.840.113556.1.4.474"; //////////////////////////////////////////////////////////////////////////// // // return codes // //////////////////////////////////////////////////////////////////////////// static final int LDAP_SUCCESS = 0; static final int LDAP_OPERATIONS_ERROR = 1; static final int LDAP_PROTOCOL_ERROR = 2; static final int LDAP_TIME_LIMIT_EXCEEDED = 3; static final int LDAP_SIZE_LIMIT_EXCEEDED = 4; static final int LDAP_COMPARE_FALSE = 5; static final int LDAP_COMPARE_TRUE = 6; static final int LDAP_AUTH_METHOD_NOT_SUPPORTED = 7; static final int LDAP_STRONG_AUTH_REQUIRED = 8; static final int LDAP_PARTIAL_RESULTS = 9; // Slapd static final int LDAP_REFERRAL = 10; // LDAPv3 static final int LDAP_ADMIN_LIMIT_EXCEEDED = 11; // LDAPv3 static final int LDAP_UNAVAILABLE_CRITICAL_EXTENSION = 12; // LDAPv3 static final int LDAP_CONFIDENTIALITY_REQUIRED = 13; // LDAPv3 static final int LDAP_SASL_BIND_IN_PROGRESS = 14; // LDAPv3 static final int LDAP_NO_SUCH_ATTRIBUTE = 16; static final int LDAP_UNDEFINED_ATTRIBUTE_TYPE = 17; static final int LDAP_INAPPROPRIATE_MATCHING = 18; static final int LDAP_CONSTRAINT_VIOLATION = 19; static final int LDAP_ATTRIBUTE_OR_VALUE_EXISTS = 20; static final int LDAP_INVALID_ATTRIBUTE_SYNTAX = 21; static final int LDAP_NO_SUCH_OBJECT = 32; static final int LDAP_ALIAS_PROBLEM = 33; static final int LDAP_INVALID_DN_SYNTAX = 34; static final int LDAP_IS_LEAF = 35; static final int LDAP_ALIAS_DEREFERENCING_PROBLEM = 36; static final int LDAP_INAPPROPRIATE_AUTHENTICATION = 48; static final int LDAP_INVALID_CREDENTIALS = 49; static final int LDAP_INSUFFICIENT_ACCESS_RIGHTS = 50; static final int LDAP_BUSY = 51; static final int LDAP_UNAVAILABLE = 52; static final int LDAP_UNWILLING_TO_PERFORM = 53; static final int LDAP_LOOP_DETECT = 54; static final int LDAP_NAMING_VIOLATION = 64; static final int LDAP_OBJECT_CLASS_VIOLATION = 65; static final int LDAP_NOT_ALLOWED_ON_NON_LEAF = 66; static final int LDAP_NOT_ALLOWED_ON_RDN = 67; static final int LDAP_ENTRY_ALREADY_EXISTS = 68; static final int LDAP_OBJECT_CLASS_MODS_PROHIBITED = 69; static final int LDAP_AFFECTS_MULTIPLE_DSAS = 71; // LDAPv3 static final int LDAP_OTHER = 80; static final String[] ldap_error_message = { "Success", // 0 "Operations Error", // 1 "Protocol Error", // 2 "Timelimit Exceeded", // 3 "Sizelimit Exceeded", // 4 "Compare False", // 5 "Compare True", // 6 "Authentication Method Not Supported", // 7 "Strong Authentication Required", // 8 null, "Referral", // 10 "Administrative Limit Exceeded", // 11 "Unavailable Critical Extension", // 12 "Confidentiality Required", // 13 "SASL Bind In Progress", // 14 null, "No Such Attribute", // 16 "Undefined Attribute Type", // 17 "Inappropriate Matching", // 18 "Constraint Violation", // 19 "Attribute Or Value Exists", // 20 "Invalid Attribute Syntax", // 21 null, null, null, null, null, null, null, null, null, null, "No Such Object", // 32 "Alias Problem", // 33 "Invalid DN Syntax", // 34 null, "Alias Dereferencing Problem", // 36 null, null, null, null, null, null, null, null, null, null, null, "Inappropriate Authentication", // 48 "Invalid Credentials", // 49 "Insufficient Access Rights", // 50 "Busy", // 51 "Unavailable", // 52 "Unwilling To Perform", // 53 "Loop Detect", // 54 null, null, null, null, null, null, null, null, null, "Naming Violation", // 64 "Object Class Violation", // 65 "Not Allowed On Non-leaf", // 66 "Not Allowed On RDN", // 67 "Entry Already Exists", // 68 "Object Class Modifications Prohibited", // 69 null, "Affects Multiple DSAs", // 71 null, null, null, null, null, null, null, null, "Other", // 80 null, null, null, null, null, null, null, null, null, null }; /* * Generate an error message from the LDAP error code and error diagnostic. * The message format is: * * "[LDAP: error code <errorCode> - <errorMessage>]" * * where <errorCode> is a numeric error code * and <errorMessage> is a textual description of the error (if available) * */ static String getErrorMessage(int errorCode, String errorMessage) { String message = "[LDAP: error code " + errorCode; if ((errorMessage != null) && (errorMessage.length() != 0)) { // append error message from the server message = message + " - " + errorMessage + "]"; } else { // append built-in error message try { if (ldap_error_message[errorCode] != null) { message = message + " - " + ldap_error_message[errorCode] + "]"; } } catch (ArrayIndexOutOfBoundsException ex) { message = message + "]"; } } return message; } //////////////////////////////////////////////////////////////////////////// // // Unsolicited notification support. // // An LdapClient maintains a list of LdapCtx that have registered // for UnsolicitedNotifications. This is a list because a single // LdapClient might be shared among multiple contexts. // // When addUnsolicited() is invoked, the LdapCtx is added to the list. // // When Connection receives an unsolicited notification (msgid == 0), // it invokes LdapClient.processUnsolicited(). processUnsolicited() // parses the Extended Response. If there are registered listeners, // LdapClient creates an UnsolicitedNotification from the response // and informs each LdapCtx to fire an event for the notification. // If it is a DISCONNECT notification, the connection is closed and a // NamingExceptionEvent is fired to the listeners. // // When the connection is closed out-of-band like this, the next // time a method is invoked on LdapClient, an IOException is thrown. // // removeUnsolicited() is invoked to remove an LdapCtx from this client. // //////////////////////////////////////////////////////////////////////////// private Vector<LdapCtx> unsolicited = new Vector<>(3); void addUnsolicited(LdapCtx ctx) { if (debug > 0) { System.err.println("LdapClient.addUnsolicited" + ctx); } unsolicited.addElement(ctx); } void removeUnsolicited(LdapCtx ctx) { if (debug > 0) { System.err.println("LdapClient.removeUnsolicited" + ctx); } unsolicited.removeElement(ctx); } // NOTE: Cannot be synchronized because this is called asynchronously // by the reader thread in Connection. Instead, sync on 'unsolicited' Vector. void processUnsolicited(BerDecoder ber) { if (debug > 0) { System.err.println("LdapClient.processUnsolicited"); } try { // Parse the response LdapResult res = new LdapResult(); ber.parseSeq(null); // init seq ber.parseInt(); // msg id; should be 0; ignored if (ber.parseByte() != LDAP_REP_EXTENSION) { throw new IOException( "Unsolicited Notification must be an Extended Response"); } ber.parseLength(); parseExtResponse(ber, res); if (DISCONNECT_OID.equals(res.extensionId)) { // force closing of connection forceClose(pooled); } LdapCtx first = null; UnsolicitedNotification notice = null; synchronized (unsolicited) { if (unsolicited.size() > 0) { first = unsolicited.elementAt(0); // Create an UnsolicitedNotification using the parsed data // Need a 'ctx' object because we want to use the context's // list of provider control factories. notice = new UnsolicitedResponseImpl( res.extensionId, res.extensionValue, res.referrals, res.status, res.errorMessage, res.matchedDN, (res.resControls != null) ? first.convertControls(res.resControls) : null); } } if (notice != null) { // Fire UnsolicitedNotification events to listeners notifyUnsolicited(notice); // If "disconnect" notification, // notify unsolicited listeners via NamingException if (DISCONNECT_OID.equals(res.extensionId)) { notifyUnsolicited( new CommunicationException("Connection closed")); } } } catch (IOException e) { NamingException ne = new CommunicationException( "Problem parsing unsolicited notification"); ne.setRootCause(e); notifyUnsolicited(ne); } catch (NamingException e) { notifyUnsolicited(e); } } private void notifyUnsolicited(Object e) { Vector<LdapCtx> unsolicitedCopy; synchronized (unsolicited) { unsolicitedCopy = new Vector<>(unsolicited); if (e instanceof NamingException) { unsolicited.setSize(0); // no more listeners after exception } } for (int i = 0; i < unsolicitedCopy.size(); i++) { unsolicitedCopy.elementAt(i).fireUnsolicited(e); } } private void ensureOpen() throws IOException { if (conn == null || !conn.useable) { if (conn != null && conn.closureReason != null) { throw conn.closureReason; } else { throw new IOException("connection closed"); } } } // package private (used by LdapCtx) static LdapClient getInstance(boolean usePool, String hostname, int port, String factory, int connectTimeout, int readTimeout, OutputStream trace, int version, String authMechanism, Control[] ctls, String protocol, String user, Object passwd, Hashtable<?,?> env) throws NamingException { if (usePool) { if (LdapPoolManager.isPoolingAllowed(factory, trace, authMechanism, protocol, env)) { LdapClient answer = LdapPoolManager.getLdapClient( hostname, port, factory, connectTimeout, readTimeout, trace, version, authMechanism, ctls, protocol, user, passwd, env); answer.referenceCount = 1; // always one when starting out return answer; } } return new LdapClient(hostname, port, factory, connectTimeout, readTimeout, trace, null); } }
⏎ com/sun/jndi/ldap/LdapClient.java
Or download all of them as a single archive file:
File name: java.naming-11.0.1-src.zip File size: 461792 bytes Release date: 2018-11-04 Download
⇒ JDK 11 java.net.http.jmod - Net HTTP Module
2020-09-30, 58111👍, 0💬
Popular Posts:
What Is activation.jar? I heard it's related to JAF (JavaBeans Activation Framework) 1.1? The if you...
JDK 11 java.security.jgss.jmod is the JMOD file for JDK 11 Security JGSS (Java Generic Security Serv...
JDK 17 jdk.compiler.jmod is the JMOD file for JDK 17 Compiler tool, which can be invoked by the "jav...
Java Architecture for XML Binding (JAXB) is a Java API that allows Java developers to map Java class...
What Is commons-lang3-3.1.jar? commons-lang3-3.1.jar is the JAR file for Apache Commons Lang 3.1, wh...