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.jetspeed.profiler.impl;
018:
019: import java.security.Principal;
020: import java.util.Collection;
021: import java.util.Collections;
022: import java.util.HashMap;
023: import java.util.Iterator;
024: import java.util.Map;
025: import java.util.Properties;
026:
027: import javax.security.auth.Subject;
028:
029: import org.apache.commons.logging.Log;
030: import org.apache.commons.logging.LogFactory;
031: import org.apache.jetspeed.components.dao.InitablePersistenceBrokerDaoSupport;
032: import org.apache.jetspeed.profiler.ProfileLocator;
033: import org.apache.jetspeed.profiler.Profiler;
034: import org.apache.jetspeed.profiler.ProfilerException;
035: import org.apache.jetspeed.profiler.rules.PrincipalRule;
036: import org.apache.jetspeed.profiler.rules.ProfileResolvers;
037: import org.apache.jetspeed.profiler.rules.ProfilingRule;
038: import org.apache.jetspeed.profiler.rules.RuleCriterion;
039: import org.apache.jetspeed.profiler.rules.impl.AbstractProfilingRule;
040: import org.apache.jetspeed.profiler.rules.impl.PrincipalRuleImpl;
041: import org.apache.jetspeed.request.RequestContext;
042: import org.apache.jetspeed.security.SecurityHelper;
043: import org.apache.jetspeed.security.UserPrincipal;
044: import org.apache.jetspeed.security.impl.UserPrincipalImpl;
045: import org.apache.ojb.broker.query.Criteria;
046: import org.apache.ojb.broker.query.QueryFactory;
047: import org.springframework.beans.BeansException;
048: import org.springframework.beans.factory.BeanFactory;
049: import org.springframework.beans.factory.BeanFactoryAware;
050:
051: /**
052: * JetspeedTransactionalProfiler
053: *
054: * @author <a href="mailto:taylor@apache.org">David Sean Taylor </a>
055: * @version $Id: JetspeedProfilerImpl.java 553647 2007-07-05 21:42:04Z taylor $
056: */
057: public class JetspeedProfilerImpl extends
058: InitablePersistenceBrokerDaoSupport implements Profiler,
059: BeanFactoryAware {
060: /** The default rule. */
061: public final static String DEFAULT_RULE = "j1";
062:
063: /** Commons logging */
064: protected final static Log log = LogFactory
065: .getLog(JetspeedProfilerImpl.class);
066:
067: /**
068: * This is the princapl that is used if there are no principal to rule associations for the current principal
069: */
070: public final static Principal DEFAULT_RULE_PRINCIPAL = new UserPrincipalImpl(
071: "*");
072:
073: /** The default locator class implementation */
074: private String locatorBean = "ProfileLocator";
075:
076: /** The default principalRule association class implementation */
077: private Class prRuleClass;
078:
079: private String principalRuleBean = "PrincipalRule";
080:
081: /** The base (abstract) profilingRule class implementation */
082: private String profilingRuleStandardBean = "StandardProfilingRule";
083:
084: /** The base (abstract) profilingRule class implementation */
085: private String profilingRuleFallbackBean = "RoleFallbackProfilingRule";
086:
087: /** The base (abstract) profilingRule class implementation */
088: private Class profilingRuleClass = AbstractProfilingRule.class;
089:
090: /** The configured default rule for this portal */
091: private String defaultRule = DEFAULT_RULE;
092:
093: private Map principalRules = Collections
094: .synchronizedMap(new HashMap());
095:
096: private Map rulesPerPrincipal = Collections
097: .synchronizedMap(new HashMap());
098:
099: private ProfileResolvers resolvers;
100:
101: /** the default criterion bean name */
102: private String ruleCriterionBean = "RuleCriterion";
103:
104: /**
105: * added support for bean factory to create profile rules
106: */
107: private BeanFactory beanFactory;
108:
109: public JetspeedProfilerImpl(String repositoryPath,
110: ProfileResolvers resolvers) {
111: super (repositoryPath);
112: this .resolvers = resolvers;
113: }
114:
115: /**
116: * Create a JetspeedProfiler with properties. Expected properties are:
117: * defaultRule = the default profiling rule anonymousUser = the name of the
118: * anonymous user storeName = The name of the persistence store component to
119: * connect to services.profiler.locator.impl = the pluggable Profile Locator
120: * impl services.profiler.principalRule.impl = the pluggable Principal Rule
121: * impl services.profiler.profilingRule.impl = the pluggable Profiling Rule
122: * impl
123: *
124: * @param properties
125: * Properties for this component described above
126: * @throws ClassNotFoundException
127: * if any the implementation classes defined within the
128: * <code>properties</code> argument could not be found.
129: */
130: public JetspeedProfilerImpl(String repositoryPath,
131: String defaultRule, ProfileResolvers resolvers)
132: throws ClassNotFoundException {
133: this (repositoryPath, resolvers);
134: this .defaultRule = defaultRule;
135: }
136:
137: /**
138: * @deprecated As of release 2.1, property-based class references replaced
139: * by container managed bean factory
140: */
141: public JetspeedProfilerImpl(String repositoryPath,
142: String defaultRule, Properties properties,
143: ProfileResolvers resolvers) throws ClassNotFoundException {
144: this (repositoryPath, defaultRule, resolvers);
145: initModelClasses(properties); // TODO: move this to
146: // start()
147: }
148:
149: /**
150: * support passing of rule creation classes
151: */
152: public JetspeedProfilerImpl(String repositoryPath,
153: String defaultRule, ProfileResolvers resolvers,
154: Map ruleConstructors, String ruleCriterionBean)
155: throws ClassNotFoundException {
156: this (repositoryPath, defaultRule, resolvers);
157: this .ruleCriterionBean = ruleCriterionBean;
158: initRuleClasses(ruleConstructors);
159: }
160:
161: /**
162: * @param defaultRule
163: * The default rule to set.
164: */
165: public void setDefaultRule(String defaultRule) {
166: this .defaultRule = defaultRule;
167: }
168:
169: /**
170: * @deprecated As of release 2.1, property-based class references replaced
171: * by container managed bean factory
172: */
173: private void initModelClasses(Properties properties)
174: throws ClassNotFoundException {
175:
176: /**
177: * String modelName = "";
178: *
179: * if ((modelName = properties.getProperty("locator.impl")) != null) { //
180: * locatorClassName = modelName; } if ((modelName =
181: * properties.getProperty("principalRule.impl")) != null) {
182: * principalRuleClass = Class.forName(modelName); } if ((modelName =
183: * properties.getProperty("profilingRule.impl")) != null) {
184: * profilingRuleClass = Class.forName(modelName); }
185: */
186: }
187:
188: public ProfileLocator getProfile(RequestContext context,
189: String locatorName) throws ProfilerException {
190: // get the principal representing the currently logged on user
191: Subject subject = context.getSubject();
192: if (subject == null) {
193: String msg = "Invalid (null) Subject in request pipeline";
194: log.error(msg);
195: throw new ProfilerException(msg);
196: }
197: // get the UserPrincipal, finding the first UserPrincipal, or
198: // find the first principal if no UserPrincipal isn't available
199: Principal principal = SecurityHelper.getBestPrincipal(subject,
200: UserPrincipal.class);
201: if (principal == null) {
202: String msg = "Could not find a principle for subject in request pipeline";
203: log.error(msg);
204: throw new ProfilerException(msg);
205: }
206:
207: // find a profiling rule for this principal
208: ProfilingRule rule = getRuleForPrincipal(principal, locatorName);
209: if (null == rule) {
210: log.warn("Could not find profiling rule for principal: "
211: + principal);
212: rule = this .getDefaultRule();
213: }
214:
215: if (null == rule) {
216: String msg = "Couldn't find any profiling rules including default rule for principal "
217: + principal;
218: log.error(msg);
219: throw new ProfilerException(msg);
220: }
221: // create a profile locator for given rule
222: return rule.apply(context, this );
223: }
224:
225: public ProfileLocator getDefaultProfile(RequestContext context,
226: String locatorName) throws ProfilerException {
227:
228: ProfilingRule rule = getRuleForPrincipal(
229: DEFAULT_RULE_PRINCIPAL, locatorName);
230: if (null == rule) {
231: log.warn("Could not find profiling rule for principal: "
232: + DEFAULT_RULE_PRINCIPAL);
233: rule = this .getDefaultRule();
234: }
235:
236: if (null == rule) {
237: String msg = "Couldn't find any profiling rules including default rule for principal "
238: + DEFAULT_RULE_PRINCIPAL;
239: log.error(msg);
240: throw new ProfilerException(msg);
241: }
242: // create a profile locator for given rule
243: return rule.apply(context, this );
244: }
245:
246: /*
247: * (non-Javadoc)
248: *
249: * @see org.apache.jetspeed.profiler.Profiler#getProfile(org.apache.jetspeed.request.RequestContext,
250: * org.apache.jetspeed.profiler.rules.ProfilingRule)
251: */
252: public ProfileLocator getProfile(RequestContext context,
253: ProfilingRule rule) throws ProfilerException {
254: // create a profile locator for given rule
255: return rule.apply(context, this );
256: }
257:
258: /*
259: * (non-Javadoc)
260: *
261: * @see org.apache.jetspeed.profiler.Profiler#getRuleForPrincipal(java.security.Principal,
262: * java.lang.String)
263: */
264: public ProfilingRule getRuleForPrincipal(Principal principal,
265: String locatorName) {
266: ProfilingRule rule = null;
267: // lookup the rule for the given principal in our user/rule table
268: PrincipalRule pr = lookupPrincipalRule(principal.getName(),
269: locatorName);
270:
271: // if not found, fallback to the locator named rule or system wide rule
272: if (pr == null) {
273: // find rule on locator name
274: rule = getRule(locatorName);
275:
276: if (rule == null) {
277: // if not found, fallback to the system wide rule
278: rule = getDefaultRule();
279: }
280: pr = new PrincipalRuleImpl();
281: pr.setLocatorName(locatorName);
282: pr.setPrincipalName(principal.getName());
283: pr.setProfilingRule(rule);
284: principalRules.put(makePrincipalRuleKey(
285: principal.getName(), locatorName), pr);
286: } else {
287: // Get the associated rule
288: rule = pr.getProfilingRule();
289: }
290:
291: return rule;
292: }
293:
294: /**
295: * Internal method to ensure we have a valid principalRule class for queries
296: *
297: * @return the class object for the principalRule
298: */
299: private Class getPrincipalRuleClass() {
300: if (this .prRuleClass == null) {
301: try {
302: PrincipalRule tempRule = createPrincipalRule();
303: this .prRuleClass = tempRule.getClass();
304: } catch (Exception e) {
305: e.printStackTrace();
306: }
307: }
308: return this .prRuleClass;
309: }
310:
311: /*
312: * (non-Javadoc)
313: *
314: * @see org.apache.jetspeed.profiler.Profiler#setRuleForPrincipal(java.security.Principal,
315: * org.apache.jetspeed.profiler.rules.ProfilingRule, java.lang.String)
316: */
317: public void setRuleForPrincipal(Principal principal,
318: ProfilingRule rule, String locatorName) {
319: Criteria c = new Criteria();
320: c.addEqualTo("principalName", principal.getName());
321: c.addEqualTo("locatorName", locatorName);
322: PrincipalRule pr = (PrincipalRule) getPersistenceBrokerTemplate()
323: .getObjectByQuery(
324: QueryFactory.newQuery(getPrincipalRuleClass(),
325: c));
326:
327: if (pr == null) {
328: pr = new PrincipalRuleImpl(); // TODO: factory
329: pr.setPrincipalName(principal.getName());
330: pr.setLocatorName(locatorName);
331: pr.setProfilingRule(rule);
332: }
333: rule.setResolvers(resolvers);
334: pr.setProfilingRule(rule);
335: getPersistenceBrokerTemplate().store(pr);
336: principalRules.put(makePrincipalRuleKey(principal.getName(),
337: locatorName), pr);
338: this .rulesPerPrincipal.remove(principal.getName());
339: }
340:
341: private String makePrincipalRuleKey(String principal, String locator) {
342: return principal + ":" + locator;
343: }
344:
345: /**
346: * Helper function to lookup principal rule associations by principal
347: *
348: * @param principal
349: * The string representation of the principal name.
350: * @return The found PrincipalRule associated with the principal key or null
351: * if not found.
352: */
353: private PrincipalRule lookupPrincipalRule(String principal,
354: String locatorName) {
355: PrincipalRule pr = (PrincipalRule) principalRules
356: .get(makePrincipalRuleKey(principal, locatorName));
357: if (pr != null) {
358: return pr;
359: }
360: Criteria c = new Criteria();
361: c.addEqualTo("principalName", principal);
362: c.addEqualTo("locatorName", locatorName);
363:
364: pr = (PrincipalRule) getPersistenceBrokerTemplate()
365: .getObjectByQuery(
366: QueryFactory.newQuery(getPrincipalRuleClass(),
367: c));
368:
369: principalRules.put(
370: makePrincipalRuleKey(principal, locatorName), pr);
371: if (pr != null)
372: pr.getProfilingRule().setResolvers(resolvers);
373: return pr;
374: }
375:
376: /*
377: * (non-Javadoc)
378: *
379: * @see org.apache.jetspeed.profiler.Profiler#getDefaultRule()
380: */
381: public ProfilingRule getDefaultRule() {
382: return getRule(this .defaultRule);
383: }
384:
385: /*
386: * (non-Javadoc)
387: *
388: * @see org.apache.jetspeed.profiler.Profiler#getRules()
389: */
390: public Collection getRules() {
391: Collection rules = getPersistenceBrokerTemplate()
392: .getCollectionByQuery(
393: QueryFactory.newQuery(profilingRuleClass,
394: new Criteria()));
395: Iterator r = rules.iterator();
396: while (r.hasNext()) {
397: ProfilingRule rule = (ProfilingRule) r.next();
398: rule.setResolvers(resolvers);
399: }
400: return rules;
401: }
402:
403: /*
404: * (non-Javadoc)
405: *
406: * @see org.apache.jetspeed.profiler.Profiler#getRule(java.lang.String)
407: */
408: public ProfilingRule getRule(String id) {
409: Criteria c = new Criteria();
410: c.addEqualTo("id", id);
411:
412: ProfilingRule rule = (ProfilingRule) getPersistenceBrokerTemplate()
413: .getObjectByQuery(
414: QueryFactory.newQuery(profilingRuleClass, c));
415: if (rule != null) {
416: rule.setResolvers(resolvers);
417: }
418: return rule;
419: }
420:
421: /*
422: * (non-Javadoc)
423: *
424: * @see org.apache.jetspeed.profiler.Profiler#getLocatorNamesForPrincipal(java.security.Principal)
425: */
426: public String[] getLocatorNamesForPrincipal(Principal principal) {
427: Criteria c = new Criteria();
428: c.addEqualTo("principalName", principal.getName());
429:
430: Collection result = getPersistenceBrokerTemplate()
431: .getCollectionByQuery(
432: QueryFactory.newQuery(getPrincipalRuleClass(),
433: c));
434: if (result.size() == 0) {
435: return new String[] {};
436: }
437: String[] names = new String[result.size()];
438: Iterator it = result.iterator();
439: int ix = 0;
440: while (it.hasNext()) {
441: PrincipalRule pr = (PrincipalRule) it.next();
442: names[ix] = pr.getLocatorName();
443: pr.getProfilingRule().setResolvers(resolvers);
444: ix++;
445: }
446: return names;
447: }
448:
449: /*
450: * (non-Javadoc)
451: *
452: * @see org.apache.jetspeed.profiler.Profiler#getRulesForPrincipal(java.security.Principal)
453: */
454: public Collection getRulesForPrincipal(Principal principal) {
455:
456: Collection rules = (Collection) this .rulesPerPrincipal
457: .get(principal.getName());
458: if (rules != null)
459: return rules;
460: Criteria c = new Criteria();
461: c.addEqualTo("principalName", principal.getName());
462: rules = getPersistenceBrokerTemplate().getCollectionByQuery(
463: QueryFactory.newQuery(getPrincipalRuleClass(), c));
464: Iterator r = rules.iterator();
465: while (r.hasNext()) {
466: PrincipalRule pr = (PrincipalRule) r.next();
467: ProfilingRule rule = pr.getProfilingRule();
468: if (rule != null)
469: rule.setResolvers(resolvers);
470: }
471: this .rulesPerPrincipal.put(principal.getName(), rules);
472: return rules;
473: }
474:
475: /*
476: * (non-Javadoc)
477: *
478: * @see org.apache.jetspeed.profiler.Profiler#getProfileLocators(org.apache.jetspeed.request.RequestContext,
479: * java.security.Principal)
480: */
481: public Map getProfileLocators(RequestContext context,
482: Principal principal) throws ProfilerException {
483: Map locators = new HashMap();
484: Collection rules = getRulesForPrincipal(principal);
485:
486: Iterator it = rules.iterator();
487: while (it.hasNext()) {
488: PrincipalRule pr = (PrincipalRule) it.next();
489: locators.put(pr.getLocatorName(), getProfile(context, pr
490: .getLocatorName()));
491: }
492: return locators;
493: }
494:
495: public Map getDefaultProfileLocators(RequestContext context)
496: throws ProfilerException {
497: Map locators = new HashMap();
498:
499: Collection rules = getRulesForPrincipal(DEFAULT_RULE_PRINCIPAL);
500:
501: Iterator it = rules.iterator();
502: while (it.hasNext()) {
503: PrincipalRule pr = (PrincipalRule) it.next();
504: locators.put(pr.getLocatorName(), getDefaultProfile(
505: context, pr.getLocatorName()));
506: }
507: return locators;
508: }
509:
510: /*
511: * (non-Javadoc)
512: *
513: * @see org.apache.jetspeed.profiler.Profiler#storeProfilingRule(org.apache.jetspeed.profiler.rules.ProfilingRule)
514: */
515: public void storeProfilingRule(ProfilingRule rule)
516: throws ProfilerException {
517: getPersistenceBrokerTemplate().store(rule);
518: }
519:
520: /*
521: * (non-Javadoc)
522: *
523: * @see org.apache.jetspeed.profiler.Profiler#deleteProfilingRule(org.apache.jetspeed.profiler.rules.ProfilingRule)
524: */
525: public void deleteProfilingRule(ProfilingRule rule)
526: throws ProfilerException {
527: getPersistenceBrokerTemplate().delete(rule);
528: }
529:
530: /*
531: * (non-Javadoc)
532: *
533: * @see org.apache.jetspeed.profiler.Profiler#storePrincipalRule(org.apache.jetspeed.profiler.rules.PrincipalRule)
534: */
535: public void storePrincipalRule(PrincipalRule rule)
536: throws ProfilerException {
537: getPersistenceBrokerTemplate().store(rule);
538: }
539:
540: /*
541: * (non-Javadoc)
542: *
543: * @see org.apache.jetspeed.profiler.Profiler#deletePrincipalRule(org.apache.jetspeed.profiler.rules.PrincipalRule)
544: */
545: public void deletePrincipalRule(PrincipalRule rule)
546: throws ProfilerException {
547: getPersistenceBrokerTemplate().delete(rule);
548: rulesPerPrincipal.remove(rule.getPrincipalName());
549: String key = this .makePrincipalRuleKey(rule.getPrincipalName(),
550: rule.getLocatorName());
551: principalRules.remove(key);
552: }
553:
554: /*
555: * Method called automatically by Spring container upon initialization
556: *
557: * @param beanFactory automatically provided by framework @throws
558: * BeansException
559: */
560: public void setBeanFactory(BeanFactory beanFactory)
561: throws BeansException {
562: this .beanFactory = beanFactory;
563: }
564:
565: /**
566: * added logic to get the settings for creating the various rule related
567: * instances
568: *
569: * @param classes
570: * @throws ClassNotFoundException
571: */
572: private void initRuleClasses(Map beans)
573: throws ClassNotFoundException {
574:
575: String beanName = "";
576: try {
577: if ((beanName = (String) beans.get("locator")) != null) {
578: this .locatorBean = beanName;
579: }
580: } catch (Exception e) {
581: String msg = "Exception in setting locatorbeanName : "
582: + e.getLocalizedMessage();
583: log.error(msg);
584: }
585: try {
586: if ((beanName = (String) beans.get("principal")) != null) {
587: this .principalRuleBean = beanName;
588: }
589: } catch (Exception e) {
590: String msg = "Exception in setting principalRulebeanName : "
591: + e.getLocalizedMessage();
592: log.error(msg);
593: }
594: try {
595: if ((beanName = (String) beans.get("standard")) != null) {
596: this .profilingRuleStandardBean = beanName;
597: }
598: } catch (Exception e) {
599: String msg = "Exception in setting profilingRuleStandardbeanName : "
600: + e.getLocalizedMessage();
601: log.error(msg);
602: }
603: try {
604: if ((beanName = (String) beans.get("fallback")) != null) {
605: this .profilingRuleFallbackBean = beanName;
606: }
607: } catch (Exception e) {
608: String msg = "Exception in setting profilingRuleFallback : "
609: + e.getLocalizedMessage();
610: log.error(msg);
611: }
612:
613: }
614:
615: /*
616: * (non-Javadoc)
617: *
618: * @see org.apache.jetspeed.profiler.Profiler#createProfilingRule(boolean)
619: */
620: public ProfilingRule createProfilingRule(boolean standard)
621: throws ClassNotFoundException {
622: try {
623: if (standard)
624: return (ProfilingRule) beanFactory.getBean(
625: this .profilingRuleStandardBean,
626: ProfilingRule.class);
627: else
628: return (ProfilingRule) beanFactory.getBean(
629: this .profilingRuleFallbackBean,
630: ProfilingRule.class);
631:
632: } catch (BeansException e) {
633: throw new ClassNotFoundException(
634: "Spring failed to create the "
635: + (standard ? "standard" : "fallback")
636: + " profiling rule bean.", e);
637: }
638: }
639:
640: /*
641: * (non-Javadoc)
642: *
643: * @see org.apache.jetspeed.profiler.Profiler#createLocator(RequestContext)
644: */
645: public ProfileLocator createLocator(RequestContext context) {
646: try {
647: ProfileLocator locator = (ProfileLocator) beanFactory
648: .getBean(this .locatorBean, ProfileLocator.class);
649: locator.init(this , context.getPath());
650: return locator;
651: } catch (Exception e) {
652: log.error("Failed to create locator for "
653: + this .locatorBean + " error : "
654: + e.getLocalizedMessage());
655: }
656: return null;
657: }
658:
659: /*
660: * (non-Javadoc)
661: *
662: * @see org.apache.jetspeed.profiler.Profiler#createPrincipalRule()
663: */
664: public PrincipalRule createPrincipalRule()
665: throws ClassNotFoundException {
666: try {
667: PrincipalRule principalRule = (PrincipalRule) beanFactory
668: .getBean(this .principalRuleBean,
669: PrincipalRule.class);
670: return principalRule;
671: } catch (Exception e) {
672: log.error("Failed to create principalRule for "
673: + principalRuleBean + " error : "
674: + e.getLocalizedMessage());
675: throw new ClassNotFoundException(
676: "Spring failed to create the "
677: + " principal rule bean.", e);
678: }
679:
680: }
681:
682: /*
683: * (non-Javadoc)
684: *
685: * @see org.apache.jetspeed.profiler.Profiler#createRuleCriterion()
686: */
687: public RuleCriterion createRuleCriterion()
688: throws ClassNotFoundException {
689: try {
690: RuleCriterion ruleCriterion = (RuleCriterion) beanFactory
691: .getBean(this .ruleCriterionBean,
692: RuleCriterion.class);
693: return ruleCriterion;
694: } catch (Exception e) {
695: log.error("Failed to create principalRule for "
696: + ruleCriterionBean + " error : "
697: + e.getLocalizedMessage());
698: throw new ClassNotFoundException(
699: "Spring failed to create the "
700: + " rule criterion bean.", e);
701: }
702:
703: }
704:
705: }
|