Example #1
0
  public void test04SearchByLocation() {

    try {

      final PropertyMap props = new PropertyMap();
      final PropertyKey lat = TestSeven.latitude;
      final PropertyKey lon = TestSeven.longitude;
      final String type = TestSeven.class.getSimpleName();

      props.put(lat, 50.12284d);
      props.put(lon, 8.73923d);
      props.put(AbstractNode.name, "TestSeven-0");

      AbstractNode node = createTestNode(type, props);
      boolean includeDeletedAndHidden = true;
      boolean publicOnly = false;
      List<SearchAttribute> searchAttributes = new LinkedList<SearchAttribute>();

      searchAttributes.add(new TextualSearchAttribute(AbstractNode.type, type, SearchOperator.AND));
      searchAttributes.add(
          new DistanceSearchAttribute(
              "Hanauer Landstr. 200, 60314 Frankfurt, Germany", 10.0, SearchOperator.AND));

      Result result =
          searchNodeCommand.execute(includeDeletedAndHidden, publicOnly, searchAttributes);

      assertEquals(1, result.size());
      assertTrue(result.get(0).equals(node));

    } catch (FrameworkException ex) {

      logger.log(Level.SEVERE, ex.toString());
      fail("Unexpected exception");
    }
  }
Example #2
0
  @Override
  public void deleteData(final int offset, final int count) throws DOMException {

    checkWriteAccess();

    // finally, set content to concatenated left and right parts
    try {

      Services.command(securityContext, TransactionCommand.class)
          .execute(
              new StructrTransaction() {

                @Override
                public Object execute() throws FrameworkException {

                  String text = getProperty(content);

                  String leftPart = text.substring(0, offset);
                  String rightPart = text.substring(offset + count);

                  setProperty(content, leftPart.concat(rightPart));

                  return null;
                }
              });

    } catch (FrameworkException fex) {

      throw new DOMException(DOMException.INVALID_STATE_ERR, fex.toString());
    }
  }
Example #3
0
  @Override
  public void appendData(final String data) throws DOMException {

    checkWriteAccess();

    // set content to concatenated text and data
    try {

      Services.command(securityContext, TransactionCommand.class)
          .execute(
              new StructrTransaction() {

                @Override
                public Object execute() throws FrameworkException {

                  String text = getProperty(content);
                  setProperty(content, text.concat(data));

                  return null;
                }
              });

    } catch (FrameworkException fex) {

      throw new DOMException(DOMException.INVALID_STATE_ERR, fex.toString());
    }
  }
Example #4
0
  @Override
  public void processMessage(final WebSocketMessage webSocketData) {

    final GraphObject obj = getGraphObject(webSocketData.getId());
    String key = (String) webSocketData.getNodeData().get("key");

    if (obj != null) {

      PropertyKey propertyKey =
          StructrApp.getConfiguration().getPropertyKeyForJSONName(obj.getClass(), key);
      PropertyConverter converter = propertyKey.inputConverter(getWebSocket().getSecurityContext());

      Object value = obj.getProperty(propertyKey);
      if (converter != null) {

        try {
          value = converter.revert(value);

        } catch (FrameworkException ex) {

          getWebSocket()
              .send(MessageBuilder.status().code(400).message(ex.getMessage()).build(), true);
        }
      }

      webSocketData.setNodeData(key, value);

      // send only over local connection (no broadcast)
      getWebSocket().send(webSocketData, true);

    } else {

      getWebSocket().send(MessageBuilder.status().code(404).build(), true);
    }
  }
