org.dspace.installer_edm.InstallerEDMConfEDMExport.java Source code

Java tutorial

Introduction

Here is the source code for org.dspace.installer_edm.InstallerEDMConfEDMExport.java

Source

/**
 *  Copyright 2013 Spanish Minister of Education, Culture and Sport
 *
 *  written by MasMedios
 *
 *  Licensed under the EUPL, Version 1.1 or  as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "Licence");
 *
 *  You may not use this work  except in compliance with the License. You may obtain a copy of the License at:
 *
 *  http://ec.europa.eu/idabc/servlets/Docbb6d.pdf?id=31979
 *
 *  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.
 */

package org.dspace.installer_edm;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.RegexFileFilter;
import org.w3c.dom.*;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;

/**
 * @class InstallerEDMConfEDMExport
 *
 * Clase para configurar el servicio EDMExport segn el dspace instalado.
 * Se copia el archivo EDMExport de packages al directorio de trabajo del instalador para
 * poder modificarlo.
 * Se modifica web.xml dentro de EDMExport.war para que apunte al archivo dspace.cfg de dspace.
 * Se cambian archivos jar de la api de dspace y de lucene para adaptarlos a la versin de lucen del dspace desplegado
 *
 */
public class InstallerEDMConfEDMExport extends InstallerEDMBase {

    /**
     * Ruta del archivo EDMExport.war
     */
    private String eDMExportWar;

    /**
     * Archivo EDMExport.war
     */
    private File eDMExportWarFile;

    /**
     * Archivo EDMExport.war en el directorio de trabajo del instalador
     */
    private File eDMExportWarWorkFile;

    /**
     * Archivo de tipo jar para leer EDMExport.war en el directorio de trabajo del instalador
     */
    private JarFile eDMExportWarJarFile;

    /**
     * Documento jdom para leer el archivo web.xml
     */
    private Document eDMExportDocument;

    /**
     * Archivo con la api de dspace
     */
    private File dspaceApi = null;

    /**
     * Lista de jar con las libreras de lucene
     */
    private ArrayList<File> luceneLibs = null;

    /**
     * Consulta xpath para buscar la propiedad de dspace-config en web.xml
     */
    private static final String xpathDspaceConfigTemplate = "//*[contains(*,\"dspace-config\")]";

    /**
     *
     * Constructor
     *
     * @param currentStepGlobal paso actual
     * @param EDMExportWar ruta del archivo EDMExport.war
     */
    public InstallerEDMConfEDMExport(int currentStepGlobal, String EDMExportWar) {
        super(currentStepGlobal);
        this.eDMExportWar = EDMExportWar;
        this.eDMExportWarFile = new File(EDMExportWar);
    }

    /**
     * Se comprueba que el archivo EDMExport.war exista y se pueda modificar o se pide su ruta
     *
     * @return si existe y se puede modificar
     * @throws IOException
     */
    private boolean checkEDMExporWar() throws IOException {
        if (!eDMExportWarFile.exists() || !eDMExportWarFile.isFile() || !eDMExportWarFile.canWrite()) {
            installerEDMDisplay.showQuestion(currentStepGlobal, "checkEDMExporWar.notexists",
                    new String[] { eDMExportWar });
            installerEDMDisplay.showQuestion(currentStepGlobal, "checkEDMExporWar.newwar");
            String response = null;
            do {
                response = br.readLine();
                if (response == null)
                    continue;
                response = response.trim();
                if (!response.isEmpty()) {
                    eDMExportWarFile = new File(response);
                    return checkEDMExporWar();
                } else
                    return false;
            } while (true);
        }
        return true;
    }

