/******************************************************************************* * Copyright (c) 2009-2013 CWI * 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: * * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI * * Paul Klint - Paul.Klint@cwi.nl - CWI * * Arnold Lankamp - Arnold.Lankamp@cwi.nl *******************************************************************************/ package org.rascalmpl.uri.libraries; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URISyntaxException; import java.net.URL; import java.nio.charset.Charset; import org.rascalmpl.uri.ISourceLocationInput; import org.rascalmpl.uri.URIResolverRegistry; import org.rascalmpl.value.ISourceLocation; import org.rascalmpl.values.ValueFactoryFactory; /** * This class implements both input and output methods for files that reside in Java resources of a certain class. * Depending on where these resources are, i.e. on disk, or in a jar, (which depends on the classloader of the class) * some functionality may or may not work. Typically, the user will eventually get a "SchemeNotSupportedException" * if an operation is not provided. */ public abstract class ClassResourceInput implements ISourceLocationInput { protected final Class<?> clazz; protected final String scheme; protected final String prefix; public ClassResourceInput(String scheme, Class<?> clazz, String prefix) { this.clazz = clazz; this.scheme = scheme; this.prefix = normalizePrefix(prefix); } private String normalizePrefix(String prefix) { if (!prefix.startsWith("/")) { prefix = "/" + prefix; } while (prefix.endsWith("/") && prefix.length() > 1) { prefix = prefix.substring(0, prefix.length() - 2); } return prefix; } protected String getPath(ISourceLocation uri) { String path = uri.getPath(); while (path.startsWith("/")) { path = path.substring(1); } if (path.contains("//")) { path = path.replaceAll("//","/"); } return prefix + (prefix.endsWith("/") ? "" : "/") + path; } public boolean exists(ISourceLocation uri) { return clazz.getResource(getPath(uri)) != null; } public InputStream getInputStream(ISourceLocation uri) throws IOException { InputStream resourceAsStream = clazz.getResourceAsStream(getPath(uri)); if (resourceAsStream != null) { return resourceAsStream; } throw new FileNotFoundException(uri.toString()); } public String scheme() { return scheme; } public boolean isDirectory(ISourceLocation uri) { try { return URIResolverRegistry.getInstance().isDirectory(resolve(uri)); } catch (IOException e) { return false; } } public boolean isFile(ISourceLocation uri) { try { return URIResolverRegistry.getInstance().isFile(resolve(uri)); } catch (IOException e) { return false; } } protected ISourceLocation resolve(ISourceLocation uri) throws IOException { try { URL res = clazz.getResource(getPath(uri)); if(res == null) { throw new FileNotFoundException(getPath(uri)); } if (res.getProtocol().equals("jar") && res.getPath().startsWith("file:/")) { return ValueFactoryFactory.getValueFactory().sourceLocation("jar", null, res.getPath().substring("file:".length())); } return ValueFactoryFactory.getValueFactory().sourceLocation(res.toURI()); } catch (URISyntaxException e) { assert false; throw new IOException(e); } } public long lastModified(ISourceLocation uri) throws IOException { return URIResolverRegistry.getInstance().lastModified(resolve(uri)); } @Override public String[] list(ISourceLocation uri) throws IOException { return URIResolverRegistry.getInstance().listEntries(resolve(uri)); } public boolean supportsHost() { return false; } @Override public Charset getCharset(ISourceLocation uri) throws IOException { return URIResolverRegistry.getInstance().getCharset(resolve(uri)); } }