001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2007
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.faces.beans;
034:
035: import com.flexive.faces.FxJsfUtils;
036: import com.flexive.faces.messages.FxFacesMessage;
037: import com.flexive.faces.messages.FxFacesMessages;
038: import com.flexive.faces.messages.FxFacesMsgErr;
039: import com.flexive.shared.*;
040: import com.flexive.shared.structure.FxEnvironment;
041: import com.flexive.shared.content.FxContent;
042: import com.flexive.shared.content.FxPK;
043: import com.flexive.shared.exceptions.FxApplicationException;
044: import com.flexive.shared.search.AdminResultLocations;
045: import com.flexive.shared.search.ResultLocation;
046: import com.flexive.shared.security.Role;
047: import com.flexive.shared.security.UserTicket;
048: import com.flexive.war.FxRequest;
049: import com.flexive.war.filter.FxResponseWrapper;
050:
051: import javax.faces.application.FacesMessage;
052: import javax.faces.component.UIComponent;
053: import javax.faces.component.UIInput;
054: import javax.faces.context.FacesContext;
055: import static javax.faces.context.FacesContext.getCurrentInstance;
056: import javax.servlet.http.HttpServletRequest;
057: import javax.servlet.http.HttpServletResponse;
058: import java.io.Serializable;
059: import java.util.HashMap;
060: import java.util.List;
061: import java.util.Map;
062: import java.util.MissingResourceException;
063:
064: public class SystemBean implements Serializable {
065: private static final long serialVersionUID = 6592229045042549537L;
066: private static final FacesMessageMap messageMap = new FacesMessageMap();
067:
068: private long updateLanguageId = -1;
069: private Map<Object, Integer> counters;
070: private Map<Object, Integer> counterMap;
071: private Map<Object, Integer> counterValueMap;
072: private Map<String, String> webletMap;
073: private Map<String, Boolean> messageExistsMap;
074: private Map<Object, FxContent> contentMap;
075: private Map<Object, FxContent> explodedContentMap;
076:
077: public Map<String, List<FacesMessage>> getComponentMessages() {
078: return messageMap;
079: }
080:
081: /**
082: * Returns all faces messages.
083: *
084: * @return all messages
085: */
086: public List<FacesMessage> getMessages() {
087: return FxJsfUtils.getMessages(null);
088: }
089:
090: /**
091: * Returns all faces messages grouped by their summary.
092: *
093: * @return all messages
094: */
095: public List<FxFacesMessages> getGroupedFxMessages() {
096: return FxJsfUtils.getGroupedFxMessages();
097: }
098:
099: /**
100: * Returns true if grouped FxMessages are available.
101: *
102: * @return true if grouped FxMessages are available
103: */
104: public boolean getHasGroupedFxMessages() {
105: List l = getGroupedFxMessages();
106: return (l != null && l.size() > 0);
107: }
108:
109: /**
110: * Returns all faces messages.
111: *
112: * @return all messages
113: */
114: public List<FxFacesMessage> getFxMessages() {
115: return FxJsfUtils.getFxMessages();
116: }
117:
118: /**
119: * Returns true if the current request's error messages contain the
120: * given ID.
121: *
122: * @return a map that returns true if the requested key is contained in the current request's error message IDs
123: */
124: public Map<String, Boolean> getContainsErrorId() {
125: return new HashMap<String, Boolean>() {
126: public Boolean get(Object key) {
127: if (key == null) {
128: return false;
129: }
130: final String keyString = key.toString();
131: for (FxFacesMessage message : getFxMessages()) {
132: if (keyString.equals(message.getId())) {
133: return true;
134: }
135: }
136: return false;
137: }
138: };
139: }
140:
141: /**
142: * Returns the next page to display based on the request parameter page.
143: *
144: * @return the next page to display based on the request parameter page
145: */
146: public String gotoPage() {
147: return FxJsfUtils.getParameter("page");
148: }
149:
150: /**
151: * Updates the current session language supplied in the "updateLanguageId" property
152: * and re-renders the current page.
153: */
154: public void updateLanguage() {
155: try {
156: getUserTicket().overrideLanguage(
157: EJBLookup.getLanguageEngine()
158: .load(updateLanguageId));
159: } catch (FxApplicationException e) {
160: new FxFacesMsgErr(e).addToContext();
161: }
162: }
163:
164: public long getUpdateLanguageId() {
165: if (updateLanguageId == -1) {
166: updateLanguageId = getUserTicket().getLanguage().getId();
167: }
168: return updateLanguageId;
169: }
170:
171: public void setUpdateLanguageId(long updateLanguageId) {
172: this .updateLanguageId = updateLanguageId;
173: }
174:
175: /**
176: * Returns the ticket of the calling user.
177: *
178: * @return the ticket of the calling user
179: */
180: public UserTicket getUserTicket() {
181: return FxJsfUtils.getRequest().getUserTicket();
182: }
183:
184: /**
185: * Return the {@link FxContext} instance of the current request.
186: *
187: * @return the {@link FxContext} instance of the current request.
188: */
189: public FxContext getContext() {
190: return FxContext.get();
191: }
192:
193: public FxResponseWrapper getResponse() {
194: return FxJsfUtils.getResponse();
195: }
196:
197: public FxRequest getRequest() {
198: return FxJsfUtils.getRequest();
199: }
200:
201: public String getContextPath() {
202: return FxJsfUtils.getRequest().getContextPath();
203: }
204:
205: public String getFlexiveContextPath() {
206: return "/flexive";
207: }
208:
209: public String getDocumentBase() {
210: HttpServletRequest request = FxJsfUtils.getRequest()
211: .getRequest();
212: return "http://"
213: + request.getServerName()
214: + (request.getServerPort() != 80 ? ":"
215: + request.getServerPort() : "")
216: + getContextPath() + "/";
217: }
218:
219: private static class FacesMessageMap extends
220: HashMap<String, List<FacesMessage>> {
221: /**
222: * {@inheritDoc}
223: */
224: @Override
225: public List<FacesMessage> get(Object key) {
226: return FxJsfUtils.getMessages("" + key);
227: }
228: }
229:
230: /**
231: * Returns the browser that the client is using
232: *
233: * @return the browser the client is using
234: */
235: public FxRequest.Browser getBrowser() {
236: return FxJsfUtils.getRequest().getBrowser();
237: }
238:
239: /**
240: * Returns the browser that the client is using
241: *
242: * @return the browser the client is using
243: */
244: public String getBrowserAsString() {
245: return String.valueOf(FxJsfUtils.getRequest().getBrowser());
246: }
247:
248: /**
249: * Get verbose information about the flexive build
250: *
251: * @return verbose information about the flexive build
252: */
253: public String getBuildInfoVerbose() {
254: return FxSharedUtils.getFlexiveEditionFull() + " "
255: + FxSharedUtils.getFlexiveVersion() + "/build #"
256: + FxSharedUtils.getBuildNumber() + " - "
257: + FxSharedUtils.getBuildDate();
258: }
259:
260: /**
261: * Get the flexive edition
262: *
263: * @return flexive edition
264: */
265: public String getEdition() {
266: return FxSharedUtils.getFlexiveEdition();
267: }
268:
269: /**
270: * Get the flexive edition with product
271: *
272: * @return flexive edition with product
273: */
274: public String getEditionFull() {
275: return FxSharedUtils.getFlexiveEditionFull();
276: }
277:
278: /**
279: * Get information about the flexive build
280: *
281: * @return information about the flexive build
282: */
283: public String getBuildInfo() {
284: return FxSharedUtils.getFlexiveEdition() + " "
285: + FxSharedUtils.getFlexiveVersion();
286: }
287:
288: /**
289: * Get a list of all installed and deployed drops
290: *
291: * @return list of all installed and deployed drops
292: */
293: public synchronized List<String> getDrops() {
294: return FxSharedUtils.getDrops();
295: }
296:
297: /**
298: * Get the flexive header string
299: *
300: * @return header string
301: */
302: public String getHeader() {
303: String header = FxSharedUtils.getHeader();
304: if (header.indexOf("$user$") > 0)
305: header = header.replaceAll("\\$user\\$", getRequest()
306: .getUserTicket().getUserName());
307: return header;
308: }
309:
310: public ResultLocation getAdminResultLocation() {
311: return AdminResultLocations.ADMIN;
312: }
313:
314: /**
315: * <p>Provides parametric access to components.</p>
316: * <p/>
317: * For example:
318: * <pre>#{fxSystemBean.component['frm:myInputComponent']}</pre>
319: * </p>
320: *
321: * @return a mapped function returning components for clientIds
322: */
323: public Map<String, UIComponent> getComponent() {
324: return FxSharedUtils
325: .getMappedFunction(new FxSharedUtils.ParameterMapper<String, UIComponent>() {
326: public UIComponent get(Object key) {
327: return getCurrentInstance().getViewRoot()
328: .findComponent((String) key);
329: }
330: });
331: }
332:
333: /**
334: * Provides parametric access to UIInput form values. Returns the submitted value during
335: * decoding, if available, otherwise the value property is returned.
336: *
337: * @return the UIInput value property
338: */
339: public Map<String, Object> getComponentValue() {
340: return FxSharedUtils
341: .getMappedFunction(new FxSharedUtils.ParameterMapper<String, Object>() {
342: public Object get(Object key) {
343: final UIInput component = (UIInput) getCurrentInstance()
344: .getViewRoot().findComponent(
345: (String) key);
346: return component.getSubmittedValue() != null ? component
347: .getSubmittedValue()
348: : component.getValue();
349: }
350: });
351: }
352:
353: /**
354: * Check via map if the calling user is in the given role
355: *
356: * @return if the calling user is in the given role
357: */
358: public Map<String, Boolean> getIsInRole() {
359: return FxSharedUtils
360: .getMappedFunction(new FxSharedUtils.ParameterMapper<String, Boolean>() {
361: public Boolean get(Object key) {
362: return getUserTicket().isInRole(
363: Role.valueOf((String) key));
364: }
365: });
366: }
367:
368: /**
369: * Escape a String for usage in java script (remove characters like ')
370: *
371: * @return escaped String
372: */
373: public Map<String, String> getEscapeForJavaScript() {
374: return FxSharedUtils
375: .getMappedFunction(new FxSharedUtils.ParameterMapper<String, String>() {
376: public String get(Object key) {
377: return FxFormatUtils.escapeForJavaScript(
378: (String) key, false, true);
379: }
380: });
381: }
382:
383: /**
384: * Returns the lower-case name of the given JSF message severity.
385: *
386: * @return the lower-case name of the given JSF message severity.
387: */
388: public Map<FacesMessage.Severity, String> getSeverityName() {
389: return FxSharedUtils
390: .getMappedFunction(new FxSharedUtils.ParameterMapper<FacesMessage.Severity, String>() {
391: public String get(Object key) {
392: final FacesMessage.Severity severity = (FacesMessage.Severity) key;
393: if (FacesMessage.SEVERITY_ERROR
394: .equals(severity)) {
395: return "error";
396: } else if (FacesMessage.SEVERITY_FATAL
397: .equals(severity)) {
398: return "fatal";
399: } else if (FacesMessage.SEVERITY_INFO
400: .equals(severity)) {
401: return "info";
402: } else if (FacesMessage.SEVERITY_WARN
403: .equals(severity)) {
404: return "warn";
405: } else {
406: return "";
407: }
408: }
409: });
410: }
411:
412: /**
413: * Returns a new unique ID, obtained from the view root.
414: *
415: * @return a new unique ID, obtained from the view root.
416: */
417: public String getUniqueId() {
418: return getCurrentInstance().getViewRoot().createUniqueId();
419: }
420:
421: /**
422: * Provides a key-based counter service for JSF pages. Supply your (unique) key
423: * and get an auto-incremented counter value, starting with 0.
424: *
425: * @return a key-based counter service for JSF pages
426: */
427: public Map<Object, Integer> getCounter() {
428: if (counterMap == null) {
429: counterMap = FxSharedUtils
430: .getMappedFunction(new FxSharedUtils.ParameterMapper<Object, Integer>() {
431: public Integer get(Object key) {
432: if (counters == null) {
433: counters = new HashMap<Object, Integer>();
434: }
435: final int ctr = FxSharedUtils.get(counters,
436: key, -1) + 1;
437: counters.put(key, ctr);
438: return ctr;
439: }
440: });
441: }
442: return counterMap;
443: }
444:
445: /**
446: * Like {@link #getCounter()}, but only returns the current counter value without incrementing it.
447: *
448: * @return a key-based counter "reader" service for JSF pages
449: */
450: public Map<Object, Integer> getCounterValue() {
451: if (counterValueMap == null) {
452: counterValueMap = FxSharedUtils
453: .getMappedFunction(new FxSharedUtils.ParameterMapper<Object, Integer>() {
454: public Integer get(Object key) {
455: return FxSharedUtils.get(counters, key, 0);
456: }
457: });
458: }
459: return counterValueMap;
460: }
461:
462: /**
463: * Returns the URL of the weblet mapping of the given resource name (e.g. "com.flexive.faces.web/js/flexiveComponents.js").
464: *
465: * @return the URL of the weblet mapping of the given resource name (e.g. "com.flexive.faces.web/js/flexiveComponents.js").
466: */
467: public Map<String, String> getWeblet() {
468: if (webletMap == null) {
469: webletMap = FxSharedUtils
470: .getMappedFunction(new FxSharedUtils.ParameterMapper<String, String>() {
471: public String get(Object key) {
472: return getCurrentInstance()
473: .getApplication().getViewHandler()
474: .getResourceURL(
475: getCurrentInstance(),
476: "weblet://" + key);
477: }
478: });
479: }
480: return webletMap;
481: }
482:
483: /**
484: * Returns the unique page ID generated for flexive responses.
485: *
486: * @return the unique page ID generated for flexive responses.
487: */
488: public long getPageId() {
489: final HttpServletResponse response = (HttpServletResponse) FacesContext
490: .getCurrentInstance().getExternalContext()
491: .getResponse();
492: return response instanceof FxResponseWrapper ? ((FxResponseWrapper) response)
493: .getId()
494: : -1;
495: }
496:
497: /**
498: * Returns the total render time at the moment of this method call.
499: *
500: * @return the total render time at the moment of this method call.
501: */
502: public long getPageRenderTime() {
503: final HttpServletResponse response = (HttpServletResponse) FacesContext
504: .getCurrentInstance().getExternalContext()
505: .getResponse();
506: return response instanceof FxResponseWrapper ? System
507: .currentTimeMillis()
508: - ((FxResponseWrapper) response).getCreatedAt() : 0;
509: }
510:
511: /**
512: * Return true if the content tree was modified in the current request.
513: *
514: * @return true if the content tree was modified in the current request.
515: */
516: public boolean isTreeModified() {
517: return FxContext.get().getTreeWasModified();
518: }
519:
520: /**
521: * Return if this is a new flexive installation that needs initialization still
522: *
523: * @return if this is a new flexive installation that needs initialization still
524: */
525: public boolean isNewInstallation() {
526: return CacheAdmin.isNewInstallation();
527: }
528:
529: /**
530: * A utility lookup function that returns true when a message key can be resolved in
531: * {@link MessageBean}, false otherwise.
532: *
533: * @return true when a message key can be resolved in {@link MessageBean}, false otherwise.
534: */
535: public Map<String, Boolean> getMessageExists() {
536: if (messageExistsMap == null) {
537: messageExistsMap = FxSharedUtils
538: .getMappedFunction(new FxSharedUtils.ParameterMapper<String, Boolean>() {
539: public Boolean get(Object key) {
540: try {
541: MessageBean.getInstance().getResource(
542: String.valueOf(key));
543: return true; // resource exists
544: } catch (MissingResourceException e) {
545: return false; // no message for the given key available
546: }
547: }
548: });
549: }
550: return messageExistsMap;
551: }
552:
553: /**
554: * Returns mapped access to FxContent instances indexed by primary key.
555: * The key parameter can be of type {@link Long}, {@link String}, {@link com.flexive.shared.content.FxPK FxPK},
556: * or {@link com.flexive.shared.value.FxReference FxReference}, as described in
557: * {@link com.flexive.shared.content.FxPK#fromObject(Object)}.
558: *
559: * @return the content instance for the given primary key
560: */
561: public Map<Object, FxContent> getContent() {
562: if (contentMap == null) {
563: contentMap = FxSharedUtils
564: .getMappedFunction(new FxSharedUtils.ParameterMapper<Object, FxContent>() {
565: public FxContent get(Object key) {
566: try {
567: return EJBLookup.getContentEngine()
568: .load(FxPK.fromObject(key));
569: } catch (FxApplicationException e) {
570: throw e.asRuntimeException();
571: }
572: }
573: });
574: }
575: return contentMap;
576: }
577:
578: /**
579: * <p>
580: * Returns mapped access to FxContent instances indexed by primary key.
581: * The key parameter can be of type {@link Long}, {@link String}, {@link com.flexive.shared.content.FxPK FxPK},
582: * or {@link com.flexive.shared.value.FxReference FxReference}, as described in
583: * {@link com.flexive.shared.content.FxPK#fromObject(Object)}.
584: * </p>
585: * <p>
586: * The only difference to {@link #getContent()} is that the returned content instance is "exploded", i.e.
587: * that empty top-level properties and groups are properly initialized and not returned as null. This is
588: * useful for editor pages that use contents provided by this bean.
589: * </p>
590: *
591: * @return the content instance for the given primary key
592: */
593: public Map<Object, FxContent> getExplodedContent() {
594: if (explodedContentMap == null) {
595: explodedContentMap = FxSharedUtils
596: .getMappedFunction(new FxSharedUtils.ParameterMapper<Object, FxContent>() {
597: public FxContent get(Object key) {
598: try {
599: final FxContent content = EJBLookup
600: .getContentEngine().load(
601: FxPK.fromObject(key));
602: content.getRootGroup().explode(true);
603: return content;
604: } catch (FxApplicationException e) {
605: throw e.asRuntimeException();
606: }
607: }
608: });
609: }
610: return explodedContentMap;
611: }
612:
613: /**
614: * Returns the current system timestamp.
615: *
616: * @return the current system timestamp.
617: */
618: public long getCurrentTimeMillis() {
619: return System.currentTimeMillis();
620: }
621:
622: /**
623: * Get the number of failed login attempts
624: *
625: * @return number of failed login attempts
626: */
627: public long getFailedLoginAttempts() {
628: return FxContext.get().getTicket().getFailedLoginAttempts();
629: }
630:
631: /**
632: * Return the structure envirnoment (filtered for the current user).
633: *
634: * @return the structure envirnoment (filtered for the current user).
635: */
636: public FxEnvironment getEnvironment() {
637: return CacheAdmin.getFilteredEnvironment();
638: }
639: }
|