Search in sources :

Example 91 with GraphObject

use of org.structr.core.GraphObject in project structr by structr.

the class RestDataSource method getData.

// FIXME: this method is needed by the websocket search command because there is no reference node for the above method
public List<GraphObject> getData(final RenderContext renderContext, final String restQuery) throws FrameworkException {
    final Map<Pattern, Class<? extends Resource>> resourceMap = new LinkedHashMap<>();
    final SecurityContext securityContext = renderContext.getSecurityContext();
    ResourceProvider resourceProvider = renderContext.getResourceProvider();
    if (resourceProvider == null) {
        try {
            resourceProvider = UiResourceProvider.class.newInstance();
        } catch (Throwable t) {
            logger.error("Couldn't establish a resource provider", t);
            return Collections.EMPTY_LIST;
        }
    }
    // inject resources
    resourceMap.putAll(resourceProvider.getResources());
    Value<String> propertyView = new ThreadLocalPropertyView();
    propertyView.set(securityContext, PropertyView.Ui);
    HttpServletRequest request = securityContext.getRequest();
    if (request == null) {
        request = renderContext.getRequest();
    }
    // initialize variables
    // mimic HTTP request
    final HttpServletRequest wrappedRequest = new HttpServletRequestWrapper(request) {

        @Override
        public Enumeration<String> getParameterNames() {
            return new IteratorEnumeration(getParameterMap().keySet().iterator());
        }

        @Override
        public String getParameter(final String key) {
            String[] p = getParameterMap().get(key);
            return p != null ? p[0] : null;
        }

        @Override
        public String[] getParameterValues(final String key) {
            return getParameterMap().get(key);
        }

        @Override
        public Map<String, String[]> getParameterMap() {
            String[] parts = StringUtils.split(getQueryString(), "&");
            Map<String, String[]> parameterMap = new HashMap();
            for (String p : parts) {
                String[] kv = StringUtils.split(p, "=");
                if (kv.length > 1) {
                    parameterMap.put(kv[0], new String[] { kv[1] });
                }
            }
            return parameterMap;
        }

        @Override
        public String getQueryString() {
            return StringUtils.substringAfter(restQuery, "?");
        }

        @Override
        public String getPathInfo() {
            return StringUtils.substringBefore(restQuery, "?");
        }

        @Override
        public StringBuffer getRequestURL() {
            return new StringBuffer(restQuery);
        }
    };
    // store original request
    final HttpServletRequest origRequest = securityContext.getRequest();
    // update request in security context
    securityContext.setRequest(wrappedRequest);
    // HttpServletResponse response = renderContext.getResponse();
    Resource resource = null;
    try {
        resource = ResourceHelper.applyViewTransformation(wrappedRequest, securityContext, ResourceHelper.optimizeNestedResourceChain(securityContext, wrappedRequest, resourceMap, propertyView), propertyView);
    } catch (IllegalPathException | NotFoundException e) {
        logger.warn("Illegal path for REST query: {}", restQuery);
    }
    // reset request to old context
    securityContext.setRequest(origRequest);
    if (resource == null) {
        return Collections.EMPTY_LIST;
    }
    // experimental: disable result count, prevents instantiation
    // of large collections just for counting all the objects..
    securityContext.ignoreResultCount(true);
    // TODO: decide if we need to rest the REST request here
    // securityContext.checkResourceAccess(request, resource.getResourceSignature(), resource.getGrant(request, response), PropertyView.Ui);
    // add sorting & paging
    String pageSizeParameter = wrappedRequest.getParameter(JsonRestServlet.REQUEST_PARAMETER_PAGE_SIZE);
    String pageParameter = wrappedRequest.getParameter(JsonRestServlet.REQUEST_PARAMETER_PAGE_NUMBER);
    String sortOrder = wrappedRequest.getParameter(JsonRestServlet.REQUEST_PARAMETER_SORT_ORDER);
    String sortKeyName = wrappedRequest.getParameter(JsonRestServlet.REQUEST_PARAMETER_SORT_KEY);
    boolean sortDescending = (sortOrder != null && "desc".equals(sortOrder.toLowerCase()));
    int pageSize = parseInt(pageSizeParameter, NodeFactory.DEFAULT_PAGE_SIZE);
    int page = parseInt(pageParameter, NodeFactory.DEFAULT_PAGE);
    PropertyKey sortKey = null;
    // set sort key
    if (sortKeyName != null) {
        Class<? extends GraphObject> type = resource.getEntityClass();
        if (type == null) {
            // fallback to default implementation
            // if no type can be determined
            type = AbstractNode.class;
        }
        sortKey = StructrApp.getConfiguration().getPropertyKeyForDatabaseName(type, sortKeyName, false);
    }
    // do action
    Result result = Result.EMPTY_RESULT;
    try {
        result = resource.doGet(sortKey, sortDescending, pageSize, page);
    } catch (NotFoundException nfe) {
        logger.warn("No result from internal REST query: {}", restQuery);
    }
    result.setIsCollection(resource.isCollectionResource());
    result.setIsPrimitiveArray(resource.isPrimitiveArray());
    // Integer rawResultCount = (Integer) Services.getAttribute(NodeFactory.RAW_RESULT_COUNT + Thread.currentThread().getId());
    PagingHelper.addPagingParameter(result, pageSize, page);
    List<GraphObject> res = result.getResults();
    renderContext.setResult(result);
    return res != null ? res : Collections.EMPTY_LIST;
}
Also used : IllegalPathException(org.structr.rest.exception.IllegalPathException) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) NotFoundException(org.structr.rest.exception.NotFoundException) GraphObject(org.structr.core.GraphObject) LinkedHashMap(java.util.LinkedHashMap) Result(org.structr.core.Result) HttpServletRequest(javax.servlet.http.HttpServletRequest) HttpServletRequestWrapper(javax.servlet.http.HttpServletRequestWrapper) ResourceProvider(org.structr.rest.ResourceProvider) UiResourceProvider(org.structr.web.common.UiResourceProvider) Pattern(java.util.regex.Pattern) IteratorEnumeration(org.apache.commons.collections.iterators.IteratorEnumeration) Resource(org.structr.rest.resource.Resource) UiResourceProvider(org.structr.web.common.UiResourceProvider) SecurityContext(org.structr.common.SecurityContext) PropertyKey(org.structr.core.property.PropertyKey)