Example #5
0
  public void test02SearchSingleNodeByDate() {

    try {

      PropertyMap props = new PropertyMap();
      PropertyKey key = TestOne.aDate;
      Date date = new Date();
      String type = TestOne.class.getSimpleName();

      props.put(key, date);

      AbstractNode node = createTestNode(type, props);
      boolean includeDeletedAndHidden = true;
      boolean publicOnly = false;
      List<SearchAttribute> searchAttributes = new LinkedList<SearchAttribute>();

      searchAttributes.add(new TextualSearchAttribute(AbstractNode.type, type, SearchOperator.AND));
      searchAttributes.add(new FilterSearchAttribute(key, date, SearchOperator.AND));

      Result result =
          searchNodeCommand.execute(includeDeletedAndHidden, publicOnly, searchAttributes);

      assertEquals(1, result.size());
      assertTrue(result.get(0).equals(node));

    } catch (FrameworkException ex) {

      logger.log(Level.SEVERE, ex.toString());
      fail("Unexpected exception");
    }
  }
  @Override
  public void processMessage(final WebSocketMessage webSocketData) {

    final SecurityContext securityContext = getWebSocket().getSecurityContext();
    final int pageSize = webSocketData.getPageSize();
    final int page = webSocketData.getPage();

    final App app = StructrApp.getInstance(securityContext);

    try (final Tx tx = app.tx()) {

      // do search
      List<AbstractNode> filteredResults = getUnattachedNodes(app, securityContext, webSocketData);

      // save raw result count
      int resultCountBeforePaging = filteredResults.size();

      // set full result list
      webSocketData.setResult(PagingHelper.subList(filteredResults, pageSize, page, null));
      webSocketData.setRawResultCount(resultCountBeforePaging);

      // send only over local connection
      getWebSocket().send(webSocketData, true);

      tx.success();

    } catch (FrameworkException fex) {

      logger.warn("Exception occured", fex);
      getWebSocket()
          .send(
              MessageBuilder.status().code(fex.getStatus()).message(fex.getMessage()).build(),
              true);
    }
  }
  @Override
  public <T> Comparable getComparableProperty(final PropertyKey<T> key) {

    if (key != null) {

      final T propertyValue = getProperty(key, false, null); // get "raw" property without converter

      // check property converter
      PropertyConverter converter = key.databaseConverter(securityContext, this);
      if (converter != null) {

        try {
          return converter.convertForSorting(propertyValue);

        } catch (FrameworkException fex) {
          logger.log(
              Level.WARNING,
              "Unable to convert property {0} of type {1}: {2}",
              new Object[] {key.dbName(), getClass().getSimpleName(), fex.getMessage()});
        }
      }

      // conversion failed, may the property value itself is comparable
      if (propertyValue instanceof Comparable) {
        return (Comparable) propertyValue;
      }

      // last try: convertFromInput to String to make comparable
      if (propertyValue != null) {
        return propertyValue.toString();
      }
    }

    return null;
  }
  @Override
  public void cancelCheckout(final Payment payment) throws FrameworkException {

    // this is a no-op in the PayPal API, we only have to set the payment state
    try {

      payment.setToken(null);
      payment.setPaymentState(PaymentState.cancelled);

    } catch (FrameworkException fex) {
      fex.printStackTrace();
    }
  }
  @Override
  public void processMessage(WebSocketMessage webSocketData) {

    final SecurityContext securityContext = getWebSocket().getSecurityContext();
    final App app = StructrApp.getInstance(securityContext);
    final String id = webSocketData.getId();

    try (final Tx tx = app.tx()) {

      final Page page = app.get(Page.class, id);
      final List<GraphObject> result = new LinkedList<>();

      if (page != null) {

        collectActiveElements(result, page, Collections.EMPTY_SET, null, 0);

        // set full result list
        webSocketData.setResult(result);
        webSocketData.setRawResultCount(result.size());

        // send only over local connection
        getWebSocket().send(webSocketData, true);

      } else {

        getWebSocket()
            .send(
                MessageBuilder.status()
                    .code(404)
                    .message("Page with ID " + id + " not found.")
                    .build(),
                true);
      }

    } catch (FrameworkException fex) {

      logger.log(Level.WARNING, "Exception occured", fex);
      getWebSocket()
          .send(
              MessageBuilder.status().code(fex.getStatus()).message(fex.getMessage()).build(),
              true);
    }
  }
Example #10
0
  public void test01SearchSingleNodeByName() {

    try {

      PropertyMap props = new PropertyMap();
      PropertyKey key = AbstractNode.name;
      String name = "89w3hklsdfghsdkljth";

      props.put(key, name);

      AbstractNode node = createTestNode(TestOne.class.getSimpleName(), props);
      boolean includeDeletedAndHidden = true;
      boolean publicOnly = false;
      List<SearchAttribute> searchAttributes = new LinkedList<SearchAttribute>();

      searchAttributes.add(new TextualSearchAttribute(key, name, SearchOperator.AND));

      Result result =
          searchNodeCommand.execute(includeDeletedAndHidden, publicOnly, searchAttributes);

      assertTrue(result.size() == 1);
      assertTrue(result.get(0).equals(node));

      // Change name attribute and search again
      name = "klppptzoehigösoiutzüw0e9hg";

      node.setProperty(key, name);
      searchAttributes.clear();
      searchAttributes.add(new TextualSearchAttribute(key, name, SearchOperator.AND));

      result = searchNodeCommand.execute(includeDeletedAndHidden, publicOnly, searchAttributes);

      assertTrue(result.size() == 1);
      assertTrue(result.get(0).equals(node));

    } catch (FrameworkException ex) {

      logger.log(Level.SEVERE, ex.toString());
      fail("Unexpected exception");
    }
  }
Example #11
0
  public void test03SearchRelationship() {

    try {

      AbstractRelationship rel =
          ((List<AbstractRelationship>) createTestRelationships(RelType.UNDEFINED, 1)).get(0);
      PropertyKey key1 = new StringProperty("jghsdkhgshdhgsdjkfgh");
      String val1 = "54354354546806849870";

      rel.setProperty(key1, val1);
      assertTrue(rel.getProperty(key1).equals(val1));

      List<SearchAttribute> searchAttributes = new LinkedList<SearchAttribute>();

      searchAttributes.add(Search.andExactProperty(key1, val1));

      List<AbstractRelationship> result =
          (List<AbstractRelationship>) searchRelationshipCommand.execute(searchAttributes);

      assertTrue(result.size() == 1);
      assertTrue(result.get(0).equals(rel));
      searchAttributes.clear();

      val1 = "ölllldjöoa8w4rasf";

      rel.setProperty(key1, val1);
      searchAttributes.add(Search.andExactProperty(key1, val1));
      assertTrue(result.size() == 1);
      assertTrue(result.get(0).equals(rel));

    } catch (FrameworkException ex) {

      logger.log(Level.SEVERE, ex.toString());
      fail("Unexpected exception");
    }
  }
Example #12
0
  @Override
  public void insertData(final int offset, final String data) throws DOMException {

    checkWriteAccess();

    try {

      Services.command(securityContext, TransactionCommand.class)
          .execute(
              new StructrTransaction() {

                @Override
                public Object execute() throws FrameworkException {

                  String text = getProperty(content);

                  String leftPart = text.substring(0, offset);
                  String rightPart = text.substring(offset);

                  StringBuilder buf = new StringBuilder(text.length() + data.length() + 1);
                  buf.append(leftPart);
                  buf.append(data);
                  buf.append(rightPart);

                  // finally, set content to concatenated left, data and right parts
                  setProperty(content, buf.toString());

                  return null;
                }
              });

    } catch (FrameworkException fex) {

      throw new DOMException(DOMException.INVALID_STATE_ERR, fex.toString());
    }
  }
