/* * Copyright (c) 2006, 2009 Borland Software Corporation * * 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: * Artem Tikhomirov (Borland) - initial API and implementation */ package org.eclipse.gmf.internal.xpand.util; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import org.eclipse.gmf.internal.xpand.Activator; import org.eclipse.gmf.internal.xpand.inactive.StreamDecoder; import org.eclipse.gmf.internal.xpand.model.EvaluationException; import org.eclipse.m2m.internal.qvt.oml.compiler.UnitResolver; /** * Node: no support for relative paths (i.e. '..::templates::SomeTemplate.xpt') * @author artem */ public class BundleResourceManager extends ResourceManagerImpl { private final URL[] paths; public BundleResourceManager(URL... paths) { assert paths != null && paths.length > 0; this.paths = new URL[paths.length]; for (int i = 0; i < paths.length; i++) { this.paths[i] = fixTrailingSlash(paths[i]); } } /** * new URL("base:url/path1/withoutTrailingSlash", "path2/noLeadingSlash") * results in "base:url/path/path2/noLeadingSlash" - note lost "withoutTrailingSlash" part * XXX Perhaps, would be better for clients do this 'normalization'? */ private static URL fixTrailingSlash(URL u) { try { if (u.getPath() != null && !u.getPath().endsWith("/")) { return new URL(u, u.getPath() + '/'); } } catch (MalformedURLException ex) { /*IGNORE*/ } return u; } @Override protected boolean shouldCache() { return true; } @Override protected void handleParserException(ParserException ex) { throw new EvaluationException(ex.toString()); } private Reader createReader(String urlPath, URL baseUrl) throws MalformedURLException, IOException { URL u = new URL(baseUrl, urlPath); InputStream is = u.openStream(); // XXX here we ignore the fact baseUrl may point to workspace location // and hence charset can be derived from IFile // FIXME for now, go with legacy encoding as a default return new StreamDecoder(is, StreamDecoder.LEGACY_ENCODING).getReader(); } @Override protected Reader[] resolveMultiple(String fullyQualifiedName, String extension) throws IOException { final String urlPath = fullyQualifiedName.replaceAll(TypeNameUtil.NS_DELIM, "/") + '.' + extension; ArrayList<Reader> result = new ArrayList<Reader>(paths.length); for (int i = 0; i < paths.length; i++) { try { result.add(createReader(urlPath, paths[i])); } catch (MalformedURLException ex) { /*IGNORE*/ } catch (IOException ex) { // XXX perhaps, conditionally turn logging on to debug template loading issues? /*IGNORE*/ } catch (Exception ex) { // just in case Activator.logError(ex); } } if (result.isEmpty()) { throw new FileNotFoundException(fullyQualifiedName); } return result.toArray(new Reader[result.size()]); } @Override protected String resolveCFileFullPath(String fullyQualifiedName, String extension) { final String urlPath = fullyQualifiedName.replaceAll(TypeNameUtil.NS_DELIM, "/") + '.' + extension; if (paths.length > 0) { try { return new URL(paths[0], urlPath).toString(); } catch (MalformedURLException e) { /* IGNORE */ } } return fullyQualifiedName + "." + extension; } @Override protected UnitResolver getQVTUnitResolver() { return BundleUnitResolver.createResolver(Arrays.asList(paths), true); } }