Example 92 with GraphObject

use of org.structr.core.GraphObject in project structr by structr.

the class XPathGraphDataSource method getData.

@Override
public Iterable<GraphObject> getData(final RenderContext renderContext, final DOMNode referenceNode) throws FrameworkException {
    final String xpathQuery = referenceNode.getXpathQuery();
    if (StringUtils.isBlank(xpathQuery)) {
        return null;
    }
    final Document document = ((DOMNode) referenceNode).getOwnerDocument();
    final XPathFactory factory = XPathFactory.newInstance();
    final XPath xpath = factory.newXPath();
    try {
        // FIXME: this code works only with absolute xpath queries because
        // the xpath parser implementation is stupid (comparing object
        // equality using ==).
        Object result = xpath.evaluate(xpathQuery, document, XPathConstants.NODESET);
        List<GraphObject> results = new LinkedList<>();
        if (result instanceof NodeList) {
            NodeList nodes = (NodeList) result;
            int len = nodes.getLength();
            for (int i = 0; i < len; i++) {
                Node node = nodes.item(i);
                if (node instanceof GraphObject) {
                    results.add((GraphObject) node);
                }
            }
        } else if (result instanceof GraphObject) {
            results.add((GraphObject) result);
        }
        return results;
    } catch (Throwable t) {
        logger.warn("Unable to execute xpath query: {}", t.getMessage());
    }
    return Collections.EMPTY_LIST;
}
Also used : XPath(javax.xml.xpath.XPath) NodeList(org.w3c.dom.NodeList) DOMNode(org.structr.web.entity.dom.DOMNode) Node(org.w3c.dom.Node) Document(org.w3c.dom.Document) GraphObject(org.structr.core.GraphObject) LinkedList(java.util.LinkedList) XPathFactory(javax.xml.xpath.XPathFactory) GraphObject(org.structr.core.GraphObject) DOMNode(org.structr.web.entity.dom.DOMNode)

Example 93 with GraphObject

use of org.structr.core.GraphObject in project structr by structr.

the class IncludeFunction method apply.

