/******************************************************************************* * Copyright 2012 Pearson Education * * Licensed 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.semantictools.jsonld.impl; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.net.URI; import java.net.URL; import java.util.Properties; import org.semantictools.jsonld.LdAsset; import org.semantictools.jsonld.LdPublishException; import org.semantictools.jsonld.LdPublisher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An LdAssetManager that maintains a local cache of LdAssets on the file system. * * @author Greg McFall * */ public class LdAssetRepository extends LdAssetManagerImpl implements LdPublisher { private static final Logger logger = LoggerFactory.getLogger(LdAssetRepository.class); private static final String PROPERTIES_FILENAME = "asset.properties"; private static final String URI = "uri"; private static final String DEFAULT = "default"; private File root; /** * Create a new LdAssetRepository. * @param root The root directory under which assets will be stored. * @throws IOException */ public LdAssetRepository(File root) { this.root = root; } /** * Scan the specified directory for assets, and copy them into * this repository. * * @param file */ public void scan(File file) { if (file.isDirectory()) { File[] array = file.listFiles(); for (int i=0; i<array.length; i++) { scan(array[i]); } } else { LdContentType format = LdContentType.guessContentType(file.getName()); if (format != LdContentType.UNKNOWN) { try { URL location = file.toURI().toURL(); LdAsset asset = readAsset(null, location); if ((asset.getURI()!=null) && (asset.getFormat() != LdContentType.UNKNOWN)) { publish(asset); } } catch (Throwable oops) { logger.warn("failed to store asset: " + file.getPath()); } } } } /** * Copy the given asset into this repository */ public void publish(LdAsset asset) throws LdPublishException { try { File assetDir = assetDir(asset.getURI()); assetDir.mkdirs(); LdContentType format = asset.getFormat(); String formatName = format.name(); String fileName = formatName + '.' + format.getExtension(); Properties p = getAssetProperties(assetDir); p.put(formatName, fileName); p.put(URI, asset.getURI()); if (format.isDefaultType() || p.get(DEFAULT)==null) { p.put(DEFAULT, formatName); } File propertiesFile = new File(assetDir, PROPERTIES_FILENAME); FileWriter writer = new FileWriter(propertiesFile); try { p.store(writer, null); } finally { safeClose(writer); } File contentFile = new File(assetDir, fileName); try { writer = new FileWriter(contentFile); writer.write(asset.getContent()); } finally { safeClose(writer); } } catch (IOException oops) { throw new LdPublishException(asset.getURI(), oops); } } private void safeClose(FileWriter writer) { try { writer.close(); } catch (Throwable oops) { logger.warn("failed to close writer", oops); } } public LdAsset findAsset(String assetURI) { return findAsset(assetURI, null); } @Override public LdAsset findAsset(String assetURI, LdContentType format) { File assetDir = assetDir(assetURI); LdAsset asset = null; if (assetDir.exists()) { try { Properties properties = getAssetProperties(assetDir); String formatName = null; String fileName = null; if (format != null) { formatName = format.name(); fileName = properties.getProperty(format.name()); } else { // If there is an XSD file, use it by default. formatName = LdContentType.XSD.name(); fileName = properties.getProperty(formatName); if (fileName == null) { // There is no XSD file, so use the declared default format. formatName = properties.getProperty(DEFAULT); fileName = properties.getProperty(formatName); } } if (fileName == null) { return null; } File contentFile = new File(assetDir, fileName); URL location = contentFile.toURI().toURL(); if (format == null) { format = LdContentType.valueOf(LdContentType.class, formatName); } asset = new LdAsset(assetURI, format, location); if (isEagerLoading()) { asset.loadContent(); } } catch (Throwable oops) { logger.warn("Failed to load asset from repository: " + assetURI, oops); } } else { asset = loadAsset(assetURI, format); } return asset; } /** * Returns the properties of the asset whose representations are stored * in the given directory. * This file contains properties as described below: * <DL> * <DT>uri</DT><DD>The URI of the asset</DD> * <DT>default</DT><DD>The name of the default content type for the asset</DD> * <DT>{format}</DT><DD>The name of the file containing the representation of the asset in the specified format. * In this case, the property name matches the exact name of an element from the {@link LdContentType} enumeration. * </DD> * </DL> */ private Properties getAssetProperties(File assetDir) throws IOException { Properties p = new Properties(); File propertiesFile = new File(assetDir, PROPERTIES_FILENAME); if (!propertiesFile.exists()) return p; FileReader reader = new FileReader(propertiesFile); try { p.load(reader); } finally { safeClose(reader); } return p; } private File assetDir(String assetURI) { try { URI uri = new URI(assetURI); String path = uri.getAuthority() + "/" + uri.getPath(); return new File(root, path); } catch (Throwable oops) { return null; } } }