    /**
     * Abre el archivo EDMExport.war y se recorre la lista de archivos que lo componen.
     * En web.xml lo abre con jdom y pide la ruta de dspace.cfg para modificarlo
     * Para los jar con la api de dspace y de lucene muestra cul hay en el war y cul en dspace y pregunta si se cambia
     */
    public void configure() {
        try {
            // comprobar validez del war
            if (checkEDMExporWar()) {
                // copiar al directorio de trabajo
                eDMExportWarWorkFile = new File(
                        myInstallerWorkDirPath + fileSeparator + eDMExportWarFile.getName());
                copyDspaceFile2Work(eDMExportWarFile, eDMExportWarWorkFile, "configure.edmexport");

                // abrir el war
                eDMExportWarJarFile = new JarFile(eDMExportWarWorkFile);
                // buscar web.xml
                ZipEntry edmExportWebZipentry = eDMExportWarJarFile.getEntry("WEB-INF/web.xml");
                if (edmExportWebZipentry == null)
                    installerEDMDisplay.showQuestion(currentStepGlobal, "configure.notwebxml");
                else {
                    // crear dom de web.xml
                    InputStream is = eDMExportWarJarFile.getInputStream(edmExportWebZipentry);
                    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                    factory.setNamespaceAware(true);
                    DocumentBuilder builder = factory.newDocumentBuilder();
                    eDMExportDocument = builder.parse(is);
                    // buscar dspace-config
                    XPath xpathInputForms = XPathFactory.newInstance().newXPath();
                    NodeList resultsDspaceConfig = (NodeList) xpathInputForms.evaluate(xpathDspaceConfigTemplate,
                            eDMExportDocument, XPathConstants.NODESET);
                    if (resultsDspaceConfig.getLength() == 0) {
                        installerEDMDisplay.showQuestion(currentStepGlobal, "configure.nopath");
                    } else {
                        // preguntar ruta de dspace.cfg y configurar los jar
                        Element contextParam = (Element) resultsDspaceConfig.item(0);
                        if (contextParam.getTagName().equals("context-param")) {
                            NodeList resultsParamValue = contextParam.getElementsByTagName("param-value");
                            if (resultsParamValue.getLength() > 0) {
                                Element valueParam = (Element) resultsParamValue.item(0);
                                String dspaceCfg = DspaceDir + "config" + fileSeparator + "dspace.cfg";
                                installerEDMDisplay.showQuestion(currentStepGlobal, "configure.dspacecfg",
                                        new String[] { dspaceCfg });
                                File dspaceCfgFile = new File(dspaceCfg);
                                String response = null;
                                do {
                                    response = br.readLine();
                                    if (response == null)
                                        continue;
                                    response = response.trim();
                                    if (response.isEmpty()) {
                                        break;
                                    } else {
                                        dspaceCfgFile = new File(response);
                                        if (dspaceCfgFile.exists())
                                            break;
                                    }
                                } while (true);
                                Text text = eDMExportDocument.createTextNode(dspaceCfgFile.getAbsolutePath());
                                valueParam.replaceChild(text, valueParam.getFirstChild());
                                // jar con la api de dspace
                                findDspaceApi();
                                // jars con lucene
                                findLuceneLib();
                                // escribir el nuevo war con las modificaciones
                                writeNewJar();
                                eDMExportWarJarFile = new JarFile(eDMExportWarWorkFile);
                                installerEDMDisplay.showLn();
                                installerEDMDisplay.showQuestion(currentStepGlobal, "configure.dspacecfg.ok",
                                        new String[] { eDMExportWarWorkFile.getAbsolutePath() });
                            }
                        }
                    }
                }
            }
        } catch (IOException e) {
            showException(e);
            installerEDMDisplay.showQuestion(currentStepGlobal, "configure.dspacecfg.nok");
        } catch (ParserConfigurationException e) {
            showException(e);
            installerEDMDisplay.showQuestion(currentStepGlobal, "configure.dspacecfg.nok");
        } catch (SAXException e) {
            showException(e);
            installerEDMDisplay.showQuestion(currentStepGlobal, "configure.dspacecfg.nok");
        } catch (XPathExpressionException e) {
            showException(e);
            installerEDMDisplay.showQuestion(currentStepGlobal, "configure.dspacecfg.nok");
        } catch (TransformerException e) {
            showException(e);
            installerEDMDisplay.showQuestion(currentStepGlobal, "configure.dspacecfg.nok");
        }
    }

    /**
     * Busca el jar con la api de dspace en el directorio lib de dspace
     */
    private void findDspaceApi() {
        File dspaceLib = new File(DspaceDir + "lib");
        if (dspaceLib.isDirectory() && dspaceLib.canRead()) {
            FileFilter fileFilter = new RegexFileFilter("^dspace-api-\\d+.+\\.jar$");
            File[] files = dspaceLib.listFiles(fileFilter);
            if (files.length > 0) {
                dspaceApi = files[0];
                if (debug)
                    installerEDMDisplay.showQuestion(currentStepGlobal, "replaceDspaceApi.dspaceApi",
                            new String[] { dspaceApi.getAbsolutePath() });
            } else
                installerEDMDisplay.showQuestion(currentStepGlobal, "replaceDspaceApi.notmatch",
                        new String[] { dspaceLib.getAbsolutePath(), "dspace-api-\\d+.+\\.jar" });
        } else
            installerEDMDisplay.showQuestion(currentStepGlobal, "replaceDspaceApi.notdir",
                    new String[] { DspaceDir + "lib" });
    }

