private void startup(Configuration configuration) throws ServletException { if (configuration == null) { throw new ServletException("database has not been configured"); } LOG.info("configuring eXist instance"); try { if (!BrokerPool.isConfigured()) { BrokerPool.configure(1, 5, configuration); } } catch (EXistException e) { throw new ServletException(e.getMessage()); } catch (DatabaseConfigurationException e) { throw new ServletException(e.getMessage()); } try { LOG.info("registering XMLDB driver"); Class clazz = Class.forName("org.exist.xmldb.DatabaseImpl"); Database database = (Database) clazz.newInstance(); DatabaseManager.registerDatabase(database); } catch (ClassNotFoundException e) { LOG.info("ERROR", e); } catch (InstantiationException e) { LOG.info("ERROR", e); } catch (IllegalAccessException e) { LOG.info("ERROR", e); } catch (XMLDBException e) { LOG.info("ERROR", e); } }
@AfterClass public static void tearDown() { TransactionManager transact = null; Txn transaction = null; try { transact = pool.getTransactionManager(); transaction = transact.beginTransaction(); root = broker.getOrCreateCollection( transaction, XmldbURI.create(XmldbURI.ROOT_COLLECTION + "/test")); // broker.removeCollection(transaction, root); transact.commit(transaction); } catch (Exception e) { if (transaction != null) { transact.abort(transaction); } } finally { if (pool != null) pool.release(broker); } BrokerPool.stopAll(false); pool = null; root = null; }
/* (non-Javadoc) * @see javax.xml.xquery.XQConnection#close() */ public void close() throws XQException { try { BrokerPool pool = BrokerPool.getInstance(); pool.release(broker); broker = null; } catch (EXistException ee) { throw new XQException("Unable to return broker to pool"); } }
private static BrokerPool startDB() throws DatabaseConfigurationException, EXistException { String home, file = "conf.xml"; home = System.getProperty("exist.home"); if (home == null) { home = System.getProperty("user.dir"); } Configuration config = new Configuration(file, home); BrokerPool.configure(1, 5, config); return BrokerPool.getInstance(); }
@BeforeClass public static void setUp() throws Exception { TransactionManager transact = null; Txn transaction = null; try { pool = startDB(); broker = pool.get(pool.getSecurityManager().getSystemSubject()); transact = pool.getTransactionManager(); transaction = transact.beginTransaction(); root = broker.getOrCreateCollection( transaction, XmldbURI.create(XmldbURI.ROOT_COLLECTION + "/test")); broker.saveCollection(transaction, root); String existHome = System.getProperty("exist.home"); File existDir = existHome == null ? new File(".") : new File(existHome); String directory = "samples/shakespeare"; File dir = new File(existDir, directory); // store some documents. for (File f : dir.listFiles(new XMLFilenameFilter())) { IndexInfo info = root.validateXMLResource( transaction, broker, XmldbURI.create(f.getName()), new InputSource(f.toURI().toASCIIString())); root.store(transaction, broker, info, new InputSource(f.toURI().toASCIIString()), false); } IndexInfo info = root.validateXMLResource(transaction, broker, XmldbURI.create("nested.xml"), NESTED_XML); root.store(transaction, broker, info, NESTED_XML, false); transact.commit(transaction); // for the tests docs = root.allDocs(broker, new DefaultDocumentSet(), true); seqSpeech = executeQuery(broker, "//SPEECH", 2628, null); } catch (Exception e) { if (pool != null) { pool.release(broker); BrokerPool.stopAll(false); pool = null; root = null; } throw e; } }
private User authenticate(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException { // First try to validate the principial if passed from the servlet engine Principal principal = request.getUserPrincipal(); if (principal instanceof XmldbPrincipal) { String username = ((XmldbPrincipal) principal).getName(); String password = ((XmldbPrincipal) principal).getPassword(); LOG.info("Validating Principle: " + principal.getName()); User user = pool.getSecurityManager().getUser(username); if (user != null) { if (password.equalsIgnoreCase(user.getPassword())) { LOG.info("Valid User: "******"Password invalid for user: "******"User not found: " + principal.getName()); } } String auth = request.getHeader("Authorization"); if (auth == null && defaultUser != null) { return defaultUser; } return authenticator.authenticate(request, response); }
@Override public void addGroup(final Group group) throws XMLDBException { final SecurityManager manager = pool.getSecurityManager(); if (!manager.hasAdminPrivileges(user)) { throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, " you are not allowed to add role"); } if (manager.hasGroup(group.getName())) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "group '" + group.getName() + "' exists"); } try { executeWithBroker( new BrokerOperation<Void>() { @Override public Void withBroker(DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException { manager.addGroup(group); return null; } }); } catch (final Exception e) { throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, e.getMessage(), e); } }
@Override public void setUserPrimaryGroup(final String username, final String groupName) throws XMLDBException { final SecurityManager manager = pool.getSecurityManager(); if (!manager.hasGroup(groupName)) { throw new XMLDBException( ErrorCodes.PERMISSION_DENIED, "Group '" + groupName + "' does not exist!"); } if (!manager.hasAdminPrivileges(user)) { throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, "Not allowed to modify user"); } try { executeWithBroker( new BrokerOperation<Void>() { @Override public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException { final Account account = manager.getAccount(username); final Group group = manager.getGroup(groupName); account.setPrimaryGroup(group); manager.updateAccount(account); return null; } }); } catch (final Exception e) { throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, e.getMessage(), e); } }
private <R> R executeWithBroker(BrokerOperation<R> brokerOperation) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException { final Subject preserveSubject = pool.getSubject(); DBBroker broker = null; try { broker = pool.get(user); return brokerOperation.withBroker(broker); } finally { if (broker != null) { pool.release(broker); } if (preserveSubject != null) { pool.setSubject(preserveSubject); } } }
private User getDefaultUser() { if (defaultUsername != null) { User user = pool.getSecurityManager().getUser(defaultUsername); if (user != null) { if (!user.validate(defaultPassword)) { return null; } } return user; } return null; }
/** * Setup Validator object with brokerpool as db connection. * * @param pool Brokerpool */ public Validator(BrokerPool pool) { logger.info("Initializing Validator."); if (brokerPool == null) { this.brokerPool = pool; } // Get configuration config = brokerPool.getConfiguration(); // Check xerces version StringBuilder xmlLibMessage = new StringBuilder(); if (!XmlLibraryChecker.hasValidParser(xmlLibMessage)) { logger.error(xmlLibMessage); } // setup grammar brokerPool grammarPool = (GrammarPool) config.getProperty(XMLReaderObjectFactory.GRAMMER_POOL); // setup system wide catalog resolver systemCatalogResolver = (eXistXMLCatalogResolver) config.getProperty(XMLReaderObjectFactory.CATALOG_RESOLVER); }
/* (non-Javadoc) * @see javax.servlet.GenericServlet#destroy() */ public void destroy() { super.destroy(); BrokerPool.stopAll(false); }
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); } }