private String[] getAll(Map<String, ? extends List<Object>> attr, String name) {
    List<Object> values = attr.get(name);

    if (values == null) {
      if (Log.isDebugEnabled(Geonet.LDAP))
        Log.debug(Geonet.LDAP, "Attribute '" + name + "' does not exist");
      return null;
    }

    ArrayList<String> objs = new ArrayList<String>();

    for (Object obj : values) {
      if (obj != null) {
        if (Log.isDebugEnabled(Geonet.LDAP)) {
          Log.debug(
              Geonet.LDAP,
              "Attribute '" + name + "' is of type : " + obj.getClass().getSimpleName());
        }
        objs.add(obj.toString());
      } else {
        if (Log.isDebugEnabled(Geonet.LDAP)) {
          Log.debug(Geonet.LDAP, "Attribute '" + name + "' is null");
        }
      }
    }

    return objs.toArray(new String[0]);
  }
Exemple #2
0
  private void runSQL(Dbms dbms, List<String> data, boolean failOnError) throws Exception {
    StringBuffer sb = new StringBuffer();

    for (String row : data) {
      if (!row.toUpperCase().startsWith("REM") && !row.startsWith("--") && !row.trim().equals("")) {
        sb.append(" ");
        sb.append(row);

        if (row.endsWith(";")) {
          String sql = sb.toString();

          sql = sql.substring(0, sql.length() - 1);

          if (Log.isDebugEnabled(Geonet.DB)) Log.debug(Geonet.DB, "Executing " + sql);

          try {
            if (sql.trim().startsWith("SELECT")) {
              dbms.select(sql);
            } else {
              dbms.execute(sql);
            }
          } catch (SQLException e) {
            Log.warning(Geonet.DB, "SQL failure for: " + sql + ", error is:" + e.getMessage());

            if (failOnError) throw e;
          }
          sb = new StringBuffer();
        }
      }
    }
    dbms.commit();
  }
Exemple #3
0
  public void insertData(
      ServletContext servletContext, Dbms dbms, String appPath, String filePath, String filePrefix)
      throws Exception {
    if (Log.isDebugEnabled(Geonet.DB)) Log.debug(Geonet.DB, "Filling database tables");

    List<String> data = loadSqlDataFile(servletContext, dbms, appPath, filePath, filePrefix);
    runSQL(dbms, data);
  }
Exemple #4
0
  /**
   * Create database schema.
   *
   * @param servletContext
   * @param dbms
   */
  public void createSchema(
      ServletContext servletContext, Dbms dbms, String appPath, String filePath, String filePrefix)
      throws Exception {
    if (Log.isDebugEnabled(Geonet.DB)) Log.debug(Geonet.DB, "Creating database schema");

    List<String> schema = loadSchemaFile(servletContext, dbms, appPath, filePath, filePrefix);
    runSQL(dbms, schema);
  }
 /**
  * TODO javadoc.
  *
  * @param session
  * @param id
  * @return
  */
 protected static Element getMetadataFromSession(UserSession session, String id) {
   if (Log.isDebugEnabled(Geonet.EDITOR)) {
     Log.debug(Geonet.EDITOR, "Retrieving metadata from session " + session.getUserId());
   }
   Element md = (Element) session.getProperty(Geonet.Session.METADATA_EDITING + id);
   md.detach();
   return md;
 }
