/******************************************************************************* * Copyright (c) 2005, 2013 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.wst.server.core.internal; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.util.*; import org.eclipse.core.runtime.*; import org.eclipse.wst.server.core.IModule; import org.eclipse.wst.server.core.IModuleType; import org.eclipse.wst.server.core.model.IModuleFile; import org.eclipse.wst.server.core.model.IModuleFolder; import org.eclipse.wst.server.core.model.IModuleResource; import org.eclipse.wst.server.core.model.IModuleResourceDelta; import org.eclipse.wst.server.core.model.ModuleDelegate; import org.eclipse.wst.server.core.util.ModuleFile; import org.eclipse.wst.server.core.util.ModuleFolder; /** * Publish information for a specific module on a specific server. */ public class ModulePublishInfo { private static final IModuleResource[] EMPTY_MODULE_RESOURCE = new IModuleResource[0]; private static final IModuleResourceDelta[] EMPTY_MODULE_RESOURCE_DELTA = new IModuleResourceDelta[0]; private static final String MODULE_ID = "module-ids"; private static final String NAME = "name"; private static final String MODULE_TYPE_ID = "module-type-id"; private static final String MODULE_TYPE_VERSION = "module-type-version"; private static final String MODULE_IS_EXTERNAL = "module-is-external"; private static final String STAMP = "stamp"; private static final String FILE = "file"; private static final String FOLDER = "folder"; private String moduleId; private String name; private IModuleResource[] resources = EMPTY_MODULE_RESOURCE; private IModuleType moduleType; private boolean isExternal; private boolean useCache; private IModuleResource[] currentResources = null; private IModuleResourceDelta[] delta = null; private boolean hasDelta; /** * ModulePublishInfo constructor. * * @param moduleId a module id * @param name the module's name * @param moduleType the module type */ public ModulePublishInfo(String moduleId, String name, IModuleType moduleType) { super(); this.moduleId = moduleId; this.name = name; this.moduleType = moduleType; } /** * ModulePublishInfo constructor. * * @param moduleId a module id * @param name the module's name * @param moduleType the module type */ public ModulePublishInfo(String moduleId, String name, IModuleType moduleType, boolean isExternal) { super(); this.moduleId = moduleId; this.name = name; this.moduleType = moduleType; this.isExternal = isExternal; } /** * ModulePublishInfo constructor. * * @param memento a memento */ public ModulePublishInfo(IMemento memento) { super(); load(memento); } /** * ModulePublishInfo constructor. * * @param in an input stream * @throws IOException if the load fails */ public ModulePublishInfo(DataInput in) throws IOException { super(); load(in); } public String getModuleId() { return moduleId; } public String getName() { return name; } public IModuleType getModuleType() { return moduleType; } public IModuleResource[] getResources() { return resources; } public void setResources(IModuleResource[] res) { resources = res; } /** * Used only for reading from WTP 1.x workspaces. */ protected void load(IMemento memento) { if (Trace.FINEST) { Trace.trace(Trace.STRING_FINEST, "Loading module publish info for: " + memento); } try { moduleId = memento.getString(MODULE_ID); name = memento.getString(NAME); String mt = memento.getString(MODULE_TYPE_ID); String mv = memento.getString(MODULE_TYPE_VERSION); if (mt != null && mt.length() > 0) moduleType = ModuleType.getModuleType(mt, mv); String isExternalStr = memento.getString(MODULE_IS_EXTERNAL); isExternal = Boolean.parseBoolean(isExternalStr); resources = loadResource(memento, new Path("")); } catch (Exception e) { if (Trace.WARNING) { Trace.trace(Trace.STRING_WARNING, "Could not load module publish info information", e); } } } /** * Used only for reading from WTP 1.x workspaces. */ protected IModuleResource[] loadResource(IMemento memento, IPath path) { if (memento == null) return EMPTY_MODULE_RESOURCE; List<IModuleResource> list = new ArrayList<IModuleResource>(10); // load files IMemento[] children = memento.getChildren(FILE); if (children != null) { int size = children.length; for (int i = 0; i < size; i++) { String name2 = children[i].getString(NAME); long stamp = Long.parseLong(children[i].getString(STAMP)); ModuleFile file = new ModuleFile(name2, path, stamp); list.add(file); } } // load folders children = memento.getChildren(FOLDER); if (children != null) { int size = children.length; for (int i = 0; i < size; i++) { String name2 = children[i].getString(NAME); ModuleFolder folder = new ModuleFolder(null, name2, path); folder.setMembers(loadResource(children[i], path.append(name2))); list.add(folder); } } IModuleResource[] resources2 = new IModuleResource[list.size()]; list.toArray(resources2); return resources2; } protected void load(DataInput in) throws IOException { if (Trace.FINEST) { Trace.trace(Trace.STRING_FINEST, "Loading module publish info"); } moduleId = in.readUTF(); byte b = in.readByte(); // 8? if ((b & 1) != 0) name = in.readUTF(); else name = null; if ((b & 2) != 0) { String mt = in.readUTF(); String mv = in.readUTF(); if (mt != null && mt.length() > 0) moduleType = ModuleType.getModuleType(mt, mv); } else moduleType = null; resources = loadResource(in, new Path("")); } private IModuleResource[] loadResource(DataInput in, IPath path) throws IOException { int size = in.readInt(); if (size > 1000000) throw new IOException("Folder capacity limit reached"); IModuleResource[] resources2 = new IModuleResource[size]; for (int i = 0; i < size; i++) { byte b = in.readByte(); if (b == 0) { String name2 = in.readUTF(); long stamp = in.readLong(); resources2[i] = new ModuleFile(name2, path, stamp); } else if (b == 1) { String name2 = in.readUTF(); ModuleFolder folder = new ModuleFolder(null, name2, path); folder.setMembers(loadResource(in, path.append(name2))); resources2[i] = folder; } } return resources2; } protected void save(DataOutput out) { try { out.writeUTF(moduleId); byte b = 0; if (name != null) b |= 1; if (moduleType != null) b |= 2; out.writeByte(b); if (name != null) out.writeUTF(name); if (moduleType != null) { out.writeUTF(moduleType.getId()); out.writeUTF(moduleType.getVersion()); } saveResource(out, resources); } catch (Exception e) { if (Trace.SEVERE) { Trace.trace(Trace.STRING_SEVERE, "Could not save module publish info", e); } } } protected void saveResource(DataOutput out, IModuleResource[] resources2) throws IOException { if (resources2 == null) return; int size = resources2.length; out.writeInt(size); for (int i = 0; i < size; i++) { if (resources2[i] instanceof IModuleFile) { IModuleFile file = (IModuleFile) resources2[i]; out.writeByte(0); out.writeUTF(file.getName()); out.writeLong(file.getModificationStamp()); } else { IModuleFolder folder = (IModuleFolder) resources2[i]; out.writeByte(1); out.writeUTF(folder.getName()); IModuleResource[] resources3 = folder.members(); saveResource(out, resources3); } } } /** * Start using the module cache. */ protected void startCaching() { useCache = true; currentResources = null; delta = null; hasDelta = false; } /** * Fill the module cache. * * @param module */ private void fillCache(IModule[] module) { if (!useCache) return; if (currentResources != null) return; try { long time = System.currentTimeMillis(); IModule m = module[module.length - 1]; ModuleDelegate pm = (ModuleDelegate) m.loadAdapter(ModuleDelegate.class, null); if (pm == null || (m.getProject() != null && !m.getProject().isAccessible())) currentResources = EMPTY_MODULE_RESOURCE; else currentResources = pm.members(); delta = ServerPublishInfo.getDelta(resources, currentResources); hasDelta = (delta != null && delta.length > 0); if (Trace.PERFORMANCE) { Trace.trace(Trace.STRING_PERFORMANCE, "Filling publish cache for " + m.getName() + ": " + (System.currentTimeMillis() - time)); } } catch (CoreException ce) { if (Trace.WARNING) { Trace.trace(Trace.STRING_WARNING, "Couldn't fill publish cache for " + module); } } if (delta == null) delta = EMPTY_MODULE_RESOURCE_DELTA; } protected void clearCache() { useCache = false; currentResources = null; delta = null; hasDelta = false; } protected IModuleResource[] getModuleResources(IModule[] module) { if (module == null) return EMPTY_MODULE_RESOURCE; if (useCache) { fillCache(module); return currentResources; } int size = module.length; IModule m = module[size - 1]; ModuleDelegate pm = (ModuleDelegate) m.loadAdapter(ModuleDelegate.class, null); if (pm == null || (m.getProject() != null && !m.getProject().isAccessible())) return EMPTY_MODULE_RESOURCE; try { long time = System.currentTimeMillis(); IModuleResource[] x = pm.members(); if (ServerPlugin.getInstance().isDebugging()) printModule(x,"resources: "); if (Trace.PERFORMANCE) { Trace.trace(Trace.STRING_PERFORMANCE, "Time to get members() for " + module[size - 1].getName() + ": " + (System.currentTimeMillis() - time)); } return x; } catch (CoreException ce) { if (Trace.WARNING) { Trace.trace(Trace.STRING_WARNING, "Possible failure in getModuleResources", ce); } } return EMPTY_MODULE_RESOURCE; } private void printModule(IModuleResource[] r, String s) { for (IModuleResource mrr : r) { printModule(mrr, s + " "); } } private void printModule(IModuleResource r, String s) { if (Trace.RESOURCES) { Trace.trace(Trace.STRING_RESOURCES, s + r.getName()); } if (r instanceof IModuleFolder) { IModuleFolder mf = (IModuleFolder) r; IModuleResource[] mr = mf.members(); for (IModuleResource mrr : mr) { printModule(mrr, s + " "); } } } protected IModuleResourceDelta[] getDelta(IModule[] module) { if (module == null) return EMPTY_MODULE_RESOURCE_DELTA; if (useCache) { fillCache(module); return delta; } IModule m = module[module.length - 1]; ModuleDelegate pm = (ModuleDelegate) m.loadAdapter(ModuleDelegate.class, null); if (pm == null || (m.getProject() != null && !m.getProject().isAccessible())) return EMPTY_MODULE_RESOURCE_DELTA; IModuleResource[] resources2 = null; try { resources2 = pm.members(); printModule(resources2, "delta:"); } catch (CoreException ce) { if (Trace.WARNING) { Trace.trace(Trace.STRING_WARNING, "Possible failure in getDelta", ce); } } if (resources2 == null) resources2 = EMPTY_MODULE_RESOURCE; return ServerPublishInfo.getDelta(getResources(), resources2); } protected boolean hasDelta(IModule[] module) { if (module == null) return false; if (useCache) { fillCache(module); return hasDelta; } IModule m = module[module.length - 1]; ModuleDelegate pm = (ModuleDelegate) m.loadAdapter(ModuleDelegate.class, null); IModuleResource[] resources2 = null; if (pm == null || (m.getProject() != null && !m.getProject().isAccessible())) return false; try { resources2 = pm.members(); } catch (CoreException ce) { if (Trace.WARNING) { Trace.trace(Trace.STRING_WARNING, "Possible failure in hasDelta", ce); } } if (resources2 == null) resources2 = EMPTY_MODULE_RESOURCE; return ServerPublishInfo.hasDelta(getResources(), resources2); } public void fill(IModule[] module) { if (module == null) return; if (useCache) { fillCache(module); setResources(currentResources); return; } IModule m = module[module.length - 1]; ModuleDelegate pm = (ModuleDelegate) m.loadAdapter(ModuleDelegate.class, null); if (pm == null || (m.getProject() != null && !m.getProject().isAccessible())) { setResources(EMPTY_MODULE_RESOURCE); return; } try { setResources(pm.members()); } catch (CoreException ce) { if (Trace.WARNING) { Trace.trace(Trace.STRING_WARNING, "Possible failure in fill", ce); } } } /** * Return a deleted module that represents this module. * * @return a module */ protected IModule getDeletedModule() { String id = moduleId; int index = id.lastIndexOf("#"); if (index > 0) id = id.substring(index+1); return new DeletedModule(id, name, moduleType, isExternal); } public String toString() { return "ModulePublishInfo [" + moduleId + "]"; } }