@Override
public Object apply(final ActionContext ctx, final Object caller, final Object[] sources) throws FrameworkException {
    try {
        if (!(arrayHasMinLengthAndAllElementsNotNull(sources, 1) && sources[0] instanceof String)) {
            return null;
        }
        final PropertyKey<DOMNode> sharedCompKey = StructrApp.key(DOMNode.class, "sharedComponent");
        final SecurityContext securityContext = ctx.getSecurityContext();
        final App app = StructrApp.getInstance(securityContext);
        final RenderContext innerCtx = new RenderContext((RenderContext) ctx);
        final List<DOMNode> nodeList = app.nodeQuery(DOMNode.class).andName((String) sources[0]).getAsList();
        DOMNode node = null;
        /**
         * Nodes can be included via their name property These nodes MUST: 1. be unique in name 2. NOT be in the trash => have an ownerDocument AND a parent (public
         * users are not allowed to see the __ShadowDocument__ ==> this check must either be made in a superuser-context OR the __ShadowDocument could be made public?)
         *
         * These nodes can be: 1. somewhere in the pages tree 2. in the shared components 3. both ==> causes a problem because we now have multiple nodes with the same
         * name (one shared component and multiple linking instances of that component)
         *
         * INFOS:
         *
         * - If a DOMNode has "syncedNodes" it MUST BE a shared component - If a DOMNodes "sharedComponent" is set it MUST BE AN INSTANCE of a shared component => Can
         * we safely ignore these? I THINK SO!
         */
        for (final DOMNode n : nodeList) {
            if (n.inTrash()) {
                continue;
            }
            // IGNORE everything that REFERENCES a shared component!
            if (n.getProperty(sharedCompKey) == null) {
                // the DOMNode is either a shared component OR a named node in the pages tree
                if (node == null) {
                    node = n;
                } else {
                    // TODO: Do we need to remove the nodes from the nodeList which can be ignored? (references to a shared component)
                    return "Ambiguous node name \"" + ((String) sources[0]) + "\" (nodes found: " + StringUtils.join(nodeList, ", ") + ")";
                }
            }
        }
        if (node != null) {
            if (sources.length == 3 && sources[1] instanceof Iterable && sources[2] instanceof String) {
                final Iterable<GraphObject> iterable = FunctionDataSource.map((Iterable) sources[1]);
                final String dataKey = (String) sources[2];
                innerCtx.setListSource(iterable);
                node.renderNodeList(securityContext, innerCtx, 0, dataKey);
            } else {
                node.render(innerCtx, 0);
            }
            if (innerCtx.appLibRendered()) {
                ((RenderContext) ctx).setAppLibRendered(true);
            }
        } else {
            final File file = app.nodeQuery(File.class).andName((String) sources[0]).getFirst();
            if (file != null) {
                final String name = file.getProperty(NodeInterface.name);
                final String contentType = file.getContentType();
                final String charset = StringUtils.substringAfterLast(contentType, "charset=");
                final String extension = StringUtils.substringAfterLast(name, ".");
                if (contentType == null || StringUtils.isBlank(extension)) {
                    logger.warn("No valid file type detected. Please make sure {} has a valid content type set or file extension. Parameters: {}", new Object[] { name, getParametersAsString(sources) });
                    return "No valid file type detected. Please make sure " + name + " has a valid content type set or file extension.";
                }
                if (contentType.startsWith("text/css")) {
                    return "<link href=\"" + file.getPath() + "\" rel=\"stylesheet\">";
                } else if (contentType.contains("/javascript")) {
                    return "<script src=\"" + file.getPath() + "\"></script>";
                } else if (contentType.startsWith("image/svg")) {
                    try (final InputStream is = file.getInputStream()) {
                        final byte[] buffer = new byte[file.getSize().intValue()];
                        IOUtils.read(is, buffer);
                        return StringUtils.toEncodedString(buffer, Charset.forName(charset));
                    } catch (IOException ex) {
                        logger.warn("Exception for parameters: {}", getParametersAsString(sources));
                        logger.error("", ex);
                    }
                    return "<img alt=\"" + name + "\" src=\"" + file.getPath() + "\">";
                } else if (contentType.startsWith("image/")) {
                    return "<img alt=\"" + name + "\" src=\"" + file.getPath() + "\">";
                } else {
                    logger.warn("Don't know how to render content type or extension of {}. Parameters: {}", new Object[] { name, getParametersAsString(sources) });
                    return "Don't know how to render content type or extension of  " + name + ".";
                }
            }
        }
        return StringUtils.join(innerCtx.getBuffer().getQueue(), "");
    } catch (final IllegalArgumentException e) {
        logParameterError(caller, sources, ctx.isJavaScriptContext());
        return usage(ctx.isJavaScriptContext());
    }
}
Also used : StructrApp(org.structr.core.app.StructrApp) App(org.structr.core.app.App) RenderContext(org.structr.web.common.RenderContext) InputStream(java.io.InputStream) IOException(java.io.IOException) GraphObject(org.structr.core.GraphObject) SecurityContext(org.structr.common.SecurityContext) GraphObject(org.structr.core.GraphObject) DOMNode(org.structr.web.entity.dom.DOMNode) File(org.structr.web.entity.File)

