KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jetspeed > services > profiler > JetspeedProfilerService


1 /*
2  * Copyright 2000-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.jetspeed.services.profiler;
18
19 //java.util
20
import java.util.Iterator JavaDoc;
21 import java.util.LinkedList JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Locale JavaDoc;
24 import java.util.Vector JavaDoc;
25
26 import javax.servlet.ServletConfig JavaDoc;
27
28 import org.apache.commons.lang.SerializationUtils;
29 import org.apache.jetspeed.capability.CapabilityMap;
30 import org.apache.jetspeed.capability.CapabilityMapFactory;
31 import org.apache.jetspeed.om.profile.BasePSMLDocument;
32 import org.apache.jetspeed.om.profile.Control;
33 import org.apache.jetspeed.om.profile.Controller;
34 import org.apache.jetspeed.om.profile.PSMLDocument;
35 import org.apache.jetspeed.om.profile.Portlets;
36 import org.apache.jetspeed.om.profile.Profile;
37 import org.apache.jetspeed.om.profile.ProfileException;
38 import org.apache.jetspeed.om.profile.ProfileLocator;
39 import org.apache.jetspeed.om.profile.QueryLocator;
40 import org.apache.jetspeed.om.profile.Skin;
41 import org.apache.jetspeed.om.profile.psml.PsmlControl;
42 import org.apache.jetspeed.om.profile.psml.PsmlController;
43 import org.apache.jetspeed.om.profile.psml.PsmlPortlets;
44 import org.apache.jetspeed.om.profile.psml.PsmlSkin;
45 import org.apache.jetspeed.om.security.Group;
46 import org.apache.jetspeed.om.security.GroupRole;
47 import org.apache.jetspeed.om.security.JetspeedUser;
48 import org.apache.jetspeed.om.security.Role;
49 import org.apache.jetspeed.services.JetspeedSecurity;
50 import org.apache.jetspeed.services.PortalToolkit;
51 import org.apache.jetspeed.services.Profiler;
52 import org.apache.jetspeed.services.PsmlManager;
53 import org.apache.jetspeed.services.ServiceHelper;
54 import org.apache.jetspeed.services.customlocalization.CustomLocalizationService;
55 import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
56 import org.apache.jetspeed.services.logging.JetspeedLogger;
57 import org.apache.jetspeed.services.rundata.JetspeedRunData;
58 import org.apache.jetspeed.util.MimeType;
59 import org.apache.jetspeed.util.ServiceUtil;
60 import org.apache.turbine.services.InitializationException;
61 import org.apache.turbine.services.TurbineBaseService;
62 import org.apache.turbine.services.TurbineServices;
63 import org.apache.turbine.services.localization.LocalizationService;
64 import org.apache.turbine.services.resources.ResourceService;
65 import org.apache.turbine.services.resources.TurbineResources;
66 import org.apache.turbine.util.DynamicURI;
67 import org.apache.turbine.util.RunData;
68 /**
69  * <p>This is an implementation of the <code>Profiler</code> interface.
70  *
71  * This implementation maps requests to profiles (PSML resources) based on
72  * request parameters, requesting deviced capabilities, and the device's
73  * language. </p>
74  * <p>This service expects these properties to be set for correct operation:
75  * <dl>
76  * <dt>root</dt><dd>The webapp rel. path to the root profiling directory</dd>
77  * <dt>resource.default</dt><dd>The default resource filename</dd>
78  * <dt>resource.ext</dt><dd>The default resource filename extension</dd>
79  * <dt>security</dt><dd>Use security flag</dd>
80  * <dt>fallback.language</dt><dd>Use language configuration flag</dd>
81  * <dt>fallback.country</dt><dd>Use country configuration flag</dd>
82  * <dt>fallback.to.root</dt><dd>Continue falling back past media type flag</dd>
83  *
84  * </dl>
85  * </p>
86  *
87  * @author <a HREF="mailto:david@bluesunrise.com">David Sean Taylor</a>
88  * @author <a HREF="mailto:sgala@hisitech.com">Santiago Gala</a>
89  * @author <a HREF="mailto:morciuch@apache.org">Mark Orciuch</a>
90  * @version $Id: JetspeedProfilerService.java,v 1.56 2004/02/23 03:35:24 jford Exp $
91  */