Example #13
0
  public void test06DistanceSearchOnEmptyDB() {

    try {

      boolean includeDeletedAndHidden = true;
      boolean publicOnly = false;
      List<SearchAttribute> searchAttributes = new LinkedList<SearchAttribute>();

      searchAttributes.add(
          new DistanceSearchAttribute(
              "Hanauer Landstr. 200, 60314 Frankfurt, Germany", 10.0, SearchOperator.AND));

      Result result =
          searchNodeCommand.execute(includeDeletedAndHidden, publicOnly, searchAttributes);

      assertEquals(0, result.size());

    } catch (FrameworkException ex) {

      logger.log(Level.SEVERE, ex.toString());
      System.out.println(ex.toString());
      fail("Unexpected exception");
    }
  }
Example #14
0
  @Override
  public Text splitText(int offset) throws DOMException {

    checkWriteAccess();

    String text = getProperty(content);

    if (text != null) {

      int len = text.length();

      if (offset < 0 || offset > len) {

        throw new DOMException(DOMException.INDEX_SIZE_ERR, INDEX_SIZE_ERR_MESSAGE);

      } else {

        final String firstPart = text.substring(0, offset);
        final String secondPart = text.substring(offset);

        final Document document = getOwnerDocument();
        final Node parent = getParentNode();

        if (document != null && parent != null) {

          try {

            return Services.command(securityContext, TransactionCommand.class)
                .execute(
                    new StructrTransaction<Text>() {

                      @Override
                      public Text execute() throws FrameworkException {

                        // first part goes into existing text element
                        setProperty(content, firstPart);

                        // second part goes into new text element
                        Text newNode = document.createTextNode(secondPart);

                        // make new node a child of old parent
                        parent.appendChild(newNode);

                        return newNode;
                      }
                    });

          } catch (FrameworkException fex) {

            throw new DOMException(DOMException.INVALID_STATE_ERR, fex.toString());
          }

        } else {

          throw new DOMException(DOMException.INVALID_STATE_ERR, CANNOT_SPLIT_TEXT_WITHOUT_PARENT);
        }
      }
    }

    throw new DOMException(DOMException.INDEX_SIZE_ERR, INDEX_SIZE_ERR_MESSAGE);
  }
Example #15
0
  @Override
  public void render(SecurityContext securityContext, RenderContext renderContext, int depth)
      throws FrameworkException {

    if (isDeleted()
        || isHidden()
        || !displayForLocale(renderContext)
        || !displayForConditions(securityContext, renderContext)) {
      return;
    }

    String id = getUuid();
    EditMode edit = renderContext.getEditMode(securityContext.getUser(false));
    boolean inBody = renderContext.inBody();
    StringBuilder buffer = renderContext.getBuffer();

    String _contentType = getProperty(contentType);

    // fetch content with variable replacement
    String _content =
        getPropertyWithVariableReplacement(securityContext, renderContext, Content.content);

    if (!(EditMode.RAW.equals(edit))
        && (_contentType == null || ("text/plain".equals(_contentType)))) {

      _content = escapeForHtml(_content);
    }

    if (EditMode.CONTENT.equals(edit)
        && inBody
        && securityContext.isAllowed(this, Permission.write)) {

      if ("text/javascript".equals(_contentType)) {

        // Javascript will only be given some local vars
        // TODO: Is this neccessary?
        buffer
            .append("// data-structr-type='")
            .append(getType())
            .append("'\n// data-structr-id='")
            .append(id)
            .append("'\n");

      } else if ("text/css".equals(_contentType)) {

        // CSS will only be given some local vars
        // TODO: Is this neccessary?
        buffer
            .append("/* data-structr-type='")
            .append(getType())
            .append("'*/\n/* data-structr-id='")
            .append(id)
            .append("'*/\n");

      } else {

        //				// In edit mode, add an artificial 'span' tag around content nodes within body to make
        // them editable
        //				buffer.append("<span data-structr-raw-value=\"").append(getProperty(Content.content))
        //					//.append("\"
        // data-structr-content-type=\"").append(StringUtils.defaultString(getProperty(Content.contentType), ""))
        //					.append("\" data-structr-type=\"").append(getType())
        //					.append("\" data-structr-id=\"").append(id).append("\">");

        //				int l = buffer.length();
        //				buffer.replace(l-1, l, " data-structr-raw-value=\""
        //					.concat(getProperty(Content.content))
        //					.concat("\" data-structr-type=\"").concat(getType())
        //					.concat("\" data-structr-id=\"").concat(id).concat("\">"));

        buffer.append(
            "<!--data-structr-id=\""
                .concat(id)
                .concat("\" data-structr-raw-value=\"")
                .concat(getProperty(Content.content).replaceAll("\n", "\\\\n"))
                .concat("\"-->"));
        // .concat("\"
        // data-structr-raw-value=\"").concat(getProperty(Content.content)).concat("\"-->"));

      }
    }

    // No contentType-specific rendering in DATA edit mode
    // if (!edit.equals(EditMode.DATA)) {

    // examine content type and apply converter

    if (_contentType != null) {

      Adapter<String, String> converter = contentConverters.get(_contentType);

      if (converter != null) {

        try {

          // apply adapter
          _content = converter.adapt(_content);
        } catch (FrameworkException fex) {

          logger.log(Level.WARNING, "Unable to convert content: {0}", fex.getMessage());
        }
      }
    }

    // replace newlines with <br /> for rendering
    if (((_contentType == null) || _contentType.equals("text/plain"))
        && (_content != null)
        && !_content.isEmpty()) {

      _content = _content.replaceAll("[\\n]{1}", "<br>");
    }
    // }

    if (_content != null) {

      // buffer.append(indent(depth, true)).append(_content);

      // insert whitespace to make element clickable
      if (EditMode.CONTENT.equals(edit) && _content.length() == 0) {
        _content = "--- empty ---";
      }

      buffer.append(_content);
    }

    if (EditMode.CONTENT.equals(edit)
        && inBody
        && !("text/javascript".equals(getProperty(contentType)))
        && !("text/css".equals(getProperty(contentType)))) {

      //			buffer.append("</span>");
      buffer.append("<!---->");
    }
  }
