/** * Aptana Studio * Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions). * Please see the license.html included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ package com.aptana.editor.php.internal.indexer; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import com.aptana.core.logging.IdeLog; import com.aptana.editor.php.PHPEditorPlugin; import com.aptana.editor.php.indexer.IEntryValueFactory; import com.aptana.editor.php.indexer.IPHPIndexConstants; import com.aptana.editor.php.indexer.IReportable; import com.aptana.editor.php.internal.core.builder.IBuildPath; import com.aptana.editor.php.internal.core.builder.IModule; public final class IndexPersistence { private static HashMap<Integer, IEntryValueFactory> factories = new HashMap<Integer, IEntryValueFactory>(); static { IConfigurationElement[] configurationElementsFor = Platform.getExtensionRegistry().getConfigurationElementsFor( "com.aptana.editor.php.indexerEntryValue"); //$NON-NLS-1$ for (IConfigurationElement e : configurationElementsFor) { String attribute = e.getAttribute("id"); //$NON-NLS-1$ try { IEntryValueFactory vf = (IEntryValueFactory) e.createExecutableExtension("creator"); //$NON-NLS-1$ factories.put(Integer.parseInt(attribute), vf); } catch (CoreException e1) { IdeLog.logError(PHPEditorPlugin.getDefault(), "Error loading indexer entry value", e1); //$NON-NLS-1$ } } } private IndexPersistence() { } public static void load(UnpackedElementIndex index, DataInputStream di, IBuildPath pb) throws IOException { int readInt = di.readInt(); // long l0=System.currentTimeMillis(); for (int a = 0; a < readInt; a++) { IModule m = readModule(di, pb); if (m != null) { int sz = di.readInt(); long ts = di.readLong(); index.recordTimeStamp(m, ts); for (int b = 0; b < sz; b++) { int category = di.readInt(); String path = di.readUTF(); Object value = readValue(di); index.addEntry(category, path, value, m); } } } // long l1=System.currentTimeMillis(); // System.out.println("Index load:"+(l1-l0)); } public static void store(UnpackedElementIndex index, DataOutputStream da, IBuildPath pb) throws IOException { IModule[] array = index.getAllModules(); da.writeInt(array.length); int pos = 0; for (IModule m : array) { if (m == null) { IdeLog.logWarning(PHPEditorPlugin.getDefault(), "Could not write a module to the PHP index. Module was null.", PHPEditorPlugin.INDEXER_SCOPE); //$NON-NLS-1$ continue; } List<UnpackedEntry> list = index.entries.get(m); if (list == null) { list = Collections.emptyList(); } writeModule(da, m, pb); da.writeInt(list.size()); da.writeLong(index.getTimeStamp(m)); int k = 0; for (UnpackedEntry e : new ArrayList<UnpackedEntry>(list)) { store(e, da); k++; } pos++; } } private static void store(UnpackedEntry entry, DataOutputStream da) throws IOException { String entryPath = entry.getEntryPath(); int category = entry.getCategory(); Object value = entry.getValue(); da.writeInt(category); da.writeUTF(entryPath); writeValue(da, value); } private static void writeValue(DataOutputStream da, Object value) throws IOException { if (value instanceof IReportable) { IReportable p = (IReportable) value; p.store(da); return; } throw new IllegalStateException("Illegal value:" + value); //$NON-NLS-1$ } private static Object readValue(DataInputStream di) throws IOException { int cat = di.readInt(); if (cat == IPHPIndexConstants.CLASS_CATEGORY) { return new ClassPHPEntryValue(di); } else if (cat == IPHPIndexConstants.VAR_CATEGORY) { return new VariablePHPEntryValue(di); } else if (cat == IPHPIndexConstants.FUNCTION_CATEGORY) { return new FunctionPHPEntryValue(di); } else if (cat == IPHPIndexConstants.IMPORT_CATEGORY) { return new IncludePHPEntryValue(di); } else if (cat == IPHPIndexConstants.LAMBDA_FUNCTION_CATEGORY) { return new LambdaFunctionPHPEntryValue(di); } IEntryValueFactory entryValueFactory = factories.get(cat); if (entryValueFactory != null) { return entryValueFactory.createValue(di); } else { throw new IOException("Index corrupted"); //$NON-NLS-1$ } } private static IModule readModule(DataInputStream di, IBuildPath pb) throws IOException { String readUTF = di.readUTF(); Path pa = new Path(readUTF); return pb.getModuleByPath(pa); } private static void writeModule(DataOutputStream da, IModule module, IBuildPath pb) throws IOException { String portableString = module.getPath().toPortableString(); da.writeUTF(portableString); } public static void writeTypeSet(Set<Object> types, DataOutputStream da) throws IOException { if (types == null) { da.writeInt(0); return; } da.writeInt(types.size()); for (Object o : types) { writeType(o, da); } } public static Set<Object> readTypeSet(DataInputStream di) throws IOException { int readInt = di.readInt(); if (readInt == 0) { return Collections.emptySet(); } if (readInt == 1) { return Collections.singleton(readType(di)); } Set<Object> t = new HashSet<Object>(readInt); for (int a = 0; a < readInt; a++) { t.add(readType(di)); } return t; } public static Object readType(DataInputStream di) throws IOException { int readInt = di.readInt(); if (readInt == -1) { return null; } if (readInt == 0) { return di.readUTF().intern(); } if (readInt == 1) { return AbstractPathReference.read(di); } if (readInt == 2) { int len = di.readInt(); Object[] result = new Object[len]; for (int a = 0; a < len; a++) { result[a] = readType(di); } return result; } throw new IllegalArgumentException("Unknown type " + readInt); //$NON-NLS-1$ } public static void writeType(Object type, DataOutputStream da) throws IOException { if (type == null) { da.writeInt(-1); return; } if (type instanceof String) { da.writeInt(0); da.writeUTF((String) type); return; } if (type instanceof AbstractPathReference) { da.writeInt(1); AbstractPathReference p = (AbstractPathReference) type; p.write(da); return; } if (type instanceof Object[]) { Object[] tps = (Object[]) type; da.writeInt(2); da.writeInt(tps.length); for (int a = 0; a < tps.length; a++) { writeType(tps[a], da); } return; } if (type instanceof Collection<?>) { Collection<?> col = (Collection<?>) type; da.writeInt(2); da.writeInt(col.size()); for (Object obj : col) { writeType(obj, da); } return; } throw new IllegalArgumentException("Unknown type " + type); //$NON-NLS-1$ } }