001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.portal.profile.impl;
018:
019: import java.util.ArrayList;
020: import java.util.Collection;
021: import java.util.HashMap;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.Map;
025:
026: import org.apache.avalon.framework.CascadingRuntimeException;
027: import org.apache.avalon.framework.activity.Disposable;
028: import org.apache.avalon.framework.activity.Initializable;
029: import org.apache.avalon.framework.container.ContainerUtil;
030: import org.apache.avalon.framework.context.Context;
031: import org.apache.avalon.framework.context.ContextException;
032: import org.apache.avalon.framework.context.Contextualizable;
033: import org.apache.avalon.framework.parameters.ParameterException;
034: import org.apache.avalon.framework.parameters.Parameterizable;
035: import org.apache.avalon.framework.parameters.Parameters;
036: import org.apache.avalon.framework.service.ServiceException;
037: import org.apache.avalon.framework.service.ServiceManager;
038: import org.apache.avalon.framework.service.ServiceSelector;
039: import org.apache.cocoon.ProcessingException;
040: import org.apache.cocoon.components.variables.VariableResolver;
041: import org.apache.cocoon.components.variables.VariableResolverFactory;
042: import org.apache.cocoon.portal.PortalService;
043: import org.apache.cocoon.portal.coplet.CopletData;
044: import org.apache.cocoon.portal.coplet.CopletFactory;
045: import org.apache.cocoon.portal.coplet.CopletInstanceData;
046: import org.apache.cocoon.portal.coplet.adapter.CopletAdapter;
047: import org.apache.cocoon.portal.layout.Layout;
048: import org.apache.cocoon.portal.profile.PortalUser;
049: import org.apache.cocoon.portal.profile.ProfileLS;
050: import org.apache.cocoon.sitemap.PatternException;
051: import org.apache.cocoon.util.ClassUtils;
052: import org.apache.commons.collections.map.LinkedMap;
053: import org.apache.commons.lang.exception.ExceptionUtils;
054: import org.apache.excalibur.source.SourceNotFoundException;
055: import org.apache.excalibur.source.SourceValidity;
056:
057: /**
058: * @version CVS $Id: SiteProfileManager.java 603493 2007-12-12 07:09:43Z cziegeler $
059: */
060: public class SiteProfileManager extends AbstractProfileManager
061: implements Parameterizable, Contextualizable, Initializable,
062: Disposable {
063:
064: public static final String CATEGORY_GLOBAL = "global";
065:
066: protected static final class ProfileInfo {
067: public Map objects;
068: public SourceValidity validity;
069: }
070:
071: protected ProfileInfo copletBaseDatas;
072: protected ProfileInfo copletDatas;
073:
074: /** The userinfo provider - the connection to the authentication mechanism */
075: protected UserInfoProvider provider;
076:
077: /** The class name of the userinfo provider */
078: protected String userInfoProviderClassName;
079:
080: /** The component context */
081: protected Context context;
082:
083: /** The per site profiles. */
084: protected final Map profiles = new HashMap();
085:
086: /** Site expression to detect the current site. */
087: protected String siteExpression;
088:
089: /** Variable resolver factory. */
090: protected VariableResolverFactory variableFactory;
091:
092: /** Variable resolver. */
093: protected VariableResolver variableResolver;
094:
095: /* (non-Javadoc)
096: * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
097: */
098: public void contextualize(Context context) throws ContextException {
099: this .context = context;
100: }
101:
102: /**
103: * @see org.apache.cocoon.portal.profile.impl.AbstractProfileManager#service(org.apache.avalon.framework.service.ServiceManager)
104: */
105: public void service(ServiceManager manager) throws ServiceException {
106: super .service(manager);
107: this .variableFactory = (VariableResolverFactory) this .manager
108: .lookup(VariableResolverFactory.ROLE);
109: }
110:
111: /* (non-Javadoc)
112: * @see org.apache.avalon.framework.parameters.Parameterizable#parameterize(org.apache.avalon.framework.parameters.Parameters)
113: */
114: public void parameterize(Parameters params)
115: throws ParameterException {
116: this .userInfoProviderClassName = params
117: .getParameter("userinfo-provider");
118: this .siteExpression = params.getParameter("site-expression");
119: }
120:
121: /* (non-Javadoc)
122: * @see org.apache.avalon.framework.activity.Initializable#initialize()
123: */
124: public void initialize() throws Exception {
125: this .provider = (UserInfoProvider) ClassUtils
126: .newInstance(this .userInfoProviderClassName);
127: ContainerUtil.enableLogging(this .provider, this .getLogger());
128: ContainerUtil.contextualize(this .provider, this .context);
129: ContainerUtil.service(this .provider, this .manager);
130: ContainerUtil.initialize(this .provider);
131: this .copletBaseDatas = new ProfileInfo();
132: this .copletDatas = new ProfileInfo();
133: this .variableResolver = this .variableFactory
134: .lookup(this .siteExpression);
135: }
136:
137: /* (non-Javadoc)
138: * @see org.apache.avalon.framework.activity.Disposable#dispose()
139: */
140: public void dispose() {
141: ContainerUtil.dispose(this .provider);
142: this .provider = null;
143: if (this .manager != null) {
144: if (this .variableFactory != null) {
145: this .variableFactory.release(this .variableResolver);
146: this .variableResolver = null;
147: }
148: this .manager.release(this .variableFactory);
149: this .variableFactory = null;
150: this .manager = null;
151: }
152: }
153:
154: protected String getSiteName() {
155: try {
156: return this .variableResolver.resolve();
157: } catch (PatternException e) {
158: throw new CascadingRuntimeException("Unvalid pattern "
159: + this .siteExpression, e);
160: }
161: }
162:
163: protected UserProfile getUserProfile(String layoutKey) {
164: if (layoutKey == null) {
165: PortalService service = null;
166: try {
167: service = (PortalService) this .manager
168: .lookup(PortalService.ROLE);
169: layoutKey = service.getDefaultLayoutKey();
170:
171: } catch (ServiceException e) {
172: // this should never happen
173: throw new CascadingRuntimeException(
174: "Unable to lookup portal service.", e);
175: } finally {
176: this .manager.release(service);
177: }
178: }
179: final String siteKey = this .getSiteName() + ':' + layoutKey;
180: synchronized (this .profiles) {
181: final UserProfileInfo info = (UserProfileInfo) this .profiles
182: .get(siteKey);
183: if (info != null && info.profile != null) {
184: return info.profile;
185: }
186: }
187: return null;
188: }
189:
190: /**
191: * Prepares the object by using the specified factory.
192: */
193: protected void prepareObject(Object object, PortalService service)
194: throws ProcessingException {
195: if (object != null) {
196: if (object instanceof Map) {
197: object = ((Map) object).values();
198: }
199: if (object instanceof Layout) {
200: service.getComponentManager().getLayoutFactory()
201: .prepareLayout((Layout) object);
202: } else if (object instanceof Collection) {
203: ServiceSelector adapterSelector = null;
204: try {
205: final CopletFactory copletFactory = service
206: .getComponentManager().getCopletFactory();
207: final Iterator iterator = ((Collection) object)
208: .iterator();
209: while (iterator.hasNext()) {
210: final Object o = iterator.next();
211: if (o instanceof CopletData) {
212: copletFactory.prepare((CopletData) o);
213: } else if (o instanceof CopletInstanceData) {
214: if (adapterSelector == null) {
215: adapterSelector = (ServiceSelector) this .manager
216: .lookup(CopletAdapter.ROLE
217: + "Selector");
218: }
219: CopletInstanceData cid = (CopletInstanceData) o;
220: copletFactory.prepare(cid);
221: // now invoke login on each instance
222: CopletAdapter adapter = null;
223: try {
224: adapter = (CopletAdapter) adapterSelector
225: .select(cid.getCopletData()
226: .getCopletBaseData()
227: .getCopletAdapterName());
228: adapter.login(cid);
229: } finally {
230: adapterSelector.release(adapter);
231: }
232: }
233: }
234: } catch (ServiceException se) {
235: // this should never happen
236: throw new ProcessingException(
237: "Unable to get component.", se);
238: } finally {
239: this .manager.release(adapterSelector);
240: }
241: }
242: }
243: }
244:
245: /* (non-Javadoc)
246: * @see org.apache.cocoon.portal.profile.ProfileManager#login()
247: */
248: public void login() {
249: super .login();
250: try {
251: this .loadProfile(null);
252: } catch (Exception e) {
253: throw new CascadingRuntimeException(
254: "Unable to load new user profile.", e);
255: }
256: }
257:
258: /* (non-Javadoc)
259: * @see org.apache.cocoon.portal.profile.ProfileManager#getCopletInstanceData(java.lang.String)
260: */
261: public CopletInstanceData getCopletInstanceData(String copletID) {
262: final UserProfile profile = this .getUserProfile(null);
263: if (profile != null) {
264: return (CopletInstanceData) profile
265: .getCopletInstanceDatas().get(copletID);
266: }
267: return null;
268: }
269:
270: /* (non-Javadoc)
271: * @see org.apache.cocoon.portal.profile.ProfileManager#getCopletData(java.lang.String)
272: */
273: public CopletData getCopletData(String copletDataId) {
274: final UserProfile profile = this .getUserProfile(null);
275: if (profile != null) {
276: return (CopletData) profile.getCopletDatas().get(
277: copletDataId);
278: }
279: return null;
280: }
281:
282: /* (non-Javadoc)
283: * @see org.apache.cocoon.portal.profile.ProfileManager#getCopletInstanceData(org.apache.cocoon.portal.coplet.CopletData)
284: */
285: public List getCopletInstanceData(CopletData data) {
286: final UserProfile profile = this .getUserProfile(null);
287: final List coplets = new ArrayList();
288: if (profile != null) {
289: final Iterator iter = profile.getCopletInstanceDatas()
290: .values().iterator();
291: while (iter.hasNext()) {
292: final CopletInstanceData current = (CopletInstanceData) iter
293: .next();
294: if (current.getCopletData().equals(data)) {
295: coplets.add(current);
296: }
297: }
298: }
299: return coplets;
300: }
301:
302: /* (non-Javadoc)
303: * @see org.apache.cocoon.portal.profile.ProfileManager#register(org.apache.cocoon.portal.coplet.CopletInstanceData)
304: */
305: public void register(CopletInstanceData coplet) {
306: final UserProfile profile = this .getUserProfile(null);
307: profile.getCopletInstanceDatas().put(coplet.getId(), coplet);
308: }
309:
310: /* (non-Javadoc)
311: * @see org.apache.cocoon.portal.profile.ProfileManager#unregister(org.apache.cocoon.portal.coplet.CopletInstanceData)
312: */
313: public void unregister(CopletInstanceData coplet) {
314: final UserProfile profile = this .getUserProfile(null);
315: profile.getCopletInstanceDatas().remove(coplet.getId());
316: }
317:
318: /* (non-Javadoc)
319: * @see org.apache.cocoon.portal.profile.ProfileManager#register(org.apache.cocoon.portal.layout.Layout)
320: */
321: public void register(Layout layout) {
322: if (layout != null && layout.getId() != null) {
323: final UserProfile profile = this .getUserProfile(null);
324: profile.getLayouts().put(layout.getId(), layout);
325: }
326: }
327:
328: /* (non-Javadoc)
329: * @see org.apache.cocoon.portal.profile.ProfileManager#unregister(org.apache.cocoon.portal.layout.Layout)
330: */
331: public void unregister(Layout layout) {
332: if (layout != null && layout.getId() != null) {
333: final UserProfile profile = this .getUserProfile(null);
334: profile.getLayouts().remove(layout.getId());
335: }
336: }
337:
338: /* (non-Javadoc)
339: * @see org.apache.cocoon.portal.profile.ProfileManager#getPortalLayout(java.lang.String, java.lang.String)
340: */
341: public Layout getPortalLayout(String layoutKey, String layoutId) {
342: PortalService service = null;
343:
344: try {
345: service = (PortalService) this .manager
346: .lookup(PortalService.ROLE);
347: if (null == layoutKey) {
348: layoutKey = service.getDefaultLayoutKey();
349: }
350:
351: UserProfile profile = this .getUserProfile(layoutKey);
352: if (profile == null) {
353: profile = this .loadProfile(layoutKey);
354: }
355: if (profile == null) {
356: throw new RuntimeException("Unable to load profile: "
357: + layoutKey);
358: }
359: if (layoutId != null) {
360: return (Layout) profile.getLayouts().get(layoutId);
361: }
362: return profile.getRootLayout();
363: } catch (Exception ce) {
364: throw new CascadingRuntimeException(
365: "Exception during loading of profile.", ce);
366: } finally {
367: this .manager.release(service);
368: }
369: }
370:
371: /* (non-Javadoc)
372: * @see org.apache.cocoon.portal.profile.ProfileManager#getCopletDatas()
373: */
374: public Collection getCopletDatas() {
375: final UserProfile profile = this .getUserProfile(null);
376: if (profile != null) {
377: return profile.getCopletDatas().values();
378: }
379: return null;
380: }
381:
382: /* (non-Javadoc)
383: * @see org.apache.cocoon.portal.profile.ProfileManager#getCopletInstanceDatas()
384: */
385: public Collection getCopletInstanceDatas() {
386: final UserProfile profile = this .getUserProfile(null);
387: if (profile != null) {
388: return profile.getCopletInstanceDatas().values();
389: }
390: return null;
391: }
392:
393: /**
394: * Load the profile
395: */
396: protected UserProfile loadProfile(final String layoutKey)
397: throws Exception {
398: PortalService service = null;
399: try {
400: service = (PortalService) this .manager
401: .lookup(PortalService.ROLE);
402: final String siteKey = this .getSiteName()
403: + ':'
404: + (layoutKey == null ? service
405: .getDefaultLayoutKey() : layoutKey);
406:
407: // access on profiles is synchronized
408: UserProfileInfo storedProfile;
409: synchronized (this .profiles) {
410: storedProfile = (UserProfileInfo) this .profiles
411: .get(siteKey);
412: if (storedProfile == null) {
413: storedProfile = new UserProfileInfo();
414: this .profiles.put(siteKey, storedProfile);
415: }
416: }
417: // now synchronize on per site profile
418: synchronized (storedProfile) {
419: final UserInfo info = this .provider.getUserInfo(service
420: .getPortalName(), layoutKey == null ? service
421: .getDefaultLayoutKey() : layoutKey);
422: ProfileLS loader = null;
423: try {
424: loader = (ProfileLS) this .manager
425: .lookup(ProfileLS.ROLE);
426:
427: this .getSiteProfile(loader, info, service,
428: storedProfile);
429: } catch (ServiceException se) {
430: throw new CascadingRuntimeException(
431: "Unable to get profilels.", se);
432: } finally {
433: this .manager.release(loader);
434: }
435: return storedProfile.profile;
436: }
437: } catch (ServiceException se) {
438: // this can never happen
439: throw new CascadingRuntimeException(
440: "Unable to lookup portal service.", se);
441: } finally {
442: this .manager.release(service);
443: }
444: }
445:
446: protected Map getGlobalBaseDatas(final ProfileLS loader,
447: final UserInfo info, final PortalService service)
448: throws Exception {
449: final Map key = this .buildKey(CATEGORY_GLOBAL,
450: ProfileLS.PROFILETYPE_COPLETBASEDATA, info, true);
451: final Map parameters = new HashMap();
452: parameters.put(ProfileLS.PARAMETER_PROFILETYPE,
453: ProfileLS.PROFILETYPE_COPLETBASEDATA);
454:
455: synchronized (this ) {
456: if (this .copletBaseDatas.validity != null
457: && this .copletBaseDatas.validity.isValid() == SourceValidity.VALID) {
458: return this .copletBaseDatas.objects;
459: }
460: final SourceValidity newValidity = loader.getValidity(key,
461: parameters);
462: if (this .copletBaseDatas.validity != null
463: && newValidity != null
464: && this .copletBaseDatas.validity
465: .isValid(newValidity) == SourceValidity.VALID) {
466: return this .copletBaseDatas.objects;
467: }
468: this .copletBaseDatas.objects = ((CopletBaseDataManager) loader
469: .loadProfile(key, parameters)).getCopletBaseData();
470: this .copletBaseDatas.validity = newValidity;
471: this .copletDatas.objects = null;
472: this .copletDatas.validity = null;
473: this .prepareObject(this .copletBaseDatas.objects, service);
474: return this .copletBaseDatas.objects;
475: }
476: }
477:
478: protected Map getGlobalDatas(final ProfileLS loader,
479: final UserInfo info, final PortalService service,
480: final UserProfile profile) throws Exception {
481: final Map key = this .buildKey(CATEGORY_GLOBAL,
482: ProfileLS.PROFILETYPE_COPLETDATA, info, true);
483: final Map parameters = new HashMap();
484: parameters.put(ProfileLS.PARAMETER_PROFILETYPE,
485: ProfileLS.PROFILETYPE_COPLETDATA);
486: parameters.put(ProfileLS.PARAMETER_OBJECTMAP, profile
487: .getCopletBaseDatas());
488:
489: synchronized (this ) {
490:
491: if (this .copletDatas.validity != null
492: && this .copletDatas.validity.isValid() == SourceValidity.VALID) {
493: return this .copletDatas.objects;
494: }
495: final SourceValidity newValidity = loader.getValidity(key,
496: parameters);
497: if (this .copletDatas.validity != null
498: && newValidity != null
499: && this .copletDatas.validity.isValid(newValidity) == SourceValidity.VALID) {
500: return this .copletDatas.objects;
501: }
502: this .copletDatas.objects = ((CopletDataManager) loader
503: .loadProfile(key, parameters)).getCopletData();
504: this .copletDatas.validity = newValidity;
505: this .prepareObject(this .copletDatas.objects, service);
506: return this .copletDatas.objects;
507: }
508: }
509:
510: private boolean isSourceNotFoundException(Throwable t) {
511: while (t != null) {
512: if (t instanceof SourceNotFoundException) {
513: return true;
514: }
515: t = ExceptionUtils.getCause(t);
516: }
517: return false;
518: }
519:
520: protected void getSiteProfile(final ProfileLS loader,
521: final UserInfo info, final PortalService service,
522: final UserProfileInfo storedProfile) throws Exception {
523: // prepare keys and parameters first
524: final Map instanceKey = this .buildKey(CATEGORY_GLOBAL,
525: ProfileLS.PROFILETYPE_COPLETINSTANCEDATA, info, true);
526: final Map instanceParameters = new HashMap();
527: instanceParameters.put(ProfileLS.PARAMETER_PROFILETYPE,
528: ProfileLS.PROFILETYPE_COPLETINSTANCEDATA);
529: if (storedProfile.profile != null) {
530: instanceParameters.put(ProfileLS.PARAMETER_OBJECTMAP,
531: storedProfile.profile.getCopletDatas());
532: }
533:
534: final Map layoutKey = this .buildKey(CATEGORY_GLOBAL,
535: ProfileLS.PROFILETYPE_LAYOUT, info, true);
536: final Map layoutParameters = new HashMap();
537: layoutParameters.put(ProfileLS.PARAMETER_PROFILETYPE,
538: ProfileLS.PROFILETYPE_LAYOUT);
539: if (storedProfile.profile != null) {
540: layoutParameters.put(ProfileLS.PARAMETER_OBJECTMAP,
541: storedProfile.profile.getCopletInstanceDatas());
542: }
543:
544: boolean storedInstancesAreValid = false;
545: boolean storedLayoutsAreValid = false;
546:
547: // we'll check for coplet instance data first
548: if (storedProfile.profile != null) {
549: if (storedProfile.instanceValidity != null
550: && storedProfile.instanceValidity.isValid() == SourceValidity.VALID) {
551: storedInstancesAreValid = true;
552: } else {
553: final SourceValidity newValidity = loader.getValidity(
554: instanceKey, instanceParameters);
555: if (storedProfile.instanceValidity != null
556: && newValidity != null
557: && storedProfile.instanceValidity
558: .isValid(newValidity) == SourceValidity.VALID) {
559: storedInstancesAreValid = true;
560: }
561: }
562: }
563:
564: // now we check the layout
565: if (storedInstancesAreValid) {
566:
567: if (storedProfile.layoutValidity != null
568: && storedProfile.layoutValidity.isValid() == SourceValidity.VALID) {
569: storedLayoutsAreValid = true;
570: } else {
571: final SourceValidity newValidity = loader.getValidity(
572: layoutKey, layoutParameters);
573: if (storedProfile.layoutValidity != null
574: && newValidity != null
575: && storedProfile.layoutValidity
576: .isValid(newValidity) == SourceValidity.VALID) {
577: storedLayoutsAreValid = true;
578: }
579: }
580: }
581: if (!storedInstancesAreValid || !storedLayoutsAreValid) {
582: // we reload the whole profile
583: // update parameters
584: final UserProfile profile = new UserProfile();
585:
586: // first "load" the global data
587: profile.setCopletBaseDatas(this .getGlobalBaseDatas(loader,
588: info, service));
589: profile.setCopletDatas(this .getGlobalDatas(loader, info,
590: service, profile));
591:
592: SourceValidity instanceValidity = null;
593: SourceValidity layoutValidity = null;
594: // load instances
595: try {
596: // update parameters
597: instanceParameters.put(ProfileLS.PARAMETER_OBJECTMAP,
598: profile.getCopletDatas());
599:
600: instanceValidity = loader.getValidity(instanceKey,
601: instanceParameters);
602: final CopletInstanceDataManager cidm = (CopletInstanceDataManager) loader
603: .loadProfile(instanceKey, instanceParameters);
604: profile.setCopletInstanceDatas(cidm
605: .getCopletInstanceData());
606: this .prepareObject(profile.getCopletInstanceDatas(),
607: service);
608:
609: } catch (Exception e) {
610: if (!this .isSourceNotFoundException(e)) {
611: throw e;
612: }
613: throw new ProcessingException(
614: "No profile for coplet instance datas found.");
615: }
616:
617: // load layout
618:
619: try {
620: // update parameters
621: layoutParameters.put(ProfileLS.PARAMETER_OBJECTMAP,
622: profile.getCopletInstanceDatas());
623: layoutValidity = loader.getValidity(layoutKey,
624: layoutParameters);
625: final Layout l = (Layout) loader.loadProfile(layoutKey,
626: layoutParameters);
627: this .prepareObject(l, service);
628: profile.setRootLayout(l);
629:
630: } catch (Exception e) {
631: if (!this .isSourceNotFoundException(e)) {
632: throw e;
633: }
634: throw new ProcessingException(
635: "No profile for layout found.");
636: }
637: // everything fine: update stored profile - this will automatically have an effect on all logged in users!
638: storedProfile.instanceValidity = instanceValidity;
639: storedProfile.layoutValidity = layoutValidity;
640: storedProfile.profile = profile;
641: }
642: }
643:
644: protected Map buildKey(String category, String profileType,
645: UserInfo info, boolean load) {
646: final StringBuffer config = new StringBuffer(profileType);
647: config.append('-');
648: config.append(category);
649: config.append('-');
650: if (load) {
651: config.append("load");
652: } else {
653: config.append("save");
654: }
655: final String uri = (String) info.getConfigurations().get(
656: config.toString());
657:
658: final Map key = new LinkedMap(6);
659: key.put("baseuri", uri);
660: key.put("separator", "?");
661: key.put("portal", info.getPortalName());
662: key.put("layout", info.getLayoutKey());
663: key.put("type", category);
664: key.put("site", this .getSiteName());
665:
666: return key;
667: }
668:
669: /* (non-Javadoc)
670: * @see org.apache.cocoon.portal.profile.ProfileManager#storeProfile(org.apache.cocoon.portal.layout.Layout, java.lang.String)
671: */
672: public void storeProfile(Layout rootLayout, String layoutKey) {
673: // nothing to do
674: }
675:
676: /* (non-Javadoc)
677: * @see org.apache.cocoon.portal.profile.ProfileManager#getUser()
678: */
679: public PortalUser getUser() {
680: PortalService service = null;
681: try {
682: service = (PortalService) this .manager
683: .lookup(PortalService.ROLE);
684: final String layoutKey = service.getDefaultLayoutKey();
685: final UserInfo info = this .provider.getUserInfo(service
686: .getPortalName(), layoutKey);
687: return info;
688: } catch (Exception ce) {
689: throw new CascadingRuntimeException(
690: "Exception during getUser().", ce);
691: } finally {
692: this .manager.release(service);
693: }
694: }
695:
696: protected static final class UserProfileInfo {
697: public UserProfile profile;
698: public SourceValidity instanceValidity;
699: public SourceValidity layoutValidity;
700: }
701: }
|