Package org.apache.clerezza.rdf.storage.externalizer

Source Code of org.apache.clerezza.rdf.storage.externalizer.ExternalizingProvider

/*
* 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.
*/
package org.apache.clerezza.rdf.storage.externalizer;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.apache.clerezza.rdf.core.Graph;
import org.apache.clerezza.rdf.core.MGraph;
import org.apache.clerezza.rdf.core.TripleCollection;
import org.apache.clerezza.rdf.core.UriRef;
import org.apache.clerezza.rdf.core.access.EntityAlreadyExistsException;
import org.apache.clerezza.rdf.core.access.EntityUndeletableException;
import org.apache.clerezza.rdf.core.access.NoSuchEntityException;
import org.apache.clerezza.rdf.core.access.TcManager;
import org.apache.clerezza.rdf.core.access.TcProviderMultiplexer;
import org.apache.clerezza.rdf.core.access.WeightedTcProvider;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.felix.scr.annotations.Service;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* A {@link org.apache.clerezza.rdf.core.access.WeightedTcProvider} storing
* large literals to the file system and the triples (with references
* instead of the literals) to another TcProvider.
* <br/>
* As this provider is not currently included in any clerezza launcher, the way
* to install it is as follows:<br/>
*
* - start clerezza<br/>
* - install the bundle and set its startlevel to 3<br/>
* - shutdown clerezza<br/>
* - delete the MGraphs that shall use the externalizer from the felix cache<br/>
* - start clerezza again<br/>
*
* @author reto
*
*/
@Component
@Service(WeightedTcProvider.class)
@Property(name = "weight", intValue = 500)
@Reference(name="weightedTcProvider", policy=ReferencePolicy.DYNAMIC,
    referenceInterface=WeightedTcProvider.class,
    cardinality=ReferenceCardinality.MANDATORY_MULTIPLE)
public class ExternalizingProvider implements WeightedTcProvider {

  private static final String EXTERNALIZEDLITERALS_SUFFIX = "-externalizedliterals";

  //@Reference(policy=ReferencePolicy.DYNAMIC, cardinality=ReferenceCardinality.OPTIONAL_UNARY)
  private TcProviderMultiplexer tcProvider = new TcProviderMultiplexer();
  /**
   *  directory where all graphs are stored
   */
  private static final String RELATIVE_DATA_PATH_NAME = "externalized-literals/";
  private File dataPath;
  private static final Logger log = LoggerFactory.getLogger(ExternalizingProvider.class);
  private int weight = 500;

  public ExternalizingProvider() {
  }

  ExternalizingProvider(File directory) {
    dataPath = directory;
    tcProvider = TcManager.getInstance();
  }

  protected void activate(ComponentContext cCtx) {
    log.info("Activating literal externalizing provider");
    if (cCtx != null) {
      weight = (Integer) cCtx.getProperties().get("weight");
      dataPath = cCtx.getBundleContext().getDataFile(RELATIVE_DATA_PATH_NAME);
    }
  }

  protected void deactivate(ComponentContext cCtx) {
    dataPath = null;
  }

  @Override
  public int getWeight() {
    return weight;
  }

  /**
   * we don't do graphs
   *
   * @param name
   * @return
   * @throws NoSuchEntityException
   */
  @Override
  public Graph getGraph(UriRef name) throws NoSuchEntityException {
    throw new NoSuchEntityException(name);
  }

  @Override
  public synchronized MGraph getMGraph(UriRef name) throws NoSuchEntityException {
    if (name.getUnicodeString().endsWith(EXTERNALIZEDLITERALS_SUFFIX)) {
      throw new IllegalArgumentException();
    }
    try {
      final UriRef baseGraphName = new UriRef(name.getUnicodeString() + EXTERNALIZEDLITERALS_SUFFIX);
      if (tcProvider == null) {
        throw new RuntimeException("MGraph retrieval currently not possible: tcManager unavailable");
      }
      final MGraph baseGraph = AccessController.doPrivileged(new PrivilegedExceptionAction<MGraph>() {

        @Override
        public MGraph run() {
          return tcProvider.getMGraph(baseGraphName);
        }
      });
      return new ExternalizingMGraph(baseGraph, getHashStoreDir(name));
    } catch (PrivilegedActionException ex) {
      Throwable cause = ex.getCause();
      if (cause instanceof UnsupportedOperationException) {
        throw (UnsupportedOperationException)cause;
      }
      if (cause instanceof EntityAlreadyExistsException) {
        throw (EntityAlreadyExistsException)cause;
      }
      if (cause instanceof RuntimeException) {
        throw (RuntimeException)cause;
      }
      throw new RuntimeException(cause);
    }
  }

  @Override
  public TripleCollection getTriples(UriRef name) throws NoSuchEntityException {
    return getMGraph(name);

  }

