/*******************************************************************************
$Source: /cvs/repositories/openii3/project/java/examples/org/openeai/portlets/SelfServiceBasicPerson.java,v $
$Revision: 1.6 $
*******************************************************************************/
/**********************************************************************
This file is part of the OpenEAI sample, reference implementation,
and deployment management suite created by Tod Jackson
(tod@openeai.org) and Steve Wheat (steve@openeai.org) at
the University of Illinois Urbana-Champaign.
Copyright (C) 2002-2006 The OpenEAI Software Foundation
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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
For specific licensing details and examples of how this software
can be used to implement integrations for your enterprise, visit
http://www.OpenEai.org/licensing.
*/
package org.openeai.portlets;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.security.Principal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletConfig;
import javax.portlet.PortletException;
import javax.portlet.PortletRequest;
import javax.portlet.PortletURL;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.any_openeai_enterprise.moa.jmsobjects.coreapplication.v1_0.EnterpriseUser;
import org.any_openeai_enterprise.moa.jmsobjects.coreapplication.v1_0.EnterpriseUserPassword;
import org.any_openeai_enterprise.moa.jmsobjects.coreapplication.v1_0.NetId;
import org.any_openeai_enterprise.moa.objects.resources.v1_0.LightweightPerson;
import org.any_openeai_enterprise.moa.objects.resources.v1_0.Password;
import org.apache.log4j.Category;
import org.apache.log4j.PropertyConfigurator;
import org.jdom.Document;
import org.jdom.Element;
import org.openeai.config.AppConfig;
import org.openeai.config.EnterpriseConfigurationObjectException;
import org.openeai.config.EnterpriseFieldException;
import org.openeai.config.LoggerConfig;
import org.openeai.jms.producer.PointToPointProducer;
import org.openeai.moa.EnterpriseObjectCreateException;
import org.openeai.moa.EnterpriseObjectQueryException;
import org.openeai.moa.EnterpriseObjectUpdateException;
import org.openeai.moa.XmlEnterpriseObjectException;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.any_erp_vendor.moa.jmsobjects.person.v1_0.BasicPerson;
import com.any_erp_vendor.moa.objects.resources.v1_0.Address;
import com.any_erp_vendor.moa.objects.resources.v1_0.Email;
import com.any_erp_vendor.moa.objects.resources.v1_0.Name;
import com.any_erp_vendor.moa.objects.resources.v1_0.Phone;
/**
* <p>
* SelfServiceBasicPerson is a portlet that is used to change the portal user's BasicPerson information
* in the sample enterprise. It also makes use of EnterpriseUser and EnterpriseUserPassword messages to create all
* three messages for the portal use if any do not exist. The SelfServiceBasicPerson is also a generator
* of all the messages needed to link the portal user to all the integrated applications and services
* of the sample enterprise.
* </p>
* <p>
* It is designed to JSR-168 portlet spec to be independent of portlet containers.
* </p>
* <p>
* SelfServiceBasicPerson uses the OpenEAI framework and needs to be supplied with a deployment document. A
* properties file must also be supplied that contains the location of the deployment document. The name location
* of the properties file is specified in the portlet deployment doc, portlet.xml.
* </p>
* @author tcerven *
*/
public class SelfServiceBasicPerson extends GenericPortlet {
private Category logger;
private AppConfig appConfig;
private PointToPointProducer p2p;
private String viewXSL;
private String portletName;
/**
* <code>BASIC_PERSON</code> uses MessageObjectConfig with name="BasicPerson.v1_0".
*/
static final String BASIC_PERSON = "BasicPerson.v1_0";
/**
* <code>ENTERPRISE_USER</code> uses MessageObjectConfig with name="EnterpriseUser.v1_0".
*/
static final String ENTERPRISE_USER = "EnterpriseUser.v1_0";
/**
* <code>LIGHTWEIGHT_PERSON</code> uses MessageObjectConfig with name="LightweightPerson.v1_0".
*/
static final String LIGHTWEIGHT_PERSON = "LightweightPerson.v1_0";
/**
* <code>NET_ID</code> uses MessageObjectConfig with name="NetId".
*/
static final String NET_ID = "NetId";
/**
* <code>ENTERPRISE_USER_PASSWORD</code> uses MessageObjectConfig with name="EnterpriseUserPassword.v1_0".
*/
static final String ENTERPRISE_USER_PASSWORD="EnterpriseUserPassword.v1_0";
/**
* <code>SELF_SERVICE_PRODUCER</code> uses ProducerConfig with name="SelfServicePortletProducer".
*/
static final String SELF_SERVICE_PRODUCER = "SelfServicePortletProducer";
/**
* <code>createBasicPersonIfNotFound</code> is located in the portlet's deployment doc, portlet.xml. If this value
* is false or not present, SelfServicePortlet will not try to create the BasicPerson (and EnterpriseUser and
* EnterpriseUserPassword) object for the portal user if it doesn't exist. If true, the portlet will attempt to
* the object if it doesn't exist.
*/
private boolean createBasicPersonIfNotFound=false;
/**
* <code>eoValues</code> contains Enterprise Object values for address and phone and email types and state
* names and abbreviations.
*/
private Element eoValues=null;
/**
* <code>nameSpace</code> is the name space used for the response message.
*/
static final String nameSpace = "http://openeai.org/examples/SelfServicePortlet";
/**
* Initializes various objects needed by the portlet.
* <p>
* <ol>
* <li>
* Reads the location of the stylesheet used to translate the XML output from the portlet
* into an HTML fragment for the portal. This parameter is stored in the portlet's descriptor, portlet.xml,
* as an init-param.
* </li>
* <li>
* Reads the location of the properties file used by the OpenEAI framework to initalize an AppConfig. This
* parameter is al stored in the portlet's descriptor, portlet.xml,
* as an init-param.
* </li>
* <li>
* Creates lists of address, email and phone types as well as state names from the EO docs.
* </li>
* </p>
* @param config PortletConfig object
* @see javax.portlet.Portlet#init(javax.portlet.PortletConfig)
*/
public void init(PortletConfig config) throws PortletException {
super.init(config);
portletName = config.getPortletName();
/* get location of stylesheet */
viewXSL = config.getInitParameter("viewXSL");
if (!(viewXSL.indexOf(File.pathSeparator)==1 || viewXSL.indexOf(":")==2)) {
viewXSL = config.getPortletContext().getRealPath("/")+config.getInitParameter("viewXSL");
}
// Get the path to the properties file.
String propertyFilePath=config.getInitParameter("propertyFilePath");
if (!(propertyFilePath.indexOf(File.pathSeparator)==1 || propertyFilePath.indexOf(":")==2)) {
propertyFilePath=config.getPortletContext().getRealPath("/")+config.getInitParameter("propertyFilePath");
}
// Load the initial properties from the properties file.
Properties initProps = new Properties();
try {
InputStream in = new FileInputStream(propertyFilePath);
initProps.load(in);
in.close();
}
catch (FileNotFoundException fnfe) {
String errMsg = "["+portletName+"] Initial properties file not " +
"found. The exception is: " + fnfe.getMessage();
throw new PortletException(errMsg);
}
catch (IOException ioe) {
String errMsg = "["+portletName+"] Error loading initial " +
"properties from the properties file. The exception is: " +
ioe.getMessage();
throw new PortletException(errMsg);
}
// Initialize an AppConfig using the initial properties.
appConfig = null;
try {
appConfig = new AppConfig(initProps);
}
catch (EnterpriseConfigurationObjectException ecoe) {
String errMsg = "["+portletName+"] Error initializing AppConfig. " +
"The exception is: " + ecoe.getMessage();
throw new PortletException(errMsg);
}
// Get the logger from AppConfig.
try {
LoggerConfig lConfig = new LoggerConfig();
lConfig = (LoggerConfig)appConfig.getObjectByType(lConfig.getClass()
.getName());
logger = Category.getInstance("org.openeai.SelfService.SelfServiceProducer");
PropertyConfigurator.configure(lConfig.getProperties());
}
catch (Exception e) {
logger = org.openeai.OpenEaiObject.logger;
}
// Get the producer from AppConfig.
try {
p2p = (PointToPointProducer) appConfig.getObject(SELF_SERVICE_PRODUCER);
logger.info("p2p is "+p2p.getClass());
} catch (EnterpriseConfigurationObjectException e) {
String errMsg = "["+portletName+"] Error configuring "+SELF_SERVICE_PRODUCER+": " +
"The exception is: " + e.getMessage();
logger.error(errMsg);
throw new PortletException(errMsg);
}
// Get the value of createBasicPersonIfNotFound
createBasicPersonIfNotFound = Boolean.valueOf(
config.getInitParameter("createBasicPersonIfNotFound"))
.booleanValue();
logger.info("["+portletName+"] createBasicPersonIfNotFound="+createBasicPersonIfNotFound);
logger.info("["+portletName+"] ViewXSL="+viewXSL);
/* create element with eo values for BP (states, address types, phone types, email types) */
/* State values */
List stateList=getStates();
logger.info("["+portletName+"] stateList="+stateList);
eoValues = new Element("EoValues","",nameSpace);
if (stateList!=null) {
Element stateElements = new Element("States","",nameSpace);
Iterator i = stateList.iterator();
while (i.hasNext()) {
Element stateName = new Element("StateName","",nameSpace);
stateName.addContent((String)i.next());
stateElements.addContent(stateName);
}
eoValues.addContent(stateElements);
}
/* Address Type values */
List addressTypeList=getAddressTypes();
logger.info("["+portletName+"] addressTypeList="+addressTypeList);
if (addressTypeList!=null) {
Element addressTypeElements = new Element("AddressTypes","",nameSpace);
Iterator i = addressTypeList.iterator();
while (i.hasNext()) {
Element addressType = new Element("AddressType","",nameSpace);
addressType.addContent((String)i.next());
addressTypeElements.addContent(addressType);
}
eoValues.addContent(addressTypeElements);
}
/* Phone Type values */
List phoneTypeList=getPhoneTypes();
logger.info("["+portletName+"] phoneTypeList="+phoneTypeList);
if (phoneTypeList!=null) {
Element phoneTypeElements = new Element("PhoneTypes","",nameSpace);
Iterator i = phoneTypeList.iterator();
while (i.hasNext()) {
Element phoneType = new Element("PhoneType","",nameSpace);
phoneType.addContent((String)i.next());
phoneTypeElements.addContent(phoneType);
}
eoValues.addContent(phoneTypeElements);
}
/* Phone Type values */
List emailTypeList=getEmailTypes();
logger.info("["+portletName+"] emailTypeList="+emailTypeList);
if (emailTypeList!=null) {
Element emailTypeElements = new Element("EmailTypes","",nameSpace);
Iterator i = emailTypeList.iterator();
while (i.hasNext()) {
Element emailType = new Element("EmailType","",nameSpace);
emailType.addContent((String)i.next());
emailTypeElements.addContent(emailType);
}
eoValues.addContent(emailTypeElements);
}
}
/**
* Creates a list of state names from the EO doc (See AddressEO.xml)
* @return List containing state names
*/
private List getStates() {
ArrayList states = new ArrayList();
try {
BasicPerson bPerson =
(BasicPerson)appConfig.getObject(BASIC_PERSON);
// state drop downs
java.util.HashMap hm = bPerson.getEnterpriseFields().getFieldsForObject("Address");
org.openeai.config.Field stateField = (org.openeai.config.Field)hm.get("StateOrProvince");
org.openeai.config.EnterpriseTranslator et = stateField.getFormatter().getTranslator();
java.util.Enumeration keys = et.getMappings().keys();
while (keys.hasMoreElements()) {
String fieldName = (String)keys.nextElement();
logger.info("Field name: " + fieldName);
java.util.List l = (java.util.List)et.getMappings().get(fieldName);
for (int i=0; i<l.size(); i++) {
org.openeai.config.EnterpriseMapping em = (org.openeai.config.EnterpriseMapping)l.get(i);
states.add(em.getEnterpriseValue());
logger.info("em.getEnterpriseValue()="+em.getEnterpriseValue());
}
}
} catch (Exception e) {
logger.fatal(e.getMessage(),e);
states=null;
}
return states;
}
/**
* Creates a list of email types from the EO doc (See EmailEO.xml)
* @return List containing email types
*/
private List getEmailTypes() {
ArrayList emailTypes = new ArrayList();
BasicPerson bPerson=null;
try {
bPerson = (BasicPerson)appConfig.getObject(BASIC_PERSON);
java.util.HashMap hm3 = bPerson.getEnterpriseFields().getFieldsForObject("Email");
org.openeai.config.Field emailTypeField = (org.openeai.config.Field)hm3.get("Type");
org.openeai.config.EnterpriseTranslator et4 = emailTypeField.getFormatter().getTranslator();
java.util.Enumeration keys4 = et4.getMappings().keys();
while (keys4.hasMoreElements()) {
String fieldName = (String)keys4.nextElement();
org.openeai.OpenEaiObject.logger.info("Field name: " + fieldName);
java.util.List l = (java.util.List)et4.getMappings().get(fieldName);
for (int i=0; i<l.size(); i++) {
org.openeai.config.EnterpriseMapping em = (org.openeai.config.EnterpriseMapping)l.get(i);
emailTypes.add(em.getEnterpriseValue());
}
}
} catch (EnterpriseConfigurationObjectException e) {
e.printStackTrace();
emailTypes=null;
}
return emailTypes;
}
/**
* Creates a list of phone types from the EO doc (See PhoneEO.xml).
* @return List containing phone types
*/
private List getPhoneTypes() {
ArrayList phoneTypes = new ArrayList();
BasicPerson bPerson=null;
try {
bPerson = (BasicPerson)appConfig.getObject(BASIC_PERSON);
java.util.HashMap hm2 = bPerson.getEnterpriseFields().getFieldsForObject("Phone");
org.openeai.config.Field phoneTypeField = (org.openeai.config.Field)hm2.get("Type");
org.openeai.config.EnterpriseTranslator et3 = phoneTypeField.getFormatter().getTranslator();
java.util.Enumeration keys3 = et3.getMappings().keys();
while (keys3.hasMoreElements()) {
String fieldName = (String)keys3.nextElement();
org.openeai.OpenEaiObject.logger.info("Field name: " + fieldName);
java.util.List l = (java.util.List)et3.getMappings().get(fieldName);
for (int i=0; i<l.size(); i++) {
org.openeai.config.EnterpriseMapping em = (org.openeai.config.EnterpriseMapping)l.get(i);
phoneTypes.add(em.getEnterpriseValue());
}
}
} catch (EnterpriseConfigurationObjectException e) {
e.printStackTrace();
phoneTypes=null;
}
return phoneTypes;
}
/**
* Creates a list of address types from the EO doc (See AddressEO.xml).
* @return List containing phone types
*/
private List getAddressTypes() {
ArrayList addressTypes = new ArrayList();
BasicPerson bPerson=null;
try {
bPerson = (BasicPerson)appConfig.getObject(BASIC_PERSON);
java.util.HashMap hm = bPerson.getEnterpriseFields().getFieldsForObject("Address");
org.openeai.config.Field addressTypeField = (org.openeai.config.Field)hm.get("Type");
org.openeai.config.EnterpriseTranslator et3 = addressTypeField.getFormatter().getTranslator();
java.util.Enumeration keys3 = et3.getMappings().keys();
while (keys3.hasMoreElements()) {
String fieldName = (String)keys3.nextElement();
org.openeai.OpenEaiObject.logger.info("Field name: " + fieldName);
java.util.List l = (java.util.List)et3.getMappings().get(fieldName);
for (int i=0; i<l.size(); i++) {
org.openeai.config.EnterpriseMapping em = (org.openeai.config.EnterpriseMapping)l.get(i);
addressTypes.add(em.getEnterpriseValue());
}
}
} catch (EnterpriseConfigurationObjectException e) {
e.printStackTrace();
addressTypes=null;
}
return addressTypes;
}
/**
* Processes requests to update BasicPerson information for the portal user.
* <p>
* The BasicPerson object contains a lot of stuff and it all has to be stored in the
* PortletRequest object as parameters. This is straight-forward for non-repeating fields like LastName
* and Gender. For segments that can repeat, like Address, Phone, and Email there are many ways to
* encode the values.
* </p>
* <p>
* SelfServiceBasicPerson expects an object (segment) to be encoded so that each field in a repeating segment
* occupies the same place in an array. The request parameter name of the array is created by the segment+"."+field.
* For instance, the Phone object contains the fields, Type, AreaCode and Number. Thus, the name of the array
* that holds the Type field is "phone.type". The other request parameter names for the other fields of the
* Phone object are "phone.areacode" and "phone.number".
* </p>
* <p>
* The request.getParameterValues(paramName) method is used to extract the fields from the request and build
* the segments of the BasicPerson object. It expects that the first element of each array belongs to a field
* of the first repeating segment. So the first Phone object gets its Type from the phone.type[0], its
* Area Code from phone.areacode[0] and Number from phone.number[0]. In general, the "ith" repeating segment<br>
* <code>
* SegmentObject.Field = SegmentName.FieldName[i-1]
* </code>
* </p>
* <p>
* SelfServiceBasicPerson uses the following request parameters:
* </p>
* <h2>Request Parameters</h2>
* <table>
* <thead>
* <tr>
* <th align="left">Name</th>
* <th align="left">Type</th>
* <th align="left">Value</th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <td>'FirstName</td>
* <td>String</td>
* <td>First Name (tic is not typo)</td>
* </tr>
* <tr>
* <td>'MiddleName</td>
* <td>String</td>
* <td>Middle Name (tic is not typo)</td>
* </tr>
* <tr>
* <td>'LastName</td>
* <td>String</td>
* <td>Last Name (tic is not typo)</td>
* </tr>
* <tr>
* <td>Gender</td>
* <td>String</td>
* <td>Value constrained by EO doc</td>
* </tr>
* <tr>
* <th align="left" colspan="3">
* Address Object information contained in these arrays
* </th>
* </tr>
* <tr>
* <td>address.type</td>
* <td>String Array</td>
* <td>One Address Type for each address object (e.g. Local, Business)</td>
* </tr>
* <tr>
* <td>address.street</td>
* <td>String Array</td>
* <td>One Street address for each address object</td>
* </tr>
* <tr>
* <td>address.city</td>
* <td>String Array</td>
* <td>One City for each address object</td>
* </tr>
* <tr>
* <td>address.state</td>
* <td>String Array</td>
* <td>One State Name for each address object (e.g. Illinois, Pennsylvania)</td>
* </tr>
* <tr>
* <td>address.zip</td>
* <td>String Array</td>
* <td>One Zip Code for each address object</td>
* </tr>
* <tr>
* <tr>
* <td>address.effective</td>
* <td>String Array</td>
* <td>One Effective Date for each address object.</td>
* </tr>
* <tr>
* <th align="left" colspan="3">
* Phone Object information contained in these arrays
* </th>
* </tr>
* <tr>
* <td>phone.type</td>
* <td>String Array</td>
* <td>One Phone Type for each phone object (e.g. Home, Office)</td>
* </tr>
* <tr>
* <td>phone.areacode</td>
* <td>String Array</td>
* <td>One Area Code for each phone object.</td>
* </tr>
* <tr>
* <td>phone.number</td>
* <td>String Array</td>
* <td>One Number for each phone object.</td>
* </tr>
* <tr>
* <th align="left" colspan="3">
* Email Object information contained in these arrays
* </th>
* </tr>
* <tr>
* <td>email.type</td>
* <td>String Array</td>
* <td>One Email Type for each email object (e.g. SMTP, Other)</td>
* </tr>
* <tr>
* <td>email.status</td>
* <td>String Array</td>
* <td>One Status value for each email object (e.g. New, Active)</td>
* </tr>
* <tr>
* <td>email.preferred</td>
* <td>String Array</td>
* <td>One Preferred value for each email object (e.g. Yes, No)</td>
* </tr>
* <tr>
* <th align="left" colspan="3">
* Other request parameters
* </th>
* </tr>
* <tr>
* <td>UpdateBP</td>
* <td>String</td>
* <td>This has to exist (its value doesn't matter) or processAction() will ignore the request.</td>
* </tr>
* </tbody>
* </table>
* <p>
* The Baseline for the BasicPerson.Update-Request is stored by the doView() method as an attribute in the
* PortletSession named by the value of the BASIC_PERSON field of the SelfServiceBasicPerson class.
* </p>
* @param request contains all fields for BasicPerson. See above table.
* @param response where the output goes. Output is formatted as HTML fragment by XSLT stylesheet(viewXSL).
* @throws PortletException
* @see javax.portlet.Portlet#processAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse)
*/
public void processAction(ActionRequest request, ActionResponse response) throws PortletException {
logger.info("["+portletName+"] \n\nProcess Action Started.\n\n");
logger.info(request.getParameterMap());
// Why a tic mark (') before the name in the strings below?
// Interesting story. Has to do with the way the XSLT processor
// created the value for the local-name() function. Sometimes it would prepend a tic. Well,
// that behavior went away for unknown reasons but the tic mark is staying just in case it returns.
String firstName=request.getParameter("'FirstName");
String lastName=request.getParameter("'LastName");
String middleName=request.getParameter("'MiddleName");
if (middleName!=null && middleName.equals("")) {
middleName=null;
}
logger.info("["+portletName+"] FirstName="+firstName);
logger.info("["+portletName+"] LastName="+lastName);
String gender=request.getParameter("Gender");
logger.info("["+portletName+"] Gender="+gender);
String addressType[]=request.getParameterValues("address.type");
String addressStreet[]=request.getParameterValues("address.street");
String addressCity[]=request.getParameterValues("address.city");
String addressState[]=request.getParameterValues("address.state");
String addressZip[]=request.getParameterValues("address.zip");
String addressEffective[]=request.getParameterValues("address.effective");
String phoneType[]=request.getParameterValues("phone.type");
String phoneAreacode[]=request.getParameterValues("phone.areacode");
String phoneNumber[]=request.getParameterValues("phone.number");
String emailType[]=request.getParameterValues("email.type");
String emailStatus[]=request.getParameterValues("email.status");
String emailPreferred[]=request.getParameterValues("email.preferred");
String emailAddress[]=request.getParameterValues("email.address");
if (addressType!=null) {
logger.info("["+portletName+"] Number of addresses to process="+addressType.length);
} else {
logger.info("["+portletName+"] No addresses to process.");
}
if (phoneType!=null) {
logger.info("["+portletName+"] Number of phone to process="+phoneType.length);
} else {
logger.info("["+portletName+"] No phones to process.");
}
if (emailType!=null) {
logger.info("["+portletName+"] Number of emails to process="+emailType.length);
} else {
logger.info("["+portletName+"] No emails to process.");
}
String updateSubmitBP = request.getParameter("UpdateBP");
if (updateSubmitBP!=null) {
// doView() stores the baseline in the session object
BasicPerson bpBaseline = (BasicPerson) request.getPortletSession().getAttribute(BASIC_PERSON);
if (bpBaseline != null) {
try {
logger.info("["+portletName+"] Baseline:\n"+bpBaseline.toXmlString());
BasicPerson bp = (BasicPerson) bpBaseline.clone();
bp.setBaseline(bpBaseline);
Name name=bp.getName();
name.setLastName(lastName);
name.setFirstName(firstName);
name.setMiddleName(middleName);
bp.setName(name);
if (gender!=null) {
bp.setGender(gender);
}
List addressList = bp.getAddress();
addressList.clear();
if (addressType!=null) {
for (int i=0;i<addressType.length;i++) {
Address address=bp.newAddress();
address.setType(addressType[i]);
address.setStreet1(addressStreet[i]);
address.setCityOrLocality(addressCity[i]);
address.setStateOrProvince(addressState[i]);
address.setZipOrPostalCode(addressZip[i]);
address.setEffectiveDate(toDate("EffectiveDate",addressEffective[i]));
addressList.add(address);
}
bp.setAddress(addressList);
}
List phoneList = bp.getPhone();
phoneList.clear();
if (phoneType!=null) {
for (int i=0;i<phoneType.length;i++) {
Phone phone=bp.newPhone();
phone.setType(phoneType[i]);
phone.setPhoneArea(phoneAreacode[i]);
phone.setPhoneNumber(phoneNumber[i]);
phoneList.add(phone);
}
bp.setPhone(phoneList);
}
List emailList = bp.getEmail();
emailList.clear();
if (emailType!=null) {
for (int i=0;i<emailType.length;i++) {
Email email=bp.newEmail();
email.setType(emailType[i]);
email.setEmailAddress(emailAddress[i]);
email.setStatus(emailStatus[i]);
email.setPreferred(emailPreferred[i]);
emailList.add(email);
}
bp.setEmail(emailList);
}
bp.update(p2p);
response.setRenderParameter("actionMessage","Update successful.");
} catch (XmlEnterpriseObjectException e) {
e.printStackTrace();
throw new PortletException("XmlEnterpriseObjectException");
} catch (CloneNotSupportedException e) {
e.printStackTrace();
throw new PortletException("CloneNotSupportedException");
} catch (EnterpriseObjectUpdateException e) {
response.setRenderParameter("actionMessage",e.getMessage());
} catch (EnterpriseFieldException e) {
response.setRenderParameter("actionMessage",e.getMessage());
} catch (ParseException e) {
response.setRenderParameter("actionMessage",e.getMessage());
e.printStackTrace();
}
} else {
throw new PortletException("Update requested with no baseline.");
}
}
}
/**
* Retrieves the BasicPerson object for the portal user. Returns output of transformation, viewXSL.
* <p>
* The InstitutionalId is the only value needed to retrieve the BasicPerson object for the portal
* user. SelfServiceBasicPerson assumes that the portal container will pass this value in the
* PortletRequest.USER_INFO map in a key named "user.id".
* </p><p>
* If the BasicPerson object doesn't exist for the user.id/InstitutionalId, doView() will create one.
* <em>This is unusual behavior since changes to the model (state) are usually confined to the
* processAction() method.</em>
* One other condition, <code>createBasicPerson</code>==true</code>, is also needed before a BasicPerson is
* created.
* </p><p>
* In addition to InstitutionalId, BasicPerson also requires a Name (both last and first) for the Create-Request.
* The portal container must provide these values in the PortletRequest.USER_INFO map in keys named
* "user.name.given" and "user.name.family". The portal container can also provide an email address in a key
* named "mail" but this is optional.
* </p><p>
* In addition to creating a BasicPerson object for the portal user, doView() also updates or creates
* EnterpriseUser and EnterpriseUserPassword objects for the portal user. EnterpriseUser requires a NetId
* which requires a Principal and Domain. Principal is obtained from the portlet contaner via the
* PortletRequest.getUserPrincipal() method. Domain is hard coded "any-openeai-enterprise.org".
* TODO: Parameterize domain.
* </p><p>
* EnterpriseUserPassword also requires a Password object. Ideally, the "value" attribute would equal the
* portal user's password but this is a TODO:. For now, this value is set to be the same as the Principal.
* </p><p>
* TODO: Create the BasicPerson, EnterpriseUser and EnterpriseUserPassword in processAction() rather than
* doView(). Implement a new flow to collect the password from the user on a new form. Hash it using
* the same algorithm as the portal (here's a portal dependency though) to verify it is the same password
* as the portal user so that the value of the EnterpriseUserPassword.Password will match that of the portal.
* </p>
* @see javax.portlet.GenericPortlet#doView(javax.portlet.RenderRequest, javax.portlet.RenderResponse)
*/
protected void doView (RenderRequest request, RenderResponse response)throws PortletException, IOException{
logger.debug("["+portletName+"] doView");
Map userInfo = (Map) request.getAttribute(PortletRequest.USER_INFO);
Principal p = request.getUserPrincipal();
PortletURL portletUrl = response.createActionURL();
PortletURL refreshUrl = response.createRenderURL();
logger.info("["+portletName+"] "+"principal="+p);
response.setContentType("text/html");
Writer out = response.getWriter();
// create a document to hold the response
Document data;
Element dataRoot;
dataRoot = new Element("SelfServiceResponse", "", nameSpace);
dataRoot.setAttribute("portletUrl",portletUrl.toString());
dataRoot.setAttribute("refrestUrl",refreshUrl.toString());
Date now=new Date();
dataRoot.setAttribute("timeStamp",now.toString());
String actionString = request.getParameter("actionMessage");
if (actionString!=null) {
Element actionMessage = new Element("ActionMessage","",nameSpace);
actionMessage.addContent(actionString);
dataRoot.addContent(actionMessage);
}
data = new Document(dataRoot);
String instID=(String)userInfo.get("user.id");
String firstName=(String)userInfo.get("user.name.given");
String lastName=(String)userInfo.get("user.name.family");
String email=(String)userInfo.get("mail");
// query for a BasicPerson
if (instID==null) {
dataRoot.addContent(
new Element("Error","",nameSpace)
.addContent("No User Id"));
} else {
try {
BasicPerson bp = getBasicPerson(instID);
if (bp!=null) {
dataRoot = makeResponseMessage(dataRoot,request,instID,"retrieved",bp);
} else {
// create the basic person if allowed
if (createBasicPersonIfNotFound) {
if (firstName==null || firstName.equals("")) {
dataRoot.addContent(
new Element("Error","",nameSpace)
.addContent("No first name found for User ID "+instID));
} else {
if (lastName==null || lastName.equals("")) {
dataRoot.addContent(
new Element("Error","",nameSpace)
.addContent("No last name found for User ID "+instID));
} else {
// create the basic person using id, first and last names
bp = createBasicPerson(instID, firstName, lastName, email);
if (bp!=null) {
dataRoot = makeResponseMessage(dataRoot,request,instID,"created",bp);
}
// create EnterpriseUserPassword
updateEnterpriseUserPassword(instID, request.getUserPrincipal().getName(), "any-openeai-enterprise.org", request.getUserPrincipal().getName());
}
}
} else {
dataRoot.addContent(
new Element("Error","",nameSpace)
.addContent("No BasicPerson found for User ID "+instID));
}
}
} catch (EnterpriseConfigurationObjectException ecoe) {
dataRoot.addContent(
new Element("Error","",nameSpace)
.addContent("EnterpriseConfigurationObjectException"));
} catch (EnterpriseFieldException efe) {
dataRoot.addContent(
new Element("Error","",nameSpace)
.addContent("EnterpriseFieldException"));
} catch (EnterpriseObjectQueryException eoqe) {
dataRoot.addContent(
new Element("Error","",nameSpace)
.addContent(new Element("EnterpriseObjectQueryException","",nameSpace)
.addContent(eoqe.getMessage())));
eoqe.printStackTrace();
} catch (XmlEnterpriseObjectException e) {
dataRoot.addContent(
new Element("Error","",nameSpace)
.addContent("XmlEnterpriseObjectException"));
} catch (IOException e) {
dataRoot.addContent(
new Element("Error","",nameSpace)
.addContent("IOException"));
} catch (EnterpriseObjectCreateException e) {
dataRoot.addContent(
new Element("Error","",nameSpace)
.addContent(new Element("EnterpriseObjectCreateException","",nameSpace)
.addContent(e.getMessage())));
e.printStackTrace();
} catch (EnterpriseObjectUpdateException e) {
dataRoot.addContent(
new Element("Error","",nameSpace)
.addContent(new Element("EnterpriseObjectUpdateException","",nameSpace)
.addContent(e.getMessage())));
e.printStackTrace();
}
}
// transform the xml to html
String outMsg=outXML(data);
logger.info("["+portletName+"] "+"presentation model:\n"+outMsg);
org.jdom.Document xmlResp = data;
if (xmlResp!=null){
try {
logger.info("["+portletName+"] "+"Attempting to transform...");
String s = outTransform(xmlResp, viewXSL);
out.write(s); // send output along to client
logger.info("["+portletName+"] "+"Transformation complete.");
} catch (TransformerConfigurationException e) {
logger.error("Transformer Configuration Error: "+e.toString());
response.setContentType("text/plain");
out.write("The transformation file, '"+viewXSL+"', can not be found.");
} catch (Exception e) {
logger.error("Error: "+e.toString());
} finally {
out.close();
}
} else {
//return output from servlet
logger.fatal("["+portletName+"] Can't create XML from presentation model.");
out.write("<p>Can't create XML from model.</p>"); // send output along to client
out.write("<p>"+outMsg+"</p>"); // send output along to client
out.close();
}
}
/**
* Creates an element that contains the presentation model of the response (i.e. before transformation). Also
* saves the BasicPerson object in a PortletSession attribute to be used a baseline for subsequent updates.
* @param dataRoot container element for the response
* @param request RenderRequest is needed to get the PortletSession to set the baseline attribute.
* @param instID the portal user's InstitutionalId
* @param method a string used by the transformation
* @param bp the baseline object
* @return the fully formed presentation message
* @throws IOException
* @throws XmlEnterpriseObjectException
*/
private Element makeResponseMessage(Element dataRoot, RenderRequest request, String instID, String method, BasicPerson bp) throws XmlEnterpriseObjectException, IOException {
Element success=new Element("Success","",nameSpace);
success.setAttribute("userId",instID);
success.setAttribute("method",method);
Document bpDoc = makeDoc(bp.toXmlString());
success.addContent((Element)bpDoc.getRootElement().clone());
success.addContent(eoValues.cloneContent());
dataRoot.addContent(success);
request.getPortletSession().setAttribute(BASIC_PERSON,bp);
return dataRoot;
}
/**
* Creates a BasicPerson object for the portal user
* @param instID InstitutionalId of the user
* @param firstName
* @param lastName
* @param email optional email style address.
* @return the newly created BasicPerson object
* @throws EnterpriseConfigurationObjectException
* @throws EnterpriseFieldException
* @throws EnterpriseObjectCreateException
*/
private BasicPerson createBasicPerson(String instID, String firstName, String lastName, String email) throws EnterpriseConfigurationObjectException, EnterpriseFieldException, EnterpriseObjectCreateException {
BasicPerson aeo = (BasicPerson)appConfig.getObject(BASIC_PERSON);
logger.info("["+portletName+"] Got " + BASIC_PERSON + " from AppConfig, performing Create...");
Name aName = aeo.newName();
aName.setFirstName(firstName);
aName.setLastName(lastName);
aeo.setName(aName);
aeo.setInstitutionalId(instID);
if (!"".equals(email)) {
Email e = aeo.newEmail();
e.setEmailAddress(email);
e.setStatus("Active");
e.setType("SMTP");
e.setPreferred("No");
aeo.setEmail(0,e);
logger.info("["+portletName+"] Email address set to " + email + ".");
}
logger.info("["+portletName+"] Creating "+ BASIC_PERSON + " for user ("+instID+") "+firstName+" "+lastName+"...");
aeo.create(p2p);
logger.info("["+portletName+"] "+BASIC_PERSON + " created.");
return aeo;
}
/**
* Retrieves the portal user's BasicPerson object
* @param instId
* @return the BasicPerson object or null if it doesn't exist.
* @throws EnterpriseConfigurationObjectException
* @throws EnterpriseFieldException
* @throws EnterpriseObjectQueryException
*/
private BasicPerson getBasicPerson(String instId) throws EnterpriseConfigurationObjectException, EnterpriseFieldException, EnterpriseObjectQueryException {
LightweightPerson lPerson =
(LightweightPerson)appConfig.getObject(LIGHTWEIGHT_PERSON);
logger.info("["+portletName+"] Got LightweightPerson...");
lPerson.setInstitutionalId(instId);
logger.info("["+portletName+"] Set instid on lightweight person...");
BasicPerson aeo = (BasicPerson)appConfig.getObject(BASIC_PERSON);
logger.info("["+portletName+"] Got " + BASIC_PERSON + " from AppConfig, performing Query...");
java.util.List a = aeo.query(lPerson, p2p);
logger.info("["+portletName+"] Executed Query...");
StringBuffer results = new StringBuffer();
if (a.size() == 0) {
logger.info("["+portletName+"] No rows found matching the query.");
return null;
}
else {
BasicPerson bp = (BasicPerson)a.get(0);
return bp;
}
}
/**
* Creates or updates the EnterpriseUser and EnterpriseUserPassword for the portal user.
* @param instID
* @param principal
* @param domain
* @param newPassword
* @return the portal user's EnterpriseUserPassword
* @throws EnterpriseConfigurationObjectException
* @throws EnterpriseFieldException
* @throws EnterpriseObjectCreateException
* @throws EnterpriseObjectQueryException
* @throws EnterpriseObjectQueryException
* @throws EnterpriseObjectUpdateException
*/
private EnterpriseUserPassword updateEnterpriseUserPassword(String instID, String principal, String domain, String newPassword)
throws EnterpriseConfigurationObjectException, EnterpriseFieldException,
EnterpriseObjectCreateException, EnterpriseObjectQueryException, EnterpriseObjectUpdateException {
EnterpriseUser eu = (EnterpriseUser)appConfig.getObject(ENTERPRISE_USER);
logger.info("["+portletName+"] Got " + ENTERPRISE_USER + " from AppConfig, performing Query...");
NetId netId = eu.newNetId();
logger.info("["+portletName+"] Got NetId...");
netId.setPrincipal(principal);
netId.setDomain(domain);
LightweightPerson lPerson = eu.newLightweightPerson();
logger.info("["+portletName+"] Got LightweightPerson...");
lPerson.setInstitutionalId(instID);
logger.info("["+portletName+"] Set instid on lightweight person...");
eu.setLightweightPerson(lPerson);
eu.addNetId(netId);
List euQueryList = eu.query(netId,p2p);
if (euQueryList.size()==0) {
//create the enterprise user
eu.create(p2p);
logger.info("["+portletName+"] Created EnterpriseUser for "
+principal+"@"+domain+"("+instID+")");
} else {
eu = (EnterpriseUser) euQueryList.get(0);
logger.info("["+portletName+"] Found EnterpriseUser: " + eu);
}
EnterpriseUserPassword eup=(EnterpriseUserPassword)appConfig.getObject(ENTERPRISE_USER_PASSWORD);
eup.setEnterpriseUser(eu);
Password p = eup.newPassword();
p.setValue(newPassword);
p.setType("secure credential");
p.setEncryption("cleartext");
java.util.List returnedEup = eup.query(eu, p2p);
if (returnedEup.size() == 0) {
//create the password
eup.setPassword(p);
eup.create(p2p);
logger.info("["+portletName+"] Created the EntepriseUserPassword");
return eup;
} else {
//update the password
EnterpriseUserPassword baselineEup = (EnterpriseUserPassword) returnedEup.get(0);
logger.info("["+portletName+"] baseline="+baselineEup);
eup.setBaseline(baselineEup);
eup.setPassword(p);
eup.update(p2p);
return eup;
}
}
/**
* Creates a Document from a string source.
* @param sXml
* @return document equvalent to string source.
* @throws IOException
*/
private org.jdom.Document makeDoc(String sXml) throws IOException {
org.jdom.Document jdomDoc=null;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource(new StringReader(sXml));
org.w3c.dom.Document doc = db.parse(is);
//convert to jdom
org.jdom.input.DOMBuilder jdomBuilder = new org.jdom.input.DOMBuilder();
jdomDoc = jdomBuilder.build(doc);
//convert to string
org.jdom.DocType dt = null;
jdomDoc.setDocType(dt);
} catch (ParserConfigurationException pce) {
logger.warn("[makeDoc] ParserConfigurationException: " + pce.getMessage());
} catch (SAXException saxe) {
logger.warn("[makeDoc] SAXException: " + saxe.getMessage());
} catch (IOException ioe) {
logger.warn("[makeDoc] IOException: " + ioe.getMessage());
}
return jdomDoc;
}
/**
* <p>Performs a transformation on a document.
* Uses xalan. Sends output to specified destination.<p>
*
* @param doc the jdom document to transform
* @param xslName the FQN of the the file that contains the
* transformation stylesheet.
* @param out the destination for the results of the transformation.
* @exception Throws up all exceptions.
*/
private String outTransform(org.jdom.Document doc, String xslName) throws Exception {
try {
TransformerFactory tFactory = TransformerFactory.newInstance();
logger.debug("[outTransform] xslName="+xslName);
Templates templates = tFactory.newTemplates(new StreamSource(xslName));
Transformer transformer = templates.newTransformer();
String contentType = null;
String docstring = outXML(doc);
StringWriter out = new StringWriter();
transformer.transform(new StreamSource(new StringReader(docstring)),
new StreamResult(out));
return out.toString();
}
catch (Exception e) {
throw e;
}
}
/**
* Creates a string from a Document
* @param doc the source document
* @return string equvalent to doucment source
*/
private String outXML(org.jdom.Document doc) {
StringWriter sw=new StringWriter();
try {
org.jdom.output.XMLOutputter outputter = new org.jdom.output.XMLOutputter();
outputter.output(doc, sw);
}
catch (Exception e) {
if (e!=null) e.printStackTrace();
}
return new String(sw.getBuffer());
}
/**
* Creates a com.any_erp_vendor.moa.objects.resources.v1_0.Date given a string in mm/dd/yyyy format and
* a name for the date.
* @param name the name of the date (e.g. BirthDate)
* @param sDate the string containing the date to use
* @return com.any_erp_vendor.moa.objects.resources.v1_0.Date representation of the date from the string.
* @throws ParseException
* @throws EnterpriseFieldException
*/
private com.any_erp_vendor.moa.objects.resources.v1_0.Date toDate(String name, String sDate) throws ParseException, EnterpriseFieldException {
SimpleDateFormat formatter = new SimpleDateFormat( "MM/dd/yyyy" );
com.any_erp_vendor.moa.objects.resources.v1_0.Date aDate=null;
if (sDate != null && sDate.length() > 0) {
java.util.Date d = formatter.parse(sDate);
Calendar calendar = new GregorianCalendar();
calendar.setTime(d);
com.any_erp_vendor.moa.objects.resources.v1_0.Date bDate = new com.any_erp_vendor.moa.objects.resources.v1_0.Date(name);
bDate.setMonth(Integer.toString(calendar.get(Calendar.MONTH)+1));
bDate.setDay(Integer.toString(calendar.get(Calendar.DAY_OF_MONTH)));
bDate.setYear(Integer.toString(calendar.get(Calendar.YEAR)));
aDate=bDate;
}
return aDate;
}
}