/******************************************************************************* * Copyright (c) 2001, 2005 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.strategy; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.jst.j2ee.commonarchivecore.internal.Archive; import org.eclipse.jst.j2ee.commonarchivecore.internal.CommonArchiveResourceHandler; import org.eclipse.jst.j2ee.commonarchivecore.internal.File; import org.eclipse.jst.j2ee.commonarchivecore.internal.ModuleFile; import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.SaveFailureException; import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveManifest; import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.FileIterator; import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.SaveFilter; import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.SaveFilterImpl; import org.eclipse.jst.j2ee.commonarchivecore.internal.util.ArchiveUtil; import org.eclipse.jst.j2ee.internal.J2EEConstants; import org.eclipse.wst.common.internal.emf.resource.CompatibilityXMIResource; import org.eclipse.wst.common.internal.emf.resource.TranslatorResource; import org.eclipse.wst.common.internal.emf.utilities.Revisit; /** * Abstract implementer off which any save strategy can subclass * * @see com.ibm.etools.archive.SaveStrategy */ public abstract class SaveStrategyImpl extends ArchiveStrategyImpl implements SaveStrategy { protected SaveFilter filter; /** * SaveStrategyImpl constructor comment. */ public SaveStrategyImpl() { super(); } /** * The default is to do nothing - subclasses should override as necessary */ public void close() throws java.io.IOException { //Default } protected abstract SaveStrategy createNestedSaveStrategy(Archive anArchive) throws java.io.IOException; /** * The default is to do nothing - subclasses should override as necessary */ public void finish() throws java.io.IOException { //Default } /** * Insert the method's description here. Creation date: (02/28/01 4:11:28 PM) * * @return com.ibm.etools.archive.SaveFilter */ public org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.SaveFilter getFilter() { if (filter == null) filter = new SaveFilterImpl(); return filter; } protected abstract OutputStream getOutputStreamForResource(Resource aResource) throws java.io.IOException; /** * @see com.ibm.etools.archive.SaveStrategy */ public boolean isDirectory() { return false; } protected boolean isLoadedResourceOrManifest(File aFile) { return getArchive().isMofResourceLoaded(aFile.getURI()) || aFile.getURI().equals(J2EEConstants.MANIFEST_URI); } public void save() throws SaveFailureException { saveManifest(); saveMofResources(); saveFiles(); } /** * @see com.ibm.etools.archive.SaveStrategy */ public void save(Archive anArchive) throws SaveFailureException { SaveStrategy strat = null; try { strat = createNestedSaveStrategy(anArchive); } catch (java.io.IOException iox) { throw new SaveFailureException(anArchive.getURI(), iox); } anArchive.save(strat); } /** * @see com.ibm.etools.archive.SaveStrategy */ public void save(File aFile, FileIterator iterator) throws SaveFailureException { if (aFile.isArchive() && shouldIterateOver((Archive) aFile)) save((Archive) aFile); else { InputStream in = null; if (!aFile.isDirectoryEntry()) { try { in = iterator.getInputStream(aFile); } catch (IOException ex) { throw new SaveFailureException(aFile.getURI(), ex); } } save(aFile, in); } } public abstract void save(File aFile, InputStream in) throws SaveFailureException; protected void saveFiles() throws SaveFailureException { try { FileIterator iterator = getArchive().getFilesForSave(); while (iterator.hasNext()) { File aFile = iterator.next(); if (shouldSave(aFile)) save(aFile, iterator); } } catch (IOException iox) { throw new SaveFailureException(CommonArchiveResourceHandler.Error_occurred_iterating_f_EXC_, iox); // = "Error occurred iterating files" } } protected void saveManifest() throws SaveFailureException { if (!shouldSave(J2EEConstants.MANIFEST_URI)) return; ArchiveManifest mf = getArchive().getManifest(); if (mf.getManifestVersion() == null || mf.getManifestVersion().equals(""))//$NON-NLS-1$ mf.setManifestVersion("1.0");//$NON-NLS-1$ save(mf); } /** * @see com.ibm.etools.archive.SaveStrategy */ public void saveMofResource(org.eclipse.emf.ecore.resource.Resource aResource) throws SaveFailureException { if (!shouldSave(aResource)) return; setEncoding(aResource); try { boolean wasModified = aResource.isModified(); OutputStream os = getOutputStreamForResource(aResource); saveMofResource(aResource, os); aResource.setModified(wasModified); } catch (Exception e) { throw new SaveFailureException(aResource.getURI().toString(), e); } } /** * @see com.ibm.etools.archive.SaveStrategy */ protected void saveMofResource(org.eclipse.emf.ecore.resource.Resource aResource, OutputStream os) throws IOException { aResource.save(os, Collections.EMPTY_MAP); } protected void saveMofResources() throws SaveFailureException { Iterator iterator = getArchive().getLoadedMofResources().iterator(); //We have to go through this process because java resources could get added during the //process of iterating and saving, and adding to a collection while iterating causes a // failure List xmiResources = new ArrayList(); //We will save the xmi resources first, then the xml resources. This way the //any necessary id's for referenced objects will have been generated prior to save List xmlResources = new ArrayList(); Resource res = null; while (iterator.hasNext()) { res = (Resource) iterator.next(); // We don't want to save the java reflection resources or uri mapped resources if (!ArchiveUtil.isJavaResource(res) && !ArchiveUtil.isRegisteredURIMapping(res) && !ArchiveUtil.isPlatformMetaResource(res)) { Revisit.revisit(); //For now, always use the mof5 format if (res instanceof CompatibilityXMIResource) ((CompatibilityXMIResource) res).setFormat(CompatibilityXMIResource.FORMAT_MOF5); if (res instanceof TranslatorResource) xmlResources.add(res); else { xmiResources.add(res); } } } basicSaveMofResources(xmiResources); basicSaveMofResources(xmlResources); } protected void basicSaveMofResources(List resources) throws SaveFailureException { Resource res = null; for (int i = 0; i < resources.size(); i++) { res = (Resource) resources.get(i); saveMofResource(res); } } protected void setEncoding(Resource aResource) { if (aResource instanceof org.eclipse.emf.ecore.xmi.XMLResource) ((org.eclipse.emf.ecore.xmi.XMLResource) aResource).setEncoding(archive.getXmlEncoding()); } /** * Insert the method's description here. Creation date: (02/28/01 4:11:28 PM) * * @param newFilter * com.ibm.etools.archive.SaveFilter */ public void setFilter(org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.SaveFilter newFilter) { filter = newFilter; } /** * Answer whether the nested archive needs to be saved one file at a time, or if we can bulk * save it from the original */ protected boolean shouldIterateOver(Archive anArchive) { return anArchive.getLoadStrategy().requiresIterationOnSave(); } protected boolean shouldSave(File aFile) { boolean loaded = isLoadedResourceOrManifest(aFile); if (loaded) { Resource res = archive.getLoadStrategy().getExistingMofResource(aFile.getURI()); if (res == null) return false; //must be manifest return !shouldSave(res); } if (getArchive().isModuleFile()) { ModuleFile m = (ModuleFile) getArchive(); if (m.getExportStrategy() != null && m.getExportStrategy().hasSaved(aFile.getURI())) return false; } return shouldSave(aFile.getURI()); } protected boolean shouldSave(Resource res) { if (!res.isModified() && getArchive().getOptions().saveOnlyDirtyMofResources()) return false; return shouldSave(res.getURI().toString()); } /** * This is the one method through which all elements of an archive (file, nested archive, mof * resource, or manifest) will be tested before saving. Subclasses can override to do something * more specific */ protected boolean shouldSave(String uri) { return getFilter().shouldSave(uri, getArchive()); } }