Exemple #6
0
  /**
   * Remove all objects in the database. Read the SQL file and check all CREATE TABLE statements to
   * collect the list of table to remove.
   *
   * @param dbms
   * @throws FileNotFoundException
   * @throws IOException
   */
  public void removeObjects(
      ServletContext servletContext, Dbms dbms, String appPath, String filePath, String filePrefix)
      throws FileNotFoundException, IOException {
    if (Log.isDebugEnabled(Geonet.DB)) Log.debug(Geonet.DB, "Removing database objects");
    List<String> schema = loadSchemaFile(servletContext, dbms, appPath, filePath, filePrefix);

    // --- step 1 : collect objects to remove
    ArrayList<ObjectInfo> objects = new ArrayList<ObjectInfo>();

    for (String row : schema)
      if (row.toUpperCase().startsWith("CREATE ")) {
        ObjectInfo oi = new ObjectInfo();
        oi.name = getObjectName(row);
        oi.type = getObjectType(row);

        if (!oi.type.toLowerCase().equals("index")) objects.add(oi);
      }

    // --- step 2 : remove objects
    while (true) {
      boolean removed = false;

      for (Iterator<ObjectInfo> i = objects.iterator(); i.hasNext(); ) {
        ObjectInfo oi = i.next();
        if (Log.isDebugEnabled(Geonet.DB)) Log.debug(Geonet.DB, "  * Dropping " + oi.name);
        String query = "DROP " + oi.type + " " + oi.name;

        if (safeExecute(dbms, query)) {
          removed = true;
          i.remove();
        }
      }

      if (objects.size() == 0) return;

      // --- if no object was removed then we have a cyclic loop
      if (!removed) {
        ArrayList<String> al = new ArrayList<String>();

        for (ObjectInfo oi : objects) al.add(oi.name);
        return;
      }
    }
  }
  private String get(Map<String, ? extends List<Object>> attr, String name) {
    List<Object> values = attr.get(name);

    if (values == null) {
      if (Log.isDebugEnabled(Geonet.LDAP))
        Log.debug(Geonet.LDAP, "Attribute '" + name + "' does not exist");
      return null;
    }

    Object obj = values.get(0);

    if (obj != null)
      if (Log.isDebugEnabled(Geonet.LDAP))
        Log.debug(
            Geonet.LDAP, "Attribute '" + name + "' is of type : " + obj.getClass().getSimpleName());
      else if (Log.isDebugEnabled(Geonet.LDAP))
        Log.debug(Geonet.LDAP, "Attribute '" + name + "' is null");

    return (obj == null) ? null : obj.toString();
  }
Exemple #8
0
 /**
  * Adds missing namespace (ie. GML) to XML inputs. It should be done by the client side but add a
  * check in here.
  *
  * @param fragment The fragment to be checked and processed.
  * @return The updated fragment.
  */
 protected static String addNamespaceToFragment(String fragment) {
   // add the gml namespace if its missing
   if (fragment.contains("<gml:") && !fragment.contains("xmlns:gml=\"")) {
     if (Log.isDebugEnabled(Geonet.EDITOR))
       Log.debug(Geonet.EDITOR, "  Add missing GML namespace.");
     fragment =
         fragment.replaceFirst(
             "<gml:([^ >]+)", "<gml:$1 xmlns:gml=\"http://www.opengis.net/gml\"");
   }
   return fragment;
 }
Exemple #9
0
  /**
   * Check if db specific SQL script exist, if not return default SQL script path.
   *
   * @param filePath
   * @param prefix
   * @param type
   * @return
   */
  private String checkFilePath(String filePath, String prefix, String type) {
    String dbFilePath = filePath + "/" + prefix + type + SQL_EXTENSION;
    File dbFile = new File(dbFilePath);
    if (dbFile.exists()) return dbFilePath;

    String defaultFilePath = filePath + "/" + prefix + "default" + SQL_EXTENSION;
    File defaultFile = new File(defaultFilePath);
    if (defaultFile.exists()) return defaultFilePath;
    else if (Log.isDebugEnabled(Geonet.DB))
      Log.debug(Geonet.DB, "  No default SQL script found: " + defaultFilePath);

    return "";
  }
