protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException { try { // Get the path String path = request.getPathInfo(); if (path == null) { response.sendError( HttpServletResponse.SC_BAD_REQUEST, "URL has no extra path information specified."); return; } int firstSlash = path.indexOf('/', 1); if (firstSlash < 0 && path.length() == 1) { response.sendError(400, "Module not specified."); return; } String moduleName = firstSlash < 0 ? path.substring(1) : path.substring(1, firstSlash); path = firstSlash < 0 ? "" : path.substring(firstSlash); AtomModule module = (AtomModule) modules.get(moduleName); if (module == null) { response.sendError(400, "Module " + moduleName + " not found."); return; } User user = null; if (noAuth.get(moduleName) == null) { // Authenticate user = authenticate(request, response); if (user == null) { // You now get a challenge if there is no user return; } } final Principal principal = new UserXmldbPrincipal(WebDAV.BASIC_AUTH, user); HttpServletRequest wrappedRequest = new HttpServletRequestWrapper(request) { public Principal getUserPrincipal() { return principal; } }; // Handle the resource DBBroker broker = null; try { broker = pool.get(user); module.process( broker, new HttpRequestMessage(request, path, '/' + moduleName), new HttpResponseMessage(response)); } catch (NotFoundException ex) { LOG.info("Resource " + path + " not found by " + moduleName, ex); response.sendError(404, ex.getMessage()); } catch (PermissionDeniedException ex) { LOG.info( "Permission denied to " + path + " by " + moduleName + " for " + user.getName(), ex); response.sendError(401, ex.getMessage()); } catch (BadRequestException ex) { LOG.info("Bad request throw from module " + moduleName, ex); response.sendError(400, ex.getMessage()); } catch (EXistException ex) { LOG.fatal("Exception getting broker from pool for user " + user.getName(), ex); response.sendError(500, "Service is not available."); } finally { pool.release(broker); } } catch (IOException ex) { LOG.fatal("I/O exception on request.", ex); try { response.sendError(500, "Service is not available."); } catch (IOException finalEx) { LOG.fatal("Cannot return 500 on exception.", ex); } } }
/* (non-Javadoc) * @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig) */ public void init(ServletConfig config) throws ServletException { super.init(config); // Configure BrokerPool try { if (BrokerPool.isConfigured()) { LOG.debug("Database already started. Skipping configuration ..."); } else { // The database isn't started, so we'll start it String confFile = config.getInitParameter("configuration"); String dbHome = config.getInitParameter("basedir"); String start = config.getInitParameter("start"); if (confFile == null) { confFile = "conf.xml"; } dbHome = (dbHome == null) ? config.getServletContext().getRealPath(".") : config.getServletContext().getRealPath(dbHome); LOG.debug("AtomServlet: exist.home=" + dbHome); File f = new File(dbHome + File.separator + confFile); LOG.debug("reading configuration from " + f.getAbsolutePath()); if (!f.canRead()) { throw new ServletException( "configuration file " + confFile + " not found or not readable"); } Configuration configuration = new Configuration(confFile, dbHome); if (start != null && start.equals("true")) { startup(configuration); } } pool = BrokerPool.getInstance(); // The default user is used when there is no authentication String option = config.getInitParameter("use-default-user"); boolean useDefaultUser = true; if (option != null) { useDefaultUser = option.trim().equals("true"); } if (useDefaultUser) { option = config.getInitParameter("user"); if (option != null) { defaultUsername = option; } option = config.getInitParameter("password"); if (option != null) { defaultPassword = option; } defaultUser = getDefaultUser(); if (defaultUser != null) { LOG.info("Using default user " + defaultUsername + " for all unauthorized requests."); } else { LOG.error( "Default user " + defaultUsername + " cannot be found. A BASIC AUTH challenge will be the default."); } } else { LOG.info( "No default user. All requires must be authorized or will result in a BASIC AUTH challenge."); defaultUser = null; } // Currently, we only support basic authentication authenticator = new BasicAuthenticator(pool); } catch (EXistException e) { throw new ServletException("No database instance available"); } catch (DatabaseConfigurationException e) { throw new ServletException("Unable to configure database instance: " + e.getMessage(), e); } // get form and container encoding's formEncoding = config.getInitParameter("form-encoding"); if (formEncoding == null) { formEncoding = DEFAULT_ENCODING; } String containerEncoding = config.getInitParameter("container-encoding"); if (containerEncoding == null) { containerEncoding = DEFAULT_ENCODING; } // Load all the modules // modules = new HashMap<String,AtomModule>(); modules = new HashMap(); noAuth = new HashMap(); String configFileOpt = config.getInitParameter("config-file"); File dbHome = pool.getConfiguration().getExistHome(); File atomConf; if (configFileOpt == null) atomConf = new File(dbHome, "atom-services.xml"); else atomConf = new File(config.getServletContext().getRealPath(configFileOpt)); config .getServletContext() .log("Checking for atom configuration in " + atomConf.getAbsolutePath()); if (atomConf.exists()) { config.getServletContext().log("Loading configuration " + atomConf.getAbsolutePath()); DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); docFactory.setNamespaceAware(true); DocumentBuilder docBuilder = null; Document confDoc = null; InputStream is = null; try { is = new FileInputStream(atomConf); InputSource src = new InputSource(new InputStreamReader(is, formEncoding)); URI docBaseURI = atomConf.toURI(); src.setSystemId(docBaseURI.toString()); docBuilder = docFactory.newDocumentBuilder(); confDoc = docBuilder.parse(src); confDoc.getDocumentElement(); // Add all the modules NodeList moduleConfList = confDoc.getElementsByTagNameNS(CONF_NS, "module"); for (int i = 0; i < moduleConfList.getLength(); i++) { Element moduleConf = (Element) moduleConfList.item(i); String name = moduleConf.getAttribute("name"); if (modules.get(name) != null) { throw new ServletException( "Module '" + name + "' is configured more than once ( child # " + (i + 1)); } if ("false".equals(moduleConf.getAttribute("authenticate"))) { noAuth.put(name, Boolean.TRUE); } String className = moduleConf.getAttribute("class"); if (className != null && className.length() > 0) { try { Class moduleClass = Class.forName(className); AtomModule amodule = (AtomModule) moduleClass.newInstance(); modules.put(name, amodule); amodule.init(new ModuleContext(config, name, atomConf.getParent())); } catch (Exception ex) { throw new ServletException( "Cannot instantiate class " + className + " for module '" + name + "' due to exception: " + ex.getMessage(), ex); } } else { // no class means query Query query = new Query(); modules.put(name, query); String allowQueryPost = moduleConf.getAttribute("query-by-post"); if ("true".equals(allowQueryPost)) { query.setQueryByPost(true); } NodeList methodList = moduleConf.getElementsByTagNameNS(CONF_NS, "method"); for (int m = 0; m < methodList.getLength(); m++) { Element methodConf = (Element) methodList.item(m); String type = methodConf.getAttribute("type"); if (type == null) { LOG.warn("No type specified for method in module " + name); continue; } // What I want but can't have because of JDK 1.4 // URI baseURI = URI.create(methodConf.getBaseURI()); URI baseURI = docBaseURI; String queryRef = methodConf.getAttribute("query"); if (queryRef == null) { LOG.warn("No query specified for method " + type + " in module " + name); continue; } boolean fromClasspath = "true".equals(methodConf.getAttribute("from-classpath")); Query.MethodConfiguration mconf = query.getMethodConfiguration(type); if (mconf == null) { LOG.warn("Unknown method " + type + " in module " + name); continue; } String responseContentType = methodConf.getAttribute("content-type"); if (responseContentType != null && responseContentType.trim().length() != 0) { mconf.setContentType(responseContentType); } URL queryURI = null; if (fromClasspath) { LOG.debug( "Nope. Attempting to get resource " + queryRef + " from " + Atom.class.getName()); queryURI = Atom.class.getResource(queryRef); } else { queryURI = baseURI.resolve(queryRef).toURL(); } LOG.debug( "Loading from module " + name + " method " + type + " from resource " + queryURI + " via classpath(" + fromClasspath + ") and ref (" + queryRef + ")"); if (queryURI == null) { throw new ServletException( "Cannot find resource " + queryRef + " for module " + name); } mconf.setQuerySource(queryURI); } query.init(new ModuleContext(config, name, atomConf.getParent())); } } } catch (IOException e) { LOG.warn(e); throw new ServletException(e.getMessage()); } catch (SAXException e) { LOG.warn(e); throw new ServletException(e.getMessage()); } catch (ParserConfigurationException e) { LOG.warn(e); throw new ServletException(e.getMessage()); } catch (EXistException e) { LOG.warn(e); throw new ServletException(e.getMessage()); } finally { if (is != null) { try { is.close(); } catch (IOException ex) { } } } } else { try { AtomProtocol protocol = new AtomProtocol(); modules.put("edit", protocol); protocol.init(new ModuleContext(config, "edit", dbHome.getAbsolutePath())); AtomFeeds feeds = new AtomFeeds(); modules.put("content", feeds); feeds.init(new ModuleContext(config, "content", dbHome.getAbsolutePath())); Query query = new Query(); query.setQueryByPost(true); modules.put("query", query); query.init(new ModuleContext(config, "query", dbHome.getAbsolutePath())); Query topics = new Query(); modules.put("topic", topics); topics .getMethodConfiguration("GET") .setQuerySource(topics.getClass().getResource("topic.xq")); topics.init(new ModuleContext(config, "topic", dbHome.getAbsolutePath())); Query introspect = new Query(); modules.put("introspect", introspect); introspect .getMethodConfiguration("GET") .setQuerySource(introspect.getClass().getResource("introspect.xq")); introspect.init(new ModuleContext(config, "introspect", dbHome.getAbsolutePath())); } catch (EXistException ex) { throw new ServletException("Exception during module init(): " + ex.getMessage(), ex); } } // XML lib checks.... StringBuffer xmlLibMessage = new StringBuffer(); if (XmlLibraryChecker.hasValidParser(xmlLibMessage)) { LOG.info(xmlLibMessage); } else { LOG.warn(xmlLibMessage); } xmlLibMessage.delete(0, xmlLibMessage.length()); if (XmlLibraryChecker.hasValidTransformer(xmlLibMessage)) { LOG.info(xmlLibMessage); } else { LOG.warn(xmlLibMessage); } }