001: /*
002: * Copyright 2005-2006 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.roller.ui.authoring.struts.actions;
018:
019: import org.apache.commons.logging.Log;
020: import org.apache.roller.RollerException;
021: import org.apache.roller.business.pings.PingTargetManager;
022: import org.apache.roller.business.RollerFactory;
023: import org.apache.roller.pojos.PingTargetData;
024: import org.apache.roller.pojos.WebsiteData;
025: import org.apache.roller.ui.authoring.struts.forms.PingTargetForm;
026: import org.apache.roller.ui.core.BasePageModel;
027: import org.apache.roller.ui.core.RequestConstants;
028: import org.apache.roller.ui.core.RollerRequest;
029: import org.apache.struts.action.*;
030: import org.apache.struts.actions.DispatchAction;
031:
032: import javax.servlet.ServletException;
033: import javax.servlet.http.HttpServletRequest;
034: import javax.servlet.http.HttpServletResponse;
035: import java.util.List;
036:
037: /**
038: * Base class for both common and custom ping target operations. The methods
039: * here apply to creating, editing and removing ping targets. Operations for
040: * maintaining automatic ping configurations are handled by
041: * {@link PingSetupAction}.
042: */
043: public abstract class BasePingTargetsAction extends DispatchAction {
044: // These are expected to be defined forwards by the concrete subclass actions.
045: protected static final String VIEW_PAGE = "pingTargets.page";
046: protected static final String PING_TARGET_EDIT_PAGE = "pingTargetEdit.page";
047: protected static final String PING_TARGET_DELETE_PAGE = "pingTargetDeleteOK.page";
048: protected static final String ACCESS_DENIED_PAGE = "access-denied";
049:
050: public abstract String getPingTargetsTitle();
051:
052: public abstract String getPingTargetEditTitle();
053:
054: public abstract String getPingTargetDeleteOKTitle();
055:
056: public BasePingTargetsAction() {
057:
058: }
059:
060: /**
061: * Implements the default action (view) if the method is not specified.
062: *
063: * @param mapping
064: * @param actionForm
065: * @param request
066: * @param response
067: * @return the same result as <code>view()</code>
068: * @throws Exception
069: * @see org.apache.struts.actions.DispatchAction#unspecified(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
070: */
071: protected ActionForward unspecified(ActionMapping mapping,
072: ActionForm actionForm, HttpServletRequest request,
073: HttpServletResponse response) throws Exception {
074: return view(mapping, actionForm, request, response);
075: }
076:
077: /**
078: * Display the ping targets.
079: *
080: * @param mapping
081: * @param form
082: * @param req
083: * @param res
084: * @return forward to the ping targets page
085: * @throws Exception
086: */
087: public ActionForward view(ActionMapping mapping, ActionForm form,
088: HttpServletRequest req, HttpServletResponse res)
089: throws Exception {
090: ActionForward forward = mapping.findForward(VIEW_PAGE);
091: RollerRequest rreq = RollerRequest.getRollerRequest(req);
092: try {
093: BasePageModel pageModel = new BasePageModel(
094: getPingTargetsTitle(), req, res, mapping);
095: req.setAttribute("model", pageModel);
096: if (!hasRequiredRights(rreq, rreq.getWebsite())) {
097: return mapping.findForward(ACCESS_DENIED_PAGE);
098: }
099:
100: List pingTargets = getPingTargets(rreq);
101: req.setAttribute("pingTargets", pingTargets);
102: return forward;
103: } catch (Exception e) {
104: getLogger().error("ERROR in action", e);
105: throw new ServletException(e);
106: }
107: }
108:
109: /**
110: * Save a ping target, new or existing (depending on whether the id is non-empty).
111: *
112: * @param mapping
113: * @param form
114: * @param req
115: * @param res
116: * @return the result of <code>view()</code> after the target is saved.
117: * @throws Exception
118: */
119: public ActionForward save(ActionMapping mapping, ActionForm form,
120: HttpServletRequest req, HttpServletResponse res)
121: throws Exception {
122: RollerRequest rreq = RollerRequest.getRollerRequest(req);
123: PingTargetManager pingTargetMgr = RollerFactory.getRoller()
124: .getPingTargetManager();
125: PingTargetForm pingTargetForm = (PingTargetForm) form;
126: try {
127: BasePageModel pageModel = new BasePageModel(
128: getPingTargetEditTitle(), req, res, mapping);
129: req.setAttribute("model", pageModel);
130: if (!hasRequiredRights(rreq, rreq.getWebsite())) {
131: return mapping.findForward(ACCESS_DENIED_PAGE);
132: }
133:
134: PingTargetData pingTarget = null;
135: String pingTargetId = pingTargetForm.getId();
136: if (pingTargetId != null && pingTargetId.length() > 0) {
137: pingTarget = pingTargetMgr.getPingTarget(pingTargetForm
138: .getId());
139: if (pingTarget == null)
140: throw new RollerException(
141: "No such ping target id: " + pingTargetId);
142: pingTargetForm.copyTo(pingTarget, req.getLocale());
143: } else {
144: pingTarget = createPingTarget(rreq, pingTargetForm);
145: }
146:
147: // Call private helper to validate ping target
148: // If there are errors, go back to the target edit page.
149: ActionMessages errors = validate(rreq, pingTarget);
150: if (!errors.isEmpty()) {
151: saveErrors(rreq.getRequest(), errors);
152: return mapping.findForward(PING_TARGET_EDIT_PAGE);
153: }
154:
155: // Appears to be ok.
156: // Save it, commit and return refreshed view of target list.
157: pingTargetMgr.savePingTarget(pingTarget);
158: RollerFactory.getRoller().flush();
159:
160: ActionMessages msgs = new ActionMessages();
161: msgs.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
162: "pingTarget.saved"));
163: saveMessages(req, msgs);
164:
165: return view(mapping, form, req, res);
166: } catch (Exception e) {
167: getLogger().error("ERROR in action", e);
168: throw new ServletException(e);
169: }
170: }
171:
172: /**
173: * Add a new ping target. Loads the edit view blank.
174: *
175: * @param mapping
176: * @param form
177: * @param req
178: * @param res
179: * @return the edit page (blank)
180: * @throws Exception
181: */
182: public ActionForward addNew(ActionMapping mapping, ActionForm form,
183: HttpServletRequest req, HttpServletResponse res)
184: throws Exception {
185: BasePageModel pageModel = new BasePageModel(
186: getPingTargetEditTitle(), req, res, mapping);
187: req.setAttribute("model", pageModel);
188: return mapping.findForward(PING_TARGET_EDIT_PAGE);
189: }
190:
191: /**
192: * Edit a ping target (load edit view)
193: *
194: * @param mapping
195: * @param form
196: * @param req
197: * @param res
198: * @return the edit view with the form populated with the ping target specified by the id in the request.
199: * @throws Exception
200: */
201: public ActionForward editSelected(ActionMapping mapping,
202: ActionForm form, HttpServletRequest req,
203: HttpServletResponse res) throws Exception {
204: ActionForward forward = mapping
205: .findForward(PING_TARGET_EDIT_PAGE);
206: RollerRequest rreq = RollerRequest.getRollerRequest(req);
207: try {
208: BasePageModel pageModel = new BasePageModel(
209: getPingTargetEditTitle(), req, res, mapping);
210: req.setAttribute("model", pageModel);
211: if (!hasRequiredRights(rreq, rreq.getWebsite())) {
212: return mapping.findForward(ACCESS_DENIED_PAGE);
213: }
214: PingTargetData pingTarget = select(rreq);
215: ((PingTargetForm) form).copyFrom(pingTarget, req
216: .getLocale());
217: return forward;
218: } catch (Exception e) {
219: getLogger().error("ERROR in action", e);
220: throw new ServletException(e);
221: }
222: }
223:
224: /**
225: * Delete a ping target (load delete confirmation view).
226: *
227: * @param mapping
228: * @param form
229: * @param req
230: * @param res
231: * @return the delete confirmation view with the form populated with the ping target specified by the id in the request.
232: * @throws Exception
233: */
234: public ActionForward deleteSelected(ActionMapping mapping,
235: ActionForm form, HttpServletRequest req,
236: HttpServletResponse res) throws Exception {
237: ActionForward forward = mapping
238: .findForward(PING_TARGET_DELETE_PAGE);
239: RollerRequest rreq = RollerRequest.getRollerRequest(req);
240: try {
241: BasePageModel pageModel = new BasePageModel(
242: getPingTargetDeleteOKTitle(), req, res, mapping);
243: req.setAttribute("model", pageModel);
244: if (!hasRequiredRights(rreq, rreq.getWebsite())) {
245: return mapping.findForward(ACCESS_DENIED_PAGE);
246: }
247: PingTargetData pingTarget = select(rreq);
248: ((PingTargetForm) form).copyFrom(pingTarget, req
249: .getLocale());
250: return forward;
251: } catch (Exception e) {
252: getLogger().error("ERROR in action", e);
253: throw new ServletException(e);
254: }
255: }
256:
257: /**
258: * Delete a ping target (already confirmed). This performs the actual deletion.
259: *
260: * @param mapping
261: * @param form
262: * @param req
263: * @param res
264: * @return the result of <code>view()</code> after the deletion
265: * @throws Exception
266: */
267: public ActionForward deleteConfirmed(ActionMapping mapping,
268: ActionForm form, HttpServletRequest req,
269: HttpServletResponse res) throws Exception {
270: RollerRequest rreq = RollerRequest.getRollerRequest(req);
271: PingTargetForm pingTargetForm = (PingTargetForm) form;
272: PingTargetManager pingTargetMgr = RollerFactory.getRoller()
273: .getPingTargetManager();
274: try {
275: if (!hasRequiredRights(rreq, rreq.getWebsite())) {
276: return mapping.findForward(ACCESS_DENIED_PAGE);
277: }
278: String pingTargetId = pingTargetForm.getId();
279: if (pingTargetId == null || pingTargetId.length() == 0) {
280: throw new RollerException("Missing ping target id.");
281: }
282: PingTargetData ping = pingTargetMgr
283: .getPingTarget(pingTargetId);
284: pingTargetMgr.removePingTarget(ping);
285: RollerFactory.getRoller().flush();
286: return view(mapping, form, req, res);
287: } catch (Exception e) {
288: getLogger().error("ERROR in action", e);
289: throw new ServletException(e);
290: }
291: }
292:
293: // TODO: Consider unifying with other RollerRequest methods
294:
295: /**
296: * Helper to select the ping target specified by the id in the request.
297: *
298: * @param rreq
299: * @return the ping target specified by the id in the request
300: * @throws RollerException
301: */
302: protected PingTargetData select(RollerRequest rreq)
303: throws RollerException {
304: String pingTargetId = rreq.getRequest().getParameter(
305: RequestConstants.PINGTARGET_ID);
306: PingTargetManager pingTargetMgr = RollerFactory.getRoller()
307: .getPingTargetManager();
308: if (pingTargetId == null || pingTargetId.length() == 0) {
309: throw new RollerException("Missing ping target id: "
310: + pingTargetId);
311: }
312:
313: PingTargetData pingTarget = pingTargetMgr
314: .getPingTarget(pingTargetId);
315: if (pingTarget == null) {
316: throw new RollerException("No such ping target id: "
317: + pingTargetId);
318: }
319: return pingTarget;
320: }
321:
322: /**
323: * Private helper to validate a ping target.
324: *
325: * @param rreq the request
326: * @param pingTarget the ping target to validate
327: * @return an <code>ActionMessages</code> object with
328: * <code>ActionMessage</code> for each error encountered,
329: * empty if no errors were encountered.
330: * @throws RollerException
331: */
332: private ActionMessages validate(RollerRequest rreq,
333: PingTargetData pingTarget) throws RollerException {
334: ActionMessages errors = new ActionMessages();
335:
336: PingTargetManager pingTargetMgr = RollerFactory.getRoller()
337: .getPingTargetManager();
338: if (!pingTargetMgr.isNameUnique(pingTarget)) {
339: errors.add(ActionMessages.GLOBAL_MESSAGE,
340: new ActionMessage("pingTarget.nameNotUnique"));
341: }
342: if (!pingTargetMgr.isUrlWellFormed(pingTarget)) {
343: errors.add(ActionMessages.GLOBAL_MESSAGE,
344: new ActionMessage("pingTarget.malformedUrl"));
345: } else if (!pingTargetMgr.isHostnameKnown(pingTarget)) {
346: errors.add(ActionMessages.GLOBAL_MESSAGE,
347: new ActionMessage("pingTarget.unknownHost"));
348: }
349: return errors;
350: }
351:
352: /**
353: * Helper defined by the subclass to determine if user has adequate
354: * rights for the action. This and the
355: * {@link org.apache.roller.pojos.PingTargetData#canSave()} method determine the
356: * access control for the action.
357: */
358: protected abstract boolean hasRequiredRights(RollerRequest rreq,
359: WebsiteData website) throws RollerException;
360:
361: /**
362: * Get the logger from the concrete subclass
363: */
364: protected abstract Log getLogger();
365:
366: /**
367: * Get the ping targets for the view. This is implemented differently in
368: * the concrete subclasses.
369: */
370: protected abstract List getPingTargets(RollerRequest rreq)
371: throws RollerException;
372:
373: /**
374: * Create a new ping target (blank). This is implemented differently in
375: * the concrete subclasses.
376: */
377: protected abstract PingTargetData createPingTarget(
378: RollerRequest rreq, PingTargetForm pingTargetForm)
379: throws RollerException;
380: }
|