/*
ExchangeStoreTask.java
This task is designed to query our Active Directory server to
obtain a list of defined Exchange Mail Store volumes. We use the
results of this query to keep our Exchange Store object list up to
date.
Created: 22 September 2010
Module By: Jonathan Abbey, jonabbey@arlut.utexas.edu
-----------------------------------------------------------------------
Ganymede Directory Management System
Copyright (C) 1996-2013
The University of Texas at Austin
Ganymede is a registered trademark of The University of Texas at Austin
Contact information
Author Email: ganymede_author@arlut.utexas.edu
Email mailing list: ganymede@arlut.utexas.edu
US Mail:
Computer Science Division
Applied Research Laboratories
The University of Texas at Austin
PO Box 8029, Austin TX 78713-8029
Telephone: (512) 835-3200
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package arlut.csd.ganymede.gasharl;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import javax.naming.Context;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchResult;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import arlut.csd.ganymede.common.Invid;
import arlut.csd.ganymede.common.NotLoggedInException;
import arlut.csd.ganymede.common.ReturnVal;
import arlut.csd.ganymede.common.SchemaConstants;
import arlut.csd.ganymede.rmi.db_object;
import arlut.csd.ganymede.server.DBEditObject;
import arlut.csd.ganymede.server.DBObject;
import arlut.csd.ganymede.server.Ganymede;
import arlut.csd.ganymede.server.GanymedeServer;
import arlut.csd.ganymede.server.GanymedeSession;
import arlut.csd.ganymede.server.StringDBField;
/*------------------------------------------------------------------------------
class
ExchangeStoreTask
------------------------------------------------------------------------------*/
/**
* This task is designed to query our Active Directory server to
* obtain a list of defined Exchange Mail Store volumes. We use the
* results of this query to keep our Exchange Store object list up to
* date.
*
* @author Jonathan Abbey jonabbey@arlut.utexas.edu
*/
public class ExchangeStoreTask implements Runnable {
static final boolean debug = true;
static final boolean skipSSLValidation = true;
static private Pattern homeMDBPat = Pattern.compile("CN=([^,]+)");
/* -- */
GanymedeSession mySession = null;
/**
*
* Just Do It (tm)
*
* @see java.lang.Runnable
*
*/
public void run()
{
boolean transactionOpen = false;
/* -- */
Ganymede.debug("Exchange Store Task: Starting");
String error = GanymedeServer.checkEnabled();
if (error != null)
{
Ganymede.debug("Deferring Exchange Store Task - semaphore disabled: " + error);
return;
}
try
{
try
{
mySession = new GanymedeSession("ExchangeStoreTask");
}
catch (RemoteException ex)
{
Ganymede.debug("Exchange Store Task: Couldn't establish session");
return;
}
// we don't want interactive handholding
mySession.enableWizards(false);
// and we want forced required fields oversight..
mySession.enableOversight(true);
ReturnVal retVal = mySession.openTransaction("Exchange Store Task");
if (retVal != null && !retVal.didSucceed())
{
Ganymede.debug("Exchange Store Task: Couldn't open transaction");
return;
}
transactionOpen = true;
// do the stuff
try
{
Map<String,String> map = getMailStores();
for (Map.Entry<String, String> entry: map.entrySet())
{
Invid x = mySession.findLabeledObject(entry.getKey(), exchangeStoreSchema.BASE);
if (x == null)
{
ReturnVal r = mySession.create_db_object(exchangeStoreSchema.BASE);
db_object obj = r.getObject();
r = obj.setFieldValue(exchangeStoreSchema.MAILSTORENAME, entry.getKey());
if (!ReturnVal.didSucceed(r))
{
throw new RuntimeException("Error setting MAIL STORE NAME: " + r.toString());
}
r = obj.setFieldValue(exchangeStoreSchema.EXCHANGEMDB, entry.getValue());
if (!ReturnVal.didSucceed(r))
{
throw new RuntimeException("Error setting EXCHANGEMDB: " + r.toString());
}
}
}
}
catch (Throwable ex)
{
Ganymede.debug("Exchange Store Query / Update bailed");
mySession.abortTransaction();
return;
}
retVal = mySession.commitTransaction();
if (retVal != null && !retVal.didSucceed())
{
// if doNormalProcessing is true, the
// transaction was not cleared, but was
// left open for a re-try. Abort it.
if (retVal.doNormalProcessing)
{
Ganymede.debug("Exchange Store Task: couldn't fully commit, trying to abort.");
mySession.abortTransaction();
}
Ganymede.debug("Exchange Store Task: Couldn't successfully commit transaction");
}
else
{
Ganymede.debug("Exchange Store Task: Transaction committed");
}
transactionOpen = false;
}
catch (NotLoggedInException ex)
{
}
catch (Throwable ex)
{
Ganymede.debug("Caught " + ex.getMessage());
}
finally
{
if (transactionOpen)
{
Ganymede.debug("Exchange Store Task: Forced to terminate early, aborting transaction");
}
mySession.logout();
}
}
/**
* Returns a Map of Exchange Mail Store names to Exchange Mail Store HomeMDB values.
*/
public Map<String,String> getMailStores()
{
Map<String,String> map = new HashMap<String,String>();
Hashtable env = new Hashtable();
String url = System.getProperty("gasharl.active_directory.url");
String principal = System.getProperty("gasharl.active_directory.security_principal");
String password = System.getProperty("gasharl.active_directory.security_password");
if (url == null)
{
throw new IllegalArgumentException("Missing Active Directory url from properties file");
}
if (principal == null)
{
throw new IllegalArgumentException("Missing Active Directory security principal from properties file");
}
if (password == null)
{
throw new IllegalArgumentException("Missing Active Directory security password from properties file");
}
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.PROVIDER_URL, url);
env.put(Context.SECURITY_PRINCIPAL, principal);
env.put(Context.SECURITY_CREDENTIALS, password);
if (skipSSLValidation)
{
env.put("java.naming.ldap.factory.socket", BlindSSLSocketFactory.class.getName());
}
DirContext ctx = null;
try
{
ctx = new InitialDirContext(env);
Attributes matchAttrs = new BasicAttributes();
matchAttrs.put(new BasicAttribute("homeMDB"));
matchAttrs.put(new BasicAttribute("msExchMailboxGuid"));
NamingEnumeration answer = ctx.search("CN=Microsoft Exchange System Objects", matchAttrs);
while (answer.hasMore())
{
SearchResult sr = (SearchResult) answer.next();
NamingEnumeration<Attribute> e = (NamingEnumeration<Attribute>)sr.getAttributes().getAll();
while (e.hasMore())
{
Attribute a = e.next();
if (a.getID().equals("homeMDB"))
{
String value = (String) a.get();
Matcher m = homeMDBPat.matcher(value);
if (m.find())
{
map.put(m.group(1), value);
}
}
}
}
}
catch (NamingException ex)
{
ex.printStackTrace();
}
finally
{
if (ctx != null)
{
try
{
ctx.close();
}
catch (NamingException ex)
{
ex.printStackTrace();
}
}
}
return map;
}
public static void main(String[] args)
{
if (args.length == 0)
{
throw new IllegalArgumentException("Missing command line argument for properties file");
}
FileInputStream fis = null;
BufferedInputStream bis = null;
try
{
fis = new FileInputStream(args[0]);
bis = new BufferedInputStream(fis);
System.getProperties().load(bis);
}
catch (IOException ex)
{
throw new IllegalArgumentException("Couldn't load properties file " + args[0]);
}
finally
{
try
{
if (bis != null)
{
bis.close();
}
}
catch (IOException ex)
{
}
}
ExchangeStoreTask task = new ExchangeStoreTask();
Map<String, String> storeMap = task.getMailStores();
for (Map.Entry<String,String> store: storeMap.entrySet())
{
System.out.println(store.getKey() + ":" + store.getValue());
}
}
}