/* * Copyright 2013 NGDATA nv * Copyright 2007 Outerthought bvba and Schaubroeck nv * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * 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 org.lilyproject.runtime.classloading; import java.util.ArrayList; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.lilyproject.runtime.module.build.VersionManager; import org.lilyproject.runtime.rapi.ModuleSource; import org.lilyproject.runtime.repository.ArtifactRef; import org.lilyproject.runtime.repository.ArtifactRepository; import org.lilyproject.runtime.repository.FileArtifactRef; import org.lilyproject.runtime.repository.RepoArtifactRef; import org.lilyproject.util.xml.DocumentHelper; import org.w3c.dom.Element; /** * Builds a ClassLoadingConfig from XML. */ public class XmlClassLoaderBuilder { private final Log log = LogFactory.getLog(getClass()); private Element element; private ModuleSource moduleSource; private ArtifactRepository repository; private VersionManager versionManager; public static ClassLoadingConfig build(Element element, ModuleSource moduleSource, ArtifactRepository repository, VersionManager versionManager) throws Exception { return new XmlClassLoaderBuilder(element, moduleSource, repository, versionManager).build(); } private XmlClassLoaderBuilder(Element element, ModuleSource moduleSource, ArtifactRepository repository, VersionManager versionManager) { this.element = element; this.moduleSource = moduleSource; this.repository = repository; this.versionManager = versionManager; } private ClassLoadingConfig build() throws Exception { List<ClasspathEntry> classpath = new ArrayList<ClasspathEntry>(); // First add module self ArtifactSharingMode selfSharingMode = ArtifactSharingMode.PROHIBITED; String selfShareModeName = element.getAttribute("share-self"); if (selfShareModeName.length() > 0) { selfSharingMode = ArtifactSharingMode.fromString(selfShareModeName); } ClasspathEntry selfEntry = new ClasspathEntry(new FileArtifactRef(moduleSource.getClassPathEntry()), selfSharingMode, moduleSource); classpath.add(selfEntry); Element classPathElement = DocumentHelper.getElementChild(element, "classpath", false); if (classPathElement != null) { Element[] classPathEls = DocumentHelper.getElementChildren(classPathElement); classpath: for (Element classPathEl : classPathEls) { if (classPathEl.getLocalName().equals("artifact") && classPathEl.getNamespaceURI() == null) { // Create ArtifactRef String groupId = DocumentHelper.getAttribute(classPathEl, "groupId", true); String artifactId = DocumentHelper.getAttribute(classPathEl, "artifactId", true); String classifier = DocumentHelper.getAttribute(classPathEl, "classifier", false); String version = DocumentHelper.getAttribute(classPathEl, "version", false); String preferredVersion = versionManager.getPreferredVersion(groupId, artifactId); version = version == null ? preferredVersion : version; if (version == null) { String message = String.format("Version for artifact %s:%s (%s) not specified, and no preference found in runtime configuration.", groupId, artifactId, classifier); throw new RuntimeException(message); } ArtifactRef artifactRef = new RepoArtifactRef(groupId, artifactId, classifier, version); // Check for double artifacts for (ClasspathEntry entry : classpath) { if (entry.getArtifactRef().equals(artifactRef)) { log.error("Classloader specification contains second reference to same artifact, will skip second reference. Artifact = " + artifactRef); continue classpath; } else if (entry.getArtifactRef().getId().equals(artifactRef.getId())) { log.warn("Classloader specification contains second reference to same artifact but different version. Artifact = " + artifactRef); } } // Creating SharingMode String sharingModeParam = classPathEl.getAttribute("share"); ArtifactSharingMode sharingMode; if (sharingModeParam == null || sharingModeParam.equals("")) { sharingMode = ArtifactSharingMode.ALLOWED; } else { sharingMode = ArtifactSharingMode.fromString(sharingModeParam); } classpath.add(new ClasspathEntry(artifactRef, sharingMode, null)); } } } return new ClassLoadingConfigImpl(classpath, repository); } }