| /******************************************************************************* |
| * Copyright (c) 2000, 2009 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.update.internal.core; |
| |
| import org.eclipse.update.core.FeatureContentProvider; |
| |
| import java.io.File; |
| import java.io.FileFilter; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.update.core.BaseSiteFactory; |
| import org.eclipse.update.core.ContentReference; |
| import org.eclipse.update.core.Feature; |
| import org.eclipse.update.core.ISite; |
| import org.eclipse.update.core.JarContentReference; |
| import org.eclipse.update.core.PluginEntry; |
| import org.eclipse.update.core.Site; |
| import org.eclipse.update.core.SiteContentProvider; |
| import org.eclipse.update.core.SiteFeatureReferenceModel; |
| import org.eclipse.update.core.Utilities; |
| import org.eclipse.update.core.model.ArchiveReferenceModel; |
| import org.eclipse.update.core.model.InvalidSiteTypeException; |
| import org.eclipse.update.core.model.SiteModel; |
| import org.eclipse.update.core.model.SiteModelFactory; |
| import org.eclipse.update.internal.model.BundleManifest; |
| import org.eclipse.update.internal.model.DefaultPluginParser; |
| import org.xml.sax.SAXException; |
| |
| public class SiteFileFactory extends BaseSiteFactory { |
| |
| // private when parsing file system |
| private SiteFile site; |
| |
| /* |
| * @see ISiteFactory#createSite(URL,boolean) |
| */ |
| public ISite createSite(URL url) throws CoreException, InvalidSiteTypeException { |
| |
| Site site = null; |
| InputStream siteStream = null; |
| SiteModelFactory factory = this; |
| |
| try { |
| // if url points to a directory |
| // attempt to parse site.xml |
| String path = url.getFile(); |
| File siteLocation = new File(path); |
| if (siteLocation.isDirectory()) { |
| url = siteLocation.toURL(); |
| File siteXMLFile = new File(siteLocation, Site.SITE_XML); |
| if (siteXMLFile.exists()) { |
| siteStream = new FileInputStream(siteXMLFile); |
| site = (Site) factory.parseSite(siteStream); |
| } else { |
| // parse siteLocation |
| site = parseSite(siteLocation); |
| } |
| } else { |
| // we are not pointing to a directory |
| // attempt to parse the file |
| try { |
| URL resolvedURL = URLEncoder.encode(url); |
| siteStream = openStream(resolvedURL); |
| site = (Site) factory.parseSite(siteStream); |
| } catch (IOException e) { |
| |
| // attempt to parse parent directory |
| File file = new File(url.getFile()); |
| File parentDirectory = file.getParentFile(); |
| |
| // do not create directory if it doesn't exist [18318] |
| // instead hrow error |
| if (parentDirectory != null && !parentDirectory.exists()) |
| throw Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_DirectoryDoesNotExist, (new String[] {file.getAbsolutePath()})), null); |
| |
| if (parentDirectory == null || !parentDirectory.isDirectory()) |
| throw Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_UnableToObtainParentDirectory, (new String[] {file.getAbsolutePath()})), null); |
| |
| site = parseSite(parentDirectory); |
| |
| } |
| } |
| |
| SiteContentProvider contentProvider = new SiteFileContentProvider(url); |
| site.setSiteContentProvider(contentProvider); |
| contentProvider.setSite(site); |
| site.resolve(url, url); |
| |
| // Do not set read only as may install in it |
| //site.markReadOnly(); |
| } catch (MalformedURLException e) { |
| throw Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_UnableToCreateURL, (new String[] {url == null ? "" : url.toExternalForm()})), e); //$NON-NLS-1$ |
| } catch (IOException e) { |
| throw Utilities.newCoreException(Messages.SiteFileFactory_UnableToAccessSite, ISite.SITE_ACCESS_EXCEPTION, e); |
| } finally { |
| try { |
| if (siteStream != null) |
| siteStream.close(); |
| } catch (IOException e) { |
| } |
| } |
| return site; |
| } |
| |
| /** |
| * Method parseSite. |
| */ |
| private Site parseSite(File directory) throws CoreException { |
| |
| this.site = (SiteFile) createSiteMapModel(); |
| |
| if (!directory.exists()) |
| throw Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_FileDoesNotExist, (new String[] {directory.getAbsolutePath()})), null); |
| |
| File pluginPath = new File(directory, Site.DEFAULT_PLUGIN_PATH); |
| |
| //PACKAGED |
| try { |
| parsePackagedFeature(directory); // in case it contains JAR files |
| } catch (EmptyDirectoryException ede) { |
| UpdateCore.log(ede.getStatus()); |
| } |
| |
| try { |
| parsePackagedPlugins(pluginPath); |
| } catch (EmptyDirectoryException ede) { |
| UpdateCore.log(ede.getStatus()); |
| } |
| |
| // INSTALLED |
| try { |
| parseInstalledFeature(directory); |
| } catch (EmptyDirectoryException ede) { |
| UpdateCore.log(ede.getStatus()); |
| } |
| |
| try { |
| parseInstalledPlugins(pluginPath); |
| } catch (EmptyDirectoryException ede) { |
| UpdateCore.log(ede.getStatus()); |
| } |
| |
| return site; |
| |
| } |
| |
| /** |
| * Method parseFeature. |
| * @throws CoreException |
| */ |
| private void parseInstalledFeature(File directory) throws CoreException { |
| |
| File featureDir = new File(directory, Site.DEFAULT_INSTALLED_FEATURE_PATH); |
| if (featureDir.exists()) { |
| String[] dir; |
| SiteFeatureReferenceModel featureRef; |
| URL featureURL; |
| File currentFeatureDir; |
| String newFilePath = null; |
| |
| try { |
| // handle the installed featuresConfigured under featuresConfigured subdirectory |
| dir = featureDir.list(); |
| if (dir == null) { |
| throw new EmptyDirectoryException(new Status(IStatus.WARNING, UpdateCore.getPlugin().getBundle().getSymbolicName(), IStatus.OK, directory.getName() + File.separator + directory.getName() + "directory is empty", null)); //$NON-NLS-1$ |
| } |
| for (int index = 0; index < dir.length; index++) { |
| |
| // the URL must ends with '/' for the bundle to be resolved |
| newFilePath = dir[index] + (dir[index].endsWith("/") ? "/" : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| currentFeatureDir = new File(featureDir, newFilePath); |
| // check if feature.xml exists |
| File featureXMLFile = new File(currentFeatureDir, Feature.FEATURE_XML); |
| if (!featureXMLFile.exists()) { |
| UpdateCore.warn("Unable to find feature.xml in directory:" + currentFeatureDir); //$NON-NLS-1$ |
| } else { |
| // PERF: remove code |
| //SiteFileFactory archiveFactory = new SiteFileFactory(); |
| featureURL = currentFeatureDir.toURL(); |
| featureRef = createFeatureReferenceModel(); |
| featureRef.setSiteModel(site); |
| featureRef.setURLString(featureURL.toExternalForm()); |
| featureRef.setType(ISite.DEFAULT_INSTALLED_FEATURE_TYPE); |
| ((Site) site).addFeatureReferenceModel(featureRef); |
| } |
| } |
| } catch (MalformedURLException e) { |
| throw Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_UnableToCreateURLForFile, (new String[] {newFilePath})), e); |
| } |
| } |
| } |
| |
| /** |
| * Method parseFeature. |
| * @throws CoreException |
| */ |
| private void parsePackagedFeature(File directory) throws CoreException { |
| |
| // FEATURES |
| File featureDir = new File(directory, Site.DEFAULT_FEATURE_PATH); |
| if (featureDir.exists()) { |
| String[] dir; |
| SiteFeatureReferenceModel featureRef; |
| URL featureURL; |
| File currentFeatureFile; |
| String newFilePath = null; |
| |
| try { |
| // only list JAR files |
| dir = featureDir.list(FeaturePackagedContentProvider.filter); |
| if (dir == null) { |
| throw new EmptyDirectoryException(new Status(IStatus.WARNING, UpdateCore.getPlugin().getBundle().getSymbolicName(), IStatus.OK, directory.getName() + File.separator + directory.getName() + "directory is empty", null)); //$NON-NLS-1$ |
| } |
| |
| for (int index = 0; index < dir.length; index++) { |
| |
| // check if the JAR file contains a feature.xml |
| currentFeatureFile = new File(featureDir, dir[index]); |
| JarContentReference ref = new JarContentReference("", currentFeatureFile); //$NON-NLS-1$ |
| ContentReference result = null; |
| try { |
| result = ref.peek(Feature.FEATURE_XML, null, null); |
| } catch (IOException e) { |
| UpdateCore.warn("Exception retrieving feature.xml in file:" + currentFeatureFile, e); //$NON-NLS-1$ |
| } |
| if (result == null) { |
| UpdateCore.warn("Unable to find feature.xml in file:" + currentFeatureFile); //$NON-NLS-1$ |
| } else { |
| featureURL = currentFeatureFile.toURL(); |
| // PERF: remove code |
| //SiteFileFactory archiveFactory = new SiteFileFactory(); |
| featureRef = createFeatureReferenceModel(); |
| featureRef.setSiteModel(site); |
| featureRef.setURLString(featureURL.toExternalForm()); |
| featureRef.setType(ISite.DEFAULT_PACKAGED_FEATURE_TYPE); |
| site.addFeatureReferenceModel(featureRef); |
| } |
| } |
| } catch (MalformedURLException e) { |
| throw Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_UnableToCreateURLForFile, (new String[] {newFilePath})), e); |
| } |
| } |
| } |
| |
| /** |
| * Method parsePlugins. |
| * |
| * look into each plugin/fragment directory, crack the plugin.xml open (or |
| * fragment.xml ???) get id and version, calculate URL... |
| * |
| * @throws CoreException |
| */ |
| private void parseInstalledPlugins(File pluginsDir) throws CoreException { |
| if (!pluginsDir.exists() || !pluginsDir.isDirectory()) { |
| return; |
| } |
| File[] dirs = pluginsDir.listFiles(new FileFilter() { |
| public boolean accept(File f) { |
| return f.isDirectory(); |
| } |
| }); |
| DefaultPluginParser parser = new DefaultPluginParser(); |
| |
| if (dirs == null) { |
| throw new EmptyDirectoryException(new Status(IStatus.WARNING, UpdateCore.getPlugin().getBundle().getSymbolicName(), IStatus.OK, pluginsDir.getName() + File.separator + pluginsDir.getName() + "directory is empty", null)); //$NON-NLS-1$ |
| } |
| for (int i = 0; i < dirs.length; i++) { |
| File pluginFile = new File(dirs[i], "META-INF/MANIFEST.MF"); //$NON-NLS-1$ |
| InputStream in = null; |
| try { |
| BundleManifest bundleManifest = new BundleManifest(pluginFile); |
| if (bundleManifest.exists()) { |
| PluginEntry entry = bundleManifest.getPluginEntry(); |
| addParsedPlugin(entry, dirs[i]); |
| } else { |
| if (!(pluginFile = new File(dirs[i], "plugin.xml")) //$NON-NLS-1$ |
| .exists()) { |
| pluginFile = new File(dirs[i], "fragment.xml"); //$NON-NLS-1$ |
| } |
| if (pluginFile != null && pluginFile.exists() && !pluginFile.isDirectory()) { |
| in = new FileInputStream(pluginFile); |
| PluginEntry entry = parser.parse(in); |
| addParsedPlugin(entry, dirs[i]); |
| } |
| } |
| } catch (IOException e) { |
| String pluginFileString = (pluginFile == null) ? null : pluginFile.getAbsolutePath(); |
| UpdateCore.log(Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_ErrorAccessing, (new String[] {pluginFileString})), e)); |
| } catch (SAXException e) { |
| String pluginFileString = (pluginFile == null) ? null : pluginFile.getAbsolutePath(); |
| UpdateCore.log(Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_ErrorParsingFile, (new String[] {pluginFileString})), e)); |
| } finally { |
| if (in != null) { |
| try { |
| in.close(); |
| } catch (IOException e) { |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * transform each Plugin and Fragment into an ArchiveReferenceModel |
| * and a PluginEntry for the Site |
| */ |
| // PERF: removed intermediate Plugin object |
| private void addParsedPlugin(PluginEntry entry, File file) throws CoreException { |
| |
| String location = null; |
| try { |
| if (entry != null) { |
| |
| // create the plugin Entry |
| ((Site) site).addPluginEntry(entry); |
| |
| // Create the Site mapping ArchiveRef->PluginEntry |
| // the id of the archiveRef is plugins\<pluginid>_<ver>.jar as per the specs |
| // PERF: remove code |
| //SiteFileFactory archiveFactory = new SiteFileFactory(); |
| ArchiveReferenceModel archive = createArchiveReferenceModel(); |
| String id = (entry.getVersionedIdentifier().toString()); |
| String pluginID = Site.DEFAULT_PLUGIN_PATH + id + FeatureContentProvider.JAR_EXTENSION; |
| archive.setPath(pluginID); |
| location = file.toURL().toExternalForm(); |
| archive.setURLString(location); |
| ((Site) site).addArchiveReferenceModel(archive); |
| |
| // TRACE |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_PARSING) { |
| UpdateCore.debug("Added archive to site:" + pluginID + " pointing to: " + location); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| } catch (MalformedURLException e) { |
| throw Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_UnableToCreateURLForFile, (new String[] {location})), e); |
| } |
| } |
| |
| /** |
| * |
| */ |
| private void parsePackagedPlugins(File pluginDir) throws CoreException { |
| if (!pluginDir.exists()) { |
| return; |
| } |
| String[] dir = pluginDir.list(FeaturePackagedContentProvider.filter); |
| |
| if (dir == null) { |
| throw new EmptyDirectoryException(new Status(IStatus.WARNING, UpdateCore.getPlugin().getBundle().getSymbolicName(), IStatus.OK, pluginDir.getName() + File.separator + pluginDir.getName() + "directory is empty", null)); //$NON-NLS-1$ |
| } |
| for (int i = 0; i < dir.length; i++) { |
| ContentReference ref = null; |
| String refString = null; |
| InputStream in = null; |
| JarContentReference jarReference = null; |
| try { |
| File file = new File(pluginDir, dir[i]); |
| jarReference = new JarContentReference(null, file); |
| ref = jarReference.peek("META-INF/MANIFEST.MF", null, null); //$NON-NLS-1$ |
| if (ref != null) { |
| in = ref.getInputStream(); |
| BundleManifest manifest = new BundleManifest(in); |
| if (manifest.exists()) { |
| |
| addParsedPlugin(manifest.getPluginEntry(), file); |
| continue; |
| } |
| } |
| ref = jarReference.peek("plugin.xml", null, null);//$NON-NLS-1$ |
| if (ref == null) { |
| ref = jarReference.peek("fragment.xml", null, null); //$NON-NLS-1$ |
| } |
| if (ref != null) { |
| in = ref.getInputStream(); |
| PluginEntry entry = new DefaultPluginParser().parse(in); |
| addParsedPlugin(entry, file); |
| } |
| } catch (Exception e) { |
| try { |
| refString = (ref == null) ? null : ref.asURL().toExternalForm(); |
| } catch (IOException ioe) { |
| } |
| |
| String message; |
| |
| if (e instanceof IOException) { |
| message = NLS.bind(Messages.SiteFileFactory_ErrorAccessing, (new String[] {refString})); |
| } else if (e instanceof SAXException) { |
| message = NLS.bind(Messages.SiteFileFactory_ErrorParsingFile, (new String[] {refString})); |
| } else { |
| message = NLS.bind(Messages.SiteFileFactory_ErrorAccessing, (new String[] {refString})); |
| }// end if |
| |
| // Log exception, but do not throw to caller. |
| // Continue with processing remaining plug-ins |
| UpdateCore.log(message, e); |
| } finally { |
| if (in != null) { |
| try { |
| in.close(); |
| } catch (IOException ce) { |
| } |
| } |
| if (jarReference != null) { |
| try { |
| jarReference.closeArchive(); |
| } catch (IOException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } |
| } |
| } |
| } |
| } |
| |
| /* |
| * @see SiteModelFactory#createSiteMapModel() |
| */ |
| public SiteModel createSiteMapModel() { |
| return new SiteFile(); |
| } |
| |
| /* |
| * @see SiteModelFactory#canParseSiteType(String) |
| */ |
| public boolean canParseSiteType(String type) { |
| return (super.canParseSiteType(type) || SiteFileContentProvider.SITE_TYPE.equalsIgnoreCase(type)); |
| } |
| |
| } |