/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2009-2013 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html * or packager/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at packager/legal/LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package org.glassfish.javaee.core.deployment; import com.sun.enterprise.config.serverbeans.DasConfig; import com.sun.enterprise.config.serverbeans.Domain; import com.sun.enterprise.config.serverbeans.Module; import com.sun.enterprise.deploy.shared.ArchiveFactory; import com.sun.enterprise.deploy.shared.FileArchive; import com.sun.enterprise.deployment.Application; import com.sun.enterprise.deployment.BundleDescriptor; import com.sun.enterprise.deployment.WebBundleDescriptor; import com.sun.enterprise.deployment.archivist.*; import com.sun.enterprise.deployment.deploy.shared.DeploymentPlanArchive; import com.sun.enterprise.deployment.deploy.shared.InputJarArchive; import com.sun.enterprise.deployment.deploy.shared.Util; import com.sun.enterprise.deployment.util.DOLUtils; import com.sun.enterprise.util.LocalStringManagerImpl; import com.sun.enterprise.util.io.FileUtils; import com.sun.enterprise.v3.common.HTMLActionReporter; import org.glassfish.api.ActionReport; import org.glassfish.api.admin.ServerEnvironment; import org.glassfish.api.deployment.ApplicationMetaDataProvider; import org.glassfish.api.deployment.DeployCommandParameters; import org.glassfish.api.deployment.DeploymentContext; import org.glassfish.api.deployment.MetaData; import org.glassfish.api.deployment.archive.ArchiveHandler; import org.glassfish.api.deployment.archive.ReadableArchive; import org.glassfish.api.deployment.archive.WritableArchive; import org.glassfish.api.container.Sniffer; import org.glassfish.deployment.common.*; import org.glassfish.hk2.classmodel.reflect.Parser; import org.glassfish.hk2.classmodel.reflect.Types; import org.glassfish.internal.api.ClassLoaderHierarchy; import org.glassfish.internal.deployment.ApplicationInfoProvider; import org.glassfish.internal.deployment.Deployment; import org.glassfish.internal.deployment.DeploymentTracing; import org.glassfish.internal.deployment.ExtendedDeploymentContext; import org.jvnet.hk2.annotations.Service; import org.glassfish.hk2.api.PreDestroy; import org.xml.sax.SAXParseException; import javax.enterprise.deploy.shared.ModuleType; import javax.inject.Inject; import javax.inject.Provider; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.Collection; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; /** * ApplicationMetada */ @Service public class DolProvider implements ApplicationMetaDataProvider<Application>, ApplicationInfoProvider { @Inject ArchivistFactory archivistFactory; @Inject protected ApplicationFactory applicationFactory; @Inject protected ArchiveFactory archiveFactory; @Inject protected DescriptorArchivist descriptorArchivist; @Inject protected ApplicationArchivist applicationArchivist; @Inject Domain domain; @Inject DasConfig dasConfig; @Inject Deployment deployment; @Inject ServerEnvironment env; @Inject Provider<ClassLoaderHierarchy> clhProvider; private static String WRITEOUT_XML = System.getProperty( "writeout.xml"); final private static LocalStringManagerImpl localStrings = new LocalStringManagerImpl(DolProvider.class); public MetaData getMetaData() { return new MetaData(false, new Class[] { Application.class }, null); } private Application processDOL(DeploymentContext dc) throws IOException { ReadableArchive sourceArchive = dc.getSource(); sourceArchive.setExtraData(Types.class, dc.getTransientAppMetaData(Types.class.getName(), Types.class)); sourceArchive.setExtraData(Parser.class, dc.getTransientAppMetaData(Parser.class.getName(), Parser.class)); ClassLoader cl = dc.getClassLoader(); DeployCommandParameters params = dc.getCommandParameters(DeployCommandParameters.class); sourceArchive.addArchiveMetaData(DeploymentProperties.APP_PROPS, dc.getAppProps()); sourceArchive.addArchiveMetaData(DeploymentProperties.COMMAND_PARAMS, params); String name = params.name(); String archiveType = dc.getArchiveHandler().getArchiveType(); Archivist archivist = archivistFactory.getArchivist(archiveType, cl); if (archivist == null) { // if no JavaEE medata was found in the archive, we return // an empty Application object return Application.createApplication(); } archivist.setAnnotationProcessingRequested(true); String xmlValidationLevel = dasConfig.getDeployXmlValidation(); archivist.setXMLValidationLevel(xmlValidationLevel); if (xmlValidationLevel.equals("none")) { archivist.setXMLValidation(false); } archivist.setRuntimeXMLValidationLevel(xmlValidationLevel); if (xmlValidationLevel.equals("none")) { archivist.setRuntimeXMLValidation(false); } Collection<Sniffer> sniffers = dc.getTransientAppMetaData(DeploymentProperties.SNIFFERS, Collection.class); archivist.setExtensionArchivists(archivistFactory.getExtensionsArchivists(sniffers, archivist.getModuleType())); ApplicationHolder holder = dc.getModuleMetaData(ApplicationHolder.class); File deploymentPlan = params.deploymentplan; handleDeploymentPlan(deploymentPlan, archivist, sourceArchive, holder); long start = System.currentTimeMillis(); Application application=null; if (holder!=null) { application = holder.app; application.setAppName(name); application.setClassLoader(cl); if (application.isVirtual()) { ModuleDescriptor md = application.getStandaloneBundleDescriptor().getModuleDescriptor(); md.setModuleName(name); } try { applicationFactory.openWith(application, sourceArchive, archivist); } catch(SAXParseException e) { throw new IOException(e); } } else { // for case where user specified --name // and it's a standalone module try { application = applicationFactory.openArchive( name, archivist, sourceArchive, true); application.setAppName(name); ModuleDescriptor md = application.getStandaloneBundleDescriptor().getModuleDescriptor(); md.setModuleName(name); } catch(SAXParseException e) { throw new IOException(e); } } application.setRegistrationName(name); sourceArchive.removeExtraData(Types.class); sourceArchive.removeExtraData(Parser.class); Logger.getAnonymousLogger().log(Level.FINE, "DOL Loading time" + (System.currentTimeMillis() - start)); return application; } public Application load(DeploymentContext dc) throws IOException { DeployCommandParameters params = dc.getCommandParameters(DeployCommandParameters.class); Application application = processDOL(dc); // write out xml files if needed if (Boolean.valueOf(WRITEOUT_XML)) { saveAppDescriptor(application, dc); } if (application.isVirtual()) { dc.addModuleMetaData(application.getStandaloneBundleDescriptor()); for (RootDeploymentDescriptor extension : application.getStandaloneBundleDescriptor().getExtensionsDescriptors()) { dc.addModuleMetaData(extension); } } addModuleConfig(dc, application); validateKeepStateOption(dc, params, application); return application; } /** * return the name for the given application */ public String getNameFor(ReadableArchive archive, DeploymentContext context) { if (context == null) { return null; } DeployCommandParameters params = context.getCommandParameters(DeployCommandParameters.class); Application application = null; try { // for these cases, the standard DD could contain the application // name for ear and module name for standalone module if (params.altdd != null || archive.exists("META-INF/application.xml") || archive.exists("WEB-INF/web.xml") || archive.exists("META-INF/ejb-jar.xml") || archive.exists("META-INF/application-client.xml") || archive.exists("META-INF/ra.xml")) { String archiveType = context.getArchiveHandler().getArchiveType() ; application = applicationFactory.createApplicationFromStandardDD(archive, archiveType); DeploymentTracing tracing = null; tracing = context.getModuleMetaData(DeploymentTracing.class); if (tracing != null) { tracing.addMark(DeploymentTracing.Mark.DOL_LOADED); } ApplicationHolder holder = new ApplicationHolder(application); context.addModuleMetaData(holder); return application.getAppName(); } } catch (Exception e) { Logger.getAnonymousLogger().log(Level.WARNING, "Error occurred", e); } return null; } /** * This method populates the Application object from a ReadableArchive * @param archive the archive for the application */ public Application processDeploymentMetaData(ReadableArchive archive) throws Exception { FileArchive expandedArchive = null; File tmpFile = null; ExtendedDeploymentContext context = null; Logger logger = Logger.getAnonymousLogger(); ClassLoader cl = null; try { String archiveName = Util.getURIName(archive.getURI()); ArchiveHandler archiveHandler = deployment.getArchiveHandler(archive); if (archiveHandler==null) { throw new IllegalArgumentException(localStrings.getLocalString("deploy.unknownarchivetype","Archive type of {0} was not recognized", archiveName)); } DeployCommandParameters parameters = new DeployCommandParameters(new File(archive.getURI())); ActionReport report = new HTMLActionReporter(); context = new DeploymentContextImpl(report, archive, parameters, env); context.setArchiveHandler(archiveHandler); String appName = archiveHandler.getDefaultApplicationName(archive, context); parameters.name = appName; if (archive instanceof InputJarArchive) { // we need to expand the archive first in this case tmpFile = File.createTempFile( archiveName,""); String path = tmpFile.getAbsolutePath(); if (!tmpFile.delete()) { logger.log(Level.WARNING, "cannot.delete.temp.file", new Object[] {path}); } File tmpDir = new File(path); tmpDir.deleteOnExit(); if (!tmpDir.exists() && !tmpDir.mkdirs()) { throw new IOException("Unable to create directory " + tmpDir.getAbsolutePath()); } expandedArchive = (FileArchive)archiveFactory.createArchive(tmpDir); archiveHandler.expand(archive, expandedArchive, context); context.setSource(expandedArchive); } context.setPhase(DeploymentContextImpl.Phase.PREPARE); ClassLoaderHierarchy clh = clhProvider.get(); context.createDeploymentClassLoader(clh, archiveHandler); cl = context.getClassLoader(); deployment.getDeployableTypes(context); deployment.getSniffers(archiveHandler, null, context); return processDOL(context); } finally { if (cl != null && cl instanceof PreDestroy) { try { PreDestroy.class.cast(cl).preDestroy(); } catch (Exception e) { // ignore } } if (context != null) { context.postDeployClean(true); } if (expandedArchive != null) { try { expandedArchive.close(); } catch (Exception e) { // ignore } } if (tmpFile != null && tmpFile.exists()) { try { FileUtils.whack(tmpFile); } catch (Exception e) { // ignore } } } } protected void handleDeploymentPlan(File deploymentPlan, Archivist archivist, ReadableArchive sourceArchive, ApplicationHolder holder) throws IOException { //Note in copying of deployment plan to the portable archive, //we should make sure the manifest in the deployment plan jar //file does not overwrite the one in the original archive if (deploymentPlan != null) { DeploymentPlanArchive dpa = new DeploymentPlanArchive(); dpa.setParentArchive(sourceArchive); dpa.open(deploymentPlan.toURI()); // need to revisit for ear case WritableArchive targetArchive = archiveFactory.createArchive( sourceArchive.getURI()); if (archivist instanceof ApplicationArchivist) { ((ApplicationArchivist)archivist).copyInto(holder.app, dpa, targetArchive, false); } else { archivist.copyInto(dpa, targetArchive, false); } } } protected void saveAppDescriptor(Application application, DeploymentContext context) throws IOException { if (application != null) { ReadableArchive archive = archiveFactory.openArchive( context.getSourceDir()); boolean isMkdirs = context.getScratchDir("xml").mkdirs(); if (isMkdirs) { WritableArchive archive2 = archiveFactory.createArchive( context.getScratchDir("xml")); descriptorArchivist.write(application, archive, archive2); // copy the additional webservice elements etc applicationArchivist.copyExtraElements(archive, archive2); } else { context.getLogger().log(Level.WARNING, "Error in creating directory " + context.getScratchDir("xml").getAbsolutePath()); } } } private void addModuleConfig(DeploymentContext dc, Application application) { DeployCommandParameters params = dc.getCommandParameters(DeployCommandParameters.class); if (!params.origin.isDeploy()) { return; } try { com.sun.enterprise.config.serverbeans.Application app_w = dc.getTransientAppMetaData(com.sun.enterprise.config.serverbeans.ServerTags.APPLICATION, com.sun.enterprise.config.serverbeans.Application.class); if (app_w != null) { if (application.isVirtual()) { Module modConfig = app_w.createChild(Module.class); app_w.getModule().add(modConfig); modConfig.setName(application.getRegistrationName()); } else { for (ModuleDescriptor moduleDesc : application.getModules()) { Module modConfig = app_w.createChild(Module.class); app_w.getModule().add(modConfig); modConfig.setName(moduleDesc.getArchiveUri()); } } } } catch (Exception e) { Logger.getAnonymousLogger().log(Level.WARNING, "failed to add the module config", e); } } private void validateKeepStateOption(DeploymentContext context, DeployCommandParameters params, Application app) { if ((params.keepstate != null && params.keepstate) || app.getKeepState()) { if (!isDASTarget(context, params)) { // for non-DAS target, and keepstate is set to true either // through deployment option or deployment descriptor // explicitly set the deployment option to false params.keepstate = false; String warningMsg = localStrings.getLocalString("not.support.keepstate.in.cluster", "Ignoring the keepstate setting: the keepstate option is only supported in developer profile and not cluster profile."); ActionReport subReport = context.getActionReport().addSubActionsReport(); subReport.setActionExitCode(ActionReport.ExitCode.WARNING); subReport.setMessage(warningMsg); context.getLogger().log(Level.WARNING, warningMsg); } } } private boolean isDASTarget(DeploymentContext context, DeployCommandParameters params) { if (DeploymentUtils.isDASTarget(params.target)) { return true; } else if (DeploymentUtils.isDomainTarget(params.target)) { List<String> targets = context.getTransientAppMetaData(DeploymentProperties.PREVIOUS_TARGETS, List.class); if (targets == null) { targets = domain.getAllReferencedTargetsForApplication( params.name); } if (targets.size() == 1 && DeploymentUtils.isDASTarget(targets.get(0))) { return true; } } return false; } }