How to set a stream as flow target using java RTC api? - java

I use below code to create a workspace :
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import com.ibm.team.repository.client.ITeamRepository;
import com.ibm.team.repository.client.ITeamRepository.ILoginHandler;
import com.ibm.team.repository.client.ITeamRepository.ILoginHandler.ILoginInfo;
import com.ibm.team.repository.client.TeamPlatform;
import com.ibm.team.repository.common.TeamRepositoryException;
import com.ibm.team.scm.client.IWorkspaceConnection;
import com.ibm.team.scm.client.IWorkspaceManager;
import com.ibm.team.scm.client.SCMPlatform;
import com.ibm.team.scm.common.IFlowTable;
public class RTCFirst {
public static void main(String args[]) {
String repositoryURI = "https://rtc.domain.com/jazz";
String userId = "myid";
String password = "****";
IProgressMonitor monitor = new NullProgressMonitor();
try {
ITeamRepository repo = logIntoTeamRepository(repositoryURI,
userId, password, monitor);
IWorkspaceManager wm = SCMPlatform.getWorkspaceManager(repo);
IWorkspaceConnection workspace = wm.createWorkspace(repo.loggedInContributor(), "Example Workspace", "Description", monitor);
IFlowTable ift = workspace.getFlowTable().getWorkingCopy();
} catch (TeamRepositoryException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static ITeamRepository logIntoTeamRepository(String repositoryURI,
String userId, String password, IProgressMonitor monitor)
throws TeamRepositoryException {
System.out.println("Trying to log into repository: " + repositoryURI);
TeamPlatform.startup();
ITeamRepository teamRepository = TeamPlatform
.getTeamRepositoryService().getTeamRepository(repositoryURI);
teamRepository.registerLoginHandler(new LoginHandler(userId, password));
teamRepository.login(monitor);
System.out.println("Login succeeded.");
return teamRepository;
}
private static class LoginHandler implements ILoginHandler, ILoginInfo {
private String fUserId;
private String fPassword;
private LoginHandler(String userId, String password) {
fUserId = userId;
fPassword = password;
}
public String getUserId() {
return fUserId;
}
public String getPassword() {
return fPassword;
}
public ILoginInfo challenge(ITeamRepository repository) {
return this;
}
}
}
I think I need to populate the IFlowTable with the stream I want to flow to ? If so how can this be achieved ? I can use below code to find the stream :
IWorkspaceHandle iwh = (IWorkspaceHandle) findConnectionByName(repo , "mystream" , 1 , monitor).get(0);
private static List findConnectionByName(
ITeamRepository teamRepository, String name, int kind,
IProgressMonitor monitor) throws TeamRepositoryException {
IWorkspaceManager wm = SCMPlatform.getWorkspaceManager(teamRepository);
IWorkspaceSearchCriteria criteria = IWorkspaceSearchCriteria.FACTORY
.newInstance().setKind(kind);
if (name != null) {
criteria.setExactName(name);
}
List<IWorkspaceHandle>workspaces= wm.findWorkspaces(criteria,
Integer.MAX_VALUE, monitor);
return workspaces;
}
But once I've found the stream how do I add it as flow target ?

don't know if you still need the answer, but I use below code to add a stream (lv1Stream) as flow target of another stream (lv2Stream):
IFlowTable flowTable = lv2Stream.getFlowTable().getWorkingCopy();
flowTable.addDeliverFlow(lv1Stream.getResolvedWorkspace(), repo.getId(),
repo.getRepositoryURI(), null, lv1Stream.getDescription());
IFlowEntry flowNode =
flowTable.getDeliverFlow(lv1Stream.getResolvedWorkspace());
flowTable.setDefault(flowNode);
flowTable.setCurrent(flowNode);
lv2Stream.setFlowTable(flowTable, null);

Related

Kerberos and Active Directory - where does the Active Directory Server name get set?

Total Kerberos and Active Directory newb here trying to get a very small sample working.
Found a Java Active Directory JAAS example onLine and here is the code.
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
public class ActiveDirectoryValidator
{
private static final String USERNAME = "FOO";
private static final String PASSWORD = "BAR";
private ActiveDirectoryValidator()
{
}
public boolean validateUser(String userName, String password)
{
try
{
LoginContext lc = null;
ADCallbackHandler ch = new ADCallbackHandler();
ch.setUserId(userName);
ch.setPassword(password);
lc = new LoginContext("JaasConfig", ch);
lc.login();
return true;
}
catch (LoginException le)
{
System.err.println("Authentication failed:");
System.err.println(" " + le.getMessage());
return false;
}
catch (NullPointerException e)
{
System.err.println("Authentication failed:");
System.err.println(" " + e.getMessage());
return false;
}
}
public static void main(String[] args) throws Exception
{
ActiveDirectoryValidator validateUser = new ActiveDirectoryValidator();
if (validateUser.validateUser(USERNAME, PASSWORD))
{
System.out.print("Authentication Successful");
}
else
{
System.out.print("Authentication Failed");
}
}
}
and
import javax.security.auth.callback.*;
import java.io.IOException;
public class ADCallbackHandler implements CallbackHandler
{
private String ADUserId;
private char[] ADPassword;
public void handle(Callback[] callbacks) throws java.io.IOException, UnsupportedCallbackException
{
for (int i = 0; i < callbacks.length; i++)
{
if (callbacks[i] instanceof NameCallback)
{
NameCallback cb = (NameCallback)callbacks[i];
cb.setName(ADUserId);
}
else if (callbacks[i] instanceof PasswordCallback)
{
PasswordCallback cb = (PasswordCallback)callbacks[i];
cb.setPassword(ADPassword);
}
else
{
throw new UnsupportedCallbackException(callbacks[i]);
}
}
}
public void setUserId(String userid)
{
ADUserId = userid;
}
public void setPassword(String password)
{
ADPassword = new char[password.length()];
password.getChars(0, ADPassword.length, ADPassword, 0);
}
}
Where does the Active Directory Server name go?
I would not expect it to be in the jaas.conf file as I have seen other programs set it via the UI interface and the jaas.conf file never changes.
What am I missing?
Is this example showing something totally different?
Moved my test to a Linux machine and ultimately found 2 missing components.
1 - when executing, I needed to include the
-Djava.security.auth.login.config=mylocation/jaas.conf
2 - I needed to edit the following file to include my Active Directory information
/etc/krb5.conf
After making the necessary references and entries, it worked.

Auto-generation of email with username and random password on creation of new user

I have created a class NewUserEmail to auto generate an email with username and password while creating a new user. I am able to create the password but whenever I am trying to log in with that password, its not logging in. I am not able to generate my mail. Please guide me and let me know what is wrong with my code:
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.jscript.ClasspathScriptLocation;
import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.log4j.Logger;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
public class NewUserEmail implements NodeServicePolicies.OnCreateNodePolicy {
private Logger logger = Logger.getLogger(NewUserEmail.class);
private PolicyComponent policyComponent;
private NodeService nodeService;
private PersonService personService;
private ServiceRegistry serviceRegistry;
protected String userName = null;
protected String password = null;
protected String email = null;
protected String subject = null;
protected String body = null;
private static final String NEW_USER_EMAIL_TEMPLATE = "alfresco/module/demoact1-repo/template/new_user_email.ftl";
private static final String EMAIL_FROM = "no-reply#eisenvault.com";
public void init() {
this.email = "";
this.userName = "";
this.password = "";
this.subject = "New User Alfresco";
this.body = "";
this.policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "onCreateNode"),
ContentModel.TYPE_PERSON,
new JavaBehaviour(this, "ReportUser", org.alfresco.repo.policy.JavaBehaviour.NotificationFrequency.EVERY_EVENT)
);
}
public void onCreateNode(ChildAssociationRef childAssocRef) {
if (logger.isInfoEnabled()) logger.info(" NewUserEmail Node create policy fired");
}
public void setNodeService(NodeService nodeService) {
this.nodeService = nodeService;
}
public void setPolicyComponent(PolicyComponent policyComponent) {
this.policyComponent = policyComponent;
}
public void setServiceRegistry(ServiceRegistry serviceRegistry) {
this.serviceRegistry = serviceRegistry;
}
public String getSubject() {
return this.subject;
}
public String getBody() {
return this.body;
}
public String getEmail() {
return this.email;
}
public String getUserName() {
return this.userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public void ReportUser(ChildAssociationRef childAssocRef) {
NodeRef personRef = childAssocRef.getChildRef();
this.userName = (String) this.nodeService.getProperty(personRef, ContentModel.PROP_USERNAME);
this.email = (String) this.nodeService.getProperty(personRef, ContentModel.PROP_EMAIL);
sendEmail();
}
public void sendEmail() throws AlfrescoRuntimeException {
Map<String, Object> templateModel = new HashMap<String, Object>();
if (getEmail() != null && getEmail() != "") {
Set<NodeRef> result = serviceRegistry.getPersonService().getPeopleFilteredByProperty(ContentModel.PROP_EMAIL, getEmail(), 1);
if (result.size() == 1) {
changePassword(getUserName());
ClasspathScriptLocation location = new ClasspathScriptLocation(NEW_USER_EMAIL_TEMPLATE);
try {
if (location.getInputStream() != null) {
// Check that there is a template
templateModel.put("userName", getUserName());
templateModel.put("password", getPassword());
this.body = serviceRegistry.getTemplateService().processTemplate("freemarker", NEW_USER_EMAIL_TEMPLATE, templateModel);
}
} catch (AlfrescoRuntimeException e) {
// If template isn't found, email is constructed "manually"
logger.error("Email Template not found " + NEW_USER_EMAIL_TEMPLATE);
this.body = "<html> <body> <p> A new User has been created.</p>" +
"<p>Hello, </p><p>Your username is " + getUserName() + " and your " +
"password is " + getPassword() + "</p> " +
"<p>We strongly advise you to change your password when you log in for the first time.</p>" +
"Regards</body> </html>";
//send();
}
}
}
}
protected void send() {
MimeMessagePreparator mailPreparer = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws MessagingException {
MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
message.setTo(getEmail());
message.setSubject(getSubject());
message.setText(getBody(), true);
message.setFrom(EMAIL_FROM);
}
};
}
public void changePassword(String password) {
AuthenticationUtil.setRunAsUserSystem();
Set<NodeRef> result = serviceRegistry.getPersonService().getPeopleFilteredByProperty(ContentModel.PROP_EMAIL, getEmail(), 1);
if (result.size() == 1) {
Object[] userNodeRefs = result.toArray();
NodeRef userNodeRef = (NodeRef) userNodeRefs[0];
String username = (String) serviceRegistry.getNodeService().getProperty(userNodeRef, ContentModel.PROP_USERNAME);
// Generate random password
String newPassword = Password.generatePassword();
char[] cadChars = new char[newPassword.length()];
for (int i = 0; i < newPassword.length(); i++) {
cadChars[i] = newPassword.charAt(i);
}
serviceRegistry.getAuthenticationService().setAuthentication(username, newPassword.toCharArray());
setPassword(newPassword);
System.out.println("Password is :" + newPassword);
}
}
}
Below is a working solution.
resource/alfresco/extension/new-user-email-context.xml:
<?xml version='1.0' encoding='UTF-8'?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="newUserEmail" class="demo.NewUserEmail">
<property name="policyComponent" ref="policyComponent"/>
<property name="nodeService" ref="nodeService"/>
<property name="personService" ref="personService"/>
<property name="passwordGenerator" ref="passwordGenerator"/>
<property name="authenticationService" ref="authenticationService"/>
</bean>
</beans>
demo.NewUserEmail.java:
package demo;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.policy.*;
import org.alfresco.repo.security.authentication.PasswordGenerator;
import org.alfresco.service.cmr.repository.*;
import org.alfresco.service.cmr.security.*;
import org.alfresco.util.PropertyCheck;
import org.springframework.beans.factory.InitializingBean;
public class NewUserEmail implements
NodeServicePolicies.OnCreateNodePolicy, InitializingBean {
#Override
public void onCreateNode(ChildAssociationRef childAssocRef) {
notifyUser(childAssocRef);
}
private void notifyUser(ChildAssociationRef childAssocRef) {
NodeRef personRef = childAssocRef.getChildRef();
// get the user name
String username = (String) this.nodeService.getProperty(
personRef, ContentModel.PROP_USERNAME);
// generate the new password (Alfresco's rules)
String newPassword = passwordGenerator.generatePassword();
// set the new password
authenticationService.setAuthentication(username, newPassword.toCharArray());
// send default notification to the user
personService.notifyPerson(username, newPassword);
}
private PolicyComponent policyComponent;
private NodeService nodeService;
private PersonService personService;
private PasswordGenerator passwordGenerator;
private MutableAuthenticationService authenticationService;
public void setPolicyComponent(PolicyComponent policyComponent) {
this.policyComponent = policyComponent;
}
public void setNodeService(NodeService nodeService) {
this.nodeService = nodeService;
}
public void setPersonService(PersonService personService) {
this.personService = personService;
}
public void setPasswordGenerator(PasswordGenerator passwordGenerator) {
this.passwordGenerator = passwordGenerator;
}
public void setAuthenticationService(AuthenticationService authenticationService) {
if (authenticationService instanceof MutableAuthenticationService) {
this.authenticationService = (MutableAuthenticationService) authenticationService;
}
}
#Override
public void afterPropertiesSet() throws Exception {
PropertyCheck.mandatory(this, "policyComponent", policyComponent);
PropertyCheck.mandatory(this, "nodeService", nodeService);
PropertyCheck.mandatory(this, "passwordGenerator", passwordGenerator);
PropertyCheck.mandatory(this, "authenticationService", authenticationService);
PropertyCheck.mandatory(this, "personService", personService);
this.policyComponent.bindClassBehaviour(
NodeServicePolicies.OnCreateNodePolicy.QNAME,
ContentModel.TYPE_PERSON,
new JavaBehaviour(this,
NodeServicePolicies.OnCreateNodePolicy.QNAME.getLocalName(),
Behaviour.NotificationFrequency.TRANSACTION_COMMIT
)
);
}
}