Example 94 with GraphObject

use of org.structr.core.GraphObject in project structr by structr.

the class DeserializationStrategy method setProperties.

protected void setProperties(final SecurityContext securityContext, final GraphObject obj, final PropertyMap properties) throws FrameworkException {
    // are we allowed to set properties on related nodes?
    final Boolean allowed = (Boolean) securityContext.getAttribute("setNestedProperties");
    if (allowed != null && allowed == true) {
        final PropertyMap mergedProperties = new PropertyMap();
        for (final Entry<PropertyKey, Object> entry : properties.entrySet()) {
            final PropertyKey key = entry.getKey();
            final Object newValue = entry.getValue();
            final Object oldValue = obj.getProperty(key);
            if (newValue != null && !newValue.equals(oldValue)) {
                mergedProperties.put(key, merge(oldValue, newValue));
            }
        }
        obj.setProperties(securityContext, mergedProperties);
    }
}
Also used : PropertyMap(org.structr.core.property.PropertyMap) GraphObject(org.structr.core.GraphObject) PropertyKey(org.structr.core.property.PropertyKey)

Example 95 with GraphObject

use of org.structr.core.GraphObject in project structr by structr.

the class IdDeserializationStrategy method deserialize.

@Override
public T deserialize(final SecurityContext securityContext, final Class<T> type, final S source, final Object context) throws FrameworkException {
    final App app = StructrApp.getInstance(securityContext);
    if (source != null) {
        if (source instanceof Map) {
            final Map<String, Object> properties = (Map<String, Object>) source;
            Class<T> actualType = type;
            if (actualType != null && actualType.isInterface()) {
                // (creation wouldn't work otherwise anyway)
                if (properties.containsKey(NodeInterface.type.jsonName())) {
                    final String typeFromInput = properties.get(NodeInterface.type.jsonName()).toString();
                    actualType = StructrApp.getConfiguration().getNodeEntityClass(typeFromInput);
                    // reset type on failed check
                    if (actualType == null) {
                        actualType = type;
                    }
                }
            }
            final PropertyMap convertedProperties = PropertyMap.inputTypeToJavaType(securityContext, actualType, properties);
            final Set<PropertyKey> allProperties = StructrApp.getConfiguration().getPropertySet(type, "all");
            final Map<String, Object> foreignProps = new HashMap<>();
            T relatedNode = null;
            // If property map contains the uuid, search only for uuid
            if (convertedProperties.containsKey(GraphObject.id)) {
                relatedNode = (T) app.getNodeById(convertedProperties.get(GraphObject.id));
                if (relatedNode != null) {
                    if (!SearchCommand.isTypeAssignableFromOtherType(type, relatedNode.getClass())) {
                        throw new FrameworkException(422, "Node type mismatch", new TypeToken(type.getSimpleName(), null, type.getSimpleName()));
                    }
                    for (final PropertyKey key : convertedProperties.keySet()) {
                        if (!key.isUnique() && !key.isCompound() && !isIdentifying(actualType, key) && !allProperties.contains(key)) {
                            // store "foreign" properties (those that are to be set on the newly created relationship
                            foreignProps.put(key.jsonName(), properties.get(key.jsonName()));
                        }
                    }
                    // node found, remove UUID
                    convertedProperties.remove(GraphObject.id);
                }
            } else {
                final PropertyMap uniqueKeyValues = new PropertyMap();
                for (final PropertyKey key : convertedProperties.keySet()) {
                    if (key.isUnique() || key.isCompound() || isIdentifying(actualType, key)) {
                        uniqueKeyValues.put(key, convertedProperties.get(key));
                    } else if (!allProperties.contains(key)) {
                        // store "foreign" properties (those that are to be set on the newly created relationship
                        foreignProps.put(key.jsonName(), properties.get(key.jsonName()));
                    }
                }
                // (this is quite similar to the Cypher MERGE command),
                if (!uniqueKeyValues.isEmpty()) {
                    final List<T> possibleResults = app.nodeQuery(type).and(uniqueKeyValues).getAsList();
                    final int num = possibleResults.size();
                    switch(num) {
                        case 0:
                            // not found => will be created
                            break;
                        case 1:
                            relatedNode = possibleResults.get(0);
                            break;
                        default:
                            // more than one => not unique??
                            throw new FrameworkException(422, concat("Unable to resolve related node of type ", type.getSimpleName(), ", ambiguous result: found ", num, " nodes for the given property set."));
                    }
                } else {
                // throw exception here?
                }
            }
            if (relatedNode == null) {
                // no related node found, should we create one?
                if (relationProperty != null) {
                    final Relation relation = relationProperty.getRelation();
                    if (relationProperty.doAutocreate()) {
                        return app.create(type, convertedProperties);
                    } else {
                        throw new FrameworkException(422, concat("Cannot create ", relation.getOtherType(type).getSimpleName(), ": no matching ", type.getSimpleName(), " found for the given property set ", convertedProperties, " and autoCreate has a value of ", relationProperty.getAutocreateFlagName()));
                    }
                }
                // FIXME: when can the relationProperty be null at all?
                throw new FrameworkException(500, concat("Unable to resolve related node of type ", type.getSimpleName(), ", no relation defined."));
            } else {
                // set properties on related node?
                if (!convertedProperties.isEmpty()) {
                    setProperties(securityContext, relatedNode, convertedProperties);
                }
                if (foreignProps.isEmpty()) {
                    return relatedNode;
                } else {
                    return (T) new EntityAndPropertiesContainer(relatedNode, foreignProps);
                }
            }
        } else if (type.isAssignableFrom(source.getClass())) {
            return (T) source;
        } else {
            // interpret source as a raw ID string and fetch entity
            final GraphObject obj = app.getNodeById(source.toString());
            if (obj != null && !type.isAssignableFrom(obj.getClass())) {
                throw new FrameworkException(422, "Node type mismatch", new TypeToken(obj.getClass().getSimpleName(), null, type.getSimpleName()));
            }
            return (T) obj;
        }
    }
    return null;
}
Also used : StructrApp(org.structr.core.app.StructrApp) App(org.structr.core.app.App) FrameworkException(org.structr.common.error.FrameworkException) HashMap(java.util.HashMap) GraphObject(org.structr.core.GraphObject) EntityAndPropertiesContainer(org.structr.common.EntityAndPropertiesContainer) Relation(org.structr.core.entity.Relation) PropertyMap(org.structr.core.property.PropertyMap) TypeToken(org.structr.common.error.TypeToken) GraphObject(org.structr.core.GraphObject) HashMap(java.util.HashMap) PropertyMap(org.structr.core.property.PropertyMap) Map(java.util.Map) PropertyKey(org.structr.core.property.PropertyKey)

Aggregations

GraphObject (org.structr.core.GraphObject)151 FrameworkException (org.structr.common.error.FrameworkException)58 PropertyKey (org.structr.core.property.PropertyKey)39 LinkedList (java.util.LinkedList)35 SecurityContext (org.structr.common.SecurityContext)25 App (org.structr.core.app.App)25 StructrApp (org.structr.core.app.StructrApp)24 Tx (org.structr.core.graph.Tx)23 List (java.util.List)22 PropertyConverter (org.structr.core.converter.PropertyConverter)22 AbstractNode (org.structr.core.entity.AbstractNode)18 GraphObjectMap (org.structr.core.GraphObjectMap)17 NodeInterface (org.structr.core.graph.NodeInterface)17 LinkedHashSet (java.util.LinkedHashSet)15 PropertyMap (org.structr.core.property.PropertyMap)13 Map (java.util.Map)12 RestMethodResult (org.structr.rest.RestMethodResult)11 ConfigurationProvider (org.structr.schema.ConfigurationProvider)10 Result (org.structr.core.Result)9 ArrayList (java.util.ArrayList)8