/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at
* trunk/nasutekds/resource/legal-notices/NasuTekDS.LICENSE
* or https://NasuTekDS.dev.java.net/NasuTekDS.LICENSE.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at
* trunk/nasutekds/resource/legal-notices/NasuTekDS.LICENSE. If applicable,
* add the following below this CDDL HEADER, with the fields enclosed
* by brackets "[]" replaced with your own identifying information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2010 Sun Microsystems, Inc.
*/
package org.nasutekds.arisid;
import static org.nasutekds.server.protocols.asn1.ASN1Constants.*;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import org.nasutekds.messages.Message;
import org.nasutekds.server.controls.ControlDecoder;
import org.nasutekds.server.protocols.asn1.ASN1;
import org.nasutekds.server.protocols.asn1.ASN1Reader;
import org.nasutekds.server.protocols.asn1.ASN1Writer;
import org.nasutekds.server.types.*;
import org.openliberty.arisid.*;
import org.openliberty.arisid.log.ILogger;
import org.openliberty.arisid.log.LogHandler;
import org.openliberty.arisid.policy.IPolicy;
import org.openliberty.arisid.policy.PolicyHandler;
import org.openliberty.arisid.protocol.ldap.IPrivacyControl;
import org.w3c.dom.Element;
/**
* IGF ArisID Privacy Control implementation.
*/
public class ArisIDPrivacyControl extends Control implements
IPrivacyControl
{
/**
* ControlDecoder implentation to decode this control from a
* ByteString.
*/
private final static class Decoder implements
ControlDecoder<ArisIDPrivacyControl>
{
/**
* Decodes and constructs a Java object representing the
* encodedValue.
* <p>
* ASN.1 encoded value as per Privacy Control Specifiction:
* http://www.openliberty.org/wiki/index.php/Profile_LDAP#
* Extended_PolicySequence_Variation
*/
public ArisIDPrivacyControl decode(boolean isCritical,
ByteString value) throws DirectoryException
{
if (value == null)
{
final Message message = Message
.raw("Control contains no value");
throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message);
}
String ixnName = "";
String appName = "";
String appUri = "";
final HashMap<String, IPolicy> polMap = new HashMap<String, IPolicy>();
final ASN1Reader reader = ASN1.getReader(value);
try
{
reader.readStartSequence();
{
appName = reader.readOctetStringAsString();
appUri = reader.readOctetStringAsString();
ixnName = reader.readOctetStringAsString();
reader.readStartSequence();
{
// Get the count of policies coming
final long policyCount = reader.readInteger();
if (policyCount > 1)
{
for (int i = 0; i < policyCount; i++)
{
reader.readStartSequence();
{
final String pname = reader.readOctetStringAsString();
final String pStr = reader.readOctetStringAsString();
final Element node = phandler
.parseStringToElement(pStr);
IPolicy pol = null;
try
{
pol = phandler.parseDomPolicy(node);
}
catch (final Exception e)
{
logger.error("Error parsing policy: "
+ e.getMessage(), e);
}
polMap.put(pname, pol);
}
reader.readEndSequence();
}
}
}
reader.readEndSequence();
}
reader.readEndSequence();
}
catch (final Exception e1)
{
throw new DirectoryException(ResultCode.PROTOCOL_ERROR,
Message.raw("Unable to decode privacy control: "
+ e1.getMessage()), e1);
}
return new ArisIDPrivacyControl(isCritical, ixnName, appName,
appUri, polMap);
}
/**
* {@inheritDoc}
*/
public String getOID()
{
return IPrivacyControl.OID_IGF_CONTROL;
}
}
private static final long serialVersionUID = -2668010326604049964L;
private static final ILogger logger = LogHandler
.getLogger(ArisIDPrivacyControl.class);
private static PolicyHandler phandler = PolicyHandler.getInstance();
private String _ixnName = "";
private String _appName = "";
private String _appUri = "";
private ArisIdService _asvc = null;
private CarmlDoc _doc = null;
private HashMap<String, IPolicy> _polMap = new HashMap<String, IPolicy>();
/**
* The Control Decoder that can be used to decode this control.
*/
public static final ControlDecoder<ArisIDPrivacyControl> DECODER = new Decoder();
/**
* Creates a new non-critical IGF Privacy Control using the provided
* Interaction.
*
* @param ixn
* The interaction.
* @throws IGFException
* If an error occurred processing the Interaction.
*/
public ArisIDPrivacyControl(IInteraction ixn) throws IGFException
{
super(IPrivacyControl.OID_IGF_CONTROL, false);
_processCarmlDoc(ixn);
}
/**
* Creates a new IGF Privacy Control using the provided Interaction
* and criticality.
*
* @param ixn
* The interaction.
* @param critical
* The criticality.
* @throws IGFException
* If an error occurred processing the Interaction.
*/
public ArisIDPrivacyControl(IInteraction ixn, boolean critical)
throws IGFException
{
super(IPrivacyControl.OID_IGF_CONTROL, critical);
_processCarmlDoc(ixn);
}
private ArisIDPrivacyControl(boolean isCritical, String _ixnName,
String _appName, String _appUri, HashMap<String, IPolicy> _polMap)
{
super(IPrivacyControl.OID_IGF_CONTROL, isCritical);
this._ixnName = _ixnName;
this._appName = _appName;
this._appUri = _appUri;
this._polMap = _polMap;
}
public String getAppName()
{
return this._appName;
}
/**
* @deprecated Use {@link #getCarmlURI()} instead
*/
@Deprecated
public URI getAppURI()
{
return getCarmlURI();
}
/**
* A convenience method to obtain the CarmlDoc object referenced by
* this control. For performance reasons, the CarmlDoc object is not
* instantiated unless {@link #loadCarmlDoc(URI)} is called first.
*
* @return A CarmlDoc object containing the Controls referenced
* CarmlDoc or null if the document hasn't been loaded.
*/
public CarmlDoc getCarmlDoc()
{
return this._doc;
}
public URI getCarmlURI()
{
try
{
return new URI(this._appUri);
}
catch (final URISyntaxException e)
{
logger
.warn("Invalid CARML URI syntax exception occurred for value: "
+ this._appUri);
return null;
}
}
/*
* (non-Javadoc)
* @see
* org.openliberty.arisid.protocol.ldap.IPrivacyControl#getConstraintMap
* ()
*/
public Map<String, IPolicy> getConstraintMap()
{
return this._polMap;
}
/*
* (non-Javadoc)
* @seeorg.openliberty.arisid.protocol.ldap.IPrivacyControl#
* getDynamicConstraints (java.lang.String)
*/
public IPolicy getDynamicConstraints(String nameId)
{
return this._polMap.get(nameId);
}
/**
* {@inheritDoc}
*/
public byte[] getEncodedValue()
{
try
{
final ByteStringBuilder builder = new ByteStringBuilder();
final ASN1Writer writer = ASN1.getWriter(builder);
writeValue(writer);
writer.close();
return builder.toByteArray();
}
catch (final IOException e)
{
// Should never occur.
throw new RuntimeException(e);
}
}
/*
* (non-Javadoc)
* @see org.openliberty.arisid.protocol.ldap.IPrivacyControl#getID()
*/
public String getID()
{
return OID_IGF_CONTROL;
}
/*
* (non-Javadoc)
* @see
* org.openliberty.arisid.protocol.ldap.IPrivacyControl#getInteractionName
* ()
*/
public String getInteractionName()
{
return this._ixnName;
}
/**
* Returns the named transaction constraint.
*
* @param nameId
* The transaction constraint name.
* @return The named transaction constraint.
*/
public IPolicy getTransactionConstraints(String nameId)
{
return this._polMap.get(nameId);
}
/**
* This is a convenience method intended for servers/proxies that need
* to instantiate a CarmlDoc object. The localUri is the URI of a
* local copy of the controls referenced Carml Document.
*
* @param localUri
* A URI to a copy of the CARML document matching the
* {@link #getAppName()} of this control. If localUri is
* null, the method will use the stored URI to load the
* document.
* @throws URISyntaxException
* @throws IllegalAccessException
* @throws IGFException
* @throws InstantiationException
* @throws AttrSvcInitializedException
* @throws FileNotFoundException
*/
public void loadCarmlDoc(URI localUri) throws URISyntaxException,
FileNotFoundException, AttrSvcInitializedException,
InstantiationException, IGFException, IllegalAccessException
{
URI loadUri = localUri;
if (loadUri == null)
{
loadUri = new URI(this._appUri);
}
// TODO I wonder if this should come from a static hash to avoid
// re-parsing?
this._asvc = ArisIdServiceFactory.parseCarmlOnly(loadUri);
if (this._asvc != null)
{
this._doc = this._asvc.getCarmlDoc();
}
}
/*
* (non-Javadoc)
* @seeorg.openliberty.arisid.protocol.ldap.IPrivacyControl#
* setDynamicConstraints (java.util.Map)
*/
public void setDynamicConstraints(
Map<String, IPolicy> dynamicConstraints)
{
if (dynamicConstraints != null)
{
this._polMap.putAll(dynamicConstraints);
}
}
/*
* (non-Javadoc)
* @seeorg.openliberty.arisid.protocol.ldap.IPrivacyControl#
* setTranasactionConstraints(java.lang.String,
* org.openliberty.arisid.schema.IPolicy)
*/
public void setDynamicConstraints(String nameId,
IPolicy txnConstraints)
{
this._polMap.put(nameId, txnConstraints);
}
private void _processCarmlDoc(IInteraction ixn) throws IGFException
{
// set defaults of empty string
this._appName = "";
this._ixnName = "";
this._appUri = "";
if (ixn == null)
{
return;
}
final ArisIdService asvc = ixn.getAttributeService();
if (asvc == null)
{
return;
}
final CarmlDoc doc = asvc.getCarmlDoc();
this._appName = doc.getApplicationNameId();
if (this._appName == null)
{
this._appName = "";
}
this._appUri = doc.getCarmlURI().toString();
if (this._appUri == null)
{
this._appUri = "";
}
this._ixnName = ixn.getNameId();
if (this._ixnName == null)
{
this._ixnName = "";
}
}
/**
* Encode ASN.1 value. Encoding is as per spec:
* http://www.openliberty.org/wiki
* /index.php/Profile_LDAP#Extended_PolicySequence_Variation
*/
protected void writeValue(ASN1Writer writer) throws IOException
{
writer.writeStartSequence(UNIVERSAL_OCTET_STRING_TYPE);
{
writer.writeOctetString(_appName);
writer.writeOctetString(_appUri);
writer.writeOctetString(_ixnName);
writer.writeStartSequence();
{
writer.writeInteger(_polMap.size());
for (final Map.Entry<String, IPolicy> entry : _polMap
.entrySet())
{
writer.writeStartSequence();
{
final String nameId = entry.getKey();
final IPolicy pol = this.getTransactionConstraints(nameId);
final String strPol = phandler.policyToString(pol);
writer.writeOctetString(entry.getKey());
writer.writeOctetString(strPol);
}
writer.writeEndSequence();
}
}
writer.writeEndSequence();
}
writer.writeEndSequence();
}
}