Play Framework Compile Error: } expected but eof found

When I attempt to compile my Play Framework 2.4 project, I receive this error:
`}' expected but eof found.
In /Users/dylhunn/Documents/workspace/my-project/app/controllers/Application.java
This seems to suggest that I failed to match my braces. However, the braces are in fact correctly matched, and the error persists even when I add extra (arbitrarily many) closing curly braces.
I have already tried "activator clean."
Here is my Application.java:
package controllers;
import model.UserAccountManager;
import play.data.Form;
import play.libs.Json;
import play.mvc.*;
import harmony.core.Harmonizer;
import play.twirl.api.Content;
import views.html.*;
import java.net.URLDecoder;
import java.util.*;
import static play.data.Form.form;
public class Application extends Controller {
public Result index() {
if (validSessionIsActive()) return harmonizepage();
else return landing();
}
public Result about() {
Content html = views.html.auxtemplate.render("title", "content");
return ok(html);
}
public Result contact() {
Content html = views.html.auxtemplate.render("title", "content");
return ok(html);
}
public Result landing() {
return ok(views.html.landing.render(form(Credentials.class)));
}
public Result login(String message) {
if (validSessionIsActive()) return index();
if (message == null) message = "";
return ok(views.html.loginpage.render(Form.form(Credentials.class), message));
}
public Result logout() {
String user = session("user-email");
session().clear();
if (user == null) return login("You were not logged in.");
return login("User " + user + " has been logged out.");
}
public Result harmonizepage() {
if (!validSessionIsActive()) return login("Please sign in to acess this page.");
return ok(views.html.harmonize.render());
}
public Result testRegister() {
return ok(views.html.signuppage.render(Form.form(UserData.class));
}
public static class Credentials {
public String email;
public String password;
}
public static class UserData {
public String email;
public String password;
public String name;
public String location;
public String birthday;
}
public Result loginSubmit() {
Form<Credentials> loginForm = form(Credentials.class).bindFromRequest();
if (UserAccountManager.userRegistered(loginForm.get().email)) {
if (UserAccountManager.authenticate(loginForm.get())) { // success
session("user-email", loginForm.get().email);
return harmonizepage();
} else { // Incorrect password
return login("Incorrect password for that email address.");
}
} else { // New user
session("candidate-email", loginForm.get().email);
session("candidate-password", loginForm.get().password);
session("registration-in-progress", "true");
return login("Sorry -- signups are still closed!");
}
}
public Result signupSubmit() {
if (!session("registration-in-progress").equals("true")) return login("");
session("registration-in-progress", "false");
Form<UserData> suForm = form(UserData.class).bindFromRequest();
UserData data = suForm.get();
data.email = session("candidate-email");
data.password = session("candidate-password");
UserAccountManager.registerUser(data);
return index();
}
/**
* Checks the session cookie to see if a valid username is stored there.
*/
public static boolean validSessionIsActive() {
String email = session("user-email");
return UserAccountManager.userRegistered(email);
}
public Result harmonize(String input) {
if (!validSessionIsActive())
return badRequest("No user is currently signed in. Try closing and reopening the site");
try {
input = URLDecoder.decode(input, "UTF-8");
} catch (Exception e) {
return badRequest("The server received an unsupported URL encoding.");
}
List<String> inputChords = Arrays.asList(input.split(" "));
List<List<String>> result = new ArrayList<>();
String str = "";
for (String s : inputChords) str = str + s + " ";
try {
result = Harmonizer.harmonize(str);
} catch (Exception e) { // Harmonizing failed for some reason
return badRequest(e.getMessage());
}
return ok(Json.toJson(result));
}
}
The error message is confusing, but the problem is in the testRegister method. The render call is not properly closed.
return ok(views.html.signuppage.render(Form.form(UserData.class));
should be
return ok(views.html.signuppage.render(Form.form(UserData.class)));
The error message is probably some kind of Scala thing popping up.

How to set a password reset link to expire in 24 hours instead of no expiry

The application's password recovery functionality sends an email with a link to a page where a user sets a new password. This link does not expire if not used, which makes it possible for an attacker to re-use it in order to compromise an account. How to make a reset password link to expire in 24 hours of sending the user an email?
Can someone tell me what is the approach I should take to solve this issue?
package com.www.actions;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import com.lang.EncryptionUtil;
import com.www.crm.CrmUser;
import com.www.customer.dao.CustomerUtils;
import com.www.interceptors.SessionManager;
import com.www.services.AmsCustomerService;
import com.raleys.www.services.IAmsCustomerService;
public class PasswordUpdateAction extends BaseAction {
/** Comment for <code>serialVersionUID</code> */
private static final long serialVersionUID = 1L;
private final Logger logger = Logger.getLogger(PasswordUpdateAction.class);
private String password1 = null;
private String password2 = null;
private final SessionManager sessionManager;
public PasswordUpdateAction(SessionManager sessionManager) {
this.sessionManager = sessionManager;
}
#Override
public String execute() {
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = ServletActionContext.getRequest().getSession();
IAmsCustomerService amsCustomerService = new AmsCustomerService();
CrmUser crmUser = this.sessionManager.getCrmUser(session);
if (crmUser == null) {
request.setAttribute("errorMsg", LOGIN_MSG);
request.setAttribute("sessionErrorMsg", LOGIN_MSG);
return ERROR;
}
if (StringUtils.isBlank(this.sessionManager.getCredentials(session))) {
request.setAttribute("errorMsg", LOGIN_MSG);
request.setAttribute("sessionErrorMsg", LOGIN_MSG);
return ERROR;
}
String errorMsg = null;
try {
errorMsg = validateForm();
if (StringUtils.isBlank(errorMsg)) {
String encryptedPassword = EncryptionUtil.encodePassword(getPassword1(), "MD5");
crmUser.setPassword(encryptedPassword.toUpperCase());
int success = amsCustomerService.updateCrmUserLocally(crmUser);
if (success == 1) {
request.setAttribute("successMsg", "Your Password Has Been Updated Successfully! ");
return SUCCESS;
} else {
this.logger.error("Error Updating crmUser in Local DB. ");
errorMsg = "Unexpected error occur while updating your password, please try again.";
}
}
} catch (Exception ex) {
this.logger.error("Error, " + ex.getMessage());
errorMsg = "Unexpected error occur while updating your password, please try again.";
}
request.setAttribute("errorMsg", errorMsg);
return ERROR;
}
private String validateForm() {
return CustomerUtils.validatePasswords(getPassword1(), getPassword2());
}
public String getPassword1() {
return this.password1;
}
public void setPassword1(String password1) {
this.password1 = password1;
}
public String getPassword2() {
return this.password2;
}
public void setPassword2(String password2) {
this.password2 = password2;
}
}
Save the Date when the link expires along with the link / link key. When the user tries to change his password using that link, check that the expiry date is in the future.

Overlap of data of List in synchronized block

I have a method:
private List<String> userCns = Collections.synchronizedList(new ArrayList<String>());
private List<String> recipients = Collections.synchronizedList(new ArrayList<String>());
public void sendEmailToLegalUsers() {
try {
synchronized (lock) {
searchGroup();
if(userCns.size() > 0) {
for(String userCn : userCns) {
String mail = getUserMail(userCn);
if(mail != null) {
recipients.add(mail);
}
}
}
String docName = m_binder.getLocal("docname");
String docId = m_binder.getLocal("docid");
String url = m_binder.getLocal("serverURL");
if(recipients.size() > 0) {
m_binder.addResultSet("LOI_EVIN_MAIL", getLoiEvinMailResultSet(docName, docId, url));
for(String recipient : recipients) {
Log.info("Sending mail to: " + recipient);
InternetFunctions.sendMailToEx(recipient, "MH_LOI_EVIN_SEND_EMAIL", "Update Evin Law Compliance for the item: " + docName, m_service, true);
}
}
}
} catch (Exception e) {
Log.info("Error occurred in LDAPSendMail: "+ e.getMessage());
}
}
Now this sendEmailToLegalUsers method can be called from different threads. I am wondering is it the right way to lock the code block so that there is no chances of data mixup in the list?
Edit: whole class:
package com.edifixio.ldapsendmail.handlers;
import intradoc.common.Log;
import intradoc.data.DataResultSet;
import intradoc.server.InternetFunctions;
import intradoc.server.ServiceHandler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
public class LDAPSendMail extends ServiceHandler {
private final Object lock = new Object();
private String ldapURL;
private String baseDN;
private String groupDN;
private String username;
private String password;
private DirContext context;
private List<String> userCns = Collections.synchronizedList(new ArrayList<String>());
private List<String> recipients = Collections.synchronizedList(new ArrayList<String>());
public void sendEmailToLegalUsers() {
try {
synchronized (lock) {
searchGroup();
if(userCns.size() > 0) {
for(String userCn : userCns) {
String mail = getUserMail(userCn);
if(mail != null) {
recipients.add(mail);
}
}
}
String docName = m_binder.getLocal("docname");
String docId = m_binder.getLocal("docid");
String url = m_binder.getLocal("serverURL");
if(recipients.size() > 0) {
m_binder.addResultSet("LOI_EVIN_MAIL", getLoiEvinMailResultSet(docName, docId, url));
for(String recipient : recipients) {
Log.info("Sending mail to: " + recipient);
InternetFunctions.sendMailToEx(recipient, "MH_LOI_EVIN_SEND_EMAIL", "Update Evin Law Compliance for the item: " + docName, m_service, true);
}
}
userCns.clear();
recipients.clear();
}
} catch (Exception e) {
Log.info("Error occurred in LDAPSendMail: "+ e.getMessage());
}
}
private String getUserMail(String userCn) throws NamingException {
NamingEnumeration<SearchResult> searchResults = getLdapDirContext().search(userCn, "(objectclass=person)", getSearchControls());
while (searchResults.hasMore()){
SearchResult searchResult = searchResults.next();
Attributes attributes = searchResult.getAttributes();
Attribute mail = null;
try {
mail = attributes.get("mail");
} catch (Exception e) {
mail = null;
}
if(mail != null) {
return (String)mail.get();
}
}
return null;
}
private void searchGroup() throws NamingException {
NamingEnumeration<SearchResult> searchResults = getLdapDirContext().search(groupDN, "(objectclass=groupOfUniqueNames)", getSearchControls());
String searchGroupCn = getCNForBrand(m_binder.getLocal("brandId"), m_binder.getLocal("brandName"));
while (searchResults.hasMore()) {
SearchResult searchResult = searchResults.next();
Attributes attributes = searchResult.getAttributes();
Attribute groupCn = null;
try {
groupCn = attributes.get("cn");
} catch (Exception e) {
groupCn = null;
}
if(groupCn != null) {
if(searchGroupCn.equals((String)groupCn.get())) {
Attribute uniqueMembers = attributes.get("uniqueMember");
for(int i = 0; i < uniqueMembers.size(); i++){
String uniqueMemberCN = (String) uniqueMembers.get(i);
userCns.add(uniqueMemberCN);
}
break;
}
}
}
}
private DirContext getLdapDirContext() throws NamingException {
if(context != null) {
return context;
}
ldapURL = m_binder.getLocal("ldapUrl");
baseDN = m_binder.getLocal("baseDN");
groupDN = new StringBuilder().append("ou=").append(getAccountGroup(m_binder.getLocal("account"))).append(",").append("ou=groups,").append(baseDN).toString();
username = m_binder.getLocal("username");
password = m_binder.getLocal("password");
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapURL);
environment.put(Context.SECURITY_PRINCIPAL, username);
environment.put(Context.SECURITY_CREDENTIALS, password);
context = new InitialDirContext(environment);
return context;
}
private SearchControls getSearchControls() {
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
return searchControls;
}
private String getCNForBrand(String brandId, String brandName) {
String[] brandIdSplittedArray = brandId.split("/");
return new StringBuilder().append(brandIdSplittedArray[0]).append("-").append(brandIdSplittedArray[1]).append("-").
append(brandIdSplittedArray[2]).append("-").append(brandName.replaceAll("\\s","")).append("-LU").toString();
}
private String getAccountGroup(String account) {
return account.split("/")[1];
}
private DataResultSet getLoiEvinMailResultSet(String docName, String docId, String url) {
DataResultSet resultSet = new DataResultSet(new String[]{"DOCNAME", "DOCID", "URL"});
Vector<String> vector = new Vector<String>();
vector.add(docName);
vector.add(docId);
vector.add(url);
resultSet.addRow(vector);
return resultSet;
}
}
What is lock? Are you using it elsewhere? Typically you want the synchronized blocks to be pretty small. If you're using lock everywhere as a general purpose lock then you might be stopping a thread from doing some useful work in a totally unrelated area (i.e., one where there is no contention for shared resources).
Second, does recipients really need to be an instance variable? It seems strange that you would keep adding emails to recipients without checking to see if that email already exists in the list. I can't see any code where you're clearing our recipients either. So that is a potential issue. If you are going to be building recipients from scratch every time, then just make it a local variable in the method. If you really need access to that data, you can always pull it out of userCns.
Once you make recipients a local variable, then you only need to synchronize by using userCns as a lock:
synchronized(userCns) {
...
}
edit: Your code shows that you only use recipients once, and that's inside the sendEmailToLegalUsers method. Another thing, as I pointed out, is that you never clear recipients so that's a bug in your code. Since you don't use recipients anywhere, make it a local variable to sendEmailToLEgalUsers. Also, just synchronize over userCns. You won't need to synchronize over recipients; you can create it inside the synchronized block.
I would do
private final List<String> userCns = new ArrayList<String>();
private final List<String> recipients = new ArrayList<String>();
with
synchronized(userCns) {
// as Vivin suggests.
}
you don't need an additional lock.

Categories

Resources