/*******************************************************************************
* Copyright (c) 2008, Jay Rosenthal and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Jay Rosenthal - initial API and implementation
*******************************************************************************/
package org.eclipse.buckminster.jnlp.p2.ui.certificates;
import java.util.ArrayList;
import java.util.Iterator;
import javax.security.auth.x500.X500Principal;
/**
* X500PrincipalHelper
* <p>
* Helper class to extract pieces (attributes) of an X500Principal object for display in the UI.
* <p>
* This helper uses the X500Principal.RFC2253 format of X500Principal.getname() to parse an X500Principal name into it's
* component parts.
* <p>
* In principals which contain multiple occurrences of the same attribute,the default for all the methods is to return
* the most significant (first) attribute found.
*
*/
public class X500PrincipalHelper
{
public static int LEASTSIGNIFICANT = 0;
public static int MOSTSIGNIFICANT = 1;
public final static String attrCN = "CN"; //$NON-NLS-1$
public final static String attrOU = "OU"; //$NON-NLS-1$
public final static String attrO = "O"; //$NON-NLS-1$
public final static String attrC = "C"; //$NON-NLS-1$
public final static String attrL = "L"; //$NON-NLS-1$
public final static String attrST = "ST"; //$NON-NLS-1$
public final static String attrSTREET = "STREET";//$NON-NLS-1$
public final static String attrEMAIL = "EMAILADDRESS"; //$NON-NLS-1$
public final static String attrUID = "UID"; //$NON-NLS-1$
ArrayList rdnNameArray = new ArrayList();
private final static String attrTerminator = "="; //$NON-NLS-1$
public X500PrincipalHelper()
{
// Do nothing constructor..
// Wont be useful unless setPrincipal is called...
}
public X500PrincipalHelper(X500Principal principal)
{
parseDN(principal.getName(X500Principal.RFC2253));
}
/**
* Returns an ArrayList containing all the values for the given attribute identifier.
* <p>
*
* @param attributeID
* String containing the X500 name attribute whose values are to be returned
* @return ArrayList containing the string values of the requested attribute. Values are in the order they occur.
* May be empty.
*
*/
public ArrayList getAllValues(String attributeID)
{
ArrayList retList = new ArrayList();
String searchPart = attributeID + attrTerminator;
for(Iterator iter = rdnNameArray.iterator(); iter.hasNext();)
{
ArrayList nameList = (ArrayList)iter.next();
String namePart = (String)nameList.get(0);
if(namePart.startsWith(searchPart))
{
// Return the string starting after the ID string and the = sign that follows it.
retList.add(namePart.toString().substring(searchPart.length()));
}
}
return retList;
}
/**
* Gets the Country (C) attribute from the given X500Principal object.
* <p>
*
* @return the C attribute.
*
*/
public String getC()
{
return findPart(attrC);
}
/**
* Gets the most significant common name (CN) attribute from the given X500Principal object. For names that contains
* multiple attributes of this type. The first (most significant) one will be returned
* <p>
*
* @return the Most significant common name attribute.
*
*/
public String getCN()
{
return findPart(attrCN);
}
/**
* Gets the Email Address (EMAILADDRESS) attribute from the given X500Principal object.
* <p>
*
* @return the EMAILADDRESS attribute.
*
*/
public String getEMAILDDRESS()
{
return findPart(attrEMAIL);
}
/**
* Gets the Locale (L) attribute from the given X500Principal object.
* <p>
*
* @return the L attribute.
*
*/
public String getL()
{
return findPart(attrL);
}
/**
* Gets the most significant Organization (O) attribute from the given X500Principal object. For names that contains
* multiple attributes of this type. The first (most significant) one will be returned
* <p>
*
* @return the Most significant O attribute.
*
*/
public String getO()
{
return findPart(attrO);
}
/**
* Gets the most significant Organizational Unit (OU) attribute from the given X500Principal object. For names that
* contains multiple attributes of this type. The first (most significant) one will be returned
* <p>
*
* @return the Most significant OU attribute.
*
*/
public String getOU()
{
return findPart(attrOU);
}
/**
* Gets the State (ST) attribute from the given X500Principal object.
* <p>
*
* @return the ST attribute.
*
*/
public String getST()
{
return findPart(attrST);
}
/**
* Gets the Street (STREET) attribute from the given X500Principal object.
* <p>
*
* @return the STREET attribute.
*
*/
public String getSTREET()
{
return findPart(attrSTREET);
}
public String getUID()
{
return findPart(attrUID);
}
/**
* Set the X500Principal name object to be parsed.
* <p>
*
* @param principal
* - X500Principal
*/
public void setPrincipal(X500Principal principal)
{
parseDN(principal.getName(X500Principal.RFC2253));
}
private String findPart(String attributeID)
{
return findSignificantPart(attributeID, MOSTSIGNIFICANT);
}
private String findSignificantPart(String attributeID, int significance)
{
String retNamePart = null;
String searchPart = attributeID + attrTerminator;
for(Iterator iter = rdnNameArray.iterator(); iter.hasNext();)
{
ArrayList nameList = (ArrayList)iter.next();
String namePart = (String)nameList.get(0);
if(namePart.startsWith(searchPart))
{
// Return the string starting after the ID string and the = sign that follows it.
retNamePart = namePart.toString().substring(searchPart.length());
// By definition the first one is most significant
if(significance == MOSTSIGNIFICANT)
break;
}
}
return retNamePart;
}
/**
* Derived From: org.eclipse.osgi.internal.verifier - DNChainMatching.java
*
* Takes a distinguished name in canonical form and fills in the rdnArray with the extracted RDNs.
*
* @param dn
* the distinguished name in canonical form.
* @throws IllegalArgumentException
* if a formatting error is found.
*/
private void parseDN(String dn) throws IllegalArgumentException
{
int startIndex = 0;
char c = '\0';
ArrayList nameValues = new ArrayList();
// Clear the existing array, in case this instance is being re-used
rdnNameArray.clear();
while(startIndex < dn.length())
{
int endIndex;
for(endIndex = startIndex; endIndex < dn.length(); endIndex++)
{
c = dn.charAt(endIndex);
if(c == ',' || c == '+')
break;
if(c == '\\')
{
endIndex++; // skip the escaped char
}
}
if(endIndex > dn.length())
throw new IllegalArgumentException("unterminated escape " + dn); //$NON-NLS-1$
nameValues.add(dn.substring(startIndex, endIndex));
if(c != '+')
{
rdnNameArray.add(nameValues);
if(endIndex != dn.length())
nameValues = new ArrayList();
else
nameValues = null;
}
startIndex = endIndex + 1;
}
if(nameValues != null)
{
throw new IllegalArgumentException("improperly terminated DN " + dn); //$NON-NLS-1$
}
}
}