示例#1
0
 /**
  * Test digest authentication.
  *
  * @throws Exception exception
  */
 @Test
 public void digest() throws Exception {
   // correct credentials
   try (final QueryProcessor qp =
       new QueryProcessor(
           _HTTP_SEND_REQUEST.args(
               "<http:request xmlns:http='http://expath.org/ns/http-client' method='GET' "
                   + "send-authorization='true' auth-method='Digest' username='******' password='******' "
                   + "href='"
                   + REST_ROOT
                   + "'/>"),
           ctx)) {
     checkResponse(qp.value(), 2, HttpURLConnection.HTTP_OK);
   }
   // wrong credentials
   try (final QueryProcessor qp =
       new QueryProcessor(
           _HTTP_SEND_REQUEST.args(
                   "<http:request xmlns:http='http://expath.org/ns/http-client' method='GET' "
                       + "send-authorization='true' auth-method='Digest' username='******' password='******' "
                       + "href='"
                       + REST_ROOT
                       + "?query=()'/>")
               + "[. instance of node()][@status = '401']",
           ctx)) {
     checkResponse(qp.value(), 1, HttpURLConnection.HTTP_UNAUTHORIZED);
   }
 }
示例#2
0
  /**
   * Creates query plans.
   *
   * @param comp compiled flag
   */
  private void plan(final boolean comp) {
    if (comp != options.get(MainOptions.COMPPLAN)) return;

    // show dot plan
    try {
      if (options.get(MainOptions.DOTPLAN)) {
        final String path = options.get(MainOptions.QUERYPATH);
        final String dot =
            path.isEmpty() ? "plan.dot" : new IOFile(path).name().replaceAll("\\..*?$", ".dot");

        try (final BufferOutput bo = new BufferOutput(dot)) {
          try (final DOTSerializer d = new DOTSerializer(bo, options.get(MainOptions.DOTCOMPACT))) {
            d.serialize(qp.plan());
          }
        }
      }

      // show XML plan
      if (options.get(MainOptions.XMLPLAN)) {
        info(NL + QUERY_PLAN + COL);
        info(qp.plan().serialize().toString());
      }
    } catch (final Exception ex) {
      Util.stack(ex);
    }
  }
示例#3
0
 /**
  * Tests an erroneous query.
  *
  * @throws Exception exception
  */
 @Test
 public void error() throws Exception {
   try (final QueryProcessor qp =
       new QueryProcessor(
           _HTTP_SEND_REQUEST.args("<http:request method='get'/>", RESTURL + "unknown")
               + "[1]/@status/data()",
           ctx)) {
     assertEquals("404", qp.value().serialize().toString());
   }
 }
示例#4
0
 /**
  * Parses the query.
  *
  * @param p performance
  * @throws QueryException query exception
  */
 private void parse(final Performance p) throws QueryException {
   qp.http(http);
   for (final Entry<String, String[]> entry : vars.entrySet()) {
     final String name = entry.getKey();
     final String[] value = entry.getValue();
     if (name == null) qp.context(value[0], value[1]);
     else qp.bind(name, value[0], value[1]);
   }
   qp.parse();
   if (p != null) info.parsing += p.time();
 }
示例#5
0
 /**
  * Test sending of HTTP PUT requests.
  *
  * @throws Exception exception
  */
 @Test
 public void put() throws Exception {
   try (final QueryProcessor qp =
       new QueryProcessor(
           _HTTP_SEND_REQUEST.args(
               "<http:request method='put' status-only='true'>"
                   + "<http:body media-type='text/xml'>"
                   + BOOKS
                   + "</http:body>"
                   + "</http:request>",
               RESTURL),
           ctx)) {
     checkResponse(qp.value(), 1, HttpURLConnection.HTTP_CREATED);
   }
 }
示例#6
0
 /**
  * Returns an extended error message.
  *
  * @param err error message
  * @return result of check
  */
 private boolean extError(final String err) {
   // will only be evaluated when an error has occurred
   final StringBuilder sb = new StringBuilder();
   if (options.get(MainOptions.QUERYINFO)) {
     sb.append(info()).append(qp.info()).append(NL).append(ERROR).append(COL).append(NL);
   }
   sb.append(err);
   return error(sb.toString());
 }