    /**
     * Busca los jars con las libreras de lucene en el directorio lib de dspace
     */
    private void findLuceneLib() {
        File dspaceLib = new File(DspaceDir + "lib");
        if (dspaceLib.isDirectory() && dspaceLib.canRead()) {
            FileFilter fileFilter = new RegexFileFilter("^lucene-.+?-\\d+.+\\.jar$");
            File[] files = dspaceLib.listFiles(fileFilter);
            if (files.length > 0) {
                luceneLibs = new ArrayList<File>();
                for (File fileLucene : files) {
                    luceneLibs.add(fileLucene);
                    if (debug)
                        installerEDMDisplay.showQuestion(currentStepGlobal, "replaceLuceneCoreLib.luceneCoreLib",
                                new String[] { fileLucene.getAbsolutePath() });
                }
            } else
                installerEDMDisplay.showQuestion(currentStepGlobal, "replaceLuceneCoreLib.notmatch",
                        new String[] { dspaceLib.getAbsolutePath(), "lucene-.+?-\\d+.+\\.jar" });
        } else
            installerEDMDisplay.showQuestion(currentStepGlobal, "replaceLuceneCoreLib.notdir",
                    new String[] { DspaceDir + "lib" });
    }

    /**
     * Recorre el war para escribir los archivos web.xml, la api de dspace y los jar de lucene
     *
     * @throws IOException
     * @throws TransformerException
     */
    private void writeNewJar() throws IOException, TransformerException {
        final int BUFFER_SIZE = 1024;
        // directorio de trabajo
        File jarDir = new File(this.eDMExportWarJarFile.getName()).getParentFile();
        // archivo temporal del nuevo war
        File newJarFile = File.createTempFile("EDMExport", ".jar", jarDir);
        newJarFile.deleteOnExit();
        // flujo de escritura para el nuevo war
        JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream(newJarFile));