Exemple #10
0
  /**
   * Execute query and commit
   *
   * @param dbms
   * @param query
   * @return
   */
  private boolean safeExecute(Dbms dbms, String query) {
    try {
      dbms.execute(query);

      // --- as far as I remember, PostgreSQL needs a commit even for DDL
      dbms.commit();

      return true;
    } catch (SQLException e) {
      if (Log.isDebugEnabled(Geonet.DB))
        Log.debug(Geonet.DB, "Safe execute error: " + query + ", error is:" + e.getMessage());
      dbms.abort();
      return false;
    }
  }
  public GNResultSet(GNXMLQuery query, Object userInfo, Observer[] observers, ServiceContext srvctx)
      throws Exception {
    super(observers);
    this.query = query;
    this.srvxtx = srvctx;

    try {

      GeonetContext gc = (GeonetContext) this.srvxtx.getHandlerContext(Geonet.CONTEXT_NAME);
      SearchManager searchMan = gc.getBean(SearchManager.class);

      metasearcher = searchMan.newSearcher(SearchManager.LUCENE, Geonet.File.SEARCH_Z3950_SERVER);

    } catch (Exception e) {
      if (Log.isDebugEnabled(Geonet.Z3950_SERVER))
        Log.debug(Geonet.Z3950_SERVER, "error constructing GNresult set: " + e);
      e.printStackTrace();
    }
  }