示例#7
0
 @Override
 public void databases(final LockResult lr) {
   if (qp == null) {
     lr.writeAll = true;
   } else {
     qp.databases(lr);
     info.readLocked = lr.readAll ? null : lr.read;
     info.writeLocked = lr.writeAll ? null : lr.write;
   }
 }
示例#8
0
  /**
   * Test sending of HTTP GET requests.
   *
   * @throws Exception exception
   */
  @Test
  public void postGet() throws Exception {
    // GET1 - just send a GET request
    try (final QueryProcessor qp =
        new QueryProcessor(
            _HTTP_SEND_REQUEST.args("<http:request method='get' href='" + REST_ROOT + "'/>"),
            ctx)) {
      final Value v = qp.value();
      checkResponse(v, 2, HttpURLConnection.HTTP_OK);

      assertEquals(NodeType.DOC, v.itemAt(1).type);
    }

    // GET2 - with override-media-type='text/plain'
    try (final QueryProcessor qp =
        new QueryProcessor(
            _HTTP_SEND_REQUEST.args(
                "<http:request method='get' override-media-type='text/plain'/>", REST_ROOT),
            ctx)) {
      final Value v = qp.value();
      checkResponse(v, 2, HttpURLConnection.HTTP_OK);

      assertEquals(AtomType.STR, v.itemAt(1).type);
    }

    // Get3 - with status-only='true'
    try (final QueryProcessor qp =
        new QueryProcessor(
            _HTTP_SEND_REQUEST.args("<http:request method='get' status-only='true'/>", REST_ROOT),
            ctx)) {
      checkResponse(qp.value(), 1, HttpURLConnection.HTTP_OK);
    }
  }
示例#9
0
  /**
   * Test sending of HTTP DELETE requests.
   *
   * @throws Exception exception
   */
  @Test
  public void postDelete() throws Exception {
    // add document to be deleted
    try (final QueryProcessor qp =
        new QueryProcessor(
            _HTTP_SEND_REQUEST.args(
                "<http:request method='put'>"
                    + "<http:body media-type='text/xml'><ToBeDeleted/></http:body>"
                    + "</http:request>",
                RESTURL),
            ctx)) {
      qp.value();
    }

    // DELETE
    try (final QueryProcessor qp =
        new QueryProcessor(
            _HTTP_SEND_REQUEST.args("<http:request method='delete' status-only='true'/>", RESTURL),
            ctx)) {
      checkResponse(qp.value(), 1, HttpURLConnection.HTTP_OK);
    }
  }
示例#10
0
 /**
  * Checks if the query possibly performs updates.
  *
  * @param ctx database context
  * @param query query string
  * @return result of check
  */
 final boolean updates(final Context ctx, final String query) {
   try {
     final Performance p = new Performance();
     qp(query, ctx);
     parse(p);
     return qp.updating;
   } catch (final QueryException ex) {
     Util.debug(ex);
     exception = ex;
     qp.close();
     return false;
   }
 }
