Java tutorial
/* * FSXMLRequestHandler.java * * Copyright (c) 2012 Noterik B.V. * * This file is part of smithers, related to the Noterik Springfield project. * * Smithers is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Smithers is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Smithers. If not, see <http://www.gnu.org/licenses/>. */ package com.noterik.bart.fs.fsxml; import java.io.IOException; import java.net.InetAddress; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.Node; import org.restlet.data.MediaType; import org.restlet.ext.xml.DomRepresentation; import org.restlet.representation.Representation; import org.restlet.representation.StringRepresentation; import com.noterik.bart.fs.GlobalConfig; import com.noterik.bart.fs.cache.CacheHandler; import com.noterik.bart.fs.dao.DAOException; import com.noterik.bart.fs.fscommand.dynamic.presentation.playout.cache; import com.noterik.bart.fs.id.IdHandler; import com.noterik.bart.fs.script.FSScript; import com.noterik.bart.fs.tools.FSXMLHelper; import com.noterik.bart.fs.tools.URIHelper; import com.noterik.bart.fs.triggering.TriggerSystemManager; import com.noterik.bart.fs.type.MimeType; import com.noterik.bart.fs.type.ReferUriType; import com.noterik.bart.fs.type.ResourceNodeType; import com.noterik.springfield.tools.XMLHelper; import com.noterik.springfield.tools.fs.FSXMLBuilder; import com.noterik.springfield.tools.fs.URIParser; import com.noterik.springfield.tools.net.Message; public class FSXMLRequestHandler { private static Logger logger = Logger.getLogger(FSXMLRequestHandler.class); private static FSXMLRequestHandler instance; private FSXMLHandler fsxmlHandler; private AttributeHandler attributeHandler; private static final String EXEC_PARAM = "exec"; public static String debuglevel = "off"; /** * Empty properties xml */ private static final String DEFAULT_PROPERTIES = "<fsxml><properties></properties></fsxml>"; /* dao instances */ private static FSXMLPropertiesDAO pdao; private static FSXMLChildDAO cdao; static { // TODO: move to global config // initialize cached properties dao FSXMLPropertiesDAO pdao_uncached = GlobalConfig.instance().getDAOFactory().getFSXMLPropertiesDAO(); //CacheHandler pcHandler = GlobalConfig.instance().getPropertyCacheHandler(); pdao = new CachingDecoratorPropertiesDAO(pdao_uncached, null); // initialize cached children dao FSXMLChildDAO cdao_uncached = GlobalConfig.instance().getDAOFactory().getFSXMLChildDAO(); //CacheHandler ccHandler = GlobalConfig.instance().getChildCacheHandler(); cdao = new CachingDecoratorChildDAO(cdao_uncached, null); } private FSXMLRequestHandler() { fsxmlHandler = new FSXMLHandler(); attributeHandler = new AttributeHandler(); } public static FSXMLRequestHandler instance() { if (instance == null) { instance = new FSXMLRequestHandler(); } return instance; } /* * THE FUNCTIONS BELOW ARE ALL CALLED INTERNALLY (MOSTLY FROM SCRIPTS) * THE FUNCTIONS BELOW ARE ALL CALLED INTERNALLY (MOSTLY FROM SCRIPTS) * THE FUNCTIONS BELOW ARE ALL CALLED INTERNALLY (MOSTLY FROM SCRIPTS) * THE FUNCTIONS BELOW ARE ALL CALLED INTERNALLY (MOSTLY FROM SCRIPTS) */ public Document getNodeProperties(String uri, boolean sendEvent) { long timer_start = new Date().getTime(); Document doc = fsxmlHandler.getNodeProperties(uri, sendEvent); long timer_end = new Date().getTime(); if (debuglevel.equals("high")) System.out.println("LOADTIME=" + (timer_end - timer_start) + " uri=" + uri); return doc; } public MimeType getMimeTypeOfResource(String uri) { return fsxmlHandler.getMimeTypeOfResource(uri); } public Document getNodeProperties(String uri, int depth, boolean sendEvent) { long timer_start = new Date().getTime(); Document doc = fsxmlHandler.getNodeProperties(uri, depth, sendEvent); long timer_end = new Date().getTime(); return doc; } public boolean saveFsXml(String uri, String xml, String method, boolean sendEvent) { boolean succes = false; try { succes = fsxmlHandler.saveFsXml(uri, xml, method, sendEvent); } catch (Exception e) { logger.error("", e); } return succes; } public boolean deleteNodeProperties(String uri, boolean sendEvent) { boolean success = false; try { fsxmlHandler.deleteAllPropertiesOfUriTop(uri, sendEvent); success = true; } catch (Exception e) { logger.error("", e); e.printStackTrace(); } return success; } public void updateProperty(String uri, String property, String value, String method, boolean sendEvent) { try { saveProperty(uri, value, method, property, sendEvent); } catch (Exception e) { logger.error("", e); } } public String getPropertyValue(String uri) { String value = fsxmlHandler.getPropertyValue(uri); return value; } public void deletePropertyValue(String uri, String property) { fsxmlHandler.deleteProperty(uri, property, true); } public Document getNodePropertiesByType(String uri) { Document doc = fsxmlHandler.getNodePropertiesByType(uri); return doc; } public Document getNodePropertiesByType(String uri, int depth, int start, int limit) { Document doc = fsxmlHandler.getNodePropertiesByType(uri, depth, start, limit); return doc; } public boolean hasProperties(String uri) { boolean hp = fsxmlHandler.hasProperties(uri); return hp; } public boolean hasChildren(String uri, String type) { boolean hc = fsxmlHandler.hasChildren(uri, type); return hc; } public void addUriToChildrenOfParentResource(String uri, String type) { try { fsxmlHandler.addUriToChildrenOfParentResource(uri, type); } catch (Exception e) { logger.error("", e); } } public boolean saveAttributes(String uri, String xml, String method) { boolean succes = false; try { succes = attributeHandler.saveAttributes(uri, xml, method); } catch (Exception e) { logger.error("", e); } return succes; } /** * Returns a list of resources that refer to the specified uri. * * @param uri * @return */ public List<String> getReferParents(String uri) { List<String> refPars = attributeHandler.getReferParents(uri); return refPars; } /** * Returns only the refer this node is referring to without getting it's content, otherwise return null */ public String getRefer(String uri) { // get properties FSXMLProperties pfsxml = fsxmlHandler.getProperties(uri); if (pfsxml.getReferUri() != null) { return pfsxml.getReferUri(); } return null; } /* * END END END END */ public Representation handleGET(String uri, String value, Map<String, String> GETParams) { // see if we need to execute a script //System.out.println("DO A GET"); if (GETParams != null && GETParams.containsKey(EXEC_PARAM)) { if (GETParams.get(EXEC_PARAM) != null && GETParams.get(EXEC_PARAM).equals("true")) { // check if this is actually a script FSScript fss = getScript(uri); String response = null; logger.debug("executing script"); if (fss != null) { response = fss.execute(); } else { response = FSXMLBuilder.getErrorMessage("500", "Could not find script", "The script you tried to access does not exist", "http://teamelements.noterik.com/team"); } return new StringRepresentation(response, MediaType.TEXT_XML); } } return handleGET(uri, value); } /** * Handles a GET request * * @param uri * resource uri * @param value * request body * @return */ public Representation handleGET(String uri, String value) { // get parameters from request body long timer_start = new Date().getTime(); //System.out.println("SMITERS GET="+uri+" "+value); Map<String, String> params = getParameters(value); //System.out.println("REQ="+uri+" P="+params.toString()+" V="+value); String curi = uri; if (params.size() > 0) { curi = uri + params.toString(); } // hack daniel. lets hook it into our temp cache Document doc = cache.get(curi); if (doc != null && curi.indexOf("properties") == -1 && curi.indexOf("/euscreen/") != -1) { DomRepresentation dr = null; try { dr = new DomRepresentation(MediaType.TEXT_XML); } catch (IOException e) { logger.error("", e); } dr.setDocument(XMLHelper.convert(doc)); long timer_end = new Date().getTime(); System.out.println("HIT LOADTIME_URL=" + (timer_end - timer_start) + " uri=" + curi + " CP=" + cache.getPerformance() + " CS=" + cache.getCacheSize()); return dr; } // end of cache check //Document doc = null; String cp = URIParser.getCurrentUriPart(uri); String pp = URIParser.getParentUriPart(uri); if (cp.equals(FSXMLHelper.XML_PROPERTIES)) { String correctedUri = URIParser.getPreviousUri(uri); doc = fsxmlHandler.getNodeProperties(correctedUri, 0); } else if (cp.equals(FSXMLHelper.XML_ATTRIBUTES)) { String attrs = attributeHandler.getAttributes(uri); if (attrs != null) { doc = XMLHelper.asDocument(attrs); } } else if (pp.equals(FSXMLHelper.XML_PROPERTIES)) { String property = fsxmlHandler.getPropertyValue(uri); if (property != null) { doc = XMLHelper.asDocument("<" + cp + ">" + property + "</" + cp + ">"); } } else if (pp.equals(FSXMLHelper.XML_ATTRIBUTES)) { String attr = attributeHandler.getAttributeValue(uri); if (attr != null) { doc = XMLHelper.asDocument("<" + cp + ">" + attr + "</" + cp + ">"); } } else if (URIParser.isResourceId(uri)) { // try cache (including depth) String depth = params.get("depth"); if (doc == null) { doc = fsxmlHandler.getNodeProperties(uri, params); } } else { // uri does not end with an id, so the request is for all children // of the given type String t = URIParser.getCurrentUriPart(uri); if (t.equals("domain")) { doc = fsxmlHandler.getAllDomains(); } else { doc = fsxmlHandler.getNodePropertiesByType(uri, params); } } if (doc != null) { DomRepresentation dr = null; try { dr = new DomRepresentation(MediaType.TEXT_XML); } catch (IOException e) { logger.error("", e); } dr.setDocument(XMLHelper.convert(doc)); // TODO jaap: after we decided on the way to go with the HEAD info, // probably uncomment this // dr.setSize(doc.asXML().length()); long timer_end = new Date().getTime(); if ((timer_end - timer_start) > 30 && curi.indexOf("properties") == -1 && curi.indexOf("/euscreen/") != -1) { if (params.size() == 0) { cache.put(curi, doc); } else { cache.putParams(uri, doc, params.toString()); } System.out.println("MIS LOADTIME_URL=" + (timer_end - timer_start) + " uri=" + curi + " CP=" + cache.getPerformance() + " CS=" + cache.getCacheSize()); } return dr; } else { String response = FSXMLBuilder.getErrorMessage("404", "No data available", "No properties were found for this resource", "http://teamelements.noterik.com/team"); return new StringRepresentation(response, MediaType.TEXT_XML); } } public Document handleDocGET(String uri, String value) { // get parameters from request body long timer_start = new Date().getTime(); Map<String, String> params = getParameters(value); //System.out.println("REQ="+uri+" P="+params.toString()); String curi = uri; if (params.size() > 0) { curi = uri + params.toString(); } Document doc = null; String cp = URIParser.getCurrentUriPart(uri); String pp = URIParser.getParentUriPart(uri); if (cp.equals(FSXMLHelper.XML_PROPERTIES)) { String correctedUri = URIParser.getPreviousUri(uri); doc = fsxmlHandler.getNodeProperties(correctedUri, 0); } else if (cp.equals(FSXMLHelper.XML_ATTRIBUTES)) { String attrs = attributeHandler.getAttributes(uri); if (attrs != null) { doc = XMLHelper.asDocument(attrs); } } else if (pp.equals(FSXMLHelper.XML_PROPERTIES)) { String property = fsxmlHandler.getPropertyValue(uri); if (property != null) { doc = XMLHelper.asDocument("<" + cp + ">" + property + "</" + cp + ">"); } } else if (pp.equals(FSXMLHelper.XML_ATTRIBUTES)) { String attr = attributeHandler.getAttributeValue(uri); if (attr != null) { doc = XMLHelper.asDocument("<" + cp + ">" + attr + "</" + cp + ">"); } } else if (URIParser.isResourceId(uri)) { // try cache (including depth) String depth = params.get("depth"); if (doc == null) { doc = fsxmlHandler.getNodeProperties(uri, params); } } else { // uri does not end with an id, so the request is for all children // of the given type String t = URIParser.getCurrentUriPart(uri); if (t.equals("domain")) { doc = fsxmlHandler.getAllDomains(); } else { doc = fsxmlHandler.getNodePropertiesByType(uri, params); } } if (doc != null) { // TODO jaap: after we decided on the way to go with the HEAD info, // probably uncomment this // dr.setSize(doc.asXML().length()); long timer_end = new Date().getTime(); if ((timer_end - timer_start) > 30 && curi.indexOf("properties") == -1 && curi.indexOf("/euscreen/") != -1) { if (params.size() == 0) { cache.put(curi, doc); } else { cache.putParams(uri, doc, params.toString()); } System.out.println("MIS LOADTIME_URL=" + (timer_end - timer_start) + " uri=" + curi); } return doc; } else { return null; } } private FSScript getScript(String uri) { MimeType mt = fsxmlHandler.getMimeTypeOfResource(uri); logger.debug("FOUND MIME TYPE: " + mt.getName() + "(" + uri + ")"); if (mt == MimeType.MIMETYPE_FS_SCRIPT) { FSScript fss = TriggerSystemManager.getInstance().getScriptOfUri(uri); return fss; } else { return null; } } /** * Handle a PUT request. * * @param uri * resource uri * @param value * request body * @return */ public String handlePUT(String uri, String value) { value = value.replaceAll("\n", ""); logger.debug("xml in PUT: " + value); String cp = URIParser.getCurrentUriPart(uri); String pp = URIParser.getParentUriPart(uri); if (cp.equals(FSXMLHelper.XML_ATTRIBUTES)) { // this means it is possible to post/put attributes to the selected // resource return saveAttributesAndGetHttpResponse(URIParser.getPreviousUri(uri), value, "PUT"); } else if (cp.equals(FSXMLHelper.XML_PROPERTIES)) { // the current uri points to the properties of a resource // PropertyHandler.instance().saveFsXml(uri, value, "PUT"); return savePropertiesAndGetHttpResponse(URIParser.getPreviousUri(uri), value, "PUT"); } else if (pp.equals(FSXMLHelper.XML_PROPERTIES)) { // the current uri points to a single property return saveProperty(uri, value, "PUT", cp); } else { return FSXMLBuilder.getErrorMessage("403", "You are not allowed to send a PUT request to this resource", "Please resend to either a properties uri or a single property uri", "http://teamelements.noterik.com/team"); } } /** * Handle a POST request * * @param uri * resource uri * @param value * request body * @return */ public String handlePOST(String uri, String value) { value = value.replaceAll("\n", ""); if (URIParser.getCurrentUriPart(uri).equals(ResourceNodeType.PROPERTIES.getName())) { // current node is a properties node return FSXMLBuilder.getErrorMessage("400", "You cannot POST to a properties node", "In order to update properties, send a PUT to the correct properties node", "http://teamelements.noterik.com/team"); } else if (!URIParser.isResourceId(uri)) { // current node is the conceptual node if (!URIParser.getCurrentUriPart(uri).equals(FSXMLHelper.XML_ATTRIBUTES)) { // when pointing to a concept node, auto create an id logger.debug("Creating new id for: " + uri); int id = IdHandler.instance().insert(uri); logger.debug("Newly created id is: " + id); // add the id to the uri, so the properties can be properly // saved uri += "/" + id; if (FSXMLHelper.getTypeOfXmlContent(value).equals(FSXMLHelper.XML_PROPERTIES)) { return savePropertiesAndGetHttpResponse(uri, value, "POST"); } else { return saveAttributesAndGetHttpResponse(uri, value, "POST"); } } else { return FSXMLBuilder.getErrorMessage("403", "You are not allowed to POST to an attributes node", "In order to POST new attributes, please resend data to an id node", "http://teamelements.noterik.com/team"); } } else { if (URIParser.getParentUriPart(uri).equals(FSXMLHelper.XML_PROPERTIES)) { // when pointing to a single property node, try to add it return saveProperty(uri, value, "POST", URIParser.getCurrentUriPart(uri)); } // current node is the id node return FSXMLBuilder.getErrorMessage("403", "You are not allowed to POST to an id node", "In order to update properties, send a PUT to the correct properties node", "http://teamelements.noterik.com/team"); } } /** * Handle a DELETE call * * @param uri * resource uri * @param value * request body * @return */ public String handleDELETE(String uri, String value) { String cp = URIParser.getCurrentUriPart(uri); String pp = URIParser.getParentUriPart(uri); if (pp.equals(FSXMLHelper.XML_PROPERTIES)) { // delete single property fsxmlHandler.deleteProperty(uri, cp, true); return FSXMLBuilder.getStatusMessage("The resource property has been successfully deleted", "", uri); } if (fsxmlHandler.isAuthorized(uri)) { if (URIParser.isResourceId(uri)) { if (fsxmlHandler.hasProperties(uri)) { fsxmlHandler.deleteAllPropertiesOfUriTop(uri); return FSXMLBuilder.getStatusMessage("The resource has been successfully deleted", "", uri); } else { return FSXMLBuilder.getErrorMessage("403", "The requested resource does not exist " + "or has no properties ", "Review your uri.", "http://teamelements.noterik.com/team"); } } else { Map<String, String> childs = fsxmlHandler.getChildrenOfUri(URIParser.getPreviousUri(uri)); String type = URIParser.getCurrentUriPart(uri); logger.debug("type to remove is: " + type); Boolean success = true; String current = ""; String currentType = ""; for (Iterator<String> i = childs.keySet().iterator(); i.hasNext();) { current = i.next(); currentType = URIParser.getParentUriPart(current); logger.debug("currentType: " + currentType); System.out.println("Current = " + current + " CT=" + currentType + " T=" + type); // only remove nodes of certain type if (type.equals(currentType)) { System.out.println("HASPROP=" + fsxmlHandler.hasProperties(current)); if (fsxmlHandler.hasProperties(current)) { fsxmlHandler.deleteAllPropertiesOfUriTop(current); } else { success = true; } } } if (success) { return FSXMLBuilder.getStatusMessage("The resource has been successfully deleted", "", uri); } else { return FSXMLBuilder.getStatusMessage("Some/all of the uri's childs could not be removed", "", uri); } } } else { return FSXMLBuilder.getErrorMessage("403", "For security reasons you are not " + "allowed to do a DELETE on such a high level uri.", "Try a uri with 5 " + "or more slashes.", "http://teamelements.noterik.com/team"); } } private String saveAttributesAndGetHttpResponse(String uri, String value, String method) { if (XMLHelper.isXml(value)) { if (attributeHandler.hasReferId(uri) && method.equals("POST")) { return FSXMLBuilder.getErrorMessage("403", "This resource already exists", "If you want to update the attributes, please use a PUT request", "http://teamelements.noterik.com/team"); } if (FSXMLHelper.getTypeOfXmlContent(value).equals(FSXMLHelper.XML_ATTRIBUTES)) { if (fsxmlHandler.hasProperties(URIParser.getParentUri(uri))) { if (attributeHandler.saveAttributes(uri, value, method)) { return FSXMLBuilder.getStatusMessage("The attributes were successfully saved", "", uri); } else { return FSXMLBuilder.getErrorMessage("500", "Error during the saving of attributes", "An error occurred while saving the attributes", "http://teamelements.noterik.com/team"); } } else { return FSXMLBuilder.getErrorMessage("403", "The parent of the resource you try to access does not exist", "First make sure the parent resources exist before sending requests to this one", "http://teamelements.noterik.com/team"); } } else { return FSXMLBuilder.getErrorMessage("400", "The XML you sent is invalid", "Please send a valid attribute fsxml", "http://teamelements.noterik.com/team"); } } else { return FSXMLBuilder.getErrorMessage("400", "You are not allowed to send non-fsxml data to this resource", "This resource reflects the attributes of a node, please resend with fsxml attribute data", "http://teamelements.noterik.com/team"); } } private String savePropertiesAndGetHttpResponse(String uri, String value, String method) { if (!XMLHelper.isXml(value)) { return FSXMLBuilder.getErrorMessage("400", "You are not allowed to send non-fsxml data to this resource", "This resource reflects all properties of a node, please resend with fsxml data", "http://teamelements.noterik.com/team"); } else { String parUri = URIParser.getParentUri(uri); logger.debug("parent URI: " + parUri + "(" + URIParser.getParentUriPart(uri) + ")"); if (fsxmlHandler.hasProperties(parUri) || URIParser.getParentUriPart(uri).equals("domain")) { boolean isOk = fsxmlHandler.saveFsXml(uri, value, method); if (isOk) { if (method.equals("POST")) { return FSXMLBuilder.getStatusMessage("The properties were successfully added", "", uri); } else { return FSXMLBuilder.getStatusMessage("The properties were successfully updated", "", uri); } } else { return FSXMLBuilder.getErrorMessage("500", "Error during the saving of properties", "An error occurred while saving the properties", "http://teamelements.noterik.com/team"); } } else { return FSXMLBuilder.getErrorMessage("403", "The parent of the resource you try to access does not exist", "First make sure the parent resources exist before sending requests to this one", "http://teamelements.noterik.com/team"); } } } protected String saveProperty(String uri, String value, String method, String property) { return saveProperty(uri, value, method, property, true); } protected String saveProperty(String uri, String value, String method, String property, boolean sendEvent) { if (XMLHelper.isXml(value)) { return FSXMLBuilder.getErrorMessage("400", "You are not allowed to send fsxml data to this resource", "This is a single property resource, please just send a single value", "http://teamelements.noterik.com/team"); } else { if (method.equals("POST")) { if (fsxmlHandler.hasProperty(uri)) { return FSXMLBuilder.getErrorMessage("403", "The property you tried to add already exists", "If you want to change the property use a PUT request", "http://teamelements.noterik.com/team"); } else { fsxmlHandler.addProperty(uri, property, value, method, sendEvent); return FSXMLBuilder.getStatusMessage("The property was added successfully", "Added property: " + value + " (" + property + ")", uri); } } else { fsxmlHandler.updateProperty(uri, property, value, method, sendEvent); return FSXMLBuilder.getStatusMessage("The property was successfully updated", "Updated property: " + value + " (" + property + ")", uri); } } } /** * Get pruning parameters from request body * * @param value * @return */ private Map<String, String> getParameters(String value) { Map<String, String> params = new HashMap<String, String>(); // parse request body Node start = null, limit = null, depth = null; try { Document doc = DocumentHelper.parseText(value); start = doc.selectSingleNode("//properties/start"); limit = doc.selectSingleNode("//properties/limit"); depth = doc.selectSingleNode("//properties/depth"); } catch (Exception e) { /* * request body empty or request body could not * be parsed */ } // add to params if (start != null) { params.put("start", start.getText()); } if (limit != null) { params.put("limit", limit.getText()); } if (depth != null) { params.put("depth", depth.getText()); } return params; } /* * **************************************** THE FSXML HANDLER CLASS * **************************************** * **************************************** THE FSXML HANDLER CLASS * **************************************** * **************************************** THE FSXML HANDLER CLASS * **************************************** * **************************************** THE FSXML HANDLER CLASS * **************************************** */ private class FSXMLHandler { /** * logger */ private Logger logger = Logger.getLogger(FSXMLHandler.class); /** * Default depth used for tree pruning */ private static final int DEFAULT_DEPTH = 10; /** * Limit value when all childs should be displayed */ private static final int LIMIT_ALL = -1; /** * Default limit for tree pruning */ private static final int DEFAULT_LIMIT = LIMIT_ALL; /** * Default start for tree pruning */ private static final int DEFAULT_START = 0; /** * Default constructor */ private FSXMLHandler() { } /** * Function that removes the outer fsxml tags from a document * * @param xml * @return */ private String unwrapXml(String xml) { StringBuffer xmlB = new StringBuffer(); try { // parse xml Document doc = DocumentHelper.parseText(xml); Element root = doc.getRootElement(); Element elem; for (Iterator<Element> iter = root.elementIterator(); iter.hasNext();) { elem = iter.next(); xmlB.append(elem.asXML()); } } catch (Exception e) { logger.error("Could not unwrap xml: " + xml, e); } return xmlB.toString(); } /** * Function that puts fsxml tags around an xml document * * @param xml * @return */ private String wrapXml(String xml) { if (xml.indexOf("<fsxml>") == -1) { return "<fsxml>" + xml + "</fsxml>"; } return xml; } /** * Get the properties of this uri and send a trigger Only uris which end * with an id are allowed * * @param uri * @return */ private Document getNodeProperties(String uri) { return getNodeProperties(uri, true); } /** * * @param uri * @param params * @return */ public Document getNodeProperties(String uri, Map<String, String> params) { int depth = DEFAULT_DEPTH, start = DEFAULT_START, limit = DEFAULT_LIMIT; // convert params try { depth = Integer.parseInt(params.get("depth")); } catch (Exception e) { /* no problem, will revert to default */ } try { start = Integer.parseInt(params.get("start")); } catch (Exception e) { /* no problem, will revert to default */ } try { limit = Integer.parseInt(params.get("limit")); } catch (Exception e) { /* no problem, will revert to default */ } logger.debug("start: " + start + ", limit: " + limit + ", depth: " + depth); // only depth for now return getNodeProperties(uri, depth); } /** * Get the properties of this uri and specify if a trigger should be * send * * @param uri * @param sendEvent * trigger an event * @return */ private Document getNodeProperties(String uri, boolean sendEvent) { return getNodeProperties(uri, DEFAULT_DEPTH, sendEvent); } /** * Get the properties of this uri, send a trigger and get the children * to a specified depth. * * @param uri * @param depth * the depth to which the ancestors are shown * @return */ private Document getNodeProperties(String uri, int depth) { return getNodeProperties(uri, depth, true); } /** * Get the properties of this uri, specify if a trigger should be send, * and get the children to a specified depth. * * @param uri * @param depth * the depth to which the ancestors are shown * @param sendEvent * trigger an event * @return */ private Document getNodeProperties(String uri, int depth, boolean sendEvent) { String id = uri.substring(uri.lastIndexOf("/") + 1); Document doc = DocumentHelper.createDocument(); Element root = doc.addElement("fsxml"); Element current = root.addElement(URIParser.getResourceTypeFromUri(uri)).addAttribute("id", id); // call by reference !!! if (fsxmlHandler.getNodeProperties(uri, current, depth, 0, sendEvent) != null) { } else { doc = null; } return doc; } /** * This function returns the properties of a uri. The depth parameter * indicates how many levels of the node's childrens' properties have to * be retrieved. * * @param uri * @param current * @param depth * @param currentDepth * @return */ private Element getNodeProperties(String uri, Element current, int depth, int currentDepth, boolean sendEvent) { // trigger event if (sendEvent) { TriggerSystemManager.getInstance().getDomainTS(URIParser.getDomainFromUri(uri)).eventHappened(uri, "GET", "", ""); // send message try { cache.signal(InetAddress.getLocalHost().toString(), "GET", uri); // 27apr GlobalConfig.instance().getDispatcher().send(new Message(InetAddress.getLocalHost(),"GET",uri)); } catch (Exception e) { logger.error("Could not send message", e); } } logger.debug("Get node properties"); // stop condition if (currentDepth <= depth) { boolean hasOwnProperties = false; // get properties FSXMLProperties pfsxml = getProperties(uri); if (pfsxml != null) { // build document String xml = pfsxml.getXml(); if (xml != null && !xml.equals("")) { Element elem = null; xml = unwrapXml(xml); try { elem = (Element) DocumentHelper.parseText(xml).getRootElement().clone(); } catch (DocumentException e) { logger.error("Could not clone xml element.", e); } hasOwnProperties = true; // check if there is also a referid if (pfsxml.getReferUri() != null) { addReferProperties(elem, pfsxml.getReferUri()); current.addAttribute("referid", pfsxml.getReferUri()); } current.add(elem); // add the child elements to the current element (will // recurse) String childUri = null; String childId = null; String childType = null; Map<String, String> childs = getChildrenOfUri(uri); Iterator<String> it = childs.keySet().iterator(); while (it.hasNext()) { childUri = it.next(); childId = childUri.substring(childUri.lastIndexOf('/') + 1, childUri.length()); childType = childs.get(childUri); Element newElem = current.addElement(childType).addAttribute("id", childId); getNodeProperties(childUri, newElem, depth, currentDepth + 1, sendEvent); } } // if it does not have its own properties see if it has a refer // id if (pfsxml.getReferUri() != null && !hasOwnProperties) { current.addAttribute("referid", pfsxml.getReferUri()); ReferUriType rut = URIHelper.getReferUriType(pfsxml.getReferUri()); if (rut.equals(ReferUriType.FS_URI)) { String referXml = getReferredProperties(pfsxml.getReferUri()); logger.debug("refer xml is " + referXml); if (referXml != null) { referXml = unwrapXml(referXml); } else { referXml = "<properties><error>Dead link!</error><referid>" + pfsxml.getReferUri() + "</referid></properties>"; } Document refDoc = XMLHelper.asDocument(referXml); if (refDoc != null) { current.add(refDoc.getRootElement()); } } } if (currentDepth == 0 && !hasOwnProperties && pfsxml.getReferUri() == null) { return null; } } else { return null; } } logger.debug("got node properties"); return current; } private void addReferProperties(Element elem, String referUri) { logger.debug("NAME OF THE ELEMENT: " + elem.getName()); ReferUriType rut = URIHelper.getReferUriType(referUri); if (rut.equals(ReferUriType.FS_URI)) { String referXml = getReferredProperties(referUri); logger.debug("refer xml is " + referXml); if (referXml != null && !referXml.equals("")) { //System.out.println("REF="+referXml); referXml = unwrapXml(referXml); } else { referXml = "<properties><error>Dead link!</error><referid>" + referUri + "</referid></properties>"; } Document refDoc = XMLHelper.asDocument(referXml); if (refDoc != null) { List<Node> nodes = refDoc.selectNodes("properties/*"); // Element propertiesNode = // (Element)elem.selectSingleNode("properties"); for (Node n : nodes) { logger.debug("NAME OF THE NODE: " + n.getName()); n.detach(); elem.add(n); } } } } /** * Basic function that gets the properties of a single URI from the * database, or cache. * * @param uri * @return */ private FSXMLProperties getProperties(String uri) { // check uri if (uri.endsWith("/")) { uri = uri.substring(0, uri.length() - 1); } FSXMLProperties pfsxml = null; try { pfsxml = pdao.read(uri); } catch (DAOException e) { logger.error("", e); } return pfsxml; } /** * Get a single property value * * @param uri * @return */ private String getPropertyValue(String uri) { logger.debug("getPropertyValue: " + uri); String propXml = null; String parentUri = URIParser.getParentUri(uri); FSXMLProperties pfsxml = getProperties(parentUri); if (pfsxml == null) { return null; } if (pfsxml.getXml() != null) { propXml = pfsxml.getXml(); } else { return null; } Document propdoc = null; try { propdoc = DocumentHelper.parseText(propXml); } catch (DocumentException e) { logger.error("", e); return null; } Element elem = (Element) propdoc.selectSingleNode("//" + URIParser.getCurrentUriPart(uri)); if (elem != null) { return elem.getText(); } return null; } /** * This function gets properties referred to by a refer id. * * @param uri * @return */ private String getReferredProperties(String uri) { FSXMLProperties pfsxml = getProperties(uri); if (pfsxml != null) { if (pfsxml.getXml() != null) { return pfsxml.getXml(); } else if (pfsxml.getReferUri() != null) { return getProperties(pfsxml.getReferUri()).getXml(); } } return null; } /** * Basic function that gets the URI's of the children of the specified * URI/node * * @param uri * @deprecated use FSXMLChildDAO in stead * @return */ private Map<String, String> getChildrenOfUri(String uri) { // map to return Map<String, String> childrenMap = new LinkedHashMap<String, String>(); List<FSXMLChild> children = cdao.getChildren(uri); for (FSXMLChild child : children) { childrenMap.put(child.getReferUri(), child.getType()); } return childrenMap; } /** * Update a single property * * @param uri * @param property * @param value * @param method * @param sendEvent */ private synchronized void updateProperty(String uri, String property, String value, String method, boolean sendEvent) { String newXml = "", oldXml = "", referid; String parentUri = uri.substring(0, uri.lastIndexOf("/properties")); //System.out.println("UPDATE URL="+uri); // retry concurrency updates. if numRetries == -1, retries will be // indefinitely (-1 gives database errors) int numRetries = 10; boolean updated = false; int tries = 0; while (tries != numRetries) { //System.out.println("TRY "+tries+" URL="+uri); // delay try { Thread.sleep(10 * tries); } catch (InterruptedException e) { /* do nothing */ } FSXMLProperties properties = getProperties(parentUri); oldXml = null; referid = null; if (properties != null) { oldXml = properties.getXml(); referid = properties.getReferUri(); } if (oldXml == null) { oldXml = DEFAULT_PROPERTIES; newXml = addPropertyValue(oldXml, property, value); // try insert updated = insertConcurrentProperties(parentUri, newXml); } else { if (hasProperty(uri)) { newXml = setPropertyValue(oldXml, property, value); } else { // not sure why this can happen. probably when a video is created using only a referid String tmpXml = oldXml; if (tmpXml.equals("")) { tmpXml = DEFAULT_PROPERTIES; } newXml = addPropertyValue(tmpXml, property, value); } // try update updated = updateConcurrentProperties(parentUri, referid, newXml, oldXml); } // check if update was a succes. if so, break for loop. if (updated) { logger.debug("Updating single property successful for " + parentUri); break; } else { logger.debug( "Updating single property failed for " + parentUri + ", retrying (" + tries + ") ... "); } // update number of tries tries++; } // send event to triggersystem if (sendEvent && updated) { MimeType mt = FSXMLHelper.getMimeTypeFromXml(newXml); TriggerSystemManager.getInstance().getDomainTS(URIParser.getDomainFromUri(uri)) .eventHappened(parentUri, method, mt.getName(), newXml); // send message try { // daniel 27apr2014 cache.signal(InetAddress.getLocalHost().toString(), method, parentUri); } catch (Exception e) { logger.error("Could not send message", e); } } // catch updates that didn't succeed. if (!updated) { logger.error("Updating single property failed for " + parentUri); } } /** * Inserting properties. Could go wrong if another process or thread * already inserted properties at the same time. * * @param uri * resource uri * @param xml * properties xml * @return success insert successful or not */ private synchronized boolean insertConcurrentProperties(String uri, String xml) { // create properties String type = URIParser.getResourceTypeFromUri(uri); MimeType mt = FSXMLHelper.getMimeTypeFromXml(xml); FSXMLProperties properties = new FSXMLProperties(uri, null, type, mt.getName(), xml); // save boolean success = false; try { success = pdao.create(properties); } catch (DAOException e) { logger.error("", e); } return success; } /** * Updating properties. Could go wrong if another process or thread * already updated existing properties at the same time. * * @param uri * resource uri * @param newXml * new properties xml * @param oldXml * old properties xml * @return success update successful or not */ private synchronized boolean updateConcurrentProperties(String uri, String referid, String newXml, String oldXml) { // create properties String type = URIParser.getResourceTypeFromUri(uri); MimeType mt = FSXMLHelper.getMimeTypeFromXml(newXml); FSXMLProperties properties = new FSXMLProperties(uri, referid, type, mt.getName(), newXml); properties.setOldXml(oldXml); // save boolean success = false; try { success = pdao.update(properties); } catch (DAOException e) { logger.error("", e); } return success; } /** * Adds a single property * * @param uri * @param property * @param value * @param method * @param sendEvent */ private synchronized void addProperty(String uri, String property, String value, String method, boolean sendEvent) { String newXml = ""; String parentUri = uri.substring(0, uri.lastIndexOf("/properties")); FSXMLProperties properties = getProperties(parentUri); String xml = properties.getXml(); if (xml == null) { xml = DEFAULT_PROPERTIES; } newXml = addPropertyValue(xml, property, value); newXml = newXml.replace("\n", ""); saveProperties(parentUri, properties.getReferUri(), newXml, method, sendEvent); } /** * Deletes a single property * * @param uri * @param property * @param sendEvent */ private synchronized void deleteProperty(String uri, String property, boolean sendEvent) { String newXml = "", oldXml = "", referid; String parentUri = uri.substring(0, uri.lastIndexOf("/properties")); // retry concurrency updates. if numRetries == -1, retries will be // indefinitely int numRetries = 10; boolean updated = false; int tries = 0; while (tries != numRetries) { FSXMLProperties properties = getProperties(parentUri); oldXml = null; referid = null; if (properties != null) { oldXml = properties.getXml(); referid = properties.getReferUri(); } if (oldXml == null) { return; } else { // remove property from xml newXml = removePropertyValue(oldXml, property); // try update updated = updateConcurrentProperties(parentUri, referid, newXml, oldXml); } // check if update was a succes. if so, break for loop. if (updated) { logger.debug("Updating single property successful for " + parentUri); break; } else { logger.error( "Updating single property failed for " + parentUri + ", retrying (" + tries + ") ... "); } // update number of tries tries++; } // send event to triggersystem if (sendEvent && updated) { MimeType mt = FSXMLHelper.getMimeTypeFromXml(newXml); TriggerSystemManager.getInstance().getDomainTS(URIParser.getDomainFromUri(uri)) .eventHappened(parentUri, "DELETE", mt.getName(), newXml); // send message try { cache.signal(InetAddress.getLocalHost().toString(), "DELETE", parentUri); // 27apr GlobalConfig.instance().getDispatcher().send(new Message(InetAddress.getLocalHost(),"DELETE",parentUri)); } catch (Exception e) { logger.error("Could not send message", e); } } } /** * Update single property value in a xml file * * @param xml * @param property * @param value * @return */ private String setPropertyValue(String xml, String property, String value) { Document doc = null; try { doc = DocumentHelper.parseText(xml); Element elem = (Element) doc.selectSingleNode("/fsxml/properties/" + property); if (elem != null) { // set property value elem.setText(value); } // create new xml Element fsxml = (Element) doc.selectSingleNode("/fsxml"); xml = fsxml.asXML(); } catch (DocumentException e) { logger.error("Could not parse xml", e); } return xml; } /** * Add a single property value to an xml file * * @param xml * @param property * @param value * @return */ private String addPropertyValue(String xml, String property, String value) { Document doc = null; try { doc = DocumentHelper.parseText(xml); } catch (DocumentException e) { logger.error("", e); } Element elem = (Element) doc.selectSingleNode("/fsxml/properties"); elem.addElement(property).addText(value); Element fsxml = (Element) doc.selectSingleNode("/fsxml"); xml = fsxml.asXML(); return xml; } /** * Remove a single property value to an xml file * * @param xml * @param property * @return */ private String removePropertyValue(String xml, String property) { Document doc = null; try { doc = DocumentHelper.parseText(xml); Element elem = (Element) doc.selectSingleNode("/fsxml/properties/" + property); if (elem != null) { // remove node elem.detach(); } // create new xml Element fsxml = (Element) doc.selectSingleNode("/fsxml"); xml = fsxml.asXML(); } catch (DocumentException e) { logger.error("Could not parse xml", e); } return xml; } /** * Save fsxml on a specified uri, and sends an event * * @param uri * @param xml * @param method * @return */ private boolean saveFsXml(String uri, String xml, String method) { return saveFsXml(uri, xml, method, true); } /** * Save fsxml on a specified uri and * * @param uri * @param xml * @param method * @param sendEvent * @return */ private boolean saveFsXml(String uri, String xml, String method, boolean sendEvent) { logger.debug("**************************** Saving fsxml ( " + uri + ") **************"); boolean isOk = false; Document doc = XMLHelper.asDocument(xml); if (doc != null) { // TODO get properties string from a central variable Node node = doc.selectSingleNode("//fsxml"); if (node != null) { Element curElm = (Element) node; isOk = saveFsXmlNodes(curElm, uri, method, sendEvent); } } return isOk; } /** * Save fsxml nodes and specify if a trigger should be send * * @param curElm * @param curUri * @param method * @param sendEvent * @return */ private boolean saveFsXmlNodes(Element curElm, String curUri, String method, boolean sendEvent) { logger.debug("CURRENT URI: " + curUri + " (" + curElm.getName() + ")"); if (URIParser.getCurrentUriPart(curUri).equals("properties")) { logger.debug("Saving properties..."); logger.debug(curElm.asXML()); // TODO: copy attributes from parent (nicely) if (curElm.getParent() != null && curElm.getParent().getName().equals("fsxml") && curElm.getParent().attributeValue("mimetype") != null && !curElm.getParent().attributeValue("mimetype").equals("")) { saveProperties(URIParser.getPreviousUri(curUri), null, "<fsxml mimetype='" + curElm.getParent().attributeValue("mimetype") + "'>" + curElm.asXML() + "</fsxml>", method, sendEvent); } else { saveProperties(URIParser.getPreviousUri(curUri), null, wrapXml(curElm.asXML()), method, sendEvent); } } else { Node n = null; Element e = null; String childUri = null, childTypeUri = null; for (Iterator i = curElm.nodeIterator(); i.hasNext();) { n = (Node) i.next(); if (n instanceof Element) { e = (Element) n; if (!e.getName().equals("properties")) { String id = e.attributeValue("id"); String referId = e.attributeValue("referid"); if (id == null) { childTypeUri = curUri + "/" + e.getName(); logger.debug("Creating new id for: " + childTypeUri); // TODO: // error // when // putting // on // /asset/id/properties // (WRONG // URI) id = IdHandler.instance().insert(childTypeUri) + ""; } else { logger.debug("Id supplied for: " + curUri); } childUri = curUri + "/" + e.getName() + "/" + id; if (referId != null) { logger.debug("Saving referid (" + referId + ") for: " + childUri); attributeHandler.saveReferId(childUri, referId, method); } } else { childUri = curUri + "/" + e.getName(); } saveFsXmlNodes(e, childUri, method, sendEvent); } } } return true; } /** * Save properties * * @param uri * resource uri * @param xml * properties xml * @param method * request method * @param sendEvent * send a trigger event * @return */ private synchronized boolean saveProperties(String uri, String referid, String xml, String method, boolean sendEvent) { // TODO: authorization String type = URIParser.getResourceTypeFromUri(uri); MimeType mt = FSXMLHelper.getMimeTypeFromXml(xml); //System.out.println("MIME1="+mt.getName()); FSXMLProperties properties = null; try { properties = pdao.read(uri); } catch (DAOException e) { logger.error("", e); } boolean success = false; if (properties == null) { // create properties = new FSXMLProperties(uri, referid, type, mt.getName(), xml); try { success = pdao.create(properties); } catch (DAOException e) { logger.error("", e); } } else { // update properties.setType(type); //System.out.println("MIME2="+mt.getName()); properties.setMimetype(mt.getName()); properties.setXml(xml); try { success = pdao.update(properties); } catch (DAOException e) { logger.error("", e); } } // save children if (success) { // make sure the ids are set correctly IdHandler.instance().checkUriId(uri); // make sure the URI is linked to its parent addUriToChildrenOfParentResource(uri, type); } else { logger.error("Not adding children to parent resource for " + uri + " " + type); } // send event to triggersystem if (sendEvent) { TriggerSystemManager.getInstance().getDomainTS(URIParser.getDomainFromUri(uri)).eventHappened(uri, method, mt.getName(), xml); // send message try { cache.signal(InetAddress.getLocalHost().toString(), method, uri); // 27apr GlobalConfig.instance().getDispatcher().send(new Message(InetAddress.getLocalHost(),method,uri)); } catch (Exception e) { logger.error("Could not send message", e); } } return success; } /** * this function inserts a relation parent/child in the children table * of the data base * * @param uri * @param type */ private synchronized void addUriToChildrenOfParentResource(String uri, String type) { String id = URIParser.getCurrentUriPart(uri); String pUri = URIParser.getParentUri(uri); // remove from database if (!pUri.equals("") && !pUri.equals("/")) { FSXMLChild child = new FSXMLChild(id, pUri, uri, type); boolean success = false; try { success = cdao.create(child); } catch (DAOException e) { logger.error("", e); } if (!success) { try { success = cdao.update(child); } catch (DAOException e) { logger.error("", e); } } logger.debug("addUriToChildrenOfParentResource success: " + success); } } private boolean hasProperties(String uri) { boolean has = false; FSXMLProperties properties = null; try { properties = pdao.read(uri); } catch (DAOException e) { logger.error("", e); } has = properties != null; return has; } private boolean hasProperty(String uri) { if (!hasProperties(URIParser.getParentUri(uri))) { return false; } String xml = getProperties(URIParser.getParentUri(uri)).getXml(); String property = uri.substring(uri.lastIndexOf("/") + 1); Document doc = null; try { doc = DocumentHelper.parseText(xml); } catch (DocumentException e) { logger.error("", e); return false; } String xpath = "/fsxml/properties/" + property; Element elem = (Element) doc.selectSingleNode(xpath); if (elem != null) { return true; } return false; } /** * Delete call to top node (caching). * * @param uri */ private void deleteAllPropertiesOfUriTop(String uri) { deleteAllPropertiesOfUriTop(uri, true); } /** * Delete call to top node (caching). * * @param uri */ private void deleteAllPropertiesOfUriTop(String uri, boolean sendEvent) { deleteAllPropertiesOfUri(uri, sendEvent); // remove from cache // String parentUri = URIParser.getParentUri(URIParser.getParentUri(uri)); removed daniel didn't do anything //CacheHandler childCacheHandler = GlobalConfig.instance().getChildCacheHandler(); //childCacheHandler.delete(parentUri); } /** * this function will remove the properties of uri from the properties * table and the occurences of this uri as a children in childrens table * * @param uri */ private void deleteAllPropertiesOfUri(String uri, boolean sendEvent) { // depth first removal of nodes Map<String, String> children = getChildrenOfUri(uri); String childUri = null; for (Iterator i = children.keySet().iterator(); i.hasNext();) { childUri = i.next().toString(); deleteAllPropertiesOfUri(childUri, sendEvent); } // remove properties and children links deletePropertiesOfUri(uri, sendEvent); deleteChildrenOfUri(uri); } private synchronized void deletePropertiesOfUri(String uri, boolean sendEvent) { // get mimetype MimeType mt = getMimeTypeOfResource(uri); String parentUri = uri; if (uri.lastIndexOf("/properties") > -1) { parentUri = uri.substring(0, uri.lastIndexOf("/properties")); } FSXMLProperties properties = getProperties(parentUri); String referId = null; if (properties != null && properties.getReferUri() != null) { referId = properties.getReferUri(); } // delete try { pdao.delete(uri); } catch (DAOException e) { logger.error("", e); } if (sendEvent) { TriggerSystemManager.getInstance().getDomainTS(URIParser.getDomainFromUri(uri)).eventHappened(uri, "DELETE", mt.getName(), null); // send message try { cache.signal(InetAddress.getLocalHost().toString(), "DELETE", uri); // 27apr GlobalConfig.instance().getDispatcher().send(new Message(InetAddress.getLocalHost(),"DELETE",uri)); if (referId != null) { cache.signal(InetAddress.getLocalHost().toString(), "LINK", referId + " DELETE " + uri); } } catch (Exception e) { logger.error("Could not send message", e); } } /* * clear referred cache, since item that is deleted might * refer to another item * TODO: more efficient removal of referred items */ //CacheHandler referredCacheHandler = GlobalConfig.instance().getReferredCacheHandler(); //referredCacheHandler.deleteAll(); } /** * Does not actually delete the children of this uri. It deletes this child from its parent children. * @param uri */ private synchronized void deleteChildrenOfUri(String uri) { String id = URIParser.getCurrentUriPart(uri); String type = URIParser.getParentUriPart(uri); String pUri = URIParser.getParentUri(uri); try { cdao.delete(new FSXMLChildKey(pUri, type, id)); } catch (DAOException e) { logger.error("", e); } } /** * Get the node properties of a uri that does not end with an id Default * values for start and limit (0,-1). * * @param uri * @return */ private Document getNodePropertiesByType(String uri) { return getNodePropertiesByType(uri, DEFAULT_DEPTH, DEFAULT_START, DEFAULT_LIMIT); } /** * Get the node properties of a uri that does not end with an id * * @param uri * resource uri * @param params * pruning parameters, such as depth, start and limit * @return */ private Document getNodePropertiesByType(String uri, Map<String, String> params) { int depth = DEFAULT_DEPTH, start = DEFAULT_START, limit = DEFAULT_LIMIT; // convert params try { depth = Integer.parseInt(params.get("depth")); } catch (Exception e) { /* no problem, will revert to default */ } try { start = Integer.parseInt(params.get("start")); } catch (Exception e) { /* no problem, will revert to default */ } try { limit = Integer.parseInt(params.get("limit")); } catch (Exception e) { /* no problem, will revert to default */ } logger.debug("Start: " + start + ", limit: " + limit + ", depth: " + depth); return getNodePropertiesByType(uri, depth, start, limit); } /** * Get the node properties of a uri that does not end with an id * * @param uri * @param depth * @param start * @param limit * @return */ private Document getNodePropertiesByType(String uri, int depth, int start, int limit) { Document doc = null; // check start and limit start = start < DEFAULT_START ? DEFAULT_START : start; limit = limit < LIMIT_ALL ? LIMIT_ALL : limit; // get type of asset String type = URIParser.getCurrentUriPart(uri); uri = URIParser.getPreviousUri(uri); // debug logger.debug("Getting nodes of type for: " + uri + "(" + type + ")"); // get children and count List<FSXMLChild> children = cdao.getChildrenByType(uri, type); int totalResultsAvailable = children.size(); // create xml StringBuffer xml = new StringBuffer(); int pNow = 0, totalResultsReturned = 0; // pointers for position of resultset and number of childs unpruned. for (FSXMLChild child : children) { if (pNow >= start && (totalResultsReturned < limit || limit == LIMIT_ALL)) { // add complete child and update total pointer Document childDoc = getNodeProperties(child.getReferUri(), depth - 1); if (childDoc != null) { xml.append(unwrapXml(childDoc.asXML())); } // update pointer totalResultsReturned++; } else if (totalResultsReturned > limit && limit != LIMIT_ALL) { // stop loop break; } // update pointer pNow++; } // add information such as start, limit, depth, // totalResultsAvailable // and totalResultsReturned StringBuffer rsProperties = new StringBuffer(); rsProperties.append("<properties>"); rsProperties.append("<depth>" + depth + "</depth>"); rsProperties.append("<start>" + start + "</start>"); rsProperties.append("<limit>" + limit + "</limit>"); rsProperties.append("<totalResultsAvailable>" + totalResultsAvailable + "</totalResultsAvailable>"); rsProperties.append("<totalResultsReturned>" + totalResultsReturned + "</totalResultsReturned>"); rsProperties.append("</properties>"); // convert to document try { doc = DocumentHelper.parseText(wrapXml(rsProperties.toString() + xml.toString())); } catch (DocumentException e) { logger.error("", e); } // return return doc; } /** * Get the different domains available * * @return */ private Document getAllDomains() { List<FSXMLProperties> pList = pdao.getPropertiesByType("domain"); Document doc = null; StringBuffer xml = new StringBuffer(); for (FSXMLProperties properties : pList) { xml.append("<domain id=\"" + URIParser.getCurrentUriPart(properties.getUri()) + "\">"); xml.append(unwrapXml(properties.getXml())); xml.append("</domain>"); } try { doc = DocumentHelper.parseText(wrapXml(xml.toString())); } catch (DocumentException e) { logger.error("", e); } return doc; } /** * Get the mimetype of a uri * * @param uri * @return */ private MimeType getMimeTypeOfResource(String uri) { FSXMLProperties properties = null; try { properties = pdao.read(uri); } catch (DAOException e) { logger.error("", e); } if (properties != null && properties.getMimetype() != null && properties.getMimetype().equals(MimeType.MIMETYPE_FS_SCRIPT.getName())) { return MimeType.MIMETYPE_FS_SCRIPT; } return MimeType.MIMETYPE_FS_XML; } private boolean hasChildren(String uri, String type) { int count = cdao.getChildrenByTypeCount(uri, type); if (count == 0) { return false; } return true; } private boolean isAuthorized(String uri) { boolean is = (uri.split("/").length > 5); return is; } } /* * **************************************** THE ATTRIBUTE HANDLER CLASS * **************************************** * **************************************** THE ATTRIBUTE HANDLER CLASS * **************************************** * **************************************** THE ATTRIBUTE HANDLER CLASS * **************************************** * **************************************** THE ATTRIBUTE HANDLER CLASS * **************************************** */ private class AttributeHandler { private static final String ATTRIBUTES_TAG = "attributes"; private boolean saveAttributes(String uri, String xml, String method) { Document doc = XMLHelper.asDocument(xml); if (doc != null) { Element atrs = (Element) doc.selectSingleNode("//" + ATTRIBUTES_TAG); if (atrs != null) { Element child = null; for (Iterator<Element> i = atrs.elementIterator(); i.hasNext();) { child = (Element) i.next(); if (child.getName() != null) { if (child.getName().equals("referid")) { return saveReferId(uri, child.getText(), method); } } } } } return false; } private synchronized boolean saveReferId(String uri, String referId, String method) { // get type String type = URIParser.getResourceTypeFromUri(uri); // read old properties, update and save back FSXMLProperties properties = null; try { properties = pdao.read(uri); } catch (DAOException e) { logger.error("", e); } boolean success = false; try { if (properties == null) { properties = new FSXMLProperties(uri, referId, type, MimeType.MIMETYPE_FS_XML.getName(), DEFAULT_PROPERTIES); success = pdao.create(properties); } else { properties.setReferUri(referId); success = pdao.update(properties); } } catch (DAOException e) { logger.error("", e); } // make proper xml for event String attributesXml = "<fsxml><attributes><referid>" + referId + "</referid></attributes></fsxml>"; // make sure the URI is linked to its parent FSXMLRequestHandler.instance().addUriToChildrenOfParentResource(uri, type); TriggerSystemManager.getInstance().getDomainTS(URIParser.getDomainFromUri(uri)).eventHappened(uri, method, MimeType.MIMETYPE_FS_XML.getName(), attributesXml); // send message try { cache.signal(InetAddress.getLocalHost().toString(), method, uri); // 27apr GlobalConfig.instance().getDispatcher().send(new Message(InetAddress.getLocalHost(),method,uri)); cache.signal(InetAddress.getLocalHost().toString(), "LINK", referId + " " + method + " " + uri); } catch (Exception e) { logger.error("Could not send message", e); } // clear referred cache //CacheHandler referredCacheHandler = GlobalConfig.instance().getReferredCacheHandler(); //referredCacheHandler.delete(referId); return success; } /** * Returns a list of resources that refer to the specified uri. * * @param uri resource uri. * @return A list of resources that refer to the specified uri. */ public List<String> getReferParents(String uri) { List<String> refPars = null; // check cache //CacheHandler referredCacheHandler = GlobalConfig.instance().getReferredCacheHandler(); //refPars = (List<String>)referredCacheHandler.get(uri); if (refPars == null) { // create list refPars = new ArrayList<String>(); // get referrer properties List<FSXMLProperties> pList = pdao.getReferredProperties(uri); for (FSXMLProperties properties : pList) { refPars.add(properties.getUri()); } // store in cache //referredCacheHandler.put(uri, refPars); } // return return refPars; } private boolean hasReferId(String uri) { // get properties FSXMLProperties properties = null; try { properties = pdao.read(uri); } catch (DAOException e) { logger.error("", e); } if (properties == null) { return false; } return properties.getReferUri() != null; } /** * This function returns all of the resources attributes. * * TODO the db structure should be changed (when more attributes are * needed), so it actually has a separate table for attributes * * @param uri * @return */ private String getAttributes(String uri) { // get properties FSXMLProperties properties = null; try { properties = pdao.read(uri); } catch (DAOException e) { logger.error("", e); } // TODO: xml transformer class // create xml String attributes = "<fsxml><attributes>"; attributes += "<id>" + URIParser.getParentUriPart(uri) + "</id>"; if (properties.getReferUri() != null) { attributes += "<referid>" + properties.getReferUri() + "</referid>"; } attributes += "</attributes></fsxml>"; return attributes; } private String getAttributeValue(String uri) { String parentUri = URIParser.getPreviousUri(uri); String xml = getAttributes(parentUri); // check attributes if (xml == null) { return null; } // parse Document doc = null; try { doc = DocumentHelper.parseText(xml); } catch (DocumentException e) { logger.error("", e); } Element elem = (Element) doc.selectSingleNode("//" + URIParser.getCurrentUriPart(uri)); if (elem != null) { return elem.getText(); } return null; } } }