Exemple #12
0
  /**
   * @param dbms
   * @return
   * @throws FileNotFoundException
   * @throws IOException
   */
  private List<String> loadSchemaFile(
      ServletContext servletContext,
      Dbms dbms,
      String appPath,
      String filePath,
      String filePrefix) // FIXME :
      // use
      // resource
      // dir
      // instead
      // of
      // appPath
      throws FileNotFoundException, IOException {
    // --- find out which dbms schema to load
    String file = checkFilePath(filePath, filePrefix, DatabaseType.lookup(dbms).toString());

    if (Log.isDebugEnabled(Geonet.DB)) Log.debug(Geonet.DB, "  Loading script:" + file);

    // --- load the dbms schema
    return Lib.text.load(servletContext, appPath, file);
  }
  public int evaluate(int timeout) {
    try {
      if (Log.isDebugEnabled(Geonet.Z3950_SERVER))
        Log.debug(Geonet.Z3950_SERVER, "INCOMING XML QUERY:\n" + query);

      Element request = new Element("request");
      request.addContent(query.toGNXMLRep());

      List<String> categories = query.getCollections();
      for (String category : categories) {
        if (!category.equals("geonetwork") && !category.equals("Default"))
          request.addContent(new Element("category").setText(category));
      }

      ServiceConfig config = new ServiceConfig();

      // perform the search and save search results

      metasearcher.search(this.srvxtx, request, config);

      // System.out.println("summary:\n" + Xml.getString(s.getSummary()));
      // // DEBUG

      // Random number of records.. Set up the result set
      setFragmentCount(metasearcher.getSize());
      setTaskStatusCode(IRResultSetStatus.COMPLETE);

      this.srvxtx.getResourceManager().close();
    } catch (Throwable e) {
      Log.error(Geonet.Z3950_SERVER, "error evaluating query.." + e);
      e.printStackTrace();

      try {
        this.srvxtx.getResourceManager().abort();
      } catch (Exception e2) {
        e2.printStackTrace();
      }
    }
    return (getStatus());
  }
 /**
  * For Ajax Editing : removes metadata from session.
  *
  * @param session
  * @param id
  */
 public void removeMetadataEmbedded(UserSession session, String id) {
   if (Log.isDebugEnabled(Geonet.EDITOR))
     Log.debug(Geonet.EDITOR, "Removing metadata from session " + session.getUserId());
   session.removeProperty(Geonet.Session.METADATA_EDITING + id);
   session.removeProperty(Geonet.Session.VALIDATION_REPORT + id);
 }
 /**
  * TODO javadoc.
  *
  * @param session
  * @param md
  * @param id
  */
 private void setMetadataIntoSession(UserSession session, Element md, String id) {
   if (Log.isDebugEnabled(Geonet.EDITOR)) {
     Log.debug(Geonet.EDITOR, "Storing metadata in session " + session.getUserId());
   }
   session.setProperty(Geonet.Session.METADATA_EDITING + id, md);
 }
  /**
   * Apply a list of changes to the metadata record in current editing session.
   *
   * <p>The changes are a list of KVP. A key contains at least the element identifier from the
   * meta-document. A key starting with an "X" should contain an XML fragment for the value. The
   * following KVP combinations are allowed:
   *
   * <ul>
   *   <li>ElementId=ElementValue
   *   <li>ElementId_AttributeName=AttributeValue
   *   <li>ElementId_AttributeNamespacePrefixCOLONAttributeName=AttributeValue
   *   <li>XElementId=ElementValue
   *   <li>XElementId_ElementName=ElementValue
   * </ul>
   *
   * ElementName MUST contain "{@value #COLON_SEPARATOR}" instead of ":" for prefixed elements.
   *
   * <p>When using X key, value could contains many XML fragments (eg. &lt;gmd:keywords
   * .../&gt;{@value #XML_FRAGMENT_SEPARATOR}&lt;gmd:keywords .../&gt;) separated by {@link
   * #XML_FRAGMENT_SEPARATOR}. All those fragments are inserted to the last element of this type in
   * its parent if ElementName is set. If not, the element with ElementId is replaced.
   *
   * <p>
   *
   * @param dbms
   * @param id Metadata internal identifier.
   * @param changes List of changes to apply.
   * @return The update metadata record
   * @throws Exception
   */
  protected Element applyChangesEmbedded(Dbms dbms, String id, Hashtable changes) throws Exception {
    String schema = dataManager.getMetadataSchema(dbms, id);
    EditLib editLib = dataManager.getEditLib();

    // --- get metadata from session
    Element md = getMetadataFromSession(session, id);

    // Store XML fragments to be handled after other elements update
    Map<String, String> xmlInputs = new HashMap<String, String>();

    // --- update elements
    for (Enumeration e = changes.keys(); e.hasMoreElements(); ) {
      String ref = ((String) e.nextElement()).trim();
      String value = ((String) changes.get(ref)).trim();
      String attribute = null;

      // Avoid empty key
      if (ref.equals("")) {
        continue;
      }

      // Catch element starting with a X to replace XML fragments
      if (ref.startsWith("X")) {
        ref = ref.substring(1);
        xmlInputs.put(ref, value);
        continue;
      }

      if (updatedLocalizedTextElement(md, ref, value, editLib)) {
        continue;
      }

      int at = ref.indexOf('_');
      if (at != -1) {
        attribute = ref.substring(at + 1);
        ref = ref.substring(0, at);
      }

      Element el = editLib.findElement(md, ref);
      if (el == null) {
        Log.error(Geonet.EDITOR, MSG_ELEMENT_NOT_FOUND_AT_REF + ref);
        continue;
      }

      // Process attribute
      if (attribute != null) {
        Pair<Namespace, String> attInfo =
            parseAttributeName(attribute, COLON_SEPARATOR, id, md, dbms, editLib);
        String localname = attInfo.two();
        Namespace attrNS = attInfo.one();
        if (el.getAttribute(localname, attrNS) != null) {
          el.setAttribute(new Attribute(localname, value, attrNS));
        }
      } else {
        // Process element value
        List content = el.getContent();

        for (int i = 0; i < content.size(); i++) {
          if (content.get(i) instanceof Text) {
            el.removeContent((Text) content.get(i));
            i--;
          }
        }
        el.addContent(value);
      }
    }

    // Deals with XML fragments to insert or update
    if (!xmlInputs.isEmpty()) {

      // Loop over each XML fragments to insert or replace
      for (String ref : xmlInputs.keySet()) {
        String value = xmlInputs.get(ref);
        String name = null;
        int addIndex = ref.indexOf('_');
        if (addIndex != -1) {
          name = ref.substring(addIndex + 1);
          ref = ref.substring(0, addIndex);
        }

        // Get element to fill
        Element el = editLib.findElement(md, ref);
        if (el == null) {
          Log.error(Geonet.EDITOR, MSG_ELEMENT_NOT_FOUND_AT_REF + ref);
          continue;
        }

        if (value != null && !value.equals("")) {
          String[] fragments = value.split(XML_FRAGMENT_SEPARATOR);
          for (String fragment : fragments) {
            if (name != null) {
              if (Log.isDebugEnabled(Geonet.EDITOR))
                Log.debug(
                    Geonet.EDITOR,
                    "Add XML fragment; " + fragment + " to element with ref: " + ref);
              name = name.replace(COLON_SEPARATOR, ":");
              editLib.addFragment(schema, el, name, fragment);
            } else {
              if (Log.isDebugEnabled(Geonet.EDITOR))
                Log.debug(
                    Geonet.EDITOR,
                    "Add XML fragment; "
                        + fragment
                        + " to element with ref: "
                        + ref
                        + " replacing content.");

              // clean before update
              el.removeContent();
              fragment = addNamespaceToFragment(fragment);

              // Add content
              el.addContent(Xml.loadString(fragment, false));
            }
          }
        }
      }
    }

    // --- remove editing info
    editLib.removeEditingInfo(md);
    editLib.contractElements(md);

    return (Element) md.detach();
  }
  public static List<Element> handlePropertyName(
      String[] propertyNames,
      ServiceContext context,
      boolean freq,
      int maxRecords,
      String cswServiceSpecificConstraint,
      LuceneConfig luceneConfig)
      throws Exception {

    List<Element> domainValuesList = null;

    if (Log.isDebugEnabled(Geonet.CSW))
      Log.debug(
          Geonet.CSW,
          "Handling property names '"
              + Arrays.toString(propertyNames)
              + "' with max records of "
              + maxRecords);

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

      if (i == 0) domainValuesList = new ArrayList<Element>();

      // Initialize list of values element.
      Element listOfValues = null;

      // Generate DomainValues element
      Element domainValues = new Element("DomainValues", Csw.NAMESPACE_CSW);

      // FIXME what should be the type ???
      domainValues.setAttribute("type", "csw:Record");

      String property = propertyNames[i].trim();

      // Set propertyName in any case.
      Element pn = new Element("PropertyName", Csw.NAMESPACE_CSW);
      domainValues.addContent(pn.setText(property));

      GeonetContext gc = (GeonetContext) context.getHandlerContext(Geonet.CONTEXT_NAME);
      SearchManager sm = gc.getSearchmanager();

      IndexAndTaxonomy indexAndTaxonomy = sm.getNewIndexReader(null);
      try {
        GeonetworkMultiReader reader = indexAndTaxonomy.indexReader;
        BooleanQuery groupsQuery = (BooleanQuery) CatalogSearcher.getGroupsQuery(context);
        BooleanQuery query = null;

        // Apply CSW service specific constraint
        if (StringUtils.isNotEmpty(cswServiceSpecificConstraint)) {
          Query constraintQuery =
              CatalogSearcher.getCswServiceSpecificConstraintQuery(
                  cswServiceSpecificConstraint, luceneConfig);

          query = new BooleanQuery();

          BooleanClause.Occur occur = LuceneUtils.convertRequiredAndProhibitedToOccur(true, false);

          query.add(groupsQuery, occur);
          query.add(constraintQuery, occur);

        } else {
          query = groupsQuery;
        }

        List<Pair<String, Boolean>> sortFields =
            Collections.singletonList(Pair.read(Geonet.SearchResult.SortBy.RELEVANCE, true));
        Sort sort = LuceneSearcher.makeSort(sortFields, context.getLanguage(), false);
        CachingWrapperFilter filter = null;

        Pair<TopDocs, Element> searchResults =
            LuceneSearcher.doSearchAndMakeSummary(
                maxRecords,
                0,
                maxRecords,
                context.getLanguage(),
                null,
                reader,
                query,
                filter,
                sort,
                null,
                false,
                false,
                false,
                false // Scoring is useless for GetDomain operation
                );
        TopDocs hits = searchResults.one();

        try {
          // Get mapped lucene field in CSW configuration
          String indexField = CatalogConfiguration.getFieldMapping().get(property.toLowerCase());
          if (indexField != null) property = indexField;

          // check if params asked is in the index using getFieldNames ?
          FieldInfos fi = new SlowCompositeReaderWrapper(reader).getFieldInfos();
          if (fi.fieldInfo(property) == null) continue;

          boolean isRange = false;
          if (CatalogConfiguration.getGetRecordsRangeFields().contains(property)) isRange = true;

          if (isRange) listOfValues = new Element("RangeOfValues", Csw.NAMESPACE_CSW);
          else listOfValues = new Element("ListOfValues", Csw.NAMESPACE_CSW);

          Set<String> fields = new HashSet<String>();
          fields.add(property);
          fields.add("_isTemplate");

          // parse each document in the index
          String[] fieldValues;
          SortedSet<String> sortedValues = new TreeSet<String>();
          HashMap<String, Integer> duplicateValues = new HashMap<String, Integer>();
          for (int j = 0; j < hits.scoreDocs.length; j++) {
            DocumentStoredFieldVisitor selector = new DocumentStoredFieldVisitor(fields);
            reader.document(hits.scoreDocs[j].doc, selector);
            Document doc = selector.getDocument();

            // Skip templates and subTemplates
            String[] isTemplate = doc.getValues("_isTemplate");
            if (isTemplate[0] != null && !isTemplate[0].equals("n")) continue;

            // Get doc values for specified property
            fieldValues = doc.getValues(property);
            if (fieldValues == null) continue;

            addtoSortedSet(sortedValues, fieldValues, duplicateValues);
          }

          SummaryComparator valuesComparator =
              new SummaryComparator(SortOption.FREQUENCY, Type.STRING, context.getLanguage(), null);
          TreeSet<Map.Entry<String, Integer>> sortedValuesFrequency =
              new TreeSet<Map.Entry<String, Integer>>(valuesComparator);
          sortedValuesFrequency.addAll(duplicateValues.entrySet());

          if (freq) return createValuesByFrequency(sortedValuesFrequency);
          else listOfValues.addContent(createValuesElement(sortedValues, isRange));

        } finally {
          // any children means that the catalog was unable to determine
          // anything about the specified parameter
          if (listOfValues != null && listOfValues.getChildren().size() != 0)
            domainValues.addContent(listOfValues);

          // Add current DomainValues to the list
          domainValuesList.add(domainValues);
        }
      } finally {
        sm.releaseIndexReader(indexAndTaxonomy);
      }
    }
    return domainValuesList;
  }