Example #16
0
  @Override
  public void onWebSocketText(final String data) {

    if (data == null) {
      logger.log(Level.WARNING, "Empty text message received.");
      return;
    }

    logger.log(
        Level.FINE,
        "############################################################ RECEIVED \n{0}",
        data.substring(0, Math.min(data.length(), 1000)));

    // parse web socket data from JSON
    final WebSocketMessage webSocketData = gson.fromJson(data, WebSocketMessage.class);

    final App app = StructrApp.getInstance(securityContext);

    try (final Tx tx = app.tx()) {

      this.callback = webSocketData.getCallback();

      final String command = webSocketData.getCommand();
      final Class type = commandSet.get(command);

      final String sessionIdFromMessage = webSocketData.getSessionId();

      if (type != null) {

        if (sessionIdFromMessage != null) {

          // try to authenticated this connection by sessionId
          authenticate(sessionIdFromMessage);
        }

        // we only permit LOGIN commands if authentication based on sessionId was not successful
        if (!isAuthenticated() && !type.equals(LoginCommand.class)) {

          // send 401 Authentication Required
          send(MessageBuilder.status().code(401).message("").build(), true);

          return;
        }

        AbstractCommand abstractCommand = (AbstractCommand) type.newInstance();

        abstractCommand.setWebSocket(this);
        abstractCommand.setSession(session);
        abstractCommand.setIdProperty(idProperty);

        // store authenticated-Flag in webSocketData
        // so the command can access it
        webSocketData.setSessionValid(isAuthenticated());

        // process message
        try {

          abstractCommand.processMessage(webSocketData);

          // commit transaction
          tx.success();

        } catch (FrameworkException fex) {

          fex.printStackTrace(System.out);

          // send 400 Bad Request
          send(MessageBuilder.status().code(400).message(fex.toString()).build(), true);
        }

      } else {

        logger.log(Level.WARNING, "Unknow command {0}", command);

        // send 400 Bad Request
        send(MessageBuilder.status().code(400).message("Unknown command").build(), true);
      }

    } catch (FrameworkException | IllegalAccessException | InstantiationException t) {

      logger.log(Level.WARNING, "Unable to parse message.", t);
    }
  }
