/******************************************************************************* * Copyright (c) 2001, 2008 Oracle 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: * Oracle Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jst.jsf.designtime.internal.view.model.jsp.persistence; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.Path; import org.eclipse.jst.jsf.core.internal.JSFCorePlugin; import org.eclipse.jst.jsf.core.internal.JSFCoreTraceOptions; import org.osgi.framework.Version; /** * The definitive index of what projects are indexed for JSP tag registry * persistence. * * @author cbateman * */ class MasterIndex implements Serializable { public final static SerializableVersion CURRENT_VERSION = new SerializableVersion( 1, 0, 0); /** * */ private static final long serialVersionUID = -2725662604972649316L; private final transient String _repositoryPath; private final transient File _storageFile; private IndexHeader _header; private List<ProjectIndex> _projectIndices; public MasterIndex(final File storageFile, final String repositoryPath) { _storageFile = storageFile; _repositoryPath = repositoryPath; } public synchronized void create(final SerializableVersion version) throws IOException { if (JSFCoreTraceOptions.TRACE_JSPTAGPERSISTENCE) { JSFCoreTraceOptions.log("MasterIndex.create, version=:" //$NON-NLS-1$ + version.toString()); } _header = new IndexHeader(version); _projectIndices = new ArrayList<ProjectIndex>(); save(_storageFile); } public synchronized void save(final File file) throws IOException { FileOutputStream out = null; try { if (JSFCoreTraceOptions.TRACE_JSPTAGPERSISTENCE) { JSFCoreTraceOptions.log("Trying to save master index file: " //$NON-NLS-1$ + file.getAbsolutePath()); } out = new FileOutputStream(file); final ObjectOutputStream objStream = new ObjectOutputStream(out); objStream.writeObject(this); if (JSFCoreTraceOptions.TRACE_JSPTAGPERSISTENCE) { JSFCoreTraceOptions .log("Master index file written successfully: " //$NON-NLS-1$ + file.getAbsolutePath()); } } finally { if (out != null) { out.close(); } } } public synchronized void load(final SerializableVersion expectedVersion) throws IOException, ClassNotFoundException { FileInputStream in = null; try { if (JSFCoreTraceOptions.TRACE_JSPTAGPERSISTENCE) { JSFCoreTraceOptions.log("Trying to load master index file: " //$NON-NLS-1$ + _storageFile.getAbsolutePath()); } in = new FileInputStream(_storageFile); final ObjectInputStream objStream = new ObjectInputStream(in); MasterIndex index = (MasterIndex) objStream.readObject(); _header = index._header; _projectIndices = index._projectIndices; if (JSFCoreTraceOptions.TRACE_JSPTAGPERSISTENCE) { JSFCoreTraceOptions .log("Loaded master index file successfully:" //$NON-NLS-1$ + _storageFile.getAbsolutePath()); JSFCoreTraceOptions.log("Initial contents: "); //$NON-NLS-1$ System.out.println(index.toString()); } } finally { if (in != null) { in.close(); } } } public synchronized String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(String.format("Header: %s\n\n", _header.toString())); //$NON-NLS-1$ for (final ProjectIndex projIndex : _projectIndices) { buffer.append(String.format("\t%s\n", projIndex.toString())); //$NON-NLS-1$ } return buffer.toString(); } public synchronized ProjectIndex getProjectIndex(final IProject project) { ProjectIndex index = findIndex(project); if (index != null) { return index; } // otherwise, create. index = new ProjectIndex(0, project.getName(), _repositoryPath); index.create(); _projectIndices.add(index); try { save(_storageFile); } catch (IOException ioe) { JSFCorePlugin.log(ioe, "Failed to save master index. Project Index for " //$NON-NLS-1$ + project.toString() + " may not be saved"); //$NON-NLS-1$ } return index; } public synchronized void removeProjectIndex(final IProject project) throws IOException { final ProjectIndex index = findIndex(project); if (index != null) { _projectIndices.remove(index); if (!index.remove()) { throw new IOException("Failed to remove index file"); //$NON-NLS-1$ } } } private ProjectIndex findIndex(final IProject project) { // check if the project already exists for (final ProjectIndex index : _projectIndices) { if (index.getProjectName().equals(project.getName())) { return index; } } return null; } private void writeObject(final java.io.ObjectOutputStream out) throws IOException { out.writeObject(_header); out.writeObject(_projectIndices); } private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { _header = (IndexHeader) in.readObject(); _projectIndices = (List<ProjectIndex>) in.readObject(); } private class IndexHeader implements Serializable { /** * serializable */ private static final long serialVersionUID = 40851054201507727L; private final SerializableVersion _version; // private long _lastModifiedStamp; public IndexHeader(final SerializableVersion version) { _version = version; // _lastModifiedStamp = 0; } // protected final Version getVersion() // { // return _version.getVersion(); // } // // protected final synchronized long modified() // { // return _lastModifiedStamp++; // } // // protected final synchronized long getLastModifiedStamp() // { // return _lastModifiedStamp; // } public String toString() { return "Version: " + _version.toString(); //$NON-NLS-1$ } } static class SerializableVersion implements Serializable { private Version _version; /** * */ private static final long serialVersionUID = 5973410328814890568L; public SerializableVersion(final int major, final int minor, final int micro) { _version = new Version(major, minor, micro); } public SerializableVersion(final String versionString) { _version = new Version(versionString); } public Version getVersion() { return _version; } public String toString() { return _version.toString(); } private void writeObject(ObjectOutputStream out) throws IOException { out.writeObject(_version.toString()); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { final String versionString = (String) in.readObject(); _version = new Version(versionString); } } static class ProjectIndex implements Serializable { /** * */ private static final long serialVersionUID = 2864798175910805380L; private final String _projectName; private final String _relativePath; private final long _lastModStampOnProject; private File _file; /** * @param lastModStampOnProject * @param projectName * @param relativePath */ public ProjectIndex(final long lastModStampOnProject, final String projectName, final String relativePath) { super(); _lastModStampOnProject = lastModStampOnProject; _projectName = projectName; _relativePath = relativePath; } public boolean remove() { return _file.delete(); } public synchronized void create() { final long uniqueCode = Math .round((Math.random() * Integer.MAX_VALUE)); final String fileName = String.format("Project_%s_%x.idx", //$NON-NLS-1$ _projectName, Long.valueOf(uniqueCode)); _file = new File(new Path(_relativePath).append(fileName) .toOSString()); } public synchronized Map<String, SerializableTLDNamespace> getNamespaces() throws IOException, ClassNotFoundException { FileInputStream in = null; try { in = new FileInputStream(_file); final ObjectInputStream objStream = new ObjectInputStream(in); final Map<String, SerializableTLDNamespace> namespaces = (Map<String, SerializableTLDNamespace>) objStream .readObject(); return namespaces; } catch (FileNotFoundException nfe) { return new HashMap<String, SerializableTLDNamespace>(); } finally { if (in != null) { in.close(); } } } public synchronized void save( final Map<String, SerializableTLDNamespace> namespaces) throws IOException { FileOutputStream out = null; try { out = new FileOutputStream(_file); final ObjectOutputStream objStream = new ObjectOutputStream(out); objStream.writeObject(namespaces); } finally { if (out != null) { out.close(); } } } public String toString() { return "project= " + _projectName + ", relativePath=" //$NON-NLS-1$ //$NON-NLS-2$ + _relativePath + ", lastModified=" //$NON-NLS-1$ + _lastModStampOnProject + ", saveFile=" + _file; //$NON-NLS-1$ } // public synchronized void save() // { // if (_file != null) // { // doSave(); // } // throw new NullPointerException("_file is null"); // } // // private void doSave() throws IOException // { // FileOutputStream out = null; // // try // { // out = new FileOutputStream(_file); // final ObjectOutputStream objStream = new ObjectOutputStream(out); // objStream.writeObject(this); // } // finally // { // if (out != null) // { // out.close(); // } // } // } protected final String getProjectName() { return _projectName; } protected final String getRelativePath() { return _relativePath; } protected final long getLastModStampOnProject() { return _lastModStampOnProject; } } }