| /******************************************************************************* |
| * 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; |
| } |
| } |