/******************************************************************************* * Copyright 2011 Google Inc. All Rights Reserved. * * 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 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package com.google.gdt.eclipse.platform.launch; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Path; import org.eclipse.jst.server.core.IWebModule; import org.eclipse.osgi.util.NLS; import org.eclipse.wst.server.core.IModule; import org.eclipse.wst.server.core.IModuleType; import org.eclipse.wst.server.core.internal.ServerPlugin; import org.eclipse.wst.server.core.model.IModuleResource; import org.eclipse.wst.server.core.model.ModuleDelegate; import org.eclipse.wst.server.core.util.ModuleFile; import org.eclipse.wst.server.core.util.PublishHelper; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Publisher for WTP modules. */ // Added this annotation because of the use of the ServerPlugin class. @SuppressWarnings("restriction") public class WtpPublisher { private static final IPath[] PUBLISHING_IGNORE_PATHS = {new Path("WEB-INF").append("appengine-generated")}; // TODO remove private static final IPath WEB_INF_LIB_PATH = new Path("WEB-INF").append("lib"); /** * Publish the WST {@link IModule}s to the specified WAR directory. Note that the war directory * will be erased and then recreated based on the latest module contents. */ public static void publishModulesToWarDirectory(IProject project, IModule[] modules, IPath warDirectoryPath, boolean forceFullPublish, IProgressMonitor monitor) throws CoreException { File warDirectory = warDirectoryPath.toFile(); warDirectory.mkdirs(); // Use WTP's publishing mechanism to copy over any jst-type modules // over to the output war directory File tempFile = ServerPlugin.getInstance().getStateLocation().toFile(); PublishHelper helper = new PublishHelper(tempFile); List<IStatus> publishResult = new ArrayList<IStatus>(); for (IModule module : modules) { ModuleDelegate moduleDelegate = (ModuleDelegate) module.loadAdapter(ModuleDelegate.class, null); // Collect the general set of resources for the module ArrayList<IModuleResource> resources = new ArrayList<IModuleResource>(Arrays.asList(moduleDelegate.members())); // Allocate an ArrayList for "extra" resources, which are implied by // the general resources ArrayList<IModuleResource> extraResources = new ArrayList<IModuleResource>(); IModule[] children = null; IModuleType moduleType = module.getModuleType(); if (moduleType != null && "jst.web".equals(moduleType.getId())) { IWebModule webModule = (IWebModule) module.loadAdapter(IWebModule.class, null); if (webModule != null) { children = webModule.getModules(); } } // Examine the child modules of the current module if (children != null) { for (IModule child : children) { ModuleDelegate childModuleDelegate = (ModuleDelegate) child.loadAdapter(ModuleDelegate.class, null); IModuleResource[] mr = childModuleDelegate.members(); if ("jst.utility".equals(child.getModuleType().getId())) { /* * This type of module represents a dependent WTP "utility" project. We need to take the * resource for this module and package them up into a jar. * * Later, we'll copy the resulting jar over to the WEB-INF/lib folder. */ File jarFile = new File(tempFile, child.getName() + ".jar"); IStatus[] status = helper.publishZip(mr, new Path(jarFile.getAbsolutePath()), monitor); merge(publishResult, status); extraResources.add(new ModuleFile(jarFile, jarFile.getName(), WEB_INF_LIB_PATH)); } else if ("jst.appclient".equals(child.getModuleType().getId())) { /* * This is a strange type of module that represents those server runtime libaries with a * MainClass attribute defined in their MANIFEST file. For some reason, WTP's publishing * mechanism will not copy such libraries over automatically; we need to do it * explicitly. */ File file = mr[0].getAdapter(File.class); extraResources.add(new ModuleFile(file, file.getName(), WEB_INF_LIB_PATH)); } } } IStatus[] status; if (!forceFullPublish) { /* * First, publish over the main module, ignoring paths where the App Engine Development * server places artifacts that are useful from session-to-session. */ status = helper.publishSmart(resources.toArray(new IModuleResource[resources.size()]), warDirectoryPath, PUBLISHING_IGNORE_PATHS, monitor); } else { /* * For speed tracer */ status = helper.publishFull(resources.toArray(new IModuleResource[resources.size()]), warDirectoryPath, monitor); } merge(publishResult, status); /* * If we have any resources that are the result of child modules, then do a straight copy of * them (i.e. no smart publishing - in fact, trying to publish these resources using * smartPublish will not work; the resources have not been constructed in the form that * smartPublish expects). */ if (extraResources.size() > 0) { status = helper.publishFull(extraResources.toArray((new IModuleResource[extraResources.size()])), warDirectoryPath, monitor); merge(publishResult, status); } } if (publishResult.size() > 0) { throw new CoreException(new MultiStatus("com.gwtplugins.gdt.eclipse.platform.shared", 0, publishResult.toArray(new IStatus[publishResult.size()]), NLS.bind("Publishing of ''{0}'' failed", project.getName()), null)); } } private static void merge(List<IStatus> result, IStatus[] status) { if (result == null || status == null || status.length == 0) { return; } int size = status.length; for (int i = 0; i < size; i++) { result.add(status[i]); } } }