/******************************************************************************* * Copyright (c) 2006-2012 * Software Technology Group, Dresden University of Technology * DevBoost GmbH, Berlin, Amtsgericht Charlottenburg, HRB 140026 * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Software Technology Group - TU Dresden, Germany; * DevBoost GmbH - Berlin, Germany * - initial API and implementation ******************************************************************************/ package org.reuseware.sokan.index.solr; import static org.reuseware.sokan.index.solr.SolrConst.ALL_SYS_FIELDS; import static org.reuseware.sokan.index.solr.SolrConst.SYS_FIELD_GENERATED; import static org.reuseware.sokan.index.solr.SolrConst.SYS_FIELD_ID; import static org.reuseware.sokan.index.solr.SolrConst.SYS_FIELD_PHY_URI; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map.Entry; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrInputDocument; import org.apache.solr.schema.IndexSchema; import org.apache.solr.schema.SchemaField; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; import org.osgi.framework.Bundle; import org.reuseware.sokan.ID; import org.reuseware.sokan.IndexMetaData; import org.reuseware.sokan.IndexRow; import org.reuseware.sokan.index.SokanIndexPlugin; import org.reuseware.sokan.index.util.ResourceUtil; import org.reuseware.sokan.index.util.RowUtil; /** * Utility class to work with the Solr index. */ public final class SolrUtil { private SolrUtil() { } private static String solrHome; private static String confDir; private static String solrData; /** * Returns the field that is identified by the given value. * * @param value the value * @param fields list of fields to consider * @return the identified field */ public static String adaptField(String value, Set<String> fields) { if (value == null || value.equals("")) { return value; } if (isSystemField(value)) { return value; } String test; for (String field : fields) { test = trimSuffix(field); if (value.equals(test)) { return field; } } return null; } /** * @param field the field * @return true if the field is a predefined field */ public static boolean isSystemField(String field) { return ALL_SYS_FIELDS.contains(field); } /** * Trims the suffix of the given field. * * @param solrField the field * @return the trimmed field */ public static String trimSuffix(String solrField) { int trim = 0; if (solrField.endsWith(SolrConst.SUFFIX_MULTI)) { trim = SolrConst.SUFFIX_MULTI.length(); } else if (solrField.endsWith(SolrConst.SUFFIX_SINGLE)) { trim = SolrConst.SUFFIX_SINGLE.length(); } return solrField.substring(0, solrField.length() - trim); } /** * Converts the given Solr documents to index row objects. * * @param docs the Solr documents * @return the index rows */ public static List<IndexRow> toIndexRows(SolrDocumentList docs) { if (docs == null) { return null; } List<IndexRow> rows = new ArrayList<IndexRow>(docs.size()); String idString; String phyURI; boolean isGenerated; IndexMetaData metaData; for (SolrDocument doc : docs) { // extract system index fields: actifactID, phyURI, dirty idString = (String) doc.getFieldValue(SYS_FIELD_ID); phyURI = (String) doc.getFieldValue(SYS_FIELD_PHY_URI); Object generated = doc.getFieldValue(SYS_FIELD_GENERATED); isGenerated = generated == null ? false : (Boolean) generated; // extract dynamic meta data metaData = RowUtil.buildMetaData(); String key; for (Entry<String, Object> entry : doc) { key = entry.getKey(); if (SolrUtil.isSystemField(key)) { continue; } if (key.endsWith(SolrConst.SUFFIX_MULTI)) { metaData.putMultiple(SolrUtil.trimSuffix(key), toValueList( doc, entry.getKey())); } else { metaData.putSingle(SolrUtil.trimSuffix(key), (String) entry .getValue()); } } rows.add(RowUtil.buildIndexRow(idString, phyURI, metaData, isGenerated)); } return rows; } /** * Converts the list of artifact IDs to a list of * artifact IDs in string representation. * * @param artifactIDs the artifact IDs * @return list of IDs as strings */ public static List<String> toStringList(List<ID> artifactIDs) { List<String> uniqueFields = new ArrayList<String>(artifactIDs.size()); String field; for (ID id : artifactIDs) { field = ResourceUtil.idString(id); uniqueFields.add(field); } return uniqueFields; } /** * Converts the given row elements to Solr input document objects. * * @param newRows the newly created rows to convert * @return list of Solr input documents */ public static List<SolrInputDocument> toSolrDocs(List<IndexRow> newRows) { List<SolrInputDocument> docs = new ArrayList<SolrInputDocument>(newRows .size()); SolrInputDocument in; for (IndexRow row : newRows) { in = new SolrInputDocument(); // Sokan system fields in.addField(SYS_FIELD_ID, ResourceUtil .idString(row.getArtifactID())); in.addField(SYS_FIELD_GENERATED, row.isGenerated()); in.addField(SYS_FIELD_PHY_URI, row.getPhyURI()); // dynamic user data IndexMetaData metaData = row.getMetaData(); if (metaData != null && !metaData.isEmpty()) { // single-value fields for (Entry<String, String> pair : metaData .getSingleValueFields().entrySet()) { in.addField(pair.getKey() + SolrConst.SUFFIX_SINGLE, pair .getValue()); } // multi-value fields for (Entry<String, EList<String>> pair : metaData .getMultiValueFields().entrySet()) { in.addField(pair.getKey() + SolrConst.SUFFIX_MULTI, pair .getValue()); } } docs.add(in); } return docs; } /** * Configures Solr's logger. * * @param level the logging level */ public static void configureLogger(Level level) { Logger log = Logger.getLogger(""); log = Logger.getLogger("org.apache.solr"); // log.setUseParentHandlers(false); log.setLevel(level); } /** * Prepares a query string by correct escape characters. * * @param string the unprepared string * @return the prepared string */ public static String prepareForQuery(String string) { return string.replaceAll("\\\\", "\\\\\\\\"); } /** * Copies the given field if required. * * @param inputFile the input field * @param force true to force the copying * @return true if the copying was successful */ public static boolean copyIfNeeded(String inputFile, boolean force) { if (inputFile == null) { return false; } File solrFile = new File(getConfigurationDir() + File.separator + inputFile); try { if (solrFile.exists() && !force) { return true; } } catch (SecurityException e) { SokanIndexPlugin.logError("", e); return false; } InputStream in = null; FileOutputStream out = null; try { if (Platform.isRunning()) { Bundle bundle = Platform.getBundle(SolrConst.PLUGIN_ID); IPath path = new Path("src-conf" + File.separator + inputFile); in = FileLocator.find(bundle, path, null).openStream(); } else { in = SolrUtil.class.getResourceAsStream("../../../../../" + inputFile); } out = new FileOutputStream(solrFile, false); byte[] buffer = new byte[0xFFFF]; for (int len; (len = in.read(buffer)) != -1;) { out.write(buffer, 0, len); } } catch (IOException e1) { SokanIndexPlugin.logError("", e1); return false; } finally { if (in != null) { try { in.close(); } catch (IOException e) { SokanIndexPlugin.logError("", e); return false; } } if (out != null) { try { out.close(); } catch (IOException e) { SokanIndexPlugin.logError("", e); return false; } } } return true; } /** * @return the Solr configuration directory */ public static String getConfigurationDir() { if (confDir != null) { return confDir; } confDir = getSolrHome() + File.separator + "conf"; return confDir; } /** * @return the Solr data directory */ public static String getDataDir() { if (solrData != null) { return solrData; } solrData = getSolrHome() + File.separator + "data"; return solrData; } /** * @return the Solr home directory */ public static String getSolrHome() { if (solrHome != null) { return solrHome; } if (Platform.isRunning()) { solrHome = Platform.getLocation().toOSString(); } else { solrHome = "."; } solrHome += File.separator + ".metadata" + File.separator + ".plugins" + File.separator + "org.reuseware.sokan.index.solr" + File.separator + ".solr_home"; return solrHome; } private static EList<String> toValueList(SolrDocument doc, String key) { Collection<Object> temp = doc.getFieldValues(key); EList<String> valueList = new BasicEList<String>(temp.size()); for (Object obj : temp) { String value = (String) obj; if (value == null || value.equals("")) { continue; } valueList.add(value); } return valueList; } /** * Checks if the given Solr schema is well formed. * * @param schema the schema * @return true if the schema is well formed */ public static boolean wellFormed(IndexSchema schema) { Set<String> inSchema = new HashSet<String>(); for (Entry<String, SchemaField> entry : schema.getFields() .entrySet()) { if (ALL_SYS_FIELDS.contains(entry.getKey())) { inSchema.add(entry.getKey()); } } if (ALL_SYS_FIELDS.size() == inSchema.size()) { return true; } return false; } /** * @param schema the Solr schema * @return all fields defined in the schema */ public static Set<String> extractFields(IndexSchema schema) { return schema.getFields().keySet(); } }