Example #17
0
  @Override
  protected void doGet(final HttpServletRequest request, final HttpServletResponse response) {

    final Authenticator auth = config.getAuthenticator();
    final SecurityContext securityContext;
    final App app;

    try {
      String path = request.getPathInfo();

      // check for registration (has its own tx because of write access
      if (checkRegistration(auth, request, response, path)) {

        return;
      }

      // isolate request authentication in a transaction
      try (final Tx tx = StructrApp.getInstance().tx()) {
        securityContext = auth.initializeAndExamineRequest(request, response);
        tx.success();
      }

      app = StructrApp.getInstance(securityContext);

      try (final Tx tx = app.tx()) {

        // Ensure access mode is frontend
        securityContext.setAccessMode(AccessMode.Frontend);

        request.setCharacterEncoding("UTF-8");

        // Important: Set character encoding before calling response.getWriter() !!, see Servlet
        // Spec 5.4
        response.setCharacterEncoding("UTF-8");

        boolean dontCache = false;

        logger.log(Level.FINE, "Path info {0}", path);

        // don't continue on redirects
        if (response.getStatus() == 302) {
          return;
        }

        Principal user = securityContext.getUser(false);
        if (user != null) {

          // Don't cache if a user is logged in
          dontCache = true;
        }

        final RenderContext renderContext =
            RenderContext.getInstance(request, response, getEffectiveLocale(request));

        renderContext.setResourceProvider(config.getResourceProvider());

        EditMode edit = renderContext.getEditMode(user);

        DOMNode rootElement = null;
        AbstractNode dataNode = null;

        String[] uriParts = PathHelper.getParts(path);
        if ((uriParts == null) || (uriParts.length == 0)) {

          // find a visible page
          rootElement = findIndexPage(securityContext);

          logger.log(Level.FINE, "No path supplied, trying to find index page");

        } else {

          if (rootElement == null) {

            rootElement = findPage(securityContext, request, path);

          } else {
            dontCache = true;
          }
        }

        if (rootElement == null) { // No page found

          // Look for a file
          File file = findFile(securityContext, request, path);
          if (file != null) {

            streamFile(securityContext, file, request, response, edit);
            return;
          }

          // store remaining path parts in request
          Matcher matcher = threadLocalUUIDMatcher.get();
          boolean requestUriContainsUuids = false;

          for (int i = 0; i < uriParts.length; i++) {

            request.setAttribute(uriParts[i], i);
            matcher.reset(uriParts[i]);

            // set to "true" if part matches UUID pattern
            requestUriContainsUuids |= matcher.matches();
          }

          if (!requestUriContainsUuids) {

            // Try to find a data node by name
            dataNode = findFirstNodeByName(securityContext, request, path);

          } else {

            dataNode = findNodeByUuid(securityContext, PathHelper.getName(path));
          }

          if (dataNode != null) {

            // Last path part matches a data node
            // Remove last path part and try again searching for a page
            // clear possible entry points
            request.removeAttribute(POSSIBLE_ENTRY_POINTS);

            rootElement =
                findPage(
                    securityContext,
                    request,
                    StringUtils.substringBeforeLast(path, PathHelper.PATH_SEP));

            renderContext.setDetailsDataObject(dataNode);

            // Start rendering on data node
            if (rootElement == null && dataNode instanceof DOMNode) {

              rootElement = ((DOMNode) dataNode);
            }
          }
        }

        // Still nothing found, do error handling
        if (rootElement == null) {

          // Check if security context has set an 401 status
          if (response.getStatus() == HttpServletResponse.SC_UNAUTHORIZED) {

            try {

              UiAuthenticator.writeUnauthorized(response);

            } catch (IllegalStateException ise) {
            }

          } else {

            rootElement = notFound(response, securityContext);
          }
        }

        if (rootElement == null) {
          return;
        }

        if (EditMode.WIDGET.equals(edit) || dontCache) {

          setNoCacheHeaders(response);
        }

        if (!securityContext.isVisible(rootElement)) {

          rootElement = notFound(response, securityContext);
          if (rootElement == null) {
            return;
          }
        }

        if (securityContext.isVisible(rootElement)) {

          if (!EditMode.WIDGET.equals(edit)
              && !dontCache
              && notModifiedSince(request, response, rootElement, dontCache)) {

            ServletOutputStream out = response.getOutputStream();
            out.flush();
            // response.flushBuffer();
            out.close();

          } else {

            // prepare response
            response.setCharacterEncoding("UTF-8");

            String contentType = rootElement.getProperty(Page.contentType);

            if (contentType != null && contentType.equals("text/html")) {

              contentType = contentType.concat(";charset=UTF-8");
              response.setContentType(contentType);

            } else {

              // Default
              response.setContentType("text/html;charset=UTF-8");
            }

            response.setHeader("Strict-Transport-Security", "max-age=60");
            response.setHeader("X-Content-Type-Options", "nosniff");
            response.setHeader("X-Frame-Options", "SAMEORIGIN");
            response.setHeader("X-XSS-Protection", "1; mode=block");

            // async or not?
            boolean isAsync =
                HttpService.parseBoolean(
                    Services.getBaseConfiguration().getProperty(HttpService.ASYNC), true);
            if (isAsync) {

              final AsyncContext async = request.startAsync();
              final ServletOutputStream out = async.getResponse().getOutputStream();
              final AtomicBoolean finished = new AtomicBoolean(false);
              final DOMNode rootNode = rootElement;

              threadPool.submit(
                  new Runnable() {

                    @Override
                    public void run() {

                      try (final Tx tx = app.tx()) {

                        // final long start = System.currentTimeMillis();

                        // render
                        rootNode.render(securityContext, renderContext, 0);
                        finished.set(true);

                        // final long end = System.currentTimeMillis();
                        // System.out.println("Done in " + (end-start) + " ms");

                        tx.success();

                      } catch (Throwable t) {
                        t.printStackTrace();
                        final String errorMsg = t.getMessage();
                        try {
                          // response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                          response.sendError(
                              HttpServletResponse.SC_INTERNAL_SERVER_ERROR, errorMsg);
                          finished.set(true);
                        } catch (IOException ex) {
                          ex.printStackTrace();
                        }
                      }
                    }
                  });

              // start output write listener
              out.setWriteListener(
                  new WriteListener() {

                    @Override
                    public void onWritePossible() throws IOException {

                      try {

                        final Queue<String> queue = renderContext.getBuffer().getQueue();
                        while (out.isReady()) {

                          String buffer = null;

                          synchronized (queue) {
                            buffer = queue.poll();
                          }

                          if (buffer != null) {

                            out.print(buffer);

                          } else {

                            if (finished.get()) {

                              async.complete();
                              response.setStatus(HttpServletResponse.SC_OK);

                              // prevent this block from being called again
                              break;
                            }

                            Thread.sleep(1);
                          }
                        }

                      } catch (Throwable t) {
                        t.printStackTrace();
                      }
                    }

                    @Override
                    public void onError(Throwable t) {
                      t.printStackTrace();
                    }
                  });

            } else {

              final StringRenderBuffer buffer = new StringRenderBuffer();
              renderContext.setBuffer(buffer);

              // render
              rootElement.render(securityContext, renderContext, 0);

              response.getOutputStream().write(buffer.getBuffer().toString().getBytes("utf-8"));
              response.getOutputStream().flush();
              response.getOutputStream().close();
            }
          }

        } else {

          notFound(response, securityContext);
        }

        tx.success();

      } catch (FrameworkException fex) {
        fex.printStackTrace();
        logger.log(Level.SEVERE, "Exception while processing request", fex);
      }

    } catch (IOException | FrameworkException t) {

      t.printStackTrace();
      logger.log(Level.SEVERE, "Exception while processing request", t);
      UiAuthenticator.writeInternalServerError(response);
    }
  }
