/******************************************************************************* * Copyright (c) 2001, 2006 IBM Corporation and others. * 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jst.j2ee.commonarchivecore.internal.helpers; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import com.ibm.icu.util.StringTokenizer; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.impl.URIConverterImpl; import org.eclipse.jst.j2ee.commonarchivecore.internal.strategy.LoadStrategy; import org.eclipse.jst.jee.archive.internal.ArchiveUtil; /** * Helper class used for loading of mof resources contained within an archive; knows how to retrieve * an input stream for a given uri */ public class ArchiveURIConverterImpl extends URIConverterImpl { protected static final String fileProtocol = "file"; //$NON-NLS-1$ protected static final String platformProtocol = "platform"; //$NON-NLS-1$ private String inFilepath, outFilepath; public ArchiveURIConverterImpl(org.eclipse.jst.j2ee.commonarchivecore.internal.Archive anArchive, String resourcesPath) { setArchive(anArchive); this.resourcesPath = resourcesPath; setInputFilepath(resourcesPath); String outpath = resourcesPath; if (outpath == null) { LoadStrategy l = anArchive.getLoadStrategy(); if (l != null && l.isDirectory()) { try { outpath = l.getAbsolutePath(); } catch (FileNotFoundException ignore) { //Ignore } } } setOutputFilepath(outpath); } /** The archive from which resources will be loaded */ protected org.eclipse.jst.j2ee.commonarchivecore.internal.Archive archive; protected String resourcesPath; public org.eclipse.jst.j2ee.commonarchivecore.internal.Archive getArchive() { return archive; } @Override public InputStream createInputStream(URI uri) throws IOException { InputStream in = null; if (resourcesPath != null) in = makeInputStream(uri); if (in != null) return in; return getArchive().getInputStream(uri.toString()); } public void setArchive(org.eclipse.jst.j2ee.commonarchivecore.internal.Archive newArchive) { archive = newArchive; } /** * Gets the resourcesPath. * * @return Returns a String */ public String getResourcesPath() { return resourcesPath; } /** * Sets the resourcesPath. * * @param resourcesPath * The resourcesPath to set */ public void setResourcesPath(String resourcesPath) { this.resourcesPath = resourcesPath; setInputFilepath(resourcesPath); setOutputFilepath(resourcesPath); } @Override public URI normalize(URI uri) { return ((URIConverterImpl.URIMap)getURIMap()).getURI(uri); } /** * The input file path consists of a string of directories or zip files separated by semi-colons * that are searched when an input stream is constructed. * * @return The file path */ public String getInputFilepath() { return inFilepath; } /** * @param filepath * The file path */ public void setInputFilepath(String filepath) { inFilepath = filepath; } /** * @return The output file path */ public String getOutputFilepath() { return outFilepath; } /** * The output file path is the path name of a directory to prepend to relative file path names * when an output stream is constructed. * * @param filepath * The output file path */ public void setOutputFilepath(String filepath) { outFilepath = filepath; } /** * Convert the URI to an input stream. * * @param uri * The uri */ public InputStream makeInputStream(URI uri) throws IOException { URI converted = uri; if ((fileProtocol.equals(converted.scheme()) || converted.scheme() == null) && inFilepath != null) { return searchFilePath(converted.toString()); } URL url = createURL(converted.toString()); URLConnection urlConnection = url.openConnection(); return urlConnection.getInputStream(); } /** * Search the file path if the file portion of the URL is not absolute (does not begin with "/"; * otherwise, attempt to create an input stream for the file. */ protected InputStream searchFilePath(String filename) throws IOException { File file = new File(filename); if (file.isAbsolute()) return new FileInputStream(file); StringTokenizer st = new StringTokenizer(inFilepath, ";"); //$NON-NLS-1$ while (st.hasMoreTokens()) { String f = st.nextToken(); ZipFile zf = null; try { zf = ArchiveUtil.newZipFile(f); } catch (Exception e) { //Ignore } InputStream in = null; if (zf != null) { in = searchZipFile(zf, filename); if (in == null) try { zf.close(); } catch (Exception e) { //Ignore } } else { in = searchDirectory(f, filename); } if (in != null) return in; } return null; } /** * This method determines whether the file with the relative path name of filename exists in the * given directory. If not, it returns null; otherwise, it opens the file up and returns the * input source. * * @param dir * java.lang.String * @return java.io.InputSource */ protected InputStream searchDirectory(String dir, String filename) throws IOException { if (dir.equals(".")) //$NON-NLS-1$ dir = System.getProperty("user.dir"); //$NON-NLS-1$ File f = new File(dir + System.getProperty("file.separator") + filename.replace('/', File.separatorChar)); //$NON-NLS-1$ if (!f.exists()) return null; return new FileInputStream(f); } /** * This method determines whether there is a ZipEntry whose name is filename in the given * ZipFile. If not, it returns null; otherwise, it returns an input source to read from the * ZipEntry. * * @param zip * java.util.zip.ZipFile * @return java.io.InputSource */ protected InputStream searchZipFile(ZipFile zip, String filename) throws IOException { ZipEntry entry = zip.getEntry(filename); if (entry == null) return null; return zip.getInputStream(entry); } /** * Make a URL from the uri; if the attempt fails, attempt to append "file:" to the URI; if the * attempt still fails, attempt to replace the protocol with the file protocol. * * @param uri * The string uri */ public URL createURL(String uri) throws MalformedURLException { MalformedURLException m = null; if (uri == null) return null; URL url = null; try { url = new URL(uri); } catch (Exception e) { m = (MalformedURLException) e; } if (url != null) return url; // Either treat the URI as a filepath (if there are no : or // a : in position 1) or replace the given protocol with the // file protocol. int index = uri.indexOf(":"); //$NON-NLS-1$ if (index == -1 || index == 1) uri = fileProtocol + ":" + uri; //$NON-NLS-1$ else if (index > 0) uri = fileProtocol + ":" + uri.substring(index + 1); //$NON-NLS-1$ try { url = new URL(uri); } catch (Exception e) { //Ignore } if (url != null) return url; else if(m != null) throw m; else throw new MalformedURLException(); } /** * Convert the URI to an output stream. * * @param uri * The uri */ @Override public OutputStream createOutputStream(URI uri) throws IOException { URI converted = uri; if (platformProtocol.equals(converted.scheme())) { URL resolvedURL = resolvePlatform(new URL(converted.toString())); if (resolvedURL != null) { converted = URI.createFileURI(resolvedURL.getFile()); } } if (fileProtocol.equals(converted.scheme()) || converted.scheme() == null) { return openFileOutputStream(converted); } URL url = createURL(converted.toString()); URLConnection urlConnection = url.openConnection(); urlConnection.setDoOutput(true); return urlConnection.getOutputStream(); } protected URL resolvePlatform(URL url) throws IOException { // let WorkbenchURIConverter implement this one. return null; } /** * Open a file output stream for the given uri (the uri has file protocol). If an output file * path is specified and the file name is relative, prepend the output file path to the file * name. Make the directories that contain the file if they do not exist. */ protected OutputStream openFileOutputStream(URI uri) throws IOException { File file = new File(uri.toFileString()); if (!file.isAbsolute() && outFilepath != null) { file = new File(outFilepath + File.separator + uri.toFileString()); } String parent = file.getParent(); if (parent != null) { new File(parent).mkdirs(); } OutputStream outputStream = new FileOutputStream(file); return outputStream; } }