001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/alias/tags/sakai_2-4-1/alias-tool/tool/src/java/org/sakaiproject/alias/tool/AliasesAction.java $
003: * $Id: AliasesAction.java 13111 2006-07-31 15:59:58Z ggolden@umich.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.alias.tool;
021:
022: // imports
023: import java.util.List;
024:
025: import org.sakaiproject.alias.api.AliasEdit;
026: import org.sakaiproject.alias.cover.AliasService;
027: import org.sakaiproject.authz.cover.SecurityService;
028: import org.sakaiproject.cheftool.Context;
029: import org.sakaiproject.cheftool.JetspeedRunData;
030: import org.sakaiproject.cheftool.PagedResourceActionII;
031: import org.sakaiproject.cheftool.RunData;
032: import org.sakaiproject.cheftool.VelocityPortlet;
033: import org.sakaiproject.cheftool.api.Menu;
034: import org.sakaiproject.cheftool.api.MenuItem;
035: import org.sakaiproject.cheftool.menu.MenuEntry;
036: import org.sakaiproject.cheftool.menu.MenuImpl;
037: import org.sakaiproject.courier.api.ObservingCourier;
038: import org.sakaiproject.event.api.SessionState;
039: import org.sakaiproject.exception.IdInvalidException;
040: import org.sakaiproject.exception.IdUnusedException;
041: import org.sakaiproject.exception.IdUsedException;
042: import org.sakaiproject.exception.InUseException;
043: import org.sakaiproject.exception.PermissionException;
044: import org.sakaiproject.util.ResourceLoader;
045: import org.sakaiproject.util.StringUtil;
046:
047: /**
048: * <p>
049: * AliasesAction is the Sakai aliases editor.
050: * </p>
051: */
052: public class AliasesAction extends PagedResourceActionII {
053: /**
054: * Populate the state object, if needed.
055: */
056: /** Resource bundle using current language locale */
057: private static ResourceLoader rb = new ResourceLoader("admin");
058:
059: protected void initState(SessionState state,
060: VelocityPortlet portlet, JetspeedRunData rundata) {
061: super .initState(state, portlet, rundata);
062:
063: } // initState
064:
065: /**
066: * Setup our observer to be watching for change events for our channel.
067: *
068: * @param peid
069: * The portlet id.
070: */
071: private void updateObservationOfChannel(SessionState state,
072: String peid) {
073: // EventObservingCourier observer = (EventObservingCourier) state.getAttribute(STATE_OBSERVER);
074: //
075: // // the delivery location for this tool
076: // String deliveryId = clientWindowId(state, peid);
077: // observer.setDeliveryId(deliveryId);
078:
079: } // updateObservationOfChannel
080:
081: /**
082: * build the context
083: */
084: public String buildMainPanelContext(VelocityPortlet portlet,
085: Context context, RunData rundata, SessionState state) {
086: context.put("tlang", rb);
087: String template = null;
088:
089: // if not logged in as the super user, we won't do anything
090: if (!SecurityService.isSuperUser()) {
091: return (String) getContext(rundata).get("template")
092: + "_noaccess";
093: }
094:
095: // put $action into context for menus, forms and links
096: context.put(Menu.CONTEXT_ACTION, state
097: .getAttribute(STATE_ACTION));
098:
099: // check mode and dispatch
100: String mode = (String) state.getAttribute("mode");
101: if (mode == null) {
102: template = buildListContext(state, context);
103: } else if (mode.equals("new")) {
104: template = buildNewContext(state, context);
105: } else if (mode.equals("edit")) {
106: template = buildEditContext(state, context);
107: } else if (mode.equals("confirm")) {
108: template = buildConfirmRemoveContext(state, context);
109: } else {
110: Log.warn("chef", "AliasesAction: mode: " + mode);
111: template = buildListContext(state, context);
112: }
113:
114: String prefix = (String) getContext(rundata).get("template");
115: return prefix + template;
116:
117: } // buildNormalContext
118:
119: /**
120: * Build the context for the main list mode.
121: */
122: private String buildListContext(SessionState state, Context context) {
123: // put the service in the context
124: context.put("service", AliasService.getInstance());
125:
126: // put all aliases into the context
127: context.put("aliases", prepPage(state));
128:
129: // build the menu
130: Menu bar = new MenuImpl();
131: if (AliasService.allowAdd()) {
132: bar.add(new MenuEntry(rb.getString("alias.new"), null,
133: true, MenuItem.CHECKED_NA, "doNew"));
134: }
135:
136: // add the paging commands
137: addListPagingMenus(bar, state);
138:
139: // add the search commands
140: addSearchMenus(bar, state);
141:
142: // add the refresh commands
143: addRefreshMenus(bar, state);
144:
145: if (bar.size() > 0) {
146: context.put(Menu.CONTEXT_MENU, bar);
147: }
148:
149: return "_list";
150:
151: } // buildListContext
152:
153: /**
154: * Build the context for the new alias mode.
155: */
156: private String buildNewContext(SessionState state, Context context) {
157: return "_edit";
158:
159: } // buildNewContext
160:
161: /**
162: * Build the context for the new alias mode.
163: */
164: private String buildEditContext(SessionState state, Context context) {
165: // name the html form for alias edit fields
166: context.put("form-name", "alias-form");
167:
168: // get the alias to edit
169: AliasEdit alias = (AliasEdit) state.getAttribute("alias");
170: context.put("alias", alias);
171:
172: // build the menu
173: // we need the form fields for the remove...
174: boolean menuPopulated = false;
175: Menu bar = new MenuImpl();
176: if (AliasService.allowRemoveAlias(alias.getId())) {
177: bar
178: .add(new MenuEntry(rb.getString("alias.remove"),
179: null, true, MenuItem.CHECKED_NA,
180: "doRemove", "alias-form"));
181: menuPopulated = true;
182: }
183:
184: if (menuPopulated) {
185: state.setAttribute(Menu.STATE_MENU, bar);
186: context.put(Menu.CONTEXT_MENU, bar);
187: }
188:
189: return "_edit";
190:
191: } // buildEditContext
192:
193: /**
194: * Build the context for the new alias mode.
195: */
196: private String buildConfirmRemoveContext(SessionState state,
197: Context context) {
198: // get the alias to edit
199: AliasEdit alias = (AliasEdit) state.getAttribute("alias");
200: context.put("alias", alias);
201:
202: return "_confirm_remove";
203:
204: } // buildConfirmRemoveContext
205:
206: /**
207: * doNew called when "eventSubmit_doNew" is in the request parameters to add a new alias
208: */
209: public void doNew(RunData data, Context context) {
210: SessionState state = ((JetspeedRunData) data)
211: .getPortletSessionState(((JetspeedRunData) data)
212: .getJs_peid());
213: state.setAttribute("mode", "new");
214:
215: // mark the alias as new, so on cancel it can be deleted
216: state.setAttribute("new", "true");
217:
218: // disable auto-updates while not in list mode
219: ObservingCourier courier = (ObservingCourier) state
220: .getAttribute(STATE_OBSERVER);
221: if (courier != null)
222: courier.disable();
223:
224: } // doNew
225:
226: /**
227: * doEdit called when "eventSubmit_doEdit" is in the request parameters to edit a alias
228: */
229: public void doEdit(RunData data, Context context) {
230: SessionState state = ((JetspeedRunData) data)
231: .getPortletSessionState(((JetspeedRunData) data)
232: .getJs_peid());
233: String id = data.getParameters().getString("id");
234:
235: // get the alias
236: try {
237: AliasEdit alias = AliasService.edit(id);
238: state.setAttribute("alias", alias);
239: state.setAttribute("mode", "edit");
240:
241: // disable auto-updates while not in list mode
242: ObservingCourier courier = (ObservingCourier) state
243: .getAttribute(STATE_OBSERVER);
244: if (courier != null)
245: courier.disable();
246: } catch (IdUnusedException e) {
247: Log.warn("chef", "AliasesAction.doEdit: alias not found: "
248: + id);
249:
250: addAlert(state, rb.getString("alias.alias") + " " + id
251: + " " + rb.getString("alias.notfound"));
252: state.removeAttribute("mode");
253:
254: // make sure auto-updates are enabled
255: ObservingCourier courier = (ObservingCourier) state
256: .getAttribute(STATE_OBSERVER);
257: if (courier != null)
258: courier.enable();
259: } catch (PermissionException e) {
260: addAlert(state, rb.getString("alias.notpermis") + " " + id);
261: state.removeAttribute("mode");
262:
263: // make sure auto-updates are enabled
264: ObservingCourier courier = (ObservingCourier) state
265: .getAttribute(STATE_OBSERVER);
266: if (courier != null)
267: courier.enable();
268: } catch (InUseException e) {
269: addAlert(state, rb.getString("alias.someone") + " " + id);
270: state.removeAttribute("mode");
271:
272: // make sure auto-updates are enabled
273: ObservingCourier courier = (ObservingCourier) state
274: .getAttribute(STATE_OBSERVER);
275: if (courier != null)
276: courier.enable();
277: }
278:
279: } // doEdit
280:
281: /**
282: * doSave called when "eventSubmit_doSave" is in the request parameters to save alias edits
283: */
284: public void doSave(RunData data, Context context) {
285: SessionState state = ((JetspeedRunData) data)
286: .getPortletSessionState(((JetspeedRunData) data)
287: .getJs_peid());
288:
289: // read the form - if rejected, leave things as they are
290: if (!readAliasForm(data, state))
291: return;
292:
293: // commit the change
294: AliasEdit alias = (AliasEdit) state.getAttribute("alias");
295: if (alias != null) {
296: AliasService.commit(alias);
297: }
298:
299: // cleanup
300: state.removeAttribute("alias");
301: state.removeAttribute("new");
302:
303: // return to main mode
304: state.removeAttribute("mode");
305:
306: // make sure auto-updates are enabled
307: ObservingCourier courier = (ObservingCourier) state
308: .getAttribute(STATE_OBSERVER);
309: if (courier != null)
310: courier.enable();
311:
312: } // doSave
313:
314: /**
315: * doCancel called when "eventSubmit_doCancel" is in the request parameters to cancel alias edits
316: */
317: public void doCancel(RunData data, Context context) {
318: SessionState state = ((JetspeedRunData) data)
319: .getPortletSessionState(((JetspeedRunData) data)
320: .getJs_peid());
321:
322: // get the alias
323: AliasEdit alias = (AliasEdit) state.getAttribute("alias");
324: if (alias != null) {
325: // if this was a new, delete the alias
326: if ("true".equals(state.getAttribute("new"))) {
327: // remove
328: try {
329: AliasService.remove(alias);
330: } catch (PermissionException e) {
331: addAlert(state, rb.getString("alias.notpermis1")
332: + " " + alias.getId());
333: }
334: } else {
335: AliasService.cancel(alias);
336: }
337: }
338:
339: // cleanup
340: state.removeAttribute("alias");
341: state.removeAttribute("new");
342:
343: // return to main mode
344: state.removeAttribute("mode");
345:
346: // make sure auto-updates are enabled
347: ObservingCourier courier = (ObservingCourier) state
348: .getAttribute(STATE_OBSERVER);
349: if (courier != null)
350: courier.enable();
351:
352: } // doCancel
353:
354: /**
355: * doRemove called when "eventSubmit_doRemove" is in the request parameters to confirm removal of the alias
356: */
357: public void doRemove(RunData data, Context context) {
358: SessionState state = ((JetspeedRunData) data)
359: .getPortletSessionState(((JetspeedRunData) data)
360: .getJs_peid());
361:
362: // read the form - if rejected, leave things as they are
363: if (!readAliasForm(data, state))
364: return;
365:
366: // go to remove confirm mode
367: state.setAttribute("mode", "confirm");
368:
369: } // doRemove
370:
371: /**
372: * doRemove_confirmed called when "eventSubmit_doRemove_confirmed" is in the request parameters to remove the alias
373: */
374: public void doRemove_confirmed(RunData data, Context context) {
375: SessionState state = ((JetspeedRunData) data)
376: .getPortletSessionState(((JetspeedRunData) data)
377: .getJs_peid());
378:
379: // get the alias
380: AliasEdit alias = (AliasEdit) state.getAttribute("alias");
381:
382: // remove
383: try {
384: AliasService.remove(alias);
385: } catch (PermissionException e) {
386: addAlert(state, rb.getString("alias.notpermis1") + " "
387: + alias.getId());
388: }
389:
390: // cleanup
391: state.removeAttribute("alias");
392: state.removeAttribute("new");
393:
394: // go to main mode
395: state.removeAttribute("mode");
396:
397: // make sure auto-updates are enabled
398: ObservingCourier courier = (ObservingCourier) state
399: .getAttribute(STATE_OBSERVER);
400: if (courier != null)
401: courier.enable();
402:
403: } // doRemove_confirmed
404:
405: /**
406: * doCancel_remove called when "eventSubmit_doCancel_remove" is in the request parameters to cancel alias removal
407: */
408: public void doCancel_remove(RunData data, Context context) {
409: SessionState state = ((JetspeedRunData) data)
410: .getPortletSessionState(((JetspeedRunData) data)
411: .getJs_peid());
412:
413: // return to edit mode
414: state.setAttribute("mode", "edit");
415:
416: } // doCancel_remove
417:
418: /**
419: * Read the alias form and update the alias in state.
420: *
421: * @return true if the form is accepted, false if there's a validation error (an alertMessage will be set)
422: */
423: private boolean readAliasForm(RunData data, SessionState state) {
424: // read the form
425: String id = StringUtil.trimToNull(data.getParameters()
426: .getString("id"));
427: String target = StringUtil.trimToNull(data.getParameters()
428: .getString("target"));
429:
430: // get the alias
431: AliasEdit alias = (AliasEdit) state.getAttribute("alias");
432:
433: // add if needed
434: if (alias == null) {
435: try {
436: // add the alias, getting an edit clone to it
437: alias = AliasService.add(id);
438:
439: // put the alias in the state
440: state.setAttribute("alias", alias);
441: } catch (IdUsedException e) {
442: addAlert(state, rb.getString("alias.use"));
443: return false;
444: } catch (IdInvalidException e) {
445: addAlert(state, rb.getString("alias.invalid"));
446: return false;
447: } catch (PermissionException e) {
448: addAlert(state, rb.getString("alias.notpermis2"));
449: return false;
450: }
451: }
452:
453: // update
454: if (alias != null) {
455: alias.setTarget(target);
456: }
457:
458: return true;
459:
460: } // readAliasForm
461:
462: /**
463: * {@inheritDoc}
464: */
465: protected List readResourcesPage(SessionState state, int first,
466: int last) {
467: // search?
468: String search = StringUtil.trimToNull((String) state
469: .getAttribute(STATE_SEARCH));
470:
471: if (search != null) {
472: return AliasService.searchAliases(search, first, last);
473: }
474:
475: return AliasService.getAliases(first, last);
476: }
477:
478: /**
479: * {@inheritDoc}
480: */
481: protected int sizeResources(SessionState state) {
482: // search?
483: String search = StringUtil.trimToNull((String) state
484: .getAttribute(STATE_SEARCH));
485:
486: if (search != null) {
487: return AliasService.countSearchAliases(search);
488: }
489:
490: return AliasService.countAliases();
491: }
492:
493: } // AliasesAction
|