package grith.jgrith.voms.VOManagement;
import grisu.jcommons.interfaces.InformationManager;
import grisu.model.info.dto.VO;
import grith.jgrith.plainProxy.LocalProxy;
import grith.jgrith.utils.CredentialHelpers;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang.StringUtils;
import org.globus.gsi.GlobusCredentialException;
import org.ietf.jgss.GSSCredential;
import org.perf4j.StopWatch;
import org.perf4j.slf4j.Slf4JStopWatch;
import org.python.modules.synchronize;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Manages all VOMS servers that are of interest for the user. Information about
* these servers can be found in the $HOME/.glite/vomses or
* /etc/grid-security/vomsdir directory. Every file which contains a line like<br>
* <br>
* "Chris" "vomrsdev.vpac.org" "15003"
* "/C=AU/O=APACGrid/OU=VPAC/CN=vomrsdev.vpac.org" "Chris" <br>
* <br>
* describes one VO: "Chris" is the name of the VO, followed by the hostname of
* the VOMS server and the port the VO is mapped to. After that the DN of the
* host of the VOMS server and I don't know what the last "Chris" means.
*
* <br>
*
* @author Markus Binsteiner
*
*/
public class VOManager {
static final Logger myLogger = LoggerFactory.getLogger(VOManager.class
.getName());
public final static File USER_VOMSES = new File(
System.getProperty("user.home") + File.separator + ".glite"
+ File.separator + "vomses");
public final static File GLOBAL_VOMSES = new File("/etc/vomses");
public static final int MEMBER = 1;
public static final int NO_MEMBER = 0;
public Vector<VO> allVOs = null;
private final InformationManager im;
public VOManager() {
this(null);
}
public VOManager(InformationManager im) {
this.im = im;
}
/**
* Returns the first part of the fqan (without the role/capability part)
*
* @param cred
* the credential
* @return the (short) fqan
*/
public Map<String, VO> getAllFqans(GSSCredential cred) {
return getAllFqans(cred, false);
}
/**
* Queries all VO servers for all of the users fqans. Returns either the
* full fqan or just the VO/Group part of it
*
* @param cred
* the credential
* @param returnWholeFqan
* whether to return the full fqan (true) or not (false)
* @return the fqan
*/
public Map<String, VO> getAllFqans(final GSSCredential cred,
final boolean returnWholeFqan) {
final Map<String, VO> allFqans = Collections
.synchronizedMap(new TreeMap<String, VO>());
int size = getAllVOs().size();
if ( size == 0 ) {
return allFqans;
}
final ExecutorService executor = Executors
.newFixedThreadPool(getAllVOs().size());
for (final VO vo : getAllVOs()) {
if (VO.NON_VO.equals(vo)) {
myLogger.debug("Not looking up NON_VO groups...");
continue;
}
Thread t = new Thread() {
@Override
public void run() {
myLogger.debug("Getting all fqans for: " + vo.getVoName()
+ "...");
StopWatch sw = new Slf4JStopWatch(myLogger);
sw.start();
String[] allFqansFromThisVO = GroupManagement.getAllFqansForVO(vo,
cred);
// check whether user is in a vo at all
if (allFqansFromThisVO != null) {
for (String fqan : allFqansFromThisVO) {
if (!returnWholeFqan) {
// if ( "NULL".equals(GroupManagement.getRolePart(fqan))
// ) {
if (fqan.indexOf("/Role=") >= 0) {
fqan = fqan.substring(0, fqan.indexOf("/Role="));
}
// }
}
allFqans.put(fqan, vo);
}
}
Date end = new Date();
sw.stop("JGrith.GetFqans."+vo.getVoName(), "Getting all fqans for '"+vo.getVoName()+"' finished: "+StringUtils.join(allFqansFromThisVO, ", "));
}
};
t.setName(vo.getVoName() + "_lookup");
executor.execute(t);
}
executor.shutdown();
try {
executor.awaitTermination(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
myLogger.error("Retrieving of FQANs interrupted.", e);
}
return allFqans;
}
/**
* Checks every active VO for information about the user (using the provided
* credential) and fills in all fqans
*
* @param gssCred
* the users' credential
* @return a Map with all information about this user
*/
public Map<VO, Map<String, Set<String>>> getAllInformationAboutUser(
GSSCredential gssCred) {
Map<VO, String[]> allInfoNotProcessed = new HashMap<VO, String[]>();
for (VO vo : getAllVOs()) {
String[] allFqans = GroupManagement.getAllFqansForVO(vo, gssCred);
if (allFqans != null) {
allInfoNotProcessed.put(vo, allFqans);
}
}
Map<VO, Map<String, Set<String>>> allInfo = new HashMap<VO, Map<String, Set<String>>>();
for (VO vo : allInfoNotProcessed.keySet()) {
// get all groups
Set<String> allGroupsOfVo = new TreeSet<String>();
for (String fqan : allInfoNotProcessed.get(vo)) {
allGroupsOfVo.add(GroupManagement.getGroupPart(fqan));
}
Map<String, Set<String>> voAllInfo = new HashMap<String, Set<String>>();
// check all fqans again and this time sort the roles in
for (String fqan : allInfoNotProcessed.get(vo)) {
for (String group : allGroupsOfVo) {
if (fqan.startsWith(group + "/Role=")) {
if (voAllInfo.get(group) == null) {
voAllInfo.put(group, new TreeSet<String>());
}
voAllInfo.get(group).add(
GroupManagement.getRolePart(fqan));
break;
}
}
}
allInfo.put(vo, voAllInfo);
}
return allInfo;
}
/**
* List of all VO's that have vomses files in $HOME/.glite/vomses or if this
* directory is empty in /etc/grid-security/vomsdir
*
* @return all available VO's
*/
public synchronized Vector<VO> getAllVOs() {
if (allVOs == null) {
// if no info manager is set we look at the directory
if ( im == null ) {
Vector<VO> vos = new Vector<VO>();
File[] files = USER_VOMSES.listFiles();
if ((files == null) || (files.length == 0)) {
files = GLOBAL_VOMSES.listFiles();
}
if (files != null) {
for (File file : files) {
BufferedReader f = null;
try {
f = new BufferedReader(new FileReader(file));
} catch (FileNotFoundException e) {
continue;
}
String line = null;
try {
while ((line = f.readLine()) != null) {
VO new_vo = parseVomsesLine(line);
if (new_vo == null) {
continue;
}
vos.add(new_vo);
}
} catch (IOException e) {
continue;
}
}
}
allVOs = vos;
} else {
allVOs = new Vector<VO>(im.getAllVOs());
}
}
return allVOs;
}
public VO getVO(String vo_name) {
for (VO vo : getAllVOs()) {
if (vo_name.equals(vo.getVoName())) {
return vo;
}
}
return null;
}
public static void main(String[] args) {
GSSCredential cred = null;
try {
cred = CredentialHelpers.wrapGlobusCredential(LocalProxy
.loadGlobusCredential());
} catch (GlobusCredentialException e) {
myLogger.error(e.getLocalizedMessage());
}
VOManager vom = new VOManager(null);
Map<VO, Map<String, Set<String>>> allInfo = vom.getAllInformationAboutUser(cred);
for (VO vo : allInfo.keySet()) {
System.out.println("VO: " + vo.getVoName());
System.out.println("================================");
for (String group : allInfo.get(vo).keySet()) {
System.out.println("\n\n\tGroup: " + group);
System.out.println("\t------------------------------");
for (String role : allInfo.get(vo).get(group)) {
System.out.println("\t\tRole: " + role);
}
}
}
}
/**
* Takes the line that describes this VO and parses it to extract
* information to be able to create a VO.
*
* @param line
* the first line of a vomses file
* @return the according VO
*/
public static VO parseVomsesLine(String line) {
int start = line.indexOf("\"") + 1;
int end = line.indexOf("\"", start + 1);
if ((start < 0) || (end < 0)) {
return null;
}
String name = line.substring(start, end);
start = line.indexOf("\"", end + 1) + 1;
end = line.indexOf("\"", start + 1);
if ((start < 0) || (end < 0)) {
return null;
}
String host = line.substring(start, end);
start = line.indexOf("\"", end + 1) + 1;
end = line.indexOf("\"", start + 1);
if ((start < 0) || (end < 0)) {
return null;
}
int port = -1;
try {
port = Integer.parseInt(line.substring(start, end));
} catch (NumberFormatException e) {
return null;
}
if (port < 1) {
return null;
}
start = line.indexOf("\"", end + 1) + 1;
end = line.indexOf("\"", start + 1);
if ((start < 0) || (end < 0)) {
return null;
}
String hostDN = line.substring(start, end);
start = line.indexOf("\"", end + 1) + 1;
end = line.indexOf("\"", start + 1);
// no use for that
String stupidName = line.substring(start, end);
start = line.indexOf("\"", end + 1) + 1;
end = line.indexOf("\"", start + 1);
if (start < 1) {
myLogger.debug(name + " " + host + " " + port + " " + hostDN);
return new VO(name, host, port, hostDN);
}
String vomrsUrl = line.substring(start, end);
myLogger.debug(name + " " + host + " " + port + " " + hostDN + vomrsUrl);
return new VO(name, host, port, hostDN);
}
}