Example #18
0
  public static void analyzeSchema() {

    final App app = StructrApp.getInstance();
    final FileBasedHashLongMap<NodeInfo> nodeIdMap =
        new FileBasedHashLongMap<>(userHome + File.separator + ".structrSchemaAnalyzer");
    final GraphDatabaseService graphDb = app.command(GraphDatabaseCommand.class).execute();
    final ConfigurationProvider configuration = Services.getInstance().getConfigurationProvider();
    final Set<NodeInfo> nodeTypes = new LinkedHashSet<>();
    final Set<RelationshipInfo> relationships = new LinkedHashSet<>();
    final Map<String, SchemaNode> schemaNodes = new LinkedHashMap<>();
    final Map<String, List<TypeInfo>> typeInfoTypeMap = new LinkedHashMap<>();
    final List<TypeInfo> reducedTypeInfos = new LinkedList<>();
    final List<TypeInfo> typeInfos = new LinkedList<>();
    Iterator<Relationship> relIterator = null;
    Iterator<Node> nodeIterator = null;

    logger.log(Level.INFO, "Fetching all nodes iterator..");

    try (final Tx tx = app.tx()) {

      nodeIterator =
          Iterables.filter(
                  new StructrAndSpatialPredicate(false, false, true),
                  GlobalGraphOperations.at(graphDb).getAllNodes())
              .iterator();
      tx.success();

    } catch (FrameworkException fex) {
      fex.printStackTrace();
    }

    logger.log(Level.INFO, "Starting to analyze nodes..");

    NodeServiceCommand.bulkGraphOperation(
        SecurityContext.getSuperUserInstance(),
        nodeIterator,
        100000,
        "Analyzing nodes",
        new BulkGraphOperation<Node>() {

          @Override
          public void handleGraphObject(final SecurityContext securityContext, final Node node)
              throws FrameworkException {

            final NodeInfo nodeInfo = new NodeInfo(node);

            // hashcode of nodeInfo is derived from its property and type signature!
            nodeTypes.add(nodeInfo);

            // add node ID to our new test datastructure
            nodeIdMap.add(nodeInfo, node.getId());
          }
        });

    logger.log(Level.INFO, "Identifying common base classes..");

    try (final Tx tx = app.tx(true, false, false)) {

      // nodeTypes now contains all existing node types and their property sets
      identifyCommonBaseClasses(app, nodeTypes, nodeIdMap, typeInfos);

      tx.success();

    } catch (FrameworkException fex) {
      fex.printStackTrace();
    }

    logger.log(Level.INFO, "Collecting type information..");

    try (final Tx tx = app.tx(true, false, false)) {

      // group type infos by type
      collectTypeInfos(typeInfos, typeInfoTypeMap);

      tx.success();

    } catch (FrameworkException fex) {
      fex.printStackTrace();
    }

    logger.log(Level.INFO, "Aggregating type information..");

    try (final Tx tx = app.tx(true, false, false)) {

      // reduce type infos with more than one type
      reduceTypeInfos(typeInfoTypeMap, reducedTypeInfos);

      tx.success();

    } catch (FrameworkException fex) {
      fex.printStackTrace();
    }

    logger.log(Level.INFO, "Identifying property sets..");
    try (final Tx tx = app.tx(true, false, false)) {

      // intersect property sets of type infos
      intersectPropertySets(reducedTypeInfos);

      tx.success();

    } catch (FrameworkException fex) {
      fex.printStackTrace();
    }

    logger.log(Level.INFO, "Sorting result..");
    try (final Tx tx = app.tx(false, false, false)) {

      // sort type infos
      Collections.sort(reducedTypeInfos, new HierarchyComparator(false));

      tx.success();

    } catch (FrameworkException fex) {
      fex.printStackTrace();
    }

    final Map<String, TypeInfo> reducedTypeInfoMap = new LinkedHashMap<>();

    for (final TypeInfo info : reducedTypeInfos) {

      final String type = info.getPrimaryType();

      // map TypeInfo to type for later use
      reducedTypeInfoMap.put(type, info);

      logger.log(Level.INFO, "Starting with setting of type and ID for type {0}", type);

      NodeServiceCommand.bulkGraphOperation(
          SecurityContext.getSuperUserInstance(),
          info.getNodeIds().iterator(),
          10000,
          "Setting type and ID",
          new BulkGraphOperation<Long>() {

            @Override
            public void handleGraphObject(SecurityContext securityContext, Long nodeId)
                throws FrameworkException {

              final Node node = graphDb.getNodeById(nodeId);

              node.setProperty(GraphObject.id.dbName(), NodeServiceCommand.getNextUuid());
              node.setProperty(GraphObject.type.dbName(), type);
            }
          });
    }

    logger.log(Level.INFO, "Fetching all relationships iterator..");

    try (final Tx tx = app.tx(false, false, false)) {

      relIterator =
          Iterables.filter(
                  new StructrAndSpatialPredicate(false, false, true),
                  GlobalGraphOperations.at(graphDb).getAllRelationships())
              .iterator();
      tx.success();

    } catch (FrameworkException fex) {
      fex.printStackTrace();
    }

    logger.log(Level.INFO, "Starting with analyzing relationships..");

    NodeServiceCommand.bulkGraphOperation(
        SecurityContext.getSuperUserInstance(),
        relIterator,
        10000,
        "Analyzing relationships",
        new BulkGraphOperation<Relationship>() {

          @Override
          public void handleGraphObject(SecurityContext securityContext, Relationship rel)
              throws FrameworkException {

            final Node startNode = rel.getStartNode();
            final Node endNode = rel.getEndNode();

            // make sure node has been successfully identified above
            if (startNode.hasProperty("type") && endNode.hasProperty("type")) {

              final String relationshipType = rel.getType().name();
              final String startNodeType = (String) startNode.getProperty("type");
              final String endNodeType = (String) endNode.getProperty("type");

              relationships.add(new RelationshipInfo(startNodeType, endNodeType, relationshipType));

              // create combined type on imported relationship
              if (startNodeType != null && endNodeType != null) {

                final String combinedType =
                    getCombinedType(startNodeType, relationshipType, endNodeType);

                logger.log(
                    Level.FINE,
                    "Combined relationship type {0} found for rel type {1}, start node type {2}, end node type {3}",
                    new Object[] {combinedType, relationshipType, startNodeType, endNodeType});

                rel.setProperty(GraphObject.type.dbName(), combinedType);
              }

              // create ID on imported relationship
              rel.setProperty(GraphObject.id.dbName(), NodeServiceCommand.getNextUuid());
            }
          }
        });

    logger.log(Level.INFO, "Grouping relationships..");

    // group relationships by type
    final Map<String, List<RelationshipInfo>> relTypeInfoMap = new LinkedHashMap<>();
    for (final RelationshipInfo relInfo : relationships) {

      // final String relType         = relInfo.getRelType();
      final String combinedType =
          getCombinedType(
              relInfo.getStartNodeType(), relInfo.getRelType(), relInfo.getEndNodeType());
      List<RelationshipInfo> infos = relTypeInfoMap.get(combinedType);

      if (infos == null) {

        infos = new LinkedList<>();
        relTypeInfoMap.put(combinedType, infos);
      }

      infos.add(relInfo);
    }

    logger.log(Level.INFO, "Aggregating relationship information..");

    final List<RelationshipInfo> reducedRelationshipInfos = new ArrayList<>();
    if ("true"
        .equals(
            Services.getInstance()
                .getConfigurationValue("importer.inheritancedetection", "true"))) {

      // reduce relationship infos into one
      for (final List<RelationshipInfo> infos : relTypeInfoMap.values()) {

        reducedRelationshipInfos.addAll(reduceNodeTypes(infos, reducedTypeInfoMap));
      }

    } else {

      reducedRelationshipInfos.addAll(relationships);
    }

    logger.log(Level.INFO, "Starting with schema node creation..");

    NodeServiceCommand.bulkGraphOperation(
        SecurityContext.getSuperUserInstance(),
        reducedTypeInfos.iterator(),
        100000,
        "Creating schema nodes",
        new BulkGraphOperation<TypeInfo>() {

          @Override
          public void handleGraphObject(SecurityContext securityContext, TypeInfo typeInfo)
              throws FrameworkException {

            final String type = typeInfo.getPrimaryType();
            if (!"ReferenceNode".equals(type)) {

              final Map<String, Class> props = typeInfo.getPropertySet();
              final PropertyMap propertyMap = new PropertyMap();

              // add properties
              for (final Map.Entry<String, Class> propertyEntry : props.entrySet()) {

                final String propertyName = propertyEntry.getKey();
                final Class propertyType = propertyEntry.getValue();

                // handle array types differently
                String propertyTypeName = propertyType.getSimpleName();
                if (propertyType.isArray()) {

                  // remove "[]" from the end and append "Array" to match the appropriate parser
                  propertyTypeName =
                      propertyTypeName.substring(0, propertyTypeName.length() - 2).concat("Array");
                }

                propertyMap.put(new StringProperty("_".concat(propertyName)), propertyTypeName);
              }

              // set node type which is in "name" property
              propertyMap.put(AbstractNode.name, type);

              // check if there is an existing Structr entity with the same type
              // and make the dynamic class extend the existing class if yes.
              final Class existingType = configuration.getNodeEntityClass(type);
              if (existingType != null) {

                propertyMap.put(SchemaNode.extendsClass, existingType.getName());

              } else if (!typeInfo.getOtherTypes().isEmpty()) {

                // only the first supertype is supported
                propertyMap.put(
                    SchemaNode.extendsClass, typeInfo.getSuperclass(reducedTypeInfoMap));
              }

              final SchemaNode existingNode =
                  app.nodeQuery(SchemaNode.class).andName(type).getFirst();
              if (existingNode != null) {

                for (final Entry<PropertyKey, Object> entry : propertyMap.entrySet()) {

                  existingNode.setProperty(entry.getKey(), entry.getValue());
                }

                schemaNodes.put(type, existingNode);

              } else {

                // create schema node
                schemaNodes.put(type, app.create(SchemaNode.class, propertyMap));
              }
            }
          }
        });

    logger.log(Level.INFO, "Starting with schema relationship creation..");

    NodeServiceCommand.bulkGraphOperation(
        SecurityContext.getSuperUserInstance(),
        reducedRelationshipInfos.iterator(),
        100000,
        "Creating schema relationships",
        new BulkGraphOperation<RelationshipInfo>() {

          @Override
          public void handleGraphObject(SecurityContext securityContext, RelationshipInfo template)
              throws FrameworkException {

            final SchemaNode startNode = schemaNodes.get(template.getStartNodeType());
            final SchemaNode endNode = schemaNodes.get(template.getEndNodeType());
            final String relationshipType = template.getRelType();
            final PropertyMap propertyMap = new PropertyMap();

            propertyMap.put(SchemaRelationshipNode.sourceId, startNode.getUuid());
            propertyMap.put(SchemaRelationshipNode.targetId, endNode.getUuid());
            propertyMap.put(SchemaRelationshipNode.relationshipType, relationshipType);

            app.create(SchemaRelationshipNode.class, propertyMap);
          }
        });

    logger.log(Level.INFO, "Starting with index rebuild..");

    // rebuild index
    app.command(BulkRebuildIndexCommand.class).execute(Collections.EMPTY_MAP);
  }
  @Override
  public void processMessage(WebSocketMessage webSocketData) {

    final Map<String, Object> nodeData = webSocketData.getNodeData();
    final String parentId = (String) nodeData.get("parentId");
    final String childContent = (String) nodeData.get("childContent");
    final String pageId = webSocketData.getPageId();

    nodeData.remove("parentId");

    if (pageId != null) {

      // check for parent ID before creating any nodes
      if (parentId == null) {

        getWebSocket()
            .send(
                MessageBuilder.status()
                    .code(422)
                    .message("Cannot add node without parentId")
                    .build(),
                true);
        return;
      }

      // check if parent node with given ID exists
      final DOMNode parentNode = getDOMNode(parentId);
      if (parentNode == null) {

        getWebSocket()
            .send(MessageBuilder.status().code(404).message("Parent node not found").build(), true);
        return;
      }

      final Document document = getPage(pageId);
      if (document != null) {

        final String tagName = (String) nodeData.get("tagName");
        final App app = StructrApp.getInstance();

        nodeData.remove("tagName");

        try {
          app.beginTx();

          DOMNode newNode;

          if (tagName != null && !tagName.isEmpty()) {

            newNode = (DOMNode) document.createElement(tagName);

          } else {

            newNode = (DOMNode) document.createTextNode("#text");
          }

          // append new node to parent
          if (newNode != null) {

            parentNode.appendChild(newNode);

            for (Entry entry : nodeData.entrySet()) {

              String key = (String) entry.getKey();
              Object val = entry.getValue();

              PropertyKey propertyKey =
                  StructrApp.getConfiguration()
                      .getPropertyKeyForDatabaseName(newNode.getClass(), key);
              if (propertyKey != null) {

                try {
                  Object convertedValue = val;

                  PropertyConverter inputConverter =
                      propertyKey.inputConverter(SecurityContext.getSuperUserInstance());
                  if (inputConverter != null) {

                    convertedValue = inputConverter.convert(val);
                  }

                  // newNode.unlockReadOnlyPropertiesOnce();
                  newNode.setProperty(propertyKey, convertedValue);

                } catch (FrameworkException fex) {

                  logger.log(
                      Level.WARNING,
                      "Unable to set node property {0} of node {1} to {2}: {3}",
                      new Object[] {propertyKey, newNode.getUuid(), val, fex.getMessage()});
                }
              }
            }

            // create a child text node if content is given
            if (StringUtils.isNotBlank(childContent)) {

              DOMNode childNode = (DOMNode) document.createTextNode(childContent);

              if (newNode != null) {

                newNode.appendChild(childNode);
              }
            }
          }
          app.commitTx();

        } catch (DOMException dex) {

          // send DOM exception
          getWebSocket()
              .send(MessageBuilder.status().code(422).message(dex.getMessage()).build(), true);

        } catch (FrameworkException ex) {

          Logger.getLogger(CreateAndAppendDOMNodeCommand.class.getName())
              .log(Level.SEVERE, null, ex);

        } finally {

          app.finishTx();
        }

      } else {

        getWebSocket()
            .send(MessageBuilder.status().code(404).message("Page not found").build(), true);
      }

    } else {

      getWebSocket()
          .send(
              MessageBuilder.status()
                  .code(422)
                  .message("Cannot create node without pageId")
                  .build(),
              true);
    }
  }
  @Override
  public Object setProperty(
      final SecurityContext securityContext, final GraphObject obj, final T value)
      throws FrameworkException {

    final PropertyConverter converter = databaseConverter(securityContext, obj);
    final Object convertedValue;

    if (converter != null) {

      convertedValue = converter.convert(value);

    } else {

      convertedValue = value;
    }

    final PropertyContainer propertyContainer = obj.getPropertyContainer();
    if (propertyContainer != null) {

      if (!TransactionCommand.inTransaction()) {

        throw new NotInTransactionException("setProperty outside of transaction");
      }

      boolean internalSystemPropertiesUnlocked = (obj instanceof CreationContainer);

      // notify only non-system properties

      // collect modified properties
      if (obj instanceof AbstractNode) {

        if (!unvalidated) {

          TransactionCommand.nodeModified(
              securityContext.getCachedUser(),
              (AbstractNode) obj,
              AbstractPrimitiveProperty.this,
              propertyContainer.hasProperty(dbName())
                  ? propertyContainer.getProperty(dbName())
                  : null,
              value);
        }

        internalSystemPropertiesUnlocked = ((AbstractNode) obj).internalSystemPropertiesUnlocked;

      } else if (obj instanceof AbstractRelationship) {

        if (!unvalidated) {

          TransactionCommand.relationshipModified(
              securityContext.getCachedUser(),
              (AbstractRelationship) obj,
              AbstractPrimitiveProperty.this,
              propertyContainer.hasProperty(dbName())
                  ? propertyContainer.getProperty(dbName())
                  : null,
              value);
        }

        internalSystemPropertiesUnlocked =
            ((AbstractRelationship) obj).internalSystemPropertiesUnlocked;
      }

      // catch all sorts of errors and wrap them in a FrameworkException
      try {

        // save space
        if (convertedValue == null) {

          propertyContainer.removeProperty(dbName());

        } else {

          if (!isSystemInternal() || internalSystemPropertiesUnlocked) {

            propertyContainer.setProperty(dbName(), convertedValue);

          } else {

            logger.warn(
                "Tried to set internal system property {} to {}. Action was denied.",
                new Object[] {dbName(), convertedValue});
          }
        }

        updateAccessInformation(securityContext, propertyContainer);

      } catch (Throwable t) {

        // throw FrameworkException with the given cause
        final FrameworkException fex =
            new FrameworkException(
                500,
                "Unable to set property "
                    + jsonName()
                    + " on entity with ID "
                    + obj.getUuid()
                    + ": "
                    + t.toString());
        fex.initCause(t);

        throw fex;
      }

      if (isIndexed()) {

        // do indexing, needs to be done after
        // setProperty to make spatial index
        // work
        if (!isPassivelyIndexed()) {

          index(obj, convertedValue);
        }
      }
    }

    return null;
  }