示例#11
0
  /**
   * Test sending of HTTP POST requests.
   *
   * @throws Exception exception
   */
  @Test
  public void putPost() throws Exception {
    // PUT - query
    try (final QueryProcessor qp =
        new QueryProcessor(
            _HTTP_SEND_REQUEST.args(
                "<http:request method='put' status-only='true'>"
                    + "<http:body media-type='text/xml'>"
                    + BOOKS
                    + "</http:body>"
                    + "</http:request>",
                RESTURL),
            ctx)) {
      checkResponse(qp.value(), 1, HttpURLConnection.HTTP_CREATED);
    }

    // POST - query
    try (final QueryProcessor qp =
        new QueryProcessor(
            _HTTP_SEND_REQUEST.args(
                "<http:request method='post'>"
                    + "<http:body media-type='application/xml'>"
                    + "<query xmlns='"
                    + Prop.URL
                    + "/rest'>"
                    + "<text><![CDATA[<x>1</x>]]></text>"
                    + "</query>"
                    + "</http:body>"
                    + "</http:request>",
                RESTURL),
            ctx)) {
      checkResponse(qp.value(), 2, HttpURLConnection.HTTP_OK);
    }

    // Execute the same query but with content set from $bodies
    try (final QueryProcessor qp =
        new QueryProcessor(
            _HTTP_SEND_REQUEST.args(
                "<http:request method='post'>"
                    + "<http:body media-type='application/xml'/>"
                    + "</http:request>",
                RESTURL,
                "<query xmlns='"
                    + Prop.URL
                    + "/rest'>"
                    + "<text><![CDATA[<x>1</x>]]></text>"
                    + "</query>"),
            ctx)) {
      checkResponse(qp.value(), 2, HttpURLConnection.HTTP_OK);
    }
  }
示例#12
0
  /**
   * Refreshes the view after a file has been saved.
   *
   * @param root root directory
   * @param ctx database context
   * @throws InterruptedException interruption
   */
  void parse(final IOFile root, final Context ctx) throws InterruptedException {
    final long id = ++parseId;
    final HashSet<String> parsed = new HashSet<>();
    final TreeMap<String, InputInfo> errs = new TreeMap<>();

    // collect files to be parsed
    final ProjectCache pc = cache(root);
    final StringList mods = new StringList(), lmods = new StringList();
    for (final String path : pc) {
      final IOFile file = new IOFile(path);
      if (file.hasSuffix(IO.XQSUFFIXES)) (file.hasSuffix(IO.XQMSUFFIX) ? lmods : mods).add(path);
    }
    mods.add(lmods);

    // parse modules
    for (final String path : mods) {
      if (id != parseId) throw new InterruptedException();
      if (parsed.contains(path)) continue;

      final IOFile file = new IOFile(path);
      try (final TextInput ti = new TextInput(file)) {
        // parse query
        try (final QueryContext qc = new QueryContext(ctx)) {
          final String input = ti.cache().toString();
          final boolean lib = QueryProcessor.isLibrary(input);
          qc.parse(input, lib, path, null);
          // parsing was successful: remember path
          parsed.add(path);
          for (final byte[] mod : qc.modParsed) parsed.add(Token.string(mod));
        } catch (final QueryException ex) {
          // parsing failed: remember path
          final InputInfo ii = ex.info();
          errs.put(path, ii);
          parsed.add(ii.path());
        }
      } catch (final IOException ex) {
        // file may not be accessible
        Util.debug(ex);
      }
    }
    errors = errs;
  }
示例#13
0
  /**
   * Evaluates the specified query.
   *
   * @param query query
   * @return success flag
   */
  final boolean query(final String query) {
    final Performance p = new Performance();
    String error;
    if (exception != null) {
      error = Util.message(exception);
    } else {
      try {
        long hits = 0;
        final boolean run = options.get(MainOptions.RUNQUERY);
        final boolean serial = options.get(MainOptions.SERIALIZE);
        final int runs = Math.max(1, options.get(MainOptions.RUNS));
        for (int r = 0; r < runs; ++r) {
          // reuse existing processor instance
          if (r != 0) qp = null;
          qp(query, context);
          parse(p);
          if (r == 0) plan(false);

          qp.compile();
          info.compiling += p.time();
          if (r == 0) plan(true);
          if (!run) continue;

          final PrintOutput po = r == 0 && serial ? out : new NullOutput();
          try (final Serializer ser = qp.getSerializer(po)) {
            if (maxResults >= 0) {
              result = qp.cache(maxResults);
              info.evaluating += p.time();
              result.serialize(ser);
              hits = result.size();
            } else {
              hits = 0;
              final Iter ir = qp.iter();
              info.evaluating += p.time();
              for (Item it; (it = ir.next()) != null; ) {
                ser.serialize(it);
                ++hits;
                checkStop();
              }
            }
          }
          qp.close();
          info.serializing += p.time();
        }
        // dump some query info
        // out.flush();

        // remove string list if global locking is used and if query is updating
        if (soptions.get(StaticOptions.GLOBALLOCK) && qp.updating) {
          info.readLocked = null;
          info.writeLocked = null;
        }
        return info(info.toString(qp, out.size(), hits, options.get(MainOptions.QUERYINFO)));

      } catch (final QueryException | IOException ex) {
        exception = ex;
        error = Util.message(ex);
      } catch (final ProcException ex) {
        error = INTERRUPTED;
      } catch (final StackOverflowError ex) {
        Util.debug(ex);
        error = BASX_STACKOVERFLOW.desc;
      } catch (final RuntimeException ex) {
        extError("");
        Util.debug(info());
        throw ex;
      } finally {
        // close processor after exceptions
        if (qp != null) qp.close();
      }
    }
    return extError(error);
  }