  @Override
  public synchronized MGraph createMGraph(UriRef name)
      throws UnsupportedOperationException, EntityAlreadyExistsException {
    try {
      if (name.getUnicodeString().endsWith(EXTERNALIZEDLITERALS_SUFFIX)) {
        throw new IllegalArgumentException();
      }
      final UriRef baseGraphName = new UriRef(name.getUnicodeString() + EXTERNALIZEDLITERALS_SUFFIX);
      if (tcProvider == null) {
        throw new RuntimeException("MGraph creation currently not possible: tcManager unavailable");
      }
      final MGraph baseGraph = AccessController.doPrivileged(new PrivilegedExceptionAction<MGraph>() {

        @Override
        public MGraph run() {
          return tcProvider.createMGraph(baseGraphName);
        }
      });
      File hashStoreDir = getHashStoreDir(name);
      hashStoreDir.mkdirs();
      return new ExternalizingMGraph(baseGraph, hashStoreDir);
    } catch (PrivilegedActionException ex) {
      Throwable cause = ex.getCause();
      if (cause instanceof UnsupportedOperationException) {
        throw (UnsupportedOperationException)cause;
      }
      if (cause instanceof EntityAlreadyExistsException) {
        throw (EntityAlreadyExistsException)cause;
      }
      if (cause instanceof RuntimeException) {
        throw (RuntimeException)cause;
      }
      throw new RuntimeException(cause);
    }
  }

  @Override
  public Graph createGraph(UriRef name, TripleCollection triples)
      throws UnsupportedOperationException, EntityAlreadyExistsException {
    throw new UnsupportedOperationException();
  }

  @Override
  public void deleteTripleCollection(UriRef name)
      throws UnsupportedOperationException, NoSuchEntityException,
      EntityUndeletableException {
    try {
      final UriRef baseGraphName = new UriRef(name.getUnicodeString() + EXTERNALIZEDLITERALS_SUFFIX);
      AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {

        @Override
        public Object run() {
          tcProvider.deleteTripleCollection(baseGraphName);
          return null;
        }
      });
      delete(getHashStoreDir(name));
    } catch (PrivilegedActionException ex) {
      Throwable cause = ex.getCause();
      if (cause instanceof UnsupportedOperationException) {
        throw (UnsupportedOperationException)cause;
      }
      if (cause instanceof EntityAlreadyExistsException) {
        throw (EntityAlreadyExistsException)cause;
      }
      if (cause instanceof RuntimeException) {
        throw (RuntimeException)cause;
      }
      throw new RuntimeException(cause);
    }
  }

  /**
   * Cleans the content of the specified directory recursively.
   * @param dir  Abstract path denoting the directory to clean.
   */
  private static void cleanDirectory(File dir) {
    File[] files = dir.listFiles();
    if (files != null && files.length > 0) {
      for (File file : files) {
        delete(file);
      }
    }
  }

  /**
   * Deletes the specified file or directory.
   * @param file  Abstract path denoting the file or directory to clean.
   */
  protected static void delete(File file) {
    if (file.isDirectory()) {
      cleanDirectory(file);
    }
    file.delete();
  }

  @Override
  public Set<UriRef> getNames(Graph graph) {
    //this could be done more efficiently with an index, could be done with
    //a MultiBidiMap (BidiMap allowing multiple keys for the same value)
    Set<UriRef> result = new HashSet<UriRef>();
    for (UriRef name : listGraphs()) {
      if (getGraph(name).equals(graph)) {
        result.add(name);
      }
    }
    return result;
  }

  @Override
  public Set<UriRef> listTripleCollections() {
    Set<UriRef> result = new HashSet<UriRef>();
    result.addAll(listGraphs());
    result.addAll(listMGraphs());
    return result;
  }

  @Override
  public Set<UriRef> listGraphs() {
    return new HashSet<UriRef>();
  }

  @Override
  public Set<UriRef> listMGraphs() {
    Set<UriRef> result = getHashStoreUris();
    for (Iterator<UriRef> it = result.iterator(); it.hasNext();) {
      UriRef graphName = it.next();
      final UriRef baseGraphName = new UriRef(graphName.getUnicodeString() + EXTERNALIZEDLITERALS_SUFFIX);
      try {
        tcProvider.getMGraph(baseGraphName);
      } catch (NoSuchEntityException e) {
        log.warn("Store for externalized literals but no base graph found for {}.", graphName);
        it.remove();
      }

    }
    return result;
  }

  private File getHashStoreDir(UriRef name) {
    try {
      String subDirName = URLEncoder.encode(name.getUnicodeString(), "utf-8");
      File result = new File(dataPath, subDirName);
      return result;
    } catch (UnsupportedEncodingException ex) {
      throw new RuntimeException("utf-8 not supported", ex);
    }
  }

  private Set<UriRef> getHashStoreUris() {
    Set<UriRef> result = new HashSet<UriRef>();
    if (dataPath.exists()) {
      for (String mGraphDirName : dataPath.list()) {
        try {
          UriRef uri = new UriRef(URLDecoder.decode(mGraphDirName, "utf-8"));
          result.add(uri);
        } catch (UnsupportedEncodingException ex) {
          throw new RuntimeException("utf-8 not supported", ex);
        }
      }
    }
    return result;
  }

  /**
   * Register a provider
   *
   * @param provider
   *            the provider to be registered
   */
  protected void bindWeightedTcProvider(WeightedTcProvider provider) {
    tcProvider.addWeightedTcProvider(provider);
  }

  /**
   * Deregister a provider
   *
   * @param provider
   *            the provider to be deregistered
   */
  protected void unbindWeightedTcProvider(WeightedTcProvider provider) {
    tcProvider.removeWeightedTcProvider(provider);
  }
}
TOP

Related Classes of org.apache.clerezza.rdf.storage.externalizer.ExternalizingProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.