001: /*
002: * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions
006: * are met
007: *
008: * - Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: *
011: * - Redistribution in binary form must reproduce the above copyright
012: * notice, this list of conditions and the following disclaimer in
013: * the documentation and/or other materials provided with the
014: * distribution.
015: *
016: * Neither the name of Sun Microsystems, Inc. or the names of
017: * contributors may be used to endorse or promote products derived
018: * from this software without specific prior written permission.
019: *
020: * This software is provided "AS IS," without a warranty of any
021: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
022: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
023: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
024: * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES
025: * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
026: * DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
027: * OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
028: * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
029: * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
030: * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE,
031: * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
032: *
033: * You acknowledge that Software is not designed, licensed or intended
034: * any nuclear facility.
035: */
036:
037: package com.sun.portal.app.communityportlets.faces;
038:
039: import java.io.IOException;
040: import javax.faces.application.NavigationHandler;
041: import javax.faces.context.FacesContext;
042: import javax.faces.context.ExternalContext;
043: import javax.faces.validator.Validator;
044: import javax.faces.validator.ValidatorException;
045: import javax.faces.event.AbortProcessingException;
046: import javax.faces.component.UIComponent;
047:
048: import com.sun.web.ui.event.WizardEvent;
049: import com.sun.web.ui.event.WizardEventListener;
050: import javax.portlet.ActionResponse;
051:
052: import com.sun.portal.log.common.PortalLogger;
053:
054: import com.sun.portal.community.CommunityManager;
055: import com.sun.portal.community.CommunityException;
056: import com.sun.portal.community.CommunityServiceException;
057: import com.sun.portal.community.CommunityServiceExceptionEntry;
058: import com.sun.portal.community.CommunityId;
059: import com.sun.portal.community.TemplateTokens;
060:
061: import com.sun.portal.community.urlmanager.CommunityURLManagerFactory;
062: import com.sun.portal.community.urlmanager.CommunityURLManager;
063: import com.sun.portal.search.providers.faces.SearchActionListener;
064: import com.sun.portal.search.providers.faces.SearchHandler;
065: import com.sun.portal.search.providers.faces.Category;
066: import com.sun.portal.search.providers.faces.TaxonomyDatabase;
067:
068: import java.util.Iterator;
069: import java.util.logging.Logger;
070: import java.util.logging.Level;
071: import javax.servlet.http.HttpServletRequest;
072:
073: public class CommunityCreateHandler extends CommunityBaseHandler
074: implements TemplateTokens, Validator, WizardEventListener,
075: SearchActionListener {
076: private static final String CREATE_TYPE_KEY = "ps-community-create-type";
077:
078: public static final int NAME_MAX_LENGTH = 20;
079: public static final int DESCRIPTION_MAX_LENGTH = 256;
080:
081: private String name;
082: private String description;
083: private String templateId;
084: private String errorMessage;
085: private CommunityId createdCommunityId = null;
086: private String createdURL;
087: private boolean createFailed = false;
088: private boolean createWarned = false;
089: private String homeURL;
090: private boolean categoryRequired = false;
091: private String rdmServer;
092: private String database;
093: private String categoryRootID;
094: private Category currentCategory;
095: private static Logger logger = PortalLogger
096: .getLogger(CommunityCreateHandler.class);
097: private SearchHandler searchHandler;
098:
099: public CommunityCreateHandler() {
100: CommunityManager cmgr = getCommunityManager();
101: rdmServer = cmgr.getSearchUrl();
102: database = cmgr.getSearchDb();
103: categoryRootID = cmgr.getSearchTaxonomyRoot();
104: searchHandler = new SearchHandler(this , rdmServer, this
105: .getUserLocale(),
106: CommunityBrowseHandler.COMMUNITYBROWSE_PROPERTIES);
107: TaxonomyDatabase taxonomyDb = new TaxonomyDatabase(
108: searchHandler, rdmServer, "taxonomy", "Categories");
109: searchHandler.setTaxonomyDatabase(taxonomyDb);
110: }
111:
112: public String getCurrentCategoryInSession() {
113: HttpServletRequest request = getHttpServletRequest();
114: String category = (String) request.getSession().getAttribute(
115: CATEGORY_SESSION_ATTRIBUTE_KEY);
116: if (category != null) {
117: this .searchHandler.setCurrentCategoryId(category);
118: //currentCategory = new Category(categoryRootID, category, rdmServer, database, "create.doBrowse", "create.goTop");
119: request.getSession().removeAttribute(
120: CATEGORY_SESSION_ATTRIBUTE_KEY);
121: }
122: return "";
123: }
124:
125: /*
126: public String getCategory() {
127: if (this.searchHandlercurrentCategory != null && !currentCategory.getId().equals(categoryRootID)) {
128: return currentCategory.getRelativeID();
129: }
130: return null;
131: }*/
132:
133: public String getName() {
134: if (this .name == null) {
135: this .name = "";
136: }
137: return this .name;
138: }
139:
140: public void setName(String name) {
141: this .name = name;
142: }
143:
144: public String getCreatedName() {
145: return getCreatedCommunityId().getName();
146: }
147:
148: public CommunityId getCreatedCommunityId() {
149: return this .createdCommunityId;
150: }
151:
152: public String getCreatedURL() {
153: return this .createdURL;
154: }
155:
156: public boolean getCreateFailed() {
157: return createFailed;
158: }
159:
160: public boolean getCreateWarned() {
161: return createWarned;
162: }
163:
164: public String getHomeURL() {
165: CommunityURLManager cum = CommunityURLManagerFactory
166: .getInstance().getCommunityURLManager();
167: return cum.getCommunityHomeURL(getHttpServletRequest());
168: }
169:
170: public int getNameMaxLength() {
171: return NAME_MAX_LENGTH;
172: }
173:
174: public int getDescriptionMaxLength() {
175: return DESCRIPTION_MAX_LENGTH;
176: }
177:
178: public String getDescription() {
179: if (this .description == null) {
180: this .description = "";
181: }
182: return this .description;
183: }
184:
185: public void setDescription(String description) {
186: this .description = description;
187: }
188:
189: public String getTemplateId() {
190: if (this .templateId == null) {
191: TemplateHandler th = new TemplateHandler();
192: this .templateId = th.getDefaultTemplateId();
193: }
194:
195: return this .templateId;
196: }
197:
198: public void setTemplateId(String templateId) {
199: if (templateId != null) {
200: this .templateId = templateId;
201: }
202: }
203:
204: public String getErrorMessage() {
205:
206: return errorMessage;
207: }
208:
209: public String getTemplateName() {
210:
211: return TemplateHandler.getTemplateName(getTemplateId(),
212: getUserLocale());
213: }
214:
215: public String getTemplateDescription() {
216:
217: return TemplateHandler.getTemplateDescription(getTemplateId(),
218: getUserLocale());
219: }
220:
221: public String getTemplatePreviewImageURI() {
222:
223: return TemplateHandler.getTemplatePreviewImageURI(
224: getTemplateId(), getUserLocale());
225: }
226:
227: public String goCommunity() {
228:
229: //
230: // redirect to newly created community page
231: //
232: ExternalContext eContext = getExternalContext();
233: ActionResponse aRes = (ActionResponse) eContext.getResponse();
234: String createdURL = getCreatedURL();
235:
236: try {
237: aRes.sendRedirect(createdURL);
238: } catch (IOException ioe) {
239: logRecord(logger, Level.SEVERE, "PSCPL_CSPACF00200", ioe,
240: createdURL);
241: FacesContext context = FacesContext.getCurrentInstance();
242: throw new AbortProcessingException(getMessage(context,
243: "community_redirect_failed"), ioe);
244: }
245:
246: // clear bean
247: clear();
248:
249: return "return";
250: }
251:
252: public String goCommunityHome() {
253:
254: //
255: // redirect to community home page
256: //
257: ExternalContext eContext = getExternalContext();
258: ActionResponse aRes = (ActionResponse) eContext.getResponse();
259: String homeURL = getHomeURL();
260:
261: try {
262: aRes.sendRedirect(homeURL);
263: } catch (IOException ioe) {
264: logRecord(logger, Level.SEVERE, "PSCPL_CSPACF00201", ioe,
265: homeURL);
266: FacesContext context = FacesContext.getCurrentInstance();
267: throw new AbortProcessingException(getMessage(context,
268: "community_redirect_failed"), ioe);
269: }
270:
271: // clear bean
272: clear();
273:
274: return "return";
275: }
276:
277: public Object saveState(FacesContext context) {
278:
279: return null;
280: }
281:
282: public void restoreState(FacesContext context, Object state) {
283:
284: }
285:
286: public void setTransient(boolean newTransientValue) {
287:
288: }
289:
290: public boolean isTransient() {
291:
292: return false;
293: }
294:
295: public boolean handleEvent(WizardEvent we) {
296:
297: //
298: // override the wizard button actions
299: //
300: FacesContext context = FacesContext.getCurrentInstance();
301: NavigationHandler nh = context.getApplication()
302: .getNavigationHandler();
303:
304: switch (we.getEvent()) {
305: case WizardEvent.CANCEL:
306: case WizardEvent.CLOSE:
307: // clear bean
308: clear();
309:
310: // reset navigation to the first step
311: nh.handleNavigation(context, null, "return");
312:
313: // redirect to community home page
314: String homeURL = getHomeURL();
315: ExternalContext eContext = getExternalContext();
316: ActionResponse aRes = (ActionResponse) eContext
317: .getResponse();
318:
319: try {
320: aRes.sendRedirect(homeURL);
321: } catch (IOException ioe) {
322: logRecord(logger, Level.SEVERE, "PSCPL_CSPACF00201",
323: ioe, homeURL);
324: throw new AbortProcessingException(getMessage(context,
325: "community_redirect_failed"), ioe);
326: }
327: break;
328:
329: case WizardEvent.FINISH:
330: // create community
331: createCommunity();
332:
333: // if errors found, navigate to error page
334: if (createFailed) {
335: errorMessage = getMessage(context, "create_failed");
336: nh.handleNavigation(context, null, "error");
337: }
338: break;
339: }
340:
341: return true;
342: }
343:
344: public String getCreateType() {
345: String createType = getConfigParameter(CREATE_TYPE_KEY);
346: if (createType == null || createType.length() == 0) {
347: throw new NullPointerException("create type was null");
348: }
349:
350: return createType;
351: }
352:
353: public void createCommunity() {
354: CommunityManager cm = getCommunityManager();
355: FacesContext context = FacesContext.getCurrentInstance();
356:
357: String createType = getCreateType();
358: CommunityId cid = new CommunityId(createType, getName());
359: String searchURL = cm.getSearchUrl();
360: String searchDB = cm.getSearchDb();
361: String categoryID = searchHandler.getCurrentCategory().isRoot() ? null
362: : searchHandler.getCurrentCategory().getRelativeID();
363:
364: CommunityAccessHandler cah = (CommunityAccessHandler) context
365: .getApplication().createValueBinding("#{access}")
366: .getValue(context);
367:
368: try {
369: cm.createCommunity(cid, getTemplateId(), categoryID,
370: getDescription(), cah.isMembershipRestricted(), cah
371: .isDataSecure(), cah.isListed());
372: getHttpServletRequest()
373: .getSession()
374: .setAttribute(
375: this .COMMUNITY_CREATED_DELETE_NOTIFICATION_SESSION_ATTRIBUTE_KEY,
376: "true");
377:
378: } catch (CommunityServiceException cse) {
379: createWarned = true;
380:
381: // log failed service names w/ corresponding exceptions
382: if (logger.isLoggable(Level.WARNING)) {
383: for (Iterator i = cse.getEntries().iterator(); i
384: .hasNext();) {
385: CommunityServiceExceptionEntry entry = (CommunityServiceExceptionEntry) i
386: .next();
387: logRecord(logger, Level.WARNING,
388: "PSCPL_CSPACF00211", entry.getThrowable(),
389: new Object[] { entry.getCommunityId(),
390: entry.getServiceName() });
391: }
392: }
393: } catch (CommunityException cme) {
394: createFailed = true;
395: logRecord(logger, Level.SEVERE, "PSCPL_CSPACF00207", cme,
396: cid);
397:
398: // clean up half-baked community
399: destroyCommunity(cid, searchURL, searchDB);
400:
401: } catch (Throwable th) {
402: createFailed = true;
403: logRecord(logger, Level.SEVERE, "PSCPL_CSPACF00207", th,
404: cid);
405:
406: // clean up half-baked community
407: destroyCommunity(cid, searchURL, searchDB);
408: }
409:
410: if (!createFailed) {
411: //
412: // preserve ID of the community that just got created before clearning
413: //
414: createdCommunityId = cid;
415:
416: //
417: // generate community URL
418: //
419: CommunityURLManager cum = CommunityURLManagerFactory
420: .getInstance().getCommunityURLManager();
421: try {
422: createdURL = cum.getCommunityAccessURL(
423: getHttpServletRequest(), createdCommunityId);
424: } catch (CommunityException cme) {
425: logRecord(logger, Level.SEVERE, "PSCPL_CSPACF00209",
426: cme, createdCommunityId);
427: throw new AbortProcessingException(getMessage(context,
428: "community_create_failed"), cme);
429: }
430: }
431: }
432:
433: /*
434: * This method attempts to clean up community that failed to create.
435: **/
436: private void destroyCommunity(CommunityId cid, String searchURL,
437: String searchDB) {
438: CommunityManager cm = getCommunityManager();
439: try {
440: cm.destroyCommunity(cid, true);
441: } catch (CommunityServiceException cse) {
442: // log failed service names w/ corresponding exceptions
443: if (logger.isLoggable(Level.WARNING)) {
444: for (Iterator i = cse.getEntries().iterator(); i
445: .hasNext();) {
446: CommunityServiceExceptionEntry entry = (CommunityServiceExceptionEntry) i
447: .next();
448: logRecord(logger, Level.WARNING,
449: "PSCPL_CSPACF00212", entry.getThrowable(),
450: new Object[] { entry.getCommunityId(),
451: entry.getServiceName() });
452: }
453: }
454: } catch (CommunityException ce) {
455: // just log it.
456: logRecord(logger, Level.SEVERE, "PSCPL_CSPACF00210", ce,
457: new Object[] { cid, searchURL, searchDB });
458: }
459: }
460:
461: public void validateName(FacesContext context,
462: UIComponent component, Object value)
463: throws ValidatorException {
464: String name = (String) value;
465: //
466: // check length
467: //
468: if (name == null || name.trim().length() == 0) {
469: if (logger.isLoggable(Level.FINER)) {
470: logger.finer("PSCPL_CSPACF00202");
471: }
472: throw new ValidatorException(getFacesMessage(context,
473: "missing_community_name"));
474: }
475:
476: if (name.length() > NAME_MAX_LENGTH) {
477: if (logger.isLoggable(Level.FINER)) {
478: logger.log(Level.FINER, "PSCPL_CSPACF00203",
479: new Object[] { name,
480: Integer.toString(NAME_MAX_LENGTH) });
481: }
482: throw new ValidatorException(getFacesMessage(context,
483: "too_long_community_name"));
484: }
485:
486: //
487: // check for invalid characters
488: //
489: boolean isAlphaNumeric = name.matches("\\p{Alnum}*");
490:
491: if (!isAlphaNumeric) {
492: if (logger.isLoggable(Level.FINER)) {
493: logger.log(Level.FINER, "PSCPL_CSPACF00204", name);
494: }
495: throw new ValidatorException(getFacesMessage(context,
496: "invalid_community_name"));
497: }
498:
499: //
500: // check if the community already exists
501: //
502: boolean exists;
503: CommunityManager cm = getCommunityManager();
504: try {
505: exists = cm.existsCommunity(new CommunityId(
506: getCreateType(), name));
507: } catch (CommunityException ce) {
508: // navigate to error page
509: errorMessage = getMessage(context, "server_error");
510: NavigationHandler nh = context.getApplication()
511: .getNavigationHandler();
512: nh.handleNavigation(context, null, "error");
513: logger.log(Level.SEVERE, "PSCPL_CSPACF00208",
514: new Object[] { ce });
515: throw new AbortProcessingException(getMessage(context,
516: "server_error"));
517: }
518:
519: if (exists) {
520: if (logger.isLoggable(Level.FINER)) {
521: logger.log(Level.FINER, "PSCPL_CSPACF00205", name);
522: }
523: throw new ValidatorException(getFacesMessage(context,
524: "community_already_exists"));
525: }
526: }
527:
528: public void validateDescription(FacesContext context,
529: UIComponent component, Object value)
530: throws ValidatorException {
531: String description = (String) value;
532:
533: //
534: // check length
535: //
536: if (description.length() > DESCRIPTION_MAX_LENGTH) {
537: if (logger.isLoggable(Level.FINER)) {
538: logger
539: .log(
540: Level.FINER,
541: "PSCPL_CSPACF00206",
542: new Object[] {
543: description,
544: Integer
545: .toString(DESCRIPTION_MAX_LENGTH) });
546: }
547: throw new ValidatorException(getFacesMessage(context,
548: "too_long_community_description"));
549: }
550: }
551:
552: public void validate(FacesContext context, UIComponent component,
553: Object value) throws ValidatorException {
554: validateName(context, component, value);
555: validateDescription(context, component, value);
556: }
557:
558: protected void clear() {
559: searchHandler.setCurrentCategoryId(this .categoryRootID);
560: searchHandler.setSearched(false);
561: setName("");
562: setDescription("");
563: setTemplateId(null);
564: createFailed = false;
565: createWarned = false;
566:
567: // clear access bean
568: FacesContext context = FacesContext.getCurrentInstance();
569: CommunityAccessHandler cah = (CommunityAccessHandler) context
570: .getApplication().createValueBinding("#{access}")
571: .getValue(context);
572: cah.clear();
573: }
574:
575: public SearchHandler getSearch() {
576: return searchHandler;
577: }
578:
579: public void setCategoryRequired(boolean categoryRequired) {
580: this .categoryRequired = categoryRequired;
581: }
582:
583: public String goTop() {
584: this .searchHandler.reset();
585: return "browse";
586: }
587:
588: public String doBrowse() {
589: return "browse";
590: }
591:
592: public String getBrowseMethod() {
593: return "create.search";
594: }
595:
596: public String doSearch() {
597: return "search";
598: }
599:
600: public String doNamedSearch() {
601: return "";
602: }
603:
604: public String getSearchHandlerPath() {
605: return "create.search";
606: }
607:
608: }
|