/*
* Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
*
*/
package org.wso2.carbon.business.messaging.salesforce.core.impl;
import java.rmi.RemoteException;
import org.wso2.carbon.business.messaging.salesforce.stub.*;
import org.wso2.carbon.business.messaging.salesforce.stub.fault.ExceptionCode;
import org.wso2.carbon.business.messaging.salesforce.stub.sobject.Account;
import org.wso2.carbon.business.messaging.salesforce.stub.sobject.Contact;
import org.wso2.carbon.business.messaging.salesforce.stub.sobject.SObject;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.business.messaging.salesforce.core.SalesforceProxy;
import org.wso2.carbon.business.messaging.salesforce.core.session.SalesforceSession;
import org.wso2.carbon.business.messaging.salesforce.core.session.SessionManager;
/**
* This provides the implementation for the Java API to call the Salesforce
* Proxy services.
*
* @see org.wso2.carbon.business.messaging.salesforce.core.SalesforceProxy
*/
public class SalesforceProxyImpl implements SalesforceProxy {
private static final Log log = LogFactory.getLog(SalesforceProxyImpl.class);
/**
* Holds the reference to the actual <code>SforceServiceStub</code> stub
*/
/**
* Holds the reference to the client repository configuration.
*/
private ConfigurationContext cfgCtx;
/**
* Holds the logged in state of the current user.
*/
private boolean loggedIn = false;
/**
* Holds the login information for the session.
*/
//private LoginResult loginResult;
private LoginResult loginResult;
private SalesforceSession bindingSession;
private static final int DEFAULT_QUERY_SIZE = 200;
/**
* Constructor to accept the client's configuration context.
*
* @param configurationContext the configuration context.
*/
public SalesforceProxyImpl(ConfigurationContext configurationContext) {
cfgCtx = configurationContext;
}
public SalesforceProxyImpl(ConfigurationContext configurationContext, SalesforceSession session) {
cfgCtx = configurationContext;
setBindingSession(session);
}
/**
* Method signature Create a set of new sObjects
*
* @param sObjects the set of objects to be created.
* @throws RemoteException Error in remote connection. connection failed
* @throws InvalidSObjectFault An invalid sObject in a describeSObject(), describeSObjects(),describeLayout(),
* describeDataCategoryGroups(), describeDataCategoryGroupStructures(), create(),
* update(), retrieve(), or query() call.
* @throws InvalidIdFault A specified ID was invalid in a setPassword() or resetPassword() call.
* @throws UnexpectedErrorFault An unexpected error occurred. The error is not associated with any other API fault.
* @throws InvalidFieldFault An invalid field in a retrieve() or query() call.
* :
*/
public SaveResult[] create(SObject[] sObjects) throws RemoteException, InvalidSObjectFault,
InvalidIdFault, UnexpectedErrorFault,
InvalidFieldFault {
if (loggedIn) {
SaveResult[] results = null;
try {
SalesforceSession session = SessionManager.getManager().getSalesforceSession(getBindingSession().getId());
SforceServiceStub binding = null;
SessionHeader sh;
QueryResult qr;
if (session != null) {
synchronized (session) {
//check if not removed already
if (SessionManager.getManager().getSalesforceSession(session.getId()) != null) {
binding = createAuthServiceInstance(session.getAuthSalsesforceSession());
sh = getAuthHeader(session.getAuthSalsesforceSession());
results = binding.create(sObjects, sh, null, null, null, null, null, null, null);
} else {
//session removed/expired
//TODO handle this ? retry / ignore
return null;
}
}
} else {
//session removed/expired
//TODO handle this ? retry / ignore
}
} catch (InvalidSObjectFault e) {
if (log.isDebugEnabled()) {
log.debug("Invalid object exceptionSaveResult[ encountered:\n\n" + e.getMessage());
}
} catch (UnexpectedErrorFault e) {
if (log.isDebugEnabled()) {
log.debug("Unexpected error exception encountered:\n\n" + e.getMessage());
}
} catch (InvalidIdFault e) {
if (log.isDebugEnabled()) {
log.debug("Invalid Id exception encountered:\n\n" + e.getMessage());
}
} catch (RemoteException e) {
if (log.isDebugEnabled()) {
log.debug("Remote exception encountered:\n\n" + e.getMessage());
}
}
return results;
}
return null;
}
/**
* This method is reponsible for creating an Account Collection on salesforce.com
*
* @param sObjects account objects to be created
* @return objects representing resut of create operation
* @throws RemoteException Error in remote connection. connection failed
* @throws InvalidSObjectFault An invalid sObject in a describeSObject(), describeSObjects(),describeLayout(),
* describeDataCategoryGroups(), describeDataCategoryGroupStructures(), create(),
* update(), retrieve(), or query() call.
* @throws InvalidIdFault A specified ID was invalid in a setPassword() or resetPassword() call.
* @throws UnexpectedErrorFault An unexpected error occurred. The error is not associated with any other API fault.
* @throws InvalidFieldFault An invalid field in a retrieve() or query() call.
*/
public SaveResult[] createAccount(Account[] sObjects) throws RemoteException, InvalidSObjectFault,
InvalidIdFault, UnexpectedErrorFault,
InvalidFieldFault {
return create(sObjects);
}
/**
* Method signature Create a Query Cursor
*
* @param queryString the query string to execute salesforce.com query.
* @throws com.sforce.soap.enterprise.MalformedQueryFault
* A problem in the queryString passed in a query() call.
* @throws RemoteException Error in remote connection. connection failed
* @throws InvalidSObjectFault An invalid sObject in a describeSObject(), describeSObjects(),describeLayout(),
* describeDataCategoryGroups(), describeDataCategoryGroupStructures(), create(),
* update(), retrieve(), or query() call.
* @throws com.sforce.soap.enterprise.InvalidFieldFault
* An invalid field in a retrieve() or query() call.
* @throws com.sforce.soap.enterprise.UnexpectedErrorFault
* An unexpected error occurred. The error is not associated with any other API fault.
*/
public QueryResult query(String queryString) throws RemoteException, InvalidSObjectFault,
MalformedQueryFault, InvalidFieldFault,
UnexpectedErrorFault, InvalidIdFault,
InvalidQueryLocatorFault {
if (loggedIn) {
try {
SalesforceSession session = SessionManager.getManager().getSalesforceSession(getBindingSession().getId());
SforceServiceStub binding = null;
SessionHeader sh = null;
QueryOptions qo = null;
QueryResult qr = null;
if (session != null) {
synchronized (session) {
//check if not removed already
if (SessionManager.getManager().getSalesforceSession(session.getId()) != null) {
binding = createAuthServiceInstance(session.getAuthSalsesforceSession());
sh = getAuthHeader(session.getAuthSalsesforceSession());
qo = new QueryOptions();
qo.setBatchSize(DEFAULT_QUERY_SIZE);
qr = binding.query(queryString, sh, qo, null, null);
} else {
return null;
}
}
} else {
//TODO handle this ? retry / ignore
}
// QueryResult qr = binding.query("select FirstName, LastName from Contact", sh, qo,
// null, null);
if (log.isDebugEnabled()) {
if (qr.getSize() > 0) {
log.debug("Logged in user can see " + qr.getRecords().length +
" contact records. ");
do {
for (int i = 0; i < qr.getRecords().length; i++) {
Contact con = (Contact) qr.getRecords()[i];
String fName = con.getFirstName();
String lName = con.getLastName();
String msgStr;
if (fName == null) {
msgStr = "Contact " + (i + 1) + ": " + lName;
log.debug(msgStr);
} else {
msgStr = "Contact " + (i + 1) + ": " + fName + " " + lName;
log.debug(msgStr);
}
}
if (!qr.getDone()) {
qr = binding.queryMore(qr.getQueryLocator(), sh, qo);
} else {
break;
}
} while (qr.getSize() > 0);
} else {
log.debug("No records found.");
}
}
if (log.isDebugEnabled()) {
log.debug("Query succesfully executed....");
}
return qr;
}
catch (RemoteException ex) {
log.debug("\nFailed to execute query succesfully, error message was:" +
"\n" + ex.getMessage());
checkSessionValidity(ex);
}
catch (UnexpectedErrorFault unexpectedErrorFault) {
unexpectedErrorFault.printStackTrace();
checkSessionValidity(unexpectedErrorFault);
return null;
} catch (InvalidSObjectFault invalidSObjectFault) {
invalidSObjectFault.printStackTrace();
return null;
} catch (InvalidIdFault invalidIdFault) {
invalidIdFault.printStackTrace();
return null;
} catch (InvalidQueryLocatorFault invalidQueryLocatorFault) {
invalidQueryLocatorFault.printStackTrace();
return null;
} catch (InvalidFieldFault invalidFieldFault) {
invalidFieldFault.printStackTrace();
return null;
} catch (MalformedQueryFault malformedQueryFault) {
malformedQueryFault.printStackTrace();
return null;
}
}
return null;
}
private boolean checkSessionValidity(Exception ex) {
boolean isSessionInvalid = false;
ExceptionCode exCode = ExceptionCode.Factory.fromValue(ex.getMessage());
if (exCode == ExceptionCode.INVALID_SESSION_ID) {
removeSession();
isSessionInvalid = true;
}
return isSessionInvalid;
}
/**
* @return logout success or not
* @throws UnexpectedErrorFault
* @throws RemoteException
*/
public boolean logout() throws UnexpectedErrorFault, RemoteException {
try {
SalesforceSession session = SessionManager.getManager().getSalesforceSession(getBindingSession().getId());
SforceServiceStub binding = null;
SessionHeader sh;
if (session != null) {
synchronized (session) {
//check if not removed already
if (SessionManager.getManager().getSalesforceSession(session.getId()) != null) {
binding = createAuthServiceInstance(session.getAuthSalsesforceSession());
sh = getAuthHeader(session.getAuthSalsesforceSession());
binding.logout(sh);
removeSession();
} else {
return false;
}
}
} else {
//TODO handle this ? retry / ignore
}
if (log.isDebugEnabled()) {
log.debug("Logout Success");
}
} catch (AxisFault axisFault) {
if (log.isErrorEnabled()) {
log.error("Logout Error", axisFault);
}
return false;
} catch (RemoteException e) {
if (log.isErrorEnabled()) {
log.error("Logout Error", e);
}
return false;
} catch (UnexpectedErrorFault unexpectedErrorFault) {
if (log.isErrorEnabled()) {
log.error("Logout Error", unexpectedErrorFault);
}
return false;
}
loggedIn = false;
return true;
}
/**
* @param username the username to login to the salesforce account.
* @param password the password to login to the salesforce account.
* @return
*/
public boolean login(String username, String password) {
loginResult = null;
SforceServiceStub binding = null;
try {
//check globally available sessions
SalesforceSession session = SessionManager.createNewSession(username, password, cfgCtx);
//check if oldSession exist
SalesforceSession oldSession = SessionManager.getManager().getSalesforceSession(session.getId());
if (oldSession != null) {
synchronized (oldSession) {
//check if sessions has been removed
if (SessionManager.getManager().getSalesforceSession(oldSession.getId()) != null) {
setBindingSession(oldSession);
loginWithSession(oldSession);
} else {
//if already removed use new session
SessionManager.getManager().addSalesforceSession(session.getId(), session);
synchronized (session) {
setBindingSession(session);
loginWithSession(session);
}
}
}
} else {
SessionManager.getManager().addSalesforceSession(session.getId(), session);
synchronized (session) {
//new session
setBindingSession(session);
loginWithSession(session);
}
}
} catch (LoginFault ex) {
// The LoginFault derives from AxisFault
removeSession();
ExceptionCode exCode = ExceptionCode.Factory.fromValue(ex.getMessage());
if (exCode == ExceptionCode.FUNCTIONALITY_NOT_ENABLED ||
exCode == ExceptionCode.INVALID_CLIENT ||
exCode == ExceptionCode.INVALID_LOGIN ||
exCode == ExceptionCode.LOGIN_DURING_RESTRICTED_DOMAIN ||
exCode == ExceptionCode.LOGIN_DURING_RESTRICTED_TIME ||
exCode == ExceptionCode.ORG_LOCKED ||
exCode == ExceptionCode.PASSWORD_LOCKOUT ||
exCode == ExceptionCode.SERVER_UNAVAILABLE ||
exCode == ExceptionCode.TRIAL_EXPIRED ||
exCode == ExceptionCode.UNSUPPORTED_CLIENT) {
if (log.isDebugEnabled()) {
log.debug("Please be sure that you have a valid username " +
"and password.");
}
} else {
if (log.isDebugEnabled()) {
// Write the fault code to the console
log.debug(ex.getMessage());
// Write the fault message to the console
log.debug("An unexpected error has occurred." + ex.getMessage());
}
}
loggedIn = false;
return loggedIn;
} catch (Exception ex) {
//remove and cleanup session info
removeSession();
if (log.isDebugEnabled()) {
log.debug("An unexpected error has occurred: " + ex.getMessage());
}
ex.printStackTrace();
loggedIn = false;
return loggedIn;
}
// Check if the password has expired
if (loginResult.getPasswordExpired()) {
if (log.isDebugEnabled()) {
log.debug("An error has occurred. Your password has expired.");
}
loggedIn = false;
return loggedIn;
}
if (log.isDebugEnabled()) {
//System.out.println("Login was successful.");
log.info("Salesforce.com API Login was successful.");
log.debug("\nThe session id is: " + loginResult.getSessionId());
log.debug("\nThe new server url is: " + loginResult.getServerUrl());
}
loggedIn = true;
return loggedIn;
}
private void loginWithSession(SalesforceSession currentSession) throws RemoteException, InvalidIdFault, UnexpectedErrorFault, LoginFault {
SforceServiceStub binding;
String username = currentSession.getUsername();
String password = currentSession.getPassword();
//skip login if authenticated Salesforce session is present
if (currentSession.getAuthSalsesforceSession() == null) {
// get binding object
binding = (SforceServiceStub) new SforceServiceStub();
LoginResult loginSession = binding.login(username, password, null);
currentSession.setUsername(username);
currentSession.setPassword(password);
currentSession.setAuthSalsesforceSession(loginSession);
}
}
public GetUserInfoResult getUserInfo() {
if (loggedIn) {
GetUserInfoResult userInfo = null;
try {
SalesforceSession session = SessionManager.getManager().getSalesforceSession(getBindingSession().getId());
SforceServiceStub binding = null;
SessionHeader sh;
if (session != null) {
synchronized (session) {
//check if not removed already
if (SessionManager.getManager().getSalesforceSession(session.getId()) != null) {
binding = createAuthServiceInstance(session.getAuthSalsesforceSession());
sh = getAuthHeader(session.getAuthSalsesforceSession());
userInfo = binding.getUserInfo(sh);
} else {
return null;
}
}
} else {
//TODO handle this ? retry / ignore
}
if (log.isDebugEnabled()) {
log.debug("user Info :" + userInfo.getUserFullName());
}
} catch (AxisFault axisFault) {
if (log.isErrorEnabled()) {
log.error("Logout Error", axisFault);
}
} catch (RemoteException e) {
if (log.isErrorEnabled()) {
log.error("Logout Error", e);
}
} catch (UnexpectedErrorFault unexpectedErrorFault) {
if (log.isErrorEnabled()) {
log.error("Logout Error", unexpectedErrorFault);
}
}
return userInfo;
}
return null;
}
private SforceServiceStub createAuthServiceInstance(LoginResult loginInfo) throws
AxisFault {
SforceServiceStub binding = null;
binding = (SforceServiceStub) new SforceServiceStub(loginInfo.getServerUrl());
return binding;
}
private SessionHeader getAuthHeader(LoginResult loginInfo) {
SessionHeader sh = new SessionHeader();
sh.setSessionId(loginInfo.getSessionId());
return sh;
}
public void setLoginState(boolean loginState) {
loggedIn = loginState;
}
public void setAuthSalesforceSession(LoginResult authResult) {
loginResult = authResult;
}
public LoginResult getAuthSalesforceSession() {
return loginResult;
}
public SalesforceSession getBindingSession() {
return bindingSession;
}
public void setBindingSession(SalesforceSession bindingSession) {
this.bindingSession = bindingSession;
}
private void removeSession() {
SalesforceSession bindedSession = SessionManager.getManager().getSalesforceSession(getBindingSession().getId());
if (bindedSession != null) {
synchronized (bindedSession) {
SessionManager.getManager().removeSession(bindedSession.getId());
loggedIn = false;
loginResult = null;
setBindingSession(null);
}
}
}
}