92
93 public class JetspeedProfilerService extends TurbineBaseService
94     implements ProfilerService
95 {
96     /**
97      * Static initialization of the logger for this class
98      */

99     private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(JetspeedProfilerService.class.getName());
100     
101     // configuration keys
102
private final static String JavaDoc CONFIG_RESOURCE_DEFAULT = "resource.default";
103     private final static String JavaDoc CONFIG_RESOURCE_EXT = "resource.ext";
104     private final static String JavaDoc CONFIG_SECURITY = "security";
105     private final static String JavaDoc CONFIG_ROLE_FALLBACK = "rolefallback";
106     private final static String JavaDoc CONFIG_NEWUSER_TEMPLATE = "newuser.template";
107     private final static String JavaDoc CONFIG_NEWUSER_MEDIA = "newuser.media_types";
108     private final static String JavaDoc CONFIG_FALLBACK_LANGUAGE = "fallback.language";
109     private final static String JavaDoc CONFIG_FALLBACK_COUNTRY = "fallback.country";
110     private final static String JavaDoc CONFIG_FALLBACK_TO_ROOT = "fallback.to.root";
111     private final static String JavaDoc CONFIG_ROLE_MERGE = "rolemerge";
112     private final static String JavaDoc CONFIG_ROLE_MERGE_CONTROL = "rolemerge.control";
113     private final static String JavaDoc CONFIG_ROLE_MERGE_CONTROLLER = "rolemerge.controller";
114
115     // default configuration values
116
private final static String JavaDoc DEFAULT_CONFIG_RESOURCE_DEFAULT = "default";
117     private final static String JavaDoc DEFAULT_CONFIG_RESOURCE_EXT = ".psml";
118     private final static boolean DEFAULT_CONFIG_SECURITY = false;
119     private final static boolean DEFAULT_CONFIG_ROLE_FALLBACK = true;
120     private final static String JavaDoc DEFAULT_CONFIG_NEWUSER_TEMPLATE = null;
121     private final static String JavaDoc [] DEFAULT_CONFIG_NEWUSER_MEDIA =
122     { "html", "wml" };
123     private final static String JavaDoc DEFAULT_CONFIG_ROLE_MERGE_CONTROL = "TabControl";
124     private final static String JavaDoc DEFAULT_CONFIG_ROLE_MERGE_CONTROLLER = "TabController";
125
126     private final static String JavaDoc PATH_EXTENSION_DELIMITER = ".";
127     // messages
128
private final static String JavaDoc MSG_MISSING_PARAMETER =
129         "JetspeedProfilerService initialization failed. Missing parameter:";
130
131     // pluggable Locator and Profile classes
132
private Class JavaDoc profileClass = null;
133     private Class JavaDoc locatorClass = null;
134     
135
136     // configuration parameters
137
String JavaDoc root; // the root psml resource directory
138
String JavaDoc resourceDefault; // the default name for a resource
139
String JavaDoc resourceExt; // the default extension for a resource
140
String JavaDoc rolemergeControl; // the default control used with merged role profiles
141
String JavaDoc rolemergeController; // the default controller used with merged role profiles
142

143     // MODIFIED: A. Kempf
144
String JavaDoc newUserTemplate = DEFAULT_CONFIG_NEWUSER_TEMPLATE;
145
146     boolean useSecurity = false; // use security features
147
boolean useRoleFallback = true;
148     boolean useFallbackLanguage = true;
149     boolean useFallbackCountry = true;
150     boolean useFallbackToRoot = false;
151     boolean useRoleMerge = false;
152
153     String JavaDoc mediaTypes[] = null;
154
155     /**
156      * This methode creates a wml profile and a html profile
157      * for a new user
158      * --------------------------------------------------------------------------
159      * last modified: 10/31/01
160      * Andreas Kempf, Siemens ICM S CP PE, Munich
161      * mailto: A.Kempf@web.de
162      */

163     public Profile createProfile(RunData data, Profile profile)
164             throws ProfileException
165     {
166         Profile current = null;
167         CapabilityMap map;
168
169         if (data == null)
170         {
171             map = CapabilityMapFactory.getDefaultCapabilityMap();
172         }
173         else
174         {
175             map = ((JetspeedRunData)data).getCapability();
176         }
177         String JavaDoc mediaType = getMediaType(data, map);
178
179         // if template is null then use role-based psml
180
if (newUserTemplate == null)
181             return current;
182
183         if (mediaTypes != null)
184         {
185             Profile dummy;
186             for (int ix=0; ix < mediaTypes.length; ix++)
187             {
188                 dummy = createProfile(data, profile, mediaTypes[ix], newUserTemplate);
189                 if (mediaTypes[ix].equalsIgnoreCase(mediaType))
190                     current = dummy;
191             }
192         }
193         return current;
194     }
195
196     // --------------------------------------------------------------------------
197

198     /**
199      * This is the early initialization method called by the
200      * Turbine <code>Service</code> framework
201      * @param conf The <code>ServletConfig</code>
202      * @exception throws a <code>InitializationException</code> if the service
203      * fails to initialize
204      */

205     public synchronized void init(ServletConfig JavaDoc conf) throws InitializationException
206     {
207         
208         // already initialized
209
if (getInit()) return;
210
211         try
212         {
213             initConfiguration();
214         }
215         catch (Exception JavaDoc e)
216         {
217             logger.error("Profiler: Failed to load Service ", e);
218         }
219
220         // initialization done
221
setInit(true);
222
223      }
224
225     /**
226      * This is the shutdown method called by the
227      * Turbine <code>Service</code> framework
228      */

229     public void shutdown()
230     {
231     }
232
233     /**
234      * get the Profile object using the Rundata state and capability map
235      * this is the mapping functionality of the profiler
236      *
237      * @param rundata the rundata object for the current request
238      * @param cm the <code>CapabilityMap</code> of the current requesting device
239      * @return a new Profile object
240      */

241     public Profile getProfile(RunData data, CapabilityMap cm)
242         throws ProfileException
243     {
244         JetspeedRunData rundata = (JetspeedRunData)data;
245         Profile profile = fallbackProfile(rundata, cm);
246         if (null == profile && useRoleFallback)
247         {
248             Vector JavaDoc profiles = new Vector JavaDoc();
249             JetspeedUser user = rundata.getJetspeedUser();
250             if (user != null)
251             {
252                 try
253                 {
254                     String JavaDoc paramRole = rundata.getParameters().getString(Profiler.PARAM_ROLE);
255                     Iterator JavaDoc groupRoles = JetspeedSecurity.getRoles(user.getUserName());
256                     if (groupRoles != null)
257                     {
258                         while (groupRoles.hasNext())
259                         {
260                             // note: this is an unordered list. will need to change db schema to order it
261
GroupRole gr = (GroupRole) groupRoles.next();
262                             rundata.getParameters().setString( Profiler.PARAM_ROLE, gr.getRole().getName() );
263                             profile = fallbackProfile(rundata, cm);
264                             if (profile != null)
265                             {
266                                 profiles.add(profile);
267                             }
268                             rundata.getParameters().remove(Profiler.PARAM_ROLE);
269                         }
270                         profile = mergeRoleProfiles(data, profiles);
271
272                         // If something went wrong with merging, attempt another fallback
273
if (profile == null)
274                         {
275                             profile = fallbackProfile(rundata, cm);
276                         }
277                     }
278                     
279                     rundata.getParameters().setString(Profiler.PARAM_ROLE, paramRole);
280                 }
281                 catch (Exception JavaDoc e)
282                 {
283                     logger.error( "Error getting profile", e );
284                     throw new ProfileException(e.toString());
285                 }
286             }
287         }
288         return profile;
289     }
290
291     /**
292      * Merge role profiles to create default profile. Resulting psml will be a set of
293      * tabs. If role's psml is a tab control, each tab is placed in the resulting psml
294      * as is. Otherwise, a new tab is created and psml is placed there. In this case,
295      * tab name will be derived from role's name. For example, if role name is "news",
296      * the resulting profile name will be "News Home".
297      *
298      * @param data
299      * @param profiles Vector of profiles for all roles user is part of
300      * @return Merged profile
301      * @exception Exception
302      */

303     private Profile mergeRoleProfiles(RunData data, Vector JavaDoc profiles)
304         throws Exception JavaDoc
305     {
306         Profile result = null;
307         // If merge feature is not turned on, return
308
// profile for the first role (if any)
309
if (!this.useRoleMerge)
310         {
311             if (profiles.size() > 0)
312             {
313                 result = (Profile) profiles.get(0);
314             }
315         }
316         // Proceed with merging all profiles
317
else if (profiles.size() > 0)
318         {
319             try
320             {
321                 // Create an empty portlet container
322
Portlets portlets = new PsmlPortlets();
323                 Control control = new PsmlControl();
324                 control.setName(this.rolemergeControl);
325                 portlets.setControl(control);
326                 Controller controller = new PsmlController();
327                 controller.setName(this.rolemergeController);
328                 portlets.setController(controller);
329
330                 // Set the skin
331
Skin skin = new PsmlSkin();
332                 skin.setName(PortalToolkit.getSkin((String JavaDoc) null).getName());
333                 portlets.setSkin(skin);
334
335                 String JavaDoc mediaType = null;
336
337                 // Process each role profile
338
int paneCount = 0;
339                 for (Iterator JavaDoc it = profiles.iterator(); it.hasNext(); )
340                 {
341                     Profile roleProfile = (Profile)it.next();
342                     mediaType = mediaType == null ? roleProfile.getMediaType() : mediaType;
343                     Profile tmpProfile = (Profile) roleProfile.clone();
344                     Portlets tmpPortlets = tmpProfile.getDocument().getPortlets();
345
346                     // If topmost control is a tab control, then add each tab to the container
347
Control paneControl = tmpPortlets.getControl();
348                     if (paneControl != null && paneControl.getName().equals(this.rolemergeControl))
349                     {
350                         for (int i = 0; i < tmpPortlets.getPortletsCount(); i++)
351                         {
352                             Portlets pane = tmpPortlets.getPortlets(i);
353                             pane.setLayout(null);
354                             portlets.addPortlets(pane);
355                             paneCount++;
356                         }
357                     }
358                     // Otherwise, add the contents of profile as a pane
359
else
360                     {
361                         if (tmpPortlets.getTitle() == null)
362                         {
363                             String JavaDoc title = org.apache.turbine.util.StringUtils.firstLetterCaps(roleProfile.getRoleName());
364                             tmpPortlets.setTitle(title + " Home");
365                         }
366                         tmpPortlets.setLayout(null);
367                         portlets.addPortlets(tmpPortlets);
368                         paneCount++;
369                     }
370
371                     if (logger.isDebugEnabled())
372                     {
373                         logger.debug("Profiler: Processing profile for role " + roleProfile.getRoleName());
374                     }
375                 }
376
377                 // Create a new profile for the user
378
ProfileLocator locator = createLocator();
379                 locator.setUser((JetspeedUser) data.getUser());
380                 locator.setMediaType(mediaType);
381                 locator.setName(this.resourceDefault + this.resourceExt);
382
383                 // Regenerate the portlet ids so they are unique
384
org.apache.jetspeed.util.PortletUtils.regenerateIds(portlets);
385
386                 // Save the new profile to permament storage
387
result = this.createProfile(locator, portlets);
388
389             }
390             catch (Exception JavaDoc e)
391             {
392                 logger.error("Exception", e);
393             }
394         }
395
396         return result;
397     }
398
399     /**
400      * get the Profile object using the Rundata state and capability map
401      * this is the mapping functionality of the profiler
402      *
403      * @param rundata the rundata object for the current request
404      * @param cm the <code>CapabilityMap</code> of the current requesting device
405      * @return a new Profile object
406      */

407     protected Profile fallbackProfile(RunData data, CapabilityMap cm)
408         throws ProfileException
409     {
410         try
411         {
412             JetspeedRunData rundata = (JetspeedRunData)data;
413             Profile profile = createProfile();
414             JetspeedUser user = rundata.getJetspeedUser();
415
416             // get the media type from the capability map or rundata
417
profile.setMediaType(getMediaType(rundata, cm));
418
419             // Is it a group, role, or user resource?
420
// It can only be one
421
String JavaDoc param = rundata.getParameters().getString( Profiler.PARAM_GROUP );
422
423             if (null != param)
424             {
425                 // GROUP Resource
426
profile.setGroup( JetspeedSecurity.getGroup(param) );
427             }
428             else
429             {
430                 param = rundata.getParameters().getString( Profiler.PARAM_ROLE );
431                 if (null != param)
432                 {
433                     // ROLE Resource
434
if (user.hasLoggedIn()) // disallow role access for anonymous user
435
{
436                         profile.setRole( JetspeedSecurity.getRole(param) );
437                     }
438                     else
439                     {
440                         profile.setAnonymous(true);
441                         profile.setUser( user );
442                     }
443                 }
444                 else // it must be a user resource or anonymous resource
445
{
446                     // accessing another user's resource
447
param = rundata.getParameters().getString( Profiler.PARAM_USER );
448                     if (null != param)
449                     {
450
451                         if (param.equals(JetspeedSecurity.getAnonymousUserName()))
452                         {
453                             profile.setAnonymous(true);
454                         }
455                         if (user.getUserName().equals(param))
456                         {
457                             profile.setUser( user );
458                         }
459                         else
460                         {
461                             profile.setUser( JetspeedSecurity.getUser(param) );
462                         }
463                     }
464                     else
465                     {
466                         profile.setAnonymous(user.getUserName().equals(JetspeedSecurity.getAnonymousUserName()));
467                         profile.setUser( user );
468                     }
469                 }
470             }
471
472             // get resource name
473
StringBuffer JavaDoc resource = new StringBuffer JavaDoc();
474             param = rundata.getParameters().getString( Profiler.PARAM_PAGE );
475             if (null == param)
476             {
477                // the default resource
478
resource.append( resourceDefault );
479                 resource.append( resourceExt );
480             }
481             else
482             { // a specific resource
483
resource.append( param );
484                 if ( -1 == param.indexOf( PATH_EXTENSION_DELIMITER ) )
485                     resource.append( resourceExt );
486             }
487             profile.setName( resource.toString() );
488
489             // LANGUAGE
490
getLanguageSettings(profile, rundata);
491
492             PSMLDocument doc = fallback( profile );
493             if (null != doc)
494             {
495                 profile.setDocument( doc );
496                 return profile;
497             }
498         }
499         catch (Exception JavaDoc e)
500         {
501             logger.error( "Exception in fallbackProfile", e );
502             throw new ProfileException(e.toString());
503         }
504         return null;
505     }
506
507     /**
508      * get the Profile object using the Rundata state and capability map
509      * this is the mapping functionality of the profiler
510      *
511      * @param rundata the rundata object for the current request
512      * @return a new Profile object
513      */

514     public Profile getProfile(RunData rundata)
515         throws ProfileException
516     {
517         CapabilityMap cm = null;
518
519         if (rundata instanceof JetspeedRunData)
520         {
521             cm = ((JetspeedRunData)rundata).getCapability();
522         }
523         else
524         {
525             cm = CapabilityMapFactory.getCapabilityMap( rundata );
526         }
527
528         return getProfile(rundata, cm);
529     }
530
531     /**
532      * get the Profile object using the Rundata state and specific mimetype
533      *
534      * @deprecated Do not use a profiler method based on MimeType
535      *
536      * @param rundata the rundata object for the current request
537      * @param mt the <code>MimeType</code> of the current requesting device
538      * @return a new Profile object
539      */

540     public Profile getProfile(RunData data, MimeType mt)
541         throws ProfileException
542     {
543         CapabilityMap cm = CapabilityMapFactory.getCapabilityMap(mt.toString());
544         return getProfile(data, cm);
545     }
546
547     /**
548      * get the Profile object using a profile locator
549      *
550      * @param rundata The rundata object for the current request.
551      * @param locator The locator containing criteria describing the profile.
552      * @return a new Profile object
553      */

554     public Profile getProfile(ProfileLocator locator)
555         throws ProfileException
556     {
557         PSMLDocument doc = fallback(locator);
558         Profile profile = createProfile(locator);
559         profile.setDocument(doc);
560         return profile;
561     }
562
563     /*
564      * Gets the language and country parameters from the request using the Turbine locale detector.
565      *
566      * @param profile The profile object which is modified with the new language settings.
567      * @param rundata The request specific state.
568      */

569     protected void getLanguageSettings( Profile profile, RunData rundata )
570     {
571         String JavaDoc language = rundata.getParameters().getString(Profiler.PARAM_LANGUAGE);
572
573         if (language != null)
574         {
575             // dont use locale based fall back
576
profile.setLanguage(language);
577
578             if(! language.equals("-1"))
579             {
580                 String JavaDoc country = rundata.getParameters().getString(Profiler.PARAM_COUNTRY);
581                 if (country != null)
582                 {
583                     profile.setCountry(country);
584                 }
585             }
586         }
587         else
588         {
589             Locale JavaDoc locale = (Locale JavaDoc)rundata.getUser().getTemp("locale");
590             if (locale == null)
591             {
592                 // Get the locale store it in the user object
593
CustomLocalizationService locService = (CustomLocalizationService) ServiceUtil.getServiceByName(
594                     LocalizationService.SERVICE_NAME);
595                 locale = locService.getLocale(rundata);
596                 if (locale == null)
597                 {
598                     locale = new Locale JavaDoc(
599                                     TurbineResources.getString("locale.default.language", "en"),
600                                     TurbineResources.getString("locale.default.country", "US"));
601                 }
602                 rundata.getUser().setTemp("locale", locale);
603             }
604
605             if (useFallbackLanguage)
606             {
607                 profile.setLanguage( locale.getLanguage() );
608             }
609
610             if (useFallbackCountry)
611             {
612                 profile.setCountry( locale.getCountry() );
613             }
614         }
615     }
616
617     /*
618      * A basic profiler fallback algorithm that starts from the most specific parameters,
619      * going to the least specific parameters. The PsmlManager implementation is passed
620      * a list of ProfileLocators ordered from most specific to least specific.
621      *
622      * @param locator The profile locator criteria used to locate a profile.
623      * @param rundata The request specific state.
624      * @return The found psml document, or null if not found.
625      */

626     protected PSMLDocument fallbackList( ProfileLocator original, RunData rundata )
627     {
628         try
629         {
630             List JavaDoc locators = new LinkedList JavaDoc();
631             ProfileLocator locator = (ProfileLocator)original.clone();
632
633             locators.add( locator.clone() );
634
635             // remove country
636
if (null != original.getCountry())
637             {
638                 locator.setCountry(null);
639                 locators.add( locator.clone() );
640             }
641
642             // remove language
643
if (null != original.getLanguage())
644             {
645                 locator.setLanguage(null);
646                 locators.add( locator.clone() );
647             }
648
649             // fallback mediaType
650
if (null != original.getMediaType())
651             {
652                 locator.setMediaType(null);
653                 locators.add( locator.clone() );
654             }
655
656             if (null != original.getGroup())
657             {
658                 locator.setGroup(null);
659                 locators.add( locator.clone() );
660             }
661             else if (null != original.getRole())
662             {
663                 locator.setRole(null);
664                 locators.add( locator.clone() );
665             }
666             else if (null != original.getUser())
667             {
668                 locator.setUser(null);
669                 locators.add( locator.clone() );
670             }
671             PSMLDocument doc = PsmlManager.getDocument( locators );
672             return doc;
673
674         }
675         catch (CloneNotSupportedException JavaDoc e)
676         {
677             logger.error("Profiler: Could not clone profile locator object", e);
678         }
679         return null;
680     }
681
682     /*
683      * A basic profiler fallback algorithm that starts from the most specific parameters,
684      * going to the least specific parameters. The PsmlManager implementation is passed
685      * a list of ProfileLocators ordered from most specific to least specific.
686      *
687      * This is alternate fallback algorithm.
688      *
689      * @param locator The profile locator criteria used to locate a profile.
690      *
691      * @return PSMLDocument The located document or null.
692      */

693     protected PSMLDocument fallback(ProfileLocator locator)
694     {
695         if (logger.isDebugEnabled())
696         {
697             logger.debug( "Profiler: fallback called with: " + locator );
698         }
699
700         PSMLDocument doc = PsmlManager.getDocument( locator );
701         if (null != doc)
702             return doc;
703
704         // remove country
705
if (null != locator.getCountry() && (! locator.getCountry().equals("-1")))
706         {
707             locator.setCountry(null);
708             doc = PsmlManager.getDocument( locator );
709             if (null != doc)
710                 return doc;
711         }
712
713         // remove language
714
if (null != locator.getLanguage() && (! locator.getLanguage().equals("-1")))
715         {
716             locator.setLanguage(null);
717             doc = PsmlManager.getDocument( locator );
718             if (null != doc)
719                 return doc;
720         }
721
722         // fallback mediaType
723
if (useFallbackToRoot)
724         {
725             if (null != locator.getMediaType())
726             {
727                 locator.setMediaType(null);
728                 doc = PsmlManager.getDocument( locator );
729                 if (null != doc)
730                     return doc;
731             }
732         }
733
734         if (!useRoleFallback)
735         {
736             if (null != locator.getGroup())
737             {
738                 locator.setGroup(null);
739                 doc = PsmlManager.getDocument( locator );
740                 if (null != doc)
741                     return doc;
742             }
743             else if (null != locator.getRole())
744             {
745                 locator.setRole(null);
746                 doc = PsmlManager.getDocument( locator );
747                 if (null != doc)
748                     return doc;
749             }
750             else if (null != locator.getUser())
751             {
752                 locator.setUser(null);
753                 doc = PsmlManager.getDocument( locator );
754                 if (null != doc)
755                     return doc;
756             }
757         }
758         return doc;
759
760     }
761
762     /**
763      * Lookup the media type from the CapabilitMap.
764      * First the RunData is checked for an explicit media-type request.
765      *
766      * @param cm The <code>CapabilityMap</code> of the current requesting device.
767      * @param rundata, The <code>RunData</code> turbine request context information.
768      * @return a String, the unique name of the media type.
769      */

770     protected String JavaDoc getMediaType(RunData rundata, CapabilityMap cm)
771     {
772         String JavaDoc paramMediaType;
773         String JavaDoc media = null;
774
775         if (null != rundata)
776         {
777             paramMediaType = rundata.getParameters().getString( Profiler.PARAM_MEDIA_TYPE );
778             if (null != paramMediaType)
779             {
780                 return paramMediaType;
781             }
782         }
783
784         if (cm != null)
785         {
786             media = cm.getPreferredMediaType();
787         }
788
789         return media;
790     }
791
792     /**
793      * Loads the configuration parameters for this service from the
794      * JetspeedResources.properties file.
795      *
796      * @exception throws a <code>InitializationException</code> if the service
797      * fails to initialize
798      */

799     private void initConfiguration() throws InitializationException
800     {
801         profileClass = ServiceHelper.loadModelClass(this, "profile.impl");
802         locatorClass = ServiceHelper.loadModelClass(this, "locator.impl");
803         
804         // get configuration parameters from Jetspeed Resources
805
ResourceService serviceConf = ((TurbineServices)TurbineServices.getInstance())
806                                                      .getResources(ProfilerService.SERVICE_NAME);
807
808         resourceDefault = serviceConf.getString( CONFIG_RESOURCE_DEFAULT, DEFAULT_CONFIG_RESOURCE_DEFAULT );
809
810         resourceExt = serviceConf.getString( CONFIG_RESOURCE_EXT, DEFAULT_CONFIG_RESOURCE_EXT );
811         if (-1 == resourceExt.indexOf(PATH_EXTENSION_DELIMITER))
812         {
813             resourceExt = PATH_EXTENSION_DELIMITER + resourceExt;
814         }
815         
816         useSecurity = serviceConf.getBoolean( CONFIG_SECURITY, DEFAULT_CONFIG_SECURITY );
817
818         useRoleFallback = serviceConf.getBoolean( CONFIG_ROLE_FALLBACK, DEFAULT_CONFIG_ROLE_FALLBACK );
819
820         newUserTemplate = serviceConf.getString( CONFIG_NEWUSER_TEMPLATE, DEFAULT_CONFIG_NEWUSER_TEMPLATE );
821
822         useFallbackToRoot = serviceConf.getBoolean( CONFIG_FALLBACK_TO_ROOT, useFallbackToRoot );
823
824         useFallbackLanguage = serviceConf.getBoolean( CONFIG_FALLBACK_LANGUAGE, useFallbackLanguage );
825
826         useRoleMerge = serviceConf.getBoolean( CONFIG_ROLE_MERGE, useRoleMerge );
827
828         rolemergeControl = serviceConf.getString( CONFIG_ROLE_MERGE_CONTROL, DEFAULT_CONFIG_ROLE_MERGE_CONTROL );
829
830         rolemergeController = serviceConf.getString( CONFIG_ROLE_MERGE_CONTROLLER, DEFAULT_CONFIG_ROLE_MERGE_CONTROLLER );
831
832         if (useFallbackLanguage == false)
833         {
834             useFallbackCountry = false;
835         }
836         else
837         {
838             useFallbackCountry = serviceConf.getBoolean( CONFIG_FALLBACK_COUNTRY, useFallbackCountry );
839         }
840
841         try
842         {
843             mediaTypes = serviceConf.getStringArray(CONFIG_NEWUSER_MEDIA);
844         }
845         catch (Exception JavaDoc e)
846         {
847             logger.error( "Error getting media types", e );
848         }
849
850         if (null == mediaTypes || mediaTypes.length == 0)
851         {
852             mediaTypes = DEFAULT_CONFIG_NEWUSER_MEDIA;
853         }
854     }
855
856    /**
857     * Builds a dynamic URI based on the current profiler group/role/page
858     *
859     * @param data The rundata object for the current request.
860     * @param locator The description of the profile.
861     * @return A new dynamic URI representing all profile parameters from the locator.
862     */

863     public DynamicURI makeDynamicURI( RunData data, ProfileLocator locator )
864         throws ProfileException
865     {
866         DynamicURI uri = new DynamicURI( data );
867
868        // check mediatype to add to the uri
869
String JavaDoc mtype = locator.getMediaType();
870         if (null != mtype)
871         {
872             uri.addPathInfo(Profiler.PARAM_MEDIA_TYPE, mtype);
873         }
874
875        // check language to add to the uri
876
String JavaDoc language = locator.getLanguage();
877         if (null != language)
878         {
879             uri.addPathInfo(Profiler.PARAM_LANGUAGE, language);
880         }
881
882        // check language to add to the uri
883
String JavaDoc country = locator.getCountry();
884         if (null != country)
885         {
886             uri.addPathInfo(Profiler.PARAM_COUNTRY, country);
887         }
888
889         // check User, Group or Role to add to the uri
890
JetspeedUser user = locator.getUser();
891         if (null != user)
892         {
893             if (user.getUserName() != null)
894                 uri.addPathInfo(Profiler.PARAM_USER, user.getUserName());
895         }
896         else
897         {
898             Group group = locator.getGroup();
899             if (null != group)
900             {
901                 uri.addPathInfo(Profiler.PARAM_GROUP, group.getName());
902             }
903             else
904             {
905                 Role role = locator.getRole();
906                 if (null != role)
907                 {
908                     uri.addPathInfo(Profiler.PARAM_ROLE, role.getName());
909                 }
910             }
911         }
912
913         // check Page to add to the uri
914
String JavaDoc page = locator.getName();
915         if (null != page)
916         {
917             uri.addPathInfo(Profiler.PARAM_PAGE, page);
918         }
919
920         return uri;
921     }
922
923     /**
924      * Creates a new Profile object that can be successfully managed by
925      * the current Profiler implementation
926      *
927      * @return A new Profile object
928      */

929     public Profile createProfile()
930     {
931         return (Profile)ServiceHelper.createObject(this.profileClass);
932     }
933
934     /**
935      * Creates a new Profile object for a specific locator.
936      *
937      * @param locator The description of the profile.
938      * @return A new Profile object
939      */

940     public Profile createProfile(ProfileLocator locator)
941     {
942         Profile profile = (Profile)ServiceHelper.createObject(this.profileClass);
943         profile.init(locator);
944         return profile;
945     }
946
947     /**
948      * Creates a new ProfileLocator object that can be successfully managed by
949      * the current Profiler implementation
950      *
951      * @return A new ProfileLocator object
952      */

953     public ProfileLocator createLocator()
954     {
955         return (ProfileLocator)ServiceHelper.createObject(this.locatorClass);
956     }
957
958     /**
959      * Create a new profile given a profile locator
960      *
961      * This method assumes that you have cloned and regenerated the
962      * portlet ids if the portlets come from another profile.
963      *
964      * @param locator The description of the new profile to be created.
965      * @param portlets The PSML tree
966      */

967
968     public Profile createProfile(ProfileLocator locator, Portlets portlets)
969             throws ProfileException
970     {
971         if (portlets == null)
972         {
973             portlets = new PsmlPortlets();
974         }
975         
976         Profile profile = createProfile(locator);
977         PSMLDocument doc = new BasePSMLDocument(null, portlets);
978         profile.setDocument(doc);
979         doc = PsmlManager.createDocument(profile);
980         profile.setDocument(doc);
981         return profile;
982     }
983
984     /**
985      * Create a new profile.
986      * The profile parameter's document will be cloned.
987      *
988      * @param rundata The rundata object for the current request.
989      * @param profile The description of the new profile to be created.
990      * @param contentType create a profile for the specific contentType
991      * @param from create a profile by cloning the profile from the specific user (if null - turbine is used)
992      * @return The newly created profile.
993      * -----------------------------------------------------------
994      * Andreas Kempf, Siemens ICM S CP PE, Munich
995      */

996
997     /**
998      * This methode creates a wml profile and a html profile
999      * for a new user
1000     */

1001
1002    public Profile createProfile( RunData data, Profile profile, String JavaDoc contentType, String JavaDoc from )
1003            throws ProfileException
1004    {
1005      if ((contentType == null) || (contentType.length() < 2))
1006        contentType = "html";
1007
1008      if ((from == null) || (from.length() < 2))
1009        from = "turbine";
1010
1011
1012        if ((null == profile.getDocument()) || (!profile.getMediaType().equalsIgnoreCase (contentType)))
1013        {
1014            // locate the default resource
1015

1016            // TODO: make this configurable
1017

1018            try
1019            {
1020                ProfileLocator locator = createLocator();
1021                locator.setUser( JetspeedSecurity.getUser(from) );
1022
1023                locator.setMediaType(contentType);
1024                PSMLDocument doc = fallback(locator);
1025
1026                if (doc != null)
1027                {
1028                    PSMLDocument clonedDoc = (PSMLDocument) SerializationUtils.clone(doc);
1029                    org.apache.jetspeed.util.PortletUtils.regenerateIds(clonedDoc.getPortlets());
1030                    profile.setDocument(clonedDoc);
1031                }
1032
1033                profile.setName( resourceDefault + resourceExt );
1034
1035            }
1036            catch (Exception JavaDoc e)
1037            {
1038                logger.error( "Error creating profile", e );
1039                throw new ProfileException(e.toString());
1040            }
1041        }
1042
1043        try
1044        {
1045            profile.setMediaType(contentType);
1046
1047            PSMLDocument doc = PsmlManager.createDocument(profile);
1048            Profile newProfile = (Profile)profile.clone();
1049            newProfile.setDocument(doc);
1050
1051            return newProfile;
1052        }
1053        catch (CloneNotSupportedException JavaDoc e)
1054        {
1055            logger.error("Could not clone profile locator object: ", e);
1056        }
1057        return null;
1058
1059    }
1060
1061   /** Create a new profile.
1062     *
1063     * @deprecated Should be removed when old customizer is removed.
1064     *
1065     * @param rundata The rundata object for the current request.
1066     * @param profile The description of the new profile to be created.
1067     * @param mt The specific mime type, which is converted to a mediatype.
1068     * @return The newly created profile.
1069     */

1070    public Profile createProfile( RunData data, Profile profile, MimeType mt )
1071        throws ProfileException
1072    {
1073        CapabilityMap cm = CapabilityMapFactory.getCapabilityMap(mt.getContentType());
1074        profile.setMediaType( getMediaType(data, cm) );
1075        return createProfile(data, profile);
1076    }
1077
1078   /**
1079     * Removes a profile.
1080     *
1081     * @param locator The profile locator criteria.
1082     */

1083    public void removeProfile( ProfileLocator locator )
1084    {
1085        PsmlManager.removeDocument(locator);
1086    }
1087
1088    /** Query for a collection of profiles given a profile locator criteria.
1089     *
1090     * @param locator The profile locator criteria.
1091     * @return The list of profiles matching the locator criteria.
1092     */

1093    public Iterator JavaDoc query( QueryLocator locator )
1094    {
1095        return PsmlManager.query( locator );
1096    }
1097
1098    /**
1099     * @see org.apache.jetspeed.services.profiler.ProfilerService#useRoleProfileMerging
1100     */

1101    public boolean useRoleProfileMerging()
1102    {
1103        return this.useRoleFallback && this.useRoleMerge;
1104    }
1105}
1106
1107
Popular Tags