All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.solr.core.SolrXMLSerializer Maven / Gradle / Ivy

There is a newer version: 9.6.1
Show newest version
package org.apache.solr.core;

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.XML;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.channels.FileChannel;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class SolrXMLSerializer {
  protected static Logger log = LoggerFactory
      .getLogger(SolrXMLSerializer.class);
  
  private final static String INDENT = "  ";
  
  
  /**
   * @param w
   *          Writer to use
   * @throws IOException If there is a low-level I/O error.
   */
  void persist(Writer w, SolrXMLDef solrXMLDef) throws IOException {
    w.write("\n");
    w.write(" rootSolrAttribs = solrXMLDef.solrAttribs;
    Set solrAttribKeys = rootSolrAttribs.keySet();
    for (String key : solrAttribKeys) {
      String value = rootSolrAttribs.get(key);
      writeAttribute(w, key, value);
    }
    
    w.write(">\n");
    Properties containerProperties = solrXMLDef.containerProperties;
    if (containerProperties != null && !containerProperties.isEmpty()) {
      writeProperties(w, containerProperties, "  ");
    }

    // Output logging section if any
    if (solrXMLDef.loggingAttribs.size() > 0 || solrXMLDef.watcherAttribs.size() > 0) {
      w.write(INDENT + " ent : solrXMLDef.loggingAttribs.entrySet()) {
        writeAttribute(w, ent.getKey(), ent.getValue());
      }
      w.write(">\n");

      if (solrXMLDef.watcherAttribs.size() > 0) {
        w.write(INDENT + INDENT + " ent : solrXMLDef.watcherAttribs.entrySet()) {
          writeAttribute(w, ent.getKey(), ent.getValue());
        }
        w.write("/>\n");
      }
      w.write(INDENT + "\n");
    }

    w.write(INDENT + " coresAttribs = solrXMLDef.coresAttribs;
    Set coreAttribKeys = coresAttribs.keySet();
    for (String key : coreAttribKeys) {
      String value = coresAttribs.get(key);
      writeAttribute(w, key, value);
    }
    w.write(">\n");
    
    for (SolrCoreXMLDef coreDef : solrXMLDef.coresDefs) {
      persist(w, coreDef);
    }

    // Shard handler section
    if (solrXMLDef.shardHandlerNode != null) {
      w.write(nodeToXML(solrXMLDef.shardHandlerNode));
    }

    w.write(INDENT + "\n");
    w.write("\n");
  }

  private String nodeToXML(Node node) {
    try {
      TransformerFactory tfactory = TransformerFactory.newInstance();
      Transformer tx = tfactory.newTransformer();
      StringWriter buffer = new StringWriter();
      tx.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
      tx.transform(new DOMSource(node), new StreamResult(buffer));
      return buffer.toString();
    }
    catch (Exception e) {
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error transforming XML: " + e.getMessage());
    }
  }
  
  /** Writes the cores configuration node for a given core. */
  private void persist(Writer w, SolrCoreXMLDef coreDef) throws IOException {
    w.write(INDENT + INDENT + " keys = coreDef.coreAttribs.keySet();
    for (String key : keys) {
      writeAttribute(w, key, coreDef.coreAttribs.get(key));
    }
    Properties properties = coreDef.coreProperties;
    if (properties == null || properties.isEmpty()) w.write("/>\n"); // core
    else {
      w.write(">\n");
      writeProperties(w, properties, "      ");
      w.write(INDENT + INDENT + "\n");
    }
  }
  
  private void writeProperties(Writer w, Properties props, String indent)
      throws IOException {
    for (Map.Entry entry : props.entrySet()) {
      w.write(indent + "\n");
    }
  }
  
  private void writeAttribute(Writer w, String name, Object value)
      throws IOException {
    if (value == null) return;
    w.write(" ");
    w.write(name);
    w.write("=\"");
    XML.escapeAttributeValue(value.toString(), w);
    w.write("\"");
  }
  
  void persistFile(File file, SolrXMLDef solrXMLDef) {
    log.info("Persisting cores config to " + file.getAbsolutePath());
    
    File tmpFile = null;
    try {
      // write in temp first
      tmpFile = File.createTempFile("solr", ".xml", file.getParentFile());
      
      java.io.FileOutputStream out = new java.io.FileOutputStream(tmpFile);
      Writer writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
      try {
        persist(writer, solrXMLDef);
      } finally {
        writer.close();
        out.close();
      }
      // rename over origin or copy if this fails
      if (tmpFile != null) {
        if (tmpFile.renameTo(file)) tmpFile = null;
        else fileCopy(tmpFile, file);
      }
    } catch (java.io.FileNotFoundException xnf) {
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, xnf);
    } catch (java.io.IOException xio) {
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, xio);
    } finally {
      if (tmpFile != null) {
        if (!tmpFile.delete()) tmpFile.deleteOnExit();
      }
    }
  }
  
  /**
   * Copies a src file to a dest file: used to circumvent the platform
   * discrepancies regarding renaming files.
   */
  private static void fileCopy(File src, File dest) throws IOException {
    IOException xforward = null;
    FileInputStream fis = null;
    FileOutputStream fos = null;
    FileChannel fcin = null;
    FileChannel fcout = null;
    try {
      fis = new FileInputStream(src);
      fos = new FileOutputStream(dest);
      fcin = fis.getChannel();
      fcout = fos.getChannel();
      // do the file copy 32Mb at a time
      final int MB32 = 32 * 1024 * 1024;
      long size = fcin.size();
      long position = 0;
      while (position < size) {
        position += fcin.transferTo(position, MB32, fcout);
      }
    } catch (IOException xio) {
      xforward = xio;
    } finally {
      if (fis != null) try {
        fis.close();
        fis = null;
      } catch (IOException xio) {}
      if (fos != null) try {
        fos.close();
        fos = null;
      } catch (IOException xio) {}
      if (fcin != null && fcin.isOpen()) try {
        fcin.close();
        fcin = null;
      } catch (IOException xio) {}
      if (fcout != null && fcout.isOpen()) try {
        fcout.close();
        fcout = null;
      } catch (IOException xio) {}
    }
    if (xforward != null) {
      throw xforward;
    }
  }
  
  static public class SolrXMLDef {
    Properties containerProperties;
    Map solrAttribs;
    Map coresAttribs;
    Map loggingAttribs;
    Map watcherAttribs;
    Node shardHandlerNode;
    List coresDefs;
  }
  
  static public class SolrCoreXMLDef {
    Properties coreProperties;
    Map coreAttribs;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy