blob: b1ac164e2505a79945adc2f1d9f34eb5c12c73b6 [file] [log] [blame]
/*
* Copyright (c) 1999, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package com.sun.jndi.ldap.obj;
import com.sun.jndi.ldap.LdapCtxFactory;
import java.rmi.MarshalledObject;
import java.rmi.Remote;
import java.rmi.server.RemoteStub;
import java.util.Hashtable;
import javax.naming.ConfigurationException;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.spi.DirStateFactory;
/**
* An DirStateFactory that returns the object and Attributes
* given a java.rmi.Remote object. It handles the following different scenarios:
*<ul>
*<li>
* If object is a JRMP stub (RemoteStub), return its MarshalledObject.
*<li>
* If object is a CORBA Object or a CORBA stub,
* store as CORBA IOR (see CorbaToAttrs).
*<li>
* If all else fails, store as MarshalledObject.
*</ol>
*<p>
* The form of <tt>getStateToBind()</tt> that does not accept an
* <tt>Attributes</tt> parameter always return null because this
* factory needs to return <tt>Attributes</tt>.
* The caller should always use the form of <tt>getStateToBind()</tt>
* that accepts an <tt>Attributes</tt> parameter. This is the case if
* the service provider uses <tt>DirectoryManager</tt>.
*<p>
* This factory only works on JDK1.2 systems because it needs MarshalledObject
* and CORBA classes, which are in JDK1.2.
*
* @author Rosanna Lee
*/
public class RemoteToAttrs implements DirStateFactory {
private static final String CLASSNAME_ATTRID = "javaClassName";
private static final String CLASSNAMES_ATTRID = "javaClassNames";
private static final String STRUCTURAL_OCID = "javacontainer";
private static final String MARSHALLED_OCID = "javamarshalledobject";
public RemoteToAttrs() {
}
/**
* Returns an object and attributes for storing into LDAP that represents
* the Remote object. If the input is not a Remote object, or if
* the Remote object cannot be transformed, return null.
*
* @param orig The object to store; if not Remote; return null.
* @param name Ignored
* @param ctx Ignored
* @param env A possibly null environment. Used to get the ORB to use
* when getting the CORBA object for the Remote object using RMI-IIOP.
* @param inAttrs The possibly null attributes included with the bind.
* @return {obj, attrs} where obj is either null or the RemoteStub of the
* Remote object. It is the stub if <tt>orig</tt> is already a stub, or if
* <tt>orig</tt> has a JRMP stub. <tt>attrs</tt> is a union of
* <tt>inAttrs</tt> and and some other attributes depending on how
* <tt>orig</tt> has been transformed.
* If <tt>orig</tt> is transformed into a CORBA object, then it will
* have CORBA-related attributes (see CorbaToAttrs).
* @exception ConfigurationException If problem calling RemoteObject.toStub()
* or if problem transforming Remote object to CORBA object.
* @exception NamingException If some other problem occurred transforming
* the object.
*/
@Override
public DirStateFactory.Result getStateToBind(Object orig, Name name, Context ctx, Hashtable env, Attributes inAttrs)
throws NamingException {
if (!(orig instanceof java.rmi.Remote)) {
return null; // Only handles Remote objects
}
// A JRMP stub, just bind
if (orig instanceof RemoteStub) {
return jrmpObject(orig, inAttrs);
} else {
// Try doing CORBA mapping
try {
DirStateFactory.Result answer = RemoteToCorbaToAttrs.remoteToCorbaToAttrs((Remote) orig, env, inAttrs);
if (answer != null) {
return answer;
}
} catch (ClassNotFoundException e) {
// RMI-IIOP package not available.
// Ignore and continue because we don't want RMI/JRMP to
// have dependency on RMI-IIOP packages being available
}
}
// Otherwise, marshal object
return jrmpObject(orig, inAttrs);
}
/**
* Always return null.
* @param orig Ignored
* @param name Ignored
* @param ctx Ignored
* @param env Ignored
* @exception NamingException Not thrown
*/
@Override
public Object getStateToBind(Object orig, Name name, Context ctx, Hashtable env) throws NamingException {
// Cannot just return obj; need to return Attributes too
return null;
}
/**
* Returns a pair consisting of a MarshalledObject and attributes to
* be bound with the stub.
*
* @param obj The non-null object to store.
* @param inAttrs The possible null attributes to store with object.
* @return A non-null Result consisting of the MarshalledObject and attributes.
*/
private static DirStateFactory.Result jrmpObject(Object obj, Attributes inAttrs) throws NamingException {
try {
Object mobj = new MarshalledObject(obj);
Attributes outAttrs = null;
Attribute cname = null;
Attribute tnames = null;
Attribute objectClass = null;
if (inAttrs != null) {
// Get existing objectclass attribute
objectClass = inAttrs.get("objectClass");
if (objectClass == null && !inAttrs.isCaseIgnored()) {
// %%% workaround
objectClass = inAttrs.get("objectclass");
}
// No objectclasses supplied, use "top" to start
if (objectClass == null) {
objectClass = new BasicAttribute("objectClass", "top");
} else {
objectClass = (Attribute)objectClass.clone();
}
cname = inAttrs.get(CLASSNAME_ATTRID);
tnames = inAttrs.get(CLASSNAMES_ATTRID);
outAttrs = (Attributes)inAttrs.clone();
} else {
outAttrs = new BasicAttributes(true);
objectClass = new BasicAttribute("objectClass", "top");
}
if (cname == null) {
outAttrs.put(CLASSNAME_ATTRID, obj.getClass().getName());
}
if (tnames == null) {
Attribute tAttr = LdapCtxFactory.createTypeNameAttr(obj.getClass());
if (tAttr != null) {
outAttrs.put(tAttr);
}
}
boolean structural = objectClass.size() == 0 || (objectClass.size() == 1 && objectClass.contains("top"));
if (structural) {
objectClass.add(STRUCTURAL_OCID);
}
objectClass.add(MARSHALLED_OCID);
outAttrs.put(objectClass);
return new DirStateFactory.Result(mobj, outAttrs);
} catch (java.io.IOException e) {
NamingException ne = new NamingException("Cannot create MarshallObject for " + obj);
ne.setRootCause(e);
throw ne;
}
}
}