示例#14
0
 @Override
 public final boolean updated(final Context ctx) {
   return qp != null && qp.updates() != 0;
 }
示例#15
0
 /** Closes the query processor. */
 protected void closeQp() {
   if (qp != null) {
     qp.close();
     qp = null;
   }
 }
  public RowMutation mutationForKey(
      CFDefinition cfDef,
      ByteBuffer key,
      ColumnNameBuilder builder,
      boolean isRange,
      UpdateParameters params,
      ColumnGroupMap group)
      throws InvalidRequestException {
    QueryProcessor.validateKey(key);
    RowMutation rm = new RowMutation(cfDef.cfm.ksName, key);
    ColumnFamily cf = rm.addOrGet(columnFamily());

    if (columns.isEmpty() && builder.componentCount() == 0) {
      // No columns, delete the row
      cf.delete(new DeletionInfo(params.timestamp, params.localDeletionTime));
    } else {
      if (isRange) {
        ByteBuffer start = builder.copy().build();
        ByteBuffer end = builder.buildAsEndOfRange();
        QueryProcessor.validateColumnName(start); // If start is good, end is too
        cf.addAtom(params.makeRangeTombstone(start, end));
      } else {
        // Delete specific columns
        if (cfDef.isCompact) {
          ByteBuffer columnName = builder.build();
          QueryProcessor.validateColumnName(columnName);
          cf.addColumn(params.makeTombstone(columnName));
        } else {
          Iterator<Pair<CFDefinition.Name, Term>> iter = toRemove.iterator();
          while (iter.hasNext()) {
            Pair<CFDefinition.Name, Term> p = iter.next();
            CFDefinition.Name column = p.left;

            if (column.type.isCollection()) {
              CollectionType validator = (CollectionType) column.type;
              Term keySelected = p.right;

              if (keySelected == null) {
                // Delete the whole collection
                ByteBuffer start = builder.copy().add(column.name.key).build();
                QueryProcessor.validateColumnName(start);
                ColumnNameBuilder b = iter.hasNext() ? builder.copy() : builder;
                ByteBuffer end = b.add(column.name.key).buildAsEndOfRange();
                cf.addAtom(params.makeRangeTombstone(start, end));
              } else {
                builder.add(column.name.key);
                List<Term> args = Collections.singletonList(keySelected);

                Operation op;
                switch (validator.kind) {
                  case LIST:
                    op = ListOperation.DiscardKey(args);
                    break;
                  case SET:
                    op = SetOperation.Discard(args);
                    break;
                  case MAP:
                    op = MapOperation.DiscardKey(keySelected);
                    break;
                  default:
                    throw new InvalidRequestException("Unknown collection type: " + validator.kind);
                }

                op.execute(
                    cf,
                    builder,
                    validator,
                    params,
                    group == null ? null : group.getCollection(column.name.key));
              }
            } else {
              ColumnNameBuilder b = iter.hasNext() ? builder.copy() : builder;
              ByteBuffer columnName = b.add(column.name.key).build();
              QueryProcessor.validateColumnName(columnName);
              cf.addColumn(params.makeTombstone(columnName));
            }
          }
        }
      }
    }

    return rm;
  }