        try {
            // recorrer los archivos del war
            Enumeration<JarEntry> entries = eDMExportWarJarFile.entries();
            // libreras de lucene
            Pattern luceneLibPattern = Pattern.compile("^WEB-INF/lib/(lucene-.+?)-\\d+.+\\.jar$");
            boolean newApiCopied = false;
            if (dspaceApi == null)
                newApiCopied = true;
            boolean replace = false;
            // recorrer
            while (entries.hasMoreElements()) {
                replace = false;
                installerEDMDisplay.showProgress('.');
                JarEntry entry = entries.nextElement();
                InputStream intputStream = null;
                // todos menos web.xml
                if (!entry.getName().equals("WEB-INF/web.xml")) {
                    // api de dspace, se muestra la actual y la de dspace para pedir si se copia
                    if (!newApiCopied && entry.getName().matches("^WEB-INF/lib/dspace-api-\\d+.+\\.jar$")) {
                        String response = null;
                        do {
                            installerEDMDisplay.showLn();
                            installerEDMDisplay.showQuestion(currentStepGlobal, "writeNewJar.replace.question",
                                    new String[] { entry.getName(), "WEB-INF/lib/" + dspaceApi.getName(),
                                            dspaceApi.getAbsolutePath() });
                            response = br.readLine();
                            if (response == null)
                                continue;
                            response = response.trim();
                            if (response.isEmpty() || response.equalsIgnoreCase(answerYes)) {
                                replace = true;
                                break;
                            } else if (response.equalsIgnoreCase("n")) {
                                break;
                            }
                        } while (true);
                        // se reemplaza por la de dspace
                        if (replace) {
                            JarEntry newJarEntry = new JarEntry("WEB-INF/lib/" + dspaceApi.getName());
                            newJarEntry.setCompressedSize(-1);
                            jarOutputStream.putNextEntry(newJarEntry);
                            intputStream = new FileInputStream(dspaceApi);
                            newApiCopied = true;
                            if (debug) {
                                installerEDMDisplay.showLn();
                                installerEDMDisplay.showQuestion(currentStepGlobal, "writeNewJar.replace",
                                        new String[] { entry.getName(), "WEB-INF/lib/" + dspaceApi.getName(),
                                                dspaceApi.getAbsolutePath() });
                                installerEDMDisplay.showLn();
                            }
                        }
                    } else {
                        // libreras de lucene
                        Matcher luceneLibMatcher = luceneLibPattern.matcher(entry.getName());
                        if (luceneLibMatcher.find()) {
                            String prefixLuceneLib = luceneLibMatcher.group(1);
                            File luceneLibFile = null;
                            String patternFile = prefixLuceneLib + "-\\d+.+\\.jar";
                            for (File file : luceneLibs) {
                                if (file.getName().matches(patternFile)) {
                                    luceneLibFile = file;
                                    break;
                                }
                            }
                            if (luceneLibFile != null) {
                                String response = null;
                                do {
                                    installerEDMDisplay.showLn();
                                    installerEDMDisplay.showQuestion(currentStepGlobal,
                                            "writeNewJar.replace.question",
                                            new String[] { entry.getName(),
                                                    "WEB-INF/lib/" + luceneLibFile.getName(),
                                                    luceneLibFile.getAbsolutePath() });
                                    response = br.readLine();
                                    if (response == null)
                                        continue;
                                    response = response.trim();
                                    if (response.isEmpty() || response.equalsIgnoreCase(answerYes)) {
                                        replace = true;
                                        break;
                                    } else if (response.equalsIgnoreCase("n")) {
                                        break;
                                    }
                                } while (true);
                                // se reemplaza por la de dspace
                                if (replace) {
                                    JarEntry newJarEntry = new JarEntry("WEB-INF/lib/" + luceneLibFile.getName());
                                    newJarEntry.setCompressedSize(-1);
                                    jarOutputStream.putNextEntry(newJarEntry);
                                    intputStream = new FileInputStream(luceneLibFile);
                                    if (debug) {
                                        installerEDMDisplay.showLn();
                                        installerEDMDisplay.showQuestion(currentStepGlobal, "writeNewJar.replace",
                                                new String[] { entry.getName(),
                                                        "WEB-INF/lib/" + luceneLibFile.getName(),
                                                        luceneLibFile.getAbsolutePath() });
                                        installerEDMDisplay.showLn();
                                    }
                                }
                            }
                            // si no era la api de dspace o las libreras de lucene se copia tal cual
                        } else if (!replace) {
                            JarEntry entryOld = new JarEntry(entry);
                            entryOld.setCompressedSize(-1);
                            jarOutputStream.putNextEntry(entryOld);
                            intputStream = eDMExportWarJarFile.getInputStream(entry);
                        }
                    }
                    if (intputStream == null) {
                        if (debug)
                            installerEDMDisplay.showQuestion(currentStepGlobal, "writeNewJar.notIS",
                                    new String[] { entry.getName() });
                        continue;
                    }
                    // se lee el archivo y se copia al flujo de escritura del war
                    int count;
                    byte data[] = new byte[BUFFER_SIZE];
                    while ((count = intputStream.read(data, 0, BUFFER_SIZE)) != -1) {
                        jarOutputStream.write(data, 0, count);
                    }
                    intputStream.close();
                }
            }
            installerEDMDisplay.showLn();
            // se aade web.xml al war
            addNewWebXml(jarOutputStream);
            // cerramos el archivo jar y borramos el war
            eDMExportWarJarFile.close();
            eDMExportWarWorkFile.delete();
            // sustituimos el viejo por el temporal
            try {
                /*if (newJarFile.renameTo(eDMExportWarWorkFile) && eDMExportWarWorkFile.setExecutable(true, true)) {
                eDMExportWarWorkFile = new File(myInstallerWorkDirPath + fileSeparator + eDMExportWarFile.getName());
                } else {
                throw new IOException();
                }*/
                if (jarOutputStream != null)
                    jarOutputStream.close();
                FileUtils.moveFile(newJarFile, eDMExportWarWorkFile);
                //newJarFile.renameTo(eDMExportWarWorkFile);
                eDMExportWarWorkFile.setExecutable(true, true);
                eDMExportWarWorkFile = new File(
                        myInstallerWorkDirPath + fileSeparator + eDMExportWarFile.getName());
            } catch (Exception io) {
                io.printStackTrace();
                throw new IOException();
            }
        } finally {
            if (jarOutputStream != null) {
                jarOutputStream.close();
            }
        }
    }

    /**
     * Aadimos el contenido del documento jdom como archivo web.xml al flujo de escritura del war
     *
     * @param jarOutputStream flujo de escritura del war
     * @throws TransformerException
     * @throws IOException
     */
    private void addNewWebXml(JarOutputStream jarOutputStream) throws TransformerException, IOException {
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        //transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
        DocumentType docType = eDMExportDocument.getDoctype();
        if (docType != null) {
            if (docType.getPublicId() != null)
                transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, docType.getPublicId());
            transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, docType.getSystemId());
        }
        StringWriter sw = new StringWriter();
        StreamResult result = new StreamResult(sw);
        DOMSource source = new DOMSource(eDMExportDocument);
        transformer.transform(source, result);
        String xmlString = sw.toString();
        jarOutputStream.putNextEntry(new JarEntry("WEB-INF/web.xml"));
        jarOutputStream.write(xmlString.getBytes());
        jarOutputStream.closeEntry();
    }

}