Exemple #18
0
  /**
   * TODO javadoc.
   *
   * @param dbms
   * @param id
   * @param changes
   * @param currVersion
   * @return
   * @throws Exception
   */
  private Element applyChanges(Dbms dbms, String id, Hashtable changes, String currVersion)
      throws Exception {
    Lib.resource.checkEditPrivilege(context, id);
    Element md = xmlSerializer.select(dbms, "Metadata", id, context);

    // --- check if the metadata has been deleted
    if (md == null) {
      return null;
    }

    EditLib editLib = dataManager.getEditLib();

    String schema = dataManager.getMetadataSchema(dbms, id);
    editLib.expandElements(schema, md);
    editLib.enumerateTree(md);

    // --- check if the metadata has been modified from last time
    if (currVersion != null && !editLib.getVersion(id).equals(currVersion)) {
      return null;
    }

    // --- update elements
    for (Enumeration e = changes.keys(); e.hasMoreElements(); ) {
      String ref = ((String) e.nextElement()).trim();
      String val = ((String) changes.get(ref)).trim();
      String attr = null;

      if (updatedLocalizedTextElement(md, ref, val, editLib)) {
        continue;
      }

      int at = ref.indexOf('_');
      if (at != -1) {
        attr = ref.substring(at + 1);
        ref = ref.substring(0, at);
      }
      boolean xmlContent = false;
      if (ref.startsWith("X")) {
        ref = ref.substring(1);
        xmlContent = true;
      }
      Element el = editLib.findElement(md, ref);
      if (el == null) throw new IllegalStateException("Element not found at ref = " + ref);

      if (attr != null) {
        // The following work-around decodes any attribute name that has a COLON in it
        // The : is replaced by the word COLON in the xslt so that it can be processed
        // by the XML Serializer when an update is submitted - a better solution is
        // to modify the argument handler in Jeeves to store arguments with their name
        // as a value rather than as the element itself
        Integer indexColon = attr.indexOf("COLON");
        if (indexColon != -1) {
          String prefix = attr.substring(0, indexColon);
          String localname = attr.substring(indexColon + 5);
          String namespace =
              editLib.getNamespace(prefix + ":" + localname, md, dataManager.getSchema(schema));
          Namespace attrNS = Namespace.getNamespace(prefix, namespace);
          if (el.getAttribute(localname, attrNS) != null) {
            el.setAttribute(new Attribute(localname, val, attrNS));
          }
          // End of work-around
        } else {
          if (el.getAttribute(attr) != null) el.setAttribute(new Attribute(attr, val));
        }
      } else if (xmlContent) {
        if (Log.isDebugEnabled(Geonet.EDITOR)) Log.debug(Geonet.EDITOR, "replacing XML content");
        el.removeContent();
        val = addNamespaceToFragment(val);
        el.addContent(Xml.loadString(val, false));
      } else {
        List content = el.getContent();
        for (int i = 0; i < content.size(); i++) {
          if (content.get(i) instanceof Text) {
            el.removeContent((Text) content.get(i));
            i--;
          }
        }
        el.addContent(val);
      }
    }
    // --- remove editing info added by previous call
    editLib.removeEditingInfo(md);

    editLib.contractElements(md);
    return md;
  }
  // --------------------------------------------------------------------------
  // ---
  // --- Service
  // ---
  // --------------------------------------------------------------------------
  @Override
  public Element serviceSpecificExec(Element params, ServiceContext context) throws Exception {
    boolean readOnlyMode = super.exec(params, context) == null;
    if (readOnlyMode) {
      return null;
    }
    String message = "";
    GeonetContext gc = (GeonetContext) context.getHandlerContext(Geonet.CONTEXT_NAME);

    // gets the total popularity count (=100)
    Dbms dbms = (Dbms) context.getResourceManager().open(Geonet.Res.MAIN_DB);

    // wont work if there is no metadata
    List l = dbms.select("select sum(popularity) as sumpop from metadata").getChildren();
    if (l.size() != 1) {
      message = "cannot get popularity count";
      return null;
    }

    int cnt = Integer.parseInt(((Element) l.get(0)).getChildText("sumpop"));

    if (Log.isDebugEnabled(Geonet.SEARCH_LOGGER))
      Log.debug(Geonet.SEARCH_LOGGER, "query to get popularity by group:\n" + query);
    dbms = (Dbms) context.getResourceManager().open(Geonet.Res.MAIN_DB);

    DefaultPieDataset dataset = new DefaultPieDataset();
    List resultSet = dbms.select(query).getChildren();

    for (int i = 0; i < resultSet.size(); i++) {
      Element record = (Element) resultSet.get(i);
      String popularity = (record).getChildText("popu");
      Double d = 0.0;
      if (popularity.length() > 0) {
        d = (Double.parseDouble(popularity) / cnt) * 100;
      }
      dataset.setValue(record.getChildText("source"), d);
      // System.out.println(record.getChildText("groupname") + ", " + d);
    }

    // create a chart...
    JFreeChart chart =
        ChartFactory.createPieChart(
            null,
            dataset,
            true, // legend?
            true, // tooltips?
            false // URLs?
            );

    // hard coded values for the moment. should come from a configuration file.
    chart.setBackgroundPaint(Color.decode("#E7EDF5"));
    String chartFilename = "popubycatalog_" + System.currentTimeMillis() + ".png";

    File statFolder =
        new File(
            gc.getHandlerConfig().getMandatoryValue(Geonet.Config.RESOURCES_DIR)
                + File.separator
                + "images"
                + File.separator
                + "statTmp");
    if (!statFolder.exists()) {
      statFolder.mkdirs();
    }
    File f = new File(statFolder, chartFilename);
    this.imageMap =
        org.fao.geonet.services.statistics.ChartFactory.writeChartImage(
            chart,
            f,
            this.chartWidth,
            this.chartHeight,
            this.createTooltips,
            "graphPopuByCatalogImageMap");
    // will return some info to the XSLT:
    // dateFrom, dateTo, graphicType, chartUrl, tooltipImageMap,
    // message, chartWidth, chartHeight

    Element elResp = new Element(Jeeves.Elem.RESPONSE);
    Element elchartUrl =
        new Element("popuByCatalogUrl")
            .setText(context.getBaseUrl() + "/images/statTmp/" + chartFilename);
    Element elTooltipImageMap =
        new Element("tooltipImageMap").addContent(this.createTooltips ? this.imageMap : "");

    Element elMessage = new Element("message").setText(message);
    Element elChartWidth = new Element("chartWidth").setText("" + this.chartWidth);
    Element elChartHeight = new Element("chartHeight").setText("" + this.chartHeight);

    elResp.addContent(elchartUrl);
    elResp.addContent(elTooltipImageMap);
    elResp.addContent(elMessage);
    elResp.addContent(elChartWidth);
    elResp.addContent(elChartHeight);

    return elResp;
  }
  public InformationFragment[] getFragment(
      int startingFragment, int count, RecordFormatSpecification spec) throws IRResultSetException {
    if (Log.isDebugEnabled(Geonet.Z3950_SERVER))
      Log.debug(
          Geonet.Z3950_SERVER,
          "Request for fragment start:" + startingFragment + ", count:" + count);

    InformationFragment fragment[] = new InformationFragment[count];

    ExplicitRecordFormatSpecification rec_spec =
        new ExplicitRecordFormatSpecification("xml", null, "f");

    try {
      // build fragment data
      int from = startingFragment;
      int to = startingFragment + count - 1;

      Element request = new Element("request");
      request.addContent(new Element("from").setText(from + ""));
      request.addContent(new Element("to").setText(to + ""));
      ServiceConfig config = new ServiceConfig();

      if (Log.isDebugEnabled(Geonet.Z3950_SERVER))
        Log.debug(Geonet.Z3950_SERVER, "Search request:\n" + Xml.getString(request));
      // get result set
      Element result = this.metasearcher.present(this.srvxtx, request, config);

      if (Log.isDebugEnabled(Geonet.Z3950_SERVER))
        Log.debug(Geonet.Z3950_SERVER, "Search result:\n" + Xml.getString(result));

      // remove summary
      result.removeChildren("summary");
      @SuppressWarnings("unchecked")
      List<Element> list = result.getChildren();

      if (Log.isDebugEnabled(Geonet.Z3950_SERVER))
        Log.debug(Geonet.Z3950_SERVER, "Set name asked:" + spec);

      // save other records to fragment
      for (int i = 0; i < count; i++) {
        Element md = list.get(0);
        md.detach();

        if (Log.isDebugEnabled(Geonet.Z3950_SERVER))
          Log.debug(Geonet.Z3950_SERVER, "Returning fragment:\n" + Xml.getString(md));

        // add metadata

        // fragment[i] = new DOMTree("geonetwork", "geonetwork", null,   getRecord(md),rec_spec );
        // fragment[i].setHitNo(startingFragment+i);

        DOMOutputter outputter = new DOMOutputter();
        Document doc = new Document(md);
        org.w3c.dom.Document doc2 = outputter.output(doc);

        fragment[i] =
            new InformationFragmentImpl(
                startingFragment + i, "geonetwork", "geonetwork", null, doc2, rec_spec);
        // fragment[i] = new
        // InformationFragmentImpl(startingFragment+i,"geonetwork","geonetwork",null,doc,rec_spec);

        // System.err.println(fragment[i]);

      }
      this.srvxtx.getResourceManager().close();
      if (Log.isDebugEnabled(Geonet.Z3950_SERVER))
        Log.debug(Geonet.Z3950_SERVER, "Fragment returned");
    } catch (Throwable e) {
      try {
        this.srvxtx.getResourceManager().abort();
      } catch (Exception e2) {
        e2.printStackTrace();
      }

      if (Log.isDebugEnabled(Geonet.Z3950_SERVER))
        Log.debug(Geonet.Z3950_SERVER, "Exception: " + e.getClass().getName() + " " + e);
      // e.printStackTrace();
    }

    return fragment;
  }