| /******************************************************************************* |
| * Copyright (c) 2005, 2011 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 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 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 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); |
| |
| 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); |
| } |
| |
| public String toString() { |
| return "ModulePublishInfo [" + moduleId + "]"; |
| } |
| } |