001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/citations/tags/sakai_2-4-1/citations-servlet/servlet/src/java/org/sakaiproject/citation/servlet/CitationServlet.java $
003: * $Id: CitationServlet.java 29906 2007-05-03 13:22:13Z ajpoland@iupui.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 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.citation.servlet;
021:
022: import java.io.IOException;
023:
024: import javax.servlet.ServletConfig;
025: import javax.servlet.ServletException;
026: import javax.servlet.http.HttpServletRequest;
027: import javax.servlet.http.HttpServletResponse;
028:
029: import org.apache.commons.logging.Log;
030: import org.apache.commons.logging.LogFactory;
031:
032: import org.sakaiproject.cheftool.VmServlet;
033: import org.sakaiproject.citation.api.Citation;
034: import org.sakaiproject.citation.api.CitationCollection;
035: import org.sakaiproject.citation.api.CitationHelper;
036: import org.sakaiproject.citation.api.CitationService;
037: import org.sakaiproject.citation.api.Schema;
038: import org.sakaiproject.component.cover.ComponentManager;
039: import org.sakaiproject.content.api.ContentHostingService;
040: import org.sakaiproject.content.api.ContentResource;
041: import org.sakaiproject.entity.api.Entity;
042: import org.sakaiproject.entity.api.ResourceProperties;
043: import org.sakaiproject.entity.api.Reference;
044: import org.sakaiproject.entity.cover.EntityManager;
045: import org.sakaiproject.event.api.SessionState;
046: import org.sakaiproject.exception.IdUnusedException;
047: import org.sakaiproject.exception.InUseException;
048: import org.sakaiproject.exception.PermissionException;
049: import org.sakaiproject.exception.ServerOverloadException;
050: import org.sakaiproject.exception.TypeException;
051: import org.sakaiproject.tool.api.ActiveTool;
052: import org.sakaiproject.tool.api.Session;
053: import org.sakaiproject.tool.api.Tool;
054: import org.sakaiproject.tool.api.ToolException;
055: import org.sakaiproject.tool.cover.ActiveToolManager;
056: import org.sakaiproject.tool.cover.SessionManager;
057: import org.sakaiproject.util.BasicAuth;
058: import org.sakaiproject.util.ParameterParser;
059: import org.sakaiproject.util.ResourceLoader;
060: import org.sakaiproject.util.Validator;
061: import org.sakaiproject.util.Web;
062:
063: /**
064: *
065: *
066: */
067: //public class CitationServlet extends VelocityPortletPaneledAction
068: public class CitationServlet extends VmServlet {
069: /**
070: *
071: */
072: public static final String SERVLET_TEMPLATE = "/vm/servlet.vm";
073: private String collectionTitle;
074:
075: /** Our log (commons). */
076: private static Log M_log = LogFactory.getLog(CitationServlet.class);
077:
078: /** Resource bundle using current language locale */
079: protected static ResourceLoader rb = new ResourceLoader("citations");
080:
081: /** set to true when init'ed. */
082: protected boolean m_ready = false;
083:
084: protected BasicAuth basicAuth = null;
085:
086: protected enum Status {
087: SUCCESS, ERROR;
088: }
089:
090: /** init thread - so we don't wait in the actual init() call */
091: public class CitationServletInit extends Thread {
092: protected CitationService m_citationService;
093:
094: public void setCitationService(CitationService service) {
095: this .m_citationService = service;
096: }
097:
098: /**
099: * construct and start the init activity
100: */
101: public CitationServletInit() {
102: m_ready = false;
103: start();
104: }
105:
106: /**
107: * run the init
108: */
109: public void run() {
110: m_ready = true;
111: }
112: }
113:
114: /**
115: * initialize the AccessServlet servlet
116: *
117: * @param config
118: * the servlet config parameter
119: * @exception ServletException
120: * in case of difficulties
121: */
122: public void init(ServletConfig config) throws ServletException {
123: super .init(config);
124: startInit();
125: basicAuth = new BasicAuth();
126: basicAuth.init();
127: }
128:
129: /**
130: * Start the initialization process
131: */
132: public void startInit() {
133: new CitationServletInit();
134: }
135:
136: /**
137: * respond to an HTTP GET request
138: *
139: * @param req
140: * HttpServletRequest object with the client request
141: * @param res
142: * HttpServletResponse object back to the client
143: * @exception ServletException
144: * in case of difficulties
145: * @exception IOException
146: * in case of difficulties
147: */
148: public void doGet(HttpServletRequest req, HttpServletResponse res)
149: throws ServletException, IOException {
150: // process any login that might be present
151: basicAuth.doLogin(req);
152:
153: // catch the login helper requests
154: String option = req.getPathInfo();
155: String[] parts = option.split("/");
156:
157: if ((parts.length == 2) && ((parts[1].equals("login")))) {
158: doLogin(req, res, null);
159: } else {
160: // try to add the Citation
161: Citation citation = addCitation((ParameterParser) req
162: .getAttribute(ATTR_PARAMS), option, res);
163: if (citation != null) {
164: // return success
165: M_log.debug("doGet() [addCitation()] added Citation '"
166: + citation.getDisplayName() + "'");
167: respond(Status.SUCCESS, citation, req, res);
168: } else {
169: // return failure
170: M_log
171: .debug("doGet() [addCitation()] failed to add citation");
172: respond(Status.ERROR, null, req, res);
173: }
174: }
175: }
176:
177: /**
178: * respond to an HTTP POST request; only to handle the login process
179: *
180: * @param req
181: * HttpServletRequest object with the client request
182: * @param res
183: * HttpServletResponse object back to the client
184: * @exception ServletException
185: * in case of difficulties
186: * @exception IOException
187: * in case of difficulties
188: */
189: public void doPost(HttpServletRequest req, HttpServletResponse res)
190: throws ServletException, IOException {
191: // process any login that might be present
192: basicAuth.doLogin(req);
193:
194: // catch the login helper posts
195: String option = req.getPathInfo();
196: String[] parts = option.split("/");
197:
198: if ((parts.length == 2) && ((parts[1].equals("login")))) {
199: doLogin(req, res, null);
200: }
201:
202: else {
203: // don't handle POSTs
204: sendError(res, HttpServletResponse.SC_NOT_FOUND);
205: }
206: }
207:
208: /**
209: * handle get and post communication from the user
210: *
211: * @param req HttpServletRequest object with the client request
212: * @param res HttpServletResponse object back to the client
213: */
214: public Citation addCitation(ParameterParser params, String option,
215: HttpServletResponse res) {
216: // get the path info
217: String path = params.getPath();
218: if (path == null)
219: path = "";
220:
221: if (!m_ready) {
222: sendError(res, HttpServletResponse.SC_SERVICE_UNAVAILABLE);
223: }
224:
225: // parse the request path
226: String[] parts = option.split("/");
227: String resourceUuid = parts[1];
228:
229: // get services from ComponentManager
230: ContentHostingService contentService = (ContentHostingService) ComponentManager
231: .get("org.sakaiproject.content.api.ContentHostingService");
232: CitationService citationService = (CitationService) ComponentManager
233: .get("org.sakaiproject.citation.api.CitationService");
234:
235: CitationCollection collection = null;
236: Citation citation = null;
237:
238: try {
239: String resourceId = contentService
240: .resolveUuid(resourceUuid);
241:
242: // check to see if user has revise permission
243: if (!citationService.allowReviseCitationList(resourceId)) {
244: // revise permission denied
245: return null;
246: }
247:
248: // revise permission granted
249: ContentResource resource = contentService
250: .getResource(resourceId);
251:
252: String collectionId = new String(resource.getContent());
253: collection = citationService.getCollection(collectionId);
254:
255: String genre = params.getString("genre");
256: String[] authors = params.getStrings("au");
257: String title = params.getString("title");
258: String atitle = params.getString("atitle");
259: String volume = params.getString("volume");
260: String issue = params.getString("issue");
261: String pages = params.getString("pages");
262: String publisher = params.getString("publisher");
263: String date = params.getString("date");
264: String id = params.getString("id");
265:
266: // do we have enough info for a meaningful citation?
267: if ((title == null || title.trim().equals(""))
268: && (atitle == null || atitle.trim().equals(""))) {
269: // both title AND atitle are null
270: return null;
271: }
272:
273: // force a generic genre if we don't know any better
274: if (genre == null || genre.trim().equals("")) {
275: genre = CitationService.UNKNOWN_TYPE;
276: }
277:
278: citation = citationService.addCitation(genre);
279:
280: String info = "New citation from Google Scholar:\n\t genre:\t\t"
281: + genre;
282:
283: // Generally, only books have a title that's the actual title of the piece.
284: // We'll check to see if there's an atitle; if not, use the title as the
285: // work's title. Otherwise, use the title as the source.
286:
287: if (title != null) {
288: if (atitle != null) {
289: info += "\n\t source title:\t\t" + title;
290: citation.addPropertyValue(Schema.SOURCE_TITLE,
291: title);
292: } else {
293: info += "\n\t title:\t\t" + title;
294: citation.addPropertyValue(Schema.TITLE, title);
295: }
296: }
297:
298: if (atitle != null) {
299: info += "\n\t title:\t\t" + atitle;
300: citation.addPropertyValue(Schema.TITLE, atitle);
301: }
302:
303: if (authors != null && authors.length > 0) {
304: for (int i = 0; i < authors.length; i++) {
305: info += "\n\t au:\t\t" + authors[i];
306: citation.addPropertyValue(Schema.CREATOR,
307: authors[i]);
308: }
309: }
310:
311: if (volume != null) {
312: info += "\n\t volume:\t\t" + volume;
313: citation.addPropertyValue(Schema.VOLUME, volume);
314: }
315: if (issue != null) {
316: info += "\n\t issue:\t\t" + issue;
317: citation.addPropertyValue(Schema.ISSUE, issue);
318: }
319: if (pages != null) {
320: info += "\n\t pages:\t\t" + pages;
321: citation.addPropertyValue(Schema.PAGES, pages);
322: }
323: if (publisher != null) {
324: info += "\n\t publisher:\t\t" + publisher;
325: citation.addPropertyValue(Schema.PUBLISHER, publisher);
326: }
327: if (date != null) {
328: info += "\n\t date:\t\t" + date;
329: citation.addPropertyValue(Schema.YEAR, date);
330: }
331: if (id != null) {
332: info += "\n\t id:\t\t" + id;
333: citation.addPropertyValue(Schema.ISN, id);
334: }
335: info += "\n";
336:
337: collection.add(citation);
338: citationService.save(collection);
339:
340: //M_log.info(info);
341:
342: // get the citation list title
343: String refStr = contentService.getReference(resourceId);
344: Reference ref = EntityManager.newReference(refStr);
345: this .collectionTitle = ref.getProperties().getProperty(
346: ResourceProperties.PROP_DISPLAY_NAME);
347: } catch (PermissionException e) {
348: // TODO Auto-generated catch block
349: M_log.warn("PermissionException ", e);
350: return null;
351: } catch (IdUnusedException e) {
352: // TODO Auto-generated catch block
353: M_log.warn("IdUnusedException ", e);
354: return null;
355: } catch (TypeException e) {
356: // TODO Auto-generated catch block
357: M_log.warn("TypeException ", e);
358: return null;
359: } catch (ServerOverloadException e) {
360: // TODO Auto-generated catch block
361: M_log.warn("ServerOverloadException ", e);
362: return null;
363: }
364:
365: return citation;
366: }
367:
368: protected void respond(Status status, Citation citation,
369: HttpServletRequest req, HttpServletResponse res)
370: throws ServletException {
371: // the context wraps our real vm attribute set
372: ResourceProperties props = new org.sakaiproject.util.BaseResourceProperties();
373: setVmReference("props", props, req);
374:
375: setVmReference("validator", new Validator(), req);
376: setVmReference("tlang", rb, req);
377: res.setContentType("text/html; charset=UTF-8");
378:
379: Object success = null;
380: if (status == Status.SUCCESS) {
381: success = new Object();
382: setVmReference("citation", citation, req);
383:
384: // schedule a refresh of the main toolframe
385: // ToolSession toolSession = SessionManager.getCurrentToolSession();
386: // toolSession.setAttribute( "sakai.vppa.top.refresh", Boolean.TRUE );
387: setVmReference("topRefresh", Boolean.TRUE, req); // TODO
388: }
389:
390: // set the success flag
391: setVmReference("success", success, req);
392:
393: // include object arrays for formatted messages
394: if (collectionTitle == null
395: || collectionTitle.trim().equals("")) {
396: collectionTitle = "your current citation list";
397: }
398: Object[] titleArgs = { collectionTitle }; // TODO temporary placeholder
399: setVmReference("titleArgs", titleArgs, req);
400:
401: // return the servlet template
402: includeVm(SERVLET_TEMPLATE, req, res);
403: }
404:
405: /**
406: * Make a redirect to the login url.
407: *
408: * @param req
409: * HttpServletRequest object with the client request.
410: * @param res
411: * HttpServletResponse object back to the client.
412: * @param path
413: * The current request path, set ONLY if we want this to be where to redirect the user after successfull login
414: * @throws IOException
415: */
416: protected void doLogin(HttpServletRequest req,
417: HttpServletResponse res, String path) throws ToolException,
418: IOException {
419: // if basic auth is valid do that
420: if (basicAuth.doAuth(req, res)) {
421: //System.err.println("BASIC Auth Request Sent to the Browser ");
422: return;
423: }
424:
425: // get the Sakai session
426: Session session = SessionManager.getCurrentSession();
427:
428: // set the return path for after login if needed (Note: in session, not tool session, special for Login helper)
429: if (path != null) {
430: // where to go after
431: session.setAttribute(Tool.HELPER_DONE_URL, Web.returnUrl(
432: req, path));
433: }
434:
435: // check that we have a return path set; might have been done earlier
436: if (session.getAttribute(Tool.HELPER_DONE_URL) == null) {
437: M_log
438: .warn("doLogin - proceeding with null HELPER_DONE_URL");
439: }
440:
441: // map the request to the helper, leaving the path after ".../options" for the helper
442: ActiveTool tool = ActiveToolManager
443: .getActiveTool("sakai.login");
444: String context = req.getContextPath() + req.getServletPath()
445: + "/login";
446: tool.help(req, res, context, "/login");
447: }
448:
449: /**
450: * Utility method to return errors as the response
451: *
452: * @param res response associated with this request
453: * @param code error code
454: */
455: protected void sendError(HttpServletResponse res, int code) {
456: try {
457: res.sendError(code);
458: } catch (Throwable t) {
459: M_log.warn("sendError: " + t);
460: }
461: }
462: }
|