/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.jsf.project.capabilities;
import java.io.File;
import java.io.IOException;
import java.util.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.osgi.util.NLS;
import org.jboss.tools.common.meta.action.impl.handlers.DefaultCreateHandler;
import org.jboss.tools.common.model.*;
import org.jboss.tools.common.model.filesystems.FileSystemsHelper;
import org.jboss.tools.common.model.filesystems.impl.Libs;
import org.jboss.tools.common.model.plugin.ModelPlugin;
import org.jboss.tools.common.model.util.EclipseResourceUtil;
import org.jboss.tools.common.model.util.XModelObjectLoaderUtil;
import org.jboss.tools.common.util.FileUtil;
import org.jboss.tools.jsf.JSFModelPlugin;
import org.jboss.tools.jsf.messages.JSFUIMessages;
import org.jboss.tools.jst.web.project.WebProject;
import org.jboss.tools.jst.web.project.helpers.*;
public class LibrariesPerformer extends PerformerItem {
XModel model;
XModelObject lib;
IContainer libResource;
JarPerformer[] jarPerformers;
IFile[] conflictingFiles;
public LibrariesPerformer() {}
public String getDisplayName() {
return "Libraries";
}
public IPerformerItem[] getChildren() {
return jarPerformers;
}
public void init(XModel model, XModelObject[] libraryReferences, XModelObject[] conflictingLibraryReferences) {
this.model = model;
lib = model.getByPath("FileSystems/lib");
if(lib == null) {
XModelObject webinf = FileSystemsHelper.getWebInf(model);
if(webinf != null) lib = webinf.getChildByPath("lib");
}
if(lib != null) libResource = (IContainer)EclipseResourceUtil.getResource(lib);
ArrayList<LibrarySet> l = new ArrayList<LibrarySet>();
for (int i = 0; i < libraryReferences.length; i++) {
String n = libraryReferences[i].getAttributeValue("name");
LibrarySet set = LibrarySets.getInstance().getLibrarySet(n);
if(set != null) l.add(set);
}
LibrarySet[] sets = l.toArray(new LibrarySet[0]);
ArrayList<JarPerformer> l2 = new ArrayList<JarPerformer>();
for (int i = 0; i < sets.length; i++) {
File libraryTemplateRoot = new File(sets[i].getPath());
if(!libraryTemplateRoot.isDirectory()) continue;
String[] ss = sets[i].getJarList();
for (int j = 0; j < ss.length; j++) {
JarPerformer p = new JarPerformer();
p.setParent(this);
p.init(model, sets[i], ss[j]);
l2.add(p);
}
File[] zs = getZipList(sets[i]);
for (int j = 0; j < zs.length; j++) {
JarPerformer p = new JarPerformer();
p.setParent(this);
p.init(model, sets[i], zs[j].getName());
l2.add(p);
}
}
jarPerformers = l2.toArray(new JarPerformer[0]);
conflictingFiles = null;
IContainer r = lib == null ? null : (IContainer)lib.getAdapter(IResource.class);
if(conflictingLibraryReferences != null && lib != null && r != null) {
ArrayList<IFile> cfjs = new ArrayList<IFile>();
for (int i = 0; i < conflictingLibraryReferences.length; i++) {
String name = conflictingLibraryReferences[i].getAttributeValue("name");
collectFiles(r, name, cfjs);
}
conflictingFiles = cfjs.toArray(new IFile[0]);
}
}
private void collectFiles(IContainer r, String name, ArrayList<IFile> cfjs) {
int wildcard = name.indexOf('*');
if(wildcard < 0) {
IFile f = r.getFile(new Path(name));
if(f.exists()) cfjs.add(f);
} else {
IResource[] rs = null;
try {
rs = r.members();
} catch (CoreException e) {
ModelPlugin.getPluginLog().logError(e);
}
if(rs != null) {
String prefix = name.substring(0, wildcard);
String suffix = name.substring(wildcard);
for (int i = 0; i < rs.length; i++) {
if(!(rs[i] instanceof IFile)) continue;
String n = rs[i].getName();
if(prefix.length() > 0 && !n.startsWith(prefix)) continue;
if(suffix.length() > 0 && !n.endsWith(suffix)) continue;
cfjs.add((IFile)rs[i]);
}
}
}
}
public boolean check(PerformerContext context) {
if(!isSelected()) return true;
if(libResource == null) return false;
ServiceDialog d = model.getService();
if(conflictingFiles != null && conflictingFiles.length > 0) {
String message = NLS.bind(JSFUIMessages.PROJECT_HAS_COFLICTING_LIBRARIES, conflictingFiles[0].getName() );
int q = d.showDialog(JSFUIMessages.WARNING, message, new String[]{JSFUIMessages.YES, JSFUIMessages.NO, JSFUIMessages.CANCEL}, null, ServiceDialog.WARNING);
if(q == 2) {
return false;
}
if(q == 1) {
conflictingFiles = null;
if(jarPerformers != null) for (int i = 0; i < jarPerformers.length; i++) jarPerformers[i].setSelected(false);
return true;
}
}
String[] existing = getExistingJars();
if(existing.length == 0) return true;
String message;
if(existing.length > 1)
message = NLS.bind(JSFUIMessages.PROJECT_ALREADY_HAS_SOME_OF_LIBRARIES_INCLUDED_2, existing[0], "" + (existing.length-1) );
else
message = NLS.bind(JSFUIMessages.PROJECT_ALREADY_HAS_SOME_OF_LIBRARIES_INCLUDED, existing[0]);
int q = d.showDialog(JSFUIMessages.WARNING, message, new String[]{JSFUIMessages.OVERWRITE, JSFUIMessages.CANCEL}, null, ServiceDialog.WARNING);
return q == 0;
}
private String[] getExistingJars() {
ArrayList<String> l = new ArrayList<String>();
for (int i = 0; i < jarPerformers.length; i++) {
if(!jarPerformers[i].isSelected()) continue;
IResource r = libResource.findMember(jarPerformers[i].jar);
if(r != null && r.exists()) l.add(jarPerformers[i].jar);
}
return l.toArray(new String[0]);
}
public boolean execute(PerformerContext context) throws XModelException {
if(!isSelected()) return true;
boolean changed = false;
boolean zip = false;
XModelObject fss = FileSystemsHelper.getFileSystems(model);
File location = libResource.getLocation().toFile();
String libName = null;
XModelObject webinf = FileSystemsHelper.getWebInf(model);
File webInfDir = ((IResource)webinf.getAdapter(IResource.class)).getLocation().toFile();
libName = (location.getParentFile().equals(webInfDir))
? XModelConstants.WORKSPACE_REF + "/lib/" : location.getAbsolutePath().replace('\\', '/')+"/";
CapabilityPerformer pp = (CapabilityPerformer)getParent();
String capability = pp.capability.getAttributeValue("name");
for (int i = 0; i < jarPerformers.length; i++) {
if(!jarPerformers[i].isSelected()) continue;
context.monitor.worked(1);
LibrarySet set = jarPerformers[i].set;
File libraryTemplateRoot = new File(set.getPath());
if(!libraryTemplateRoot.isDirectory()) continue;
String ss = jarPerformers[i].jar;
File source = new File(libraryTemplateRoot, ss);
if(!source.isFile()) continue;
String n = source.getName();
if(n.endsWith(".jar")) {
File target = new File(location, ss);
String task = capability + ": " + "Added ";
String postfix = "to";
if(target.isFile()) {
task = capability + ": " + "Replaced ";
postfix = "in";
if(!target.delete()) continue;
}
FileUtil.copyFile(source, target, true);
changed = true;
String fsName = Libs.LIB_PREFIX + n;
if(fss.getChildByPath(fsName) == null) {
Properties fsProp = new Properties();
fsProp.setProperty("name", fsName);
fsProp.setProperty("location", libName + n);
fsProp.setProperty("info", "hidden=yes");
XModelObject fsJar = XModelObjectLoaderUtil.createValidObject(model, "FileSystemJar", fsProp);
if(fss.getChildByPath(fsJar.getPathPart()) == null) {
DefaultCreateHandler.addCreatedObject(fss, fsJar, false, -1);
}
}
context.changeList.add(task + n + " " + postfix + " WEB-INF/lib");
} else if(n.endsWith(".zip")) {
if(!source.isFile()) continue;
String webRoot = WebProject.getInstance(model).getWebRootLocation();
try {
FileUtil.unzip(new File(webRoot), source.getAbsolutePath());
} catch (IOException e) {
//ignore
}
zip = true;
context.changeList.add(capability + ": " + "Unpacked " + n + " to " + new File(webRoot).getName());
}
}
if(changed) {
try {
libResource.refreshLocal(IResource.DEPTH_INFINITE, null);
} catch (CoreException e) {
throw new XModelException(e);
}
model.save();
}
if(zip) {
IProject p = EclipseResourceUtil.getProject(model.getRoot());
if(p != null) try {
p.refreshLocal(IResource.DEPTH_INFINITE, null);
} catch (CoreException e) {
//ignore
}
}
if(conflictingFiles != null) {
for (int i = 0; i < conflictingFiles.length; i++) {
try {
conflictingFiles[i].delete(true, context.monitor);
context.changeList.add(capability + ": Removed " + conflictingFiles[i].getName() + " from WEB-INF/lib");
} catch (CoreException ce) {
JSFModelPlugin.getPluginLog().logError(ce);
}
}
}
context.monitor.worked(1);
return true;
}
private File[] getZipList(LibrarySet set) {
ArrayList<File> list = new ArrayList<File>();
String path = set.getPath();
File f = new File(path);
File[] fs = (f.isDirectory()) ? f.listFiles() : null;
if(fs != null) for (int i = 0; i < fs.length; i++) {
if(fs[i].getName().endsWith(".zip")) list.add(fs[i]);
}
return list.toArray(new File[0]);
}
}