/* * Copyright 2011 the original author or authors. * * 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.rioproject.monitor.service; import net.jini.admin.Administrable; import net.jini.config.Configuration; import net.jini.config.ConfigurationException; import net.jini.core.lookup.ServiceRegistrar; import net.jini.discovery.DiscoveryGroupManagement; import net.jini.discovery.DiscoveryManagement; import net.jini.lookup.DiscoveryAdmin; import org.rioproject.config.Constants; import org.rioproject.impl.opstring.OpStringUtil; import org.rioproject.opstring.ClassBundle; import org.rioproject.opstring.OperationalString; import org.rioproject.opstring.ServiceElement; import org.rioproject.resolver.RemoteRepository; import org.rioproject.resolver.Resolver; import org.rioproject.resolver.ResolverException; import org.rioproject.resolver.ResolverHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.rmi.RemoteException; import java.util.*; /** * This class is used to verify that either jars declared in an OperationalString can be served, or if the * OperationalString is configured to use artifacts, that required artifacts have been resolved */ public class DeploymentVerifier { static Logger logger = LoggerFactory.getLogger(DeploymentVerifier.class.getName()); private final List<RemoteRepository> additionalRepositories = new ArrayList<RemoteRepository>(); private final DiscoveryManagement discoveryManagement; public DeploymentVerifier(final Configuration config, final DiscoveryManagement discoveryManagement) { try { RemoteRepository[] remoteRepositories = (RemoteRepository[]) config.getEntry("org.rioproject.monitor", "remoteRepositories", RemoteRepository[].class, new RemoteRepository[0]); if(remoteRepositories.length>0) { Collections.addAll(additionalRepositories, remoteRepositories); logger.debug("Configured {} additional repositories", additionalRepositories); } } catch (ConfigurationException e) { logger.warn("Getting RemoteRepositories", e); } this.discoveryManagement = discoveryManagement; } public void verifyDeploymentRequest(final DeployRequest request) throws ResolverException, IOException { for(OperationalString o : request.getOperationalStrings()) { verifyOperationalString(o, request.getRepositories()); } } public void verifyOperationalString(final OperationalString opString, final RemoteRepository[] repositories) throws ResolverException, IOException { Resolver resolver = ResolverHelper.getResolver(); for(ServiceElement service : opString.getServices()) { verifyOperationalStringService(service, resolver, mergeRepositories(repositories, service.getRemoteRepositories())); } for(OperationalString nested : opString.getNestedOperationalStrings()) verifyOperationalString(nested, repositories); } public void verifyOperationalStringService(final ServiceElement service, final Resolver resolver, final RemoteRepository[] repositories) throws IOException, ResolverException { /* Check the component bundle for deployment as an artifact, easier check this way */ if(service.getComponentBundle().getArtifact()!=null) { resolveOperationalStringService(service, resolver, repositories); } else { OpStringUtil.checkCodebase(service, System.getProperty(Constants.CODESERVER)); } ensureGroups(service); } private void resolveOperationalStringService(final ServiceElement service, final Resolver resolver, final RemoteRepository[] repositories) throws ResolverException { StringBuilder sb = new StringBuilder(); StringBuilder sb1 = new StringBuilder(); boolean didResolve = false; for (ClassBundle export : service.getExportBundles()) { if(export.getArtifact()!=null) { sb.append(" (").append(export.getArtifact()).append("): "); resolve(export, resolver, repositories); didResolve = true; } for(String jar : export.getJARNames()) { sb1.append("\n"); sb1.append(export.getCodebase()).append(jar); } } if(didResolve) { List<RemoteRepository> remoteRepositories = new ArrayList<RemoteRepository>(); remoteRepositories.addAll(additionalRepositories); remoteRepositories.addAll(resolver.getRemoteRepositories()); service.setRemoteRepositories(remoteRepositories); } sb.append(sb1.toString()); logger.debug("{} derived classpath for loading artifact {}", service.getName(), sb.toString()); } private void resolve(final ClassBundle bundle, final Resolver resolver, final RemoteRepository[] repositories) throws ResolverException { logger.trace("Artifact: {}, resolver: {}", bundle.getArtifact(), resolver.getClass().getName()); String artifact = bundle.getArtifact(); if (artifact != null) { List<String> jars = new ArrayList<String>(); String[] artifactParts = artifact.split(" "); for(String artifactPart : artifactParts) { String[] classPath = resolver.getClassPathFor(artifactPart, repositories); for (String jar : classPath) { jar = ResolverHelper.handleWindows(jar); if(!jars.contains(jar)) jars.add(jar); } } bundle.setCodebase("file://"); bundle.setJARs(jars.toArray(new String[jars.size()])); } } RemoteRepository[] mergeRepositories(final RemoteRepository[] r1, final RemoteRepository[] r2) { Set<RemoteRepository> remoteRepositories = new HashSet<RemoteRepository>(); Collections.addAll(remoteRepositories, r1); for(RemoteRepository r : r2) { remoteRepositories.add(r); } return remoteRepositories.toArray(new RemoteRepository[remoteRepositories.size()]); } void ensureGroups(final ServiceElement serviceElement) throws IOException { if(serviceElement.getServiceBeanConfig().getGroups()==DiscoveryGroupManagement.ALL_GROUPS) { throw new IOException(String.format("Service %s has been declared for ALL_GROUPS", serviceElement.getName())); } for(ServiceRegistrar registrar : discoveryManagement.getRegistrars()) { try { List<String> toAdd = new ArrayList<String>(); DiscoveryAdmin admin = (DiscoveryAdmin) ((Administrable)registrar).getAdmin(); String[] knownGroups = admin.getMemberGroups(); for(String serviceGroup : serviceElement.getServiceBeanConfig().getGroups()) { boolean found = false; for(String known : knownGroups) { if(serviceGroup.equals(known)) { found = true; break; } } if(!found) { toAdd.add(serviceGroup); } } if(!toAdd.isEmpty()) { admin.addMemberGroups(toAdd.toArray(new String[toAdd.size()])); if(logger.isDebugEnabled()) { logger.debug("Added {} to ServiceRegistrar at {}:{}", toAdd, registrar.getLocator().getHost(), registrar.getLocator().getPort()); } } } catch (RemoteException e) { logger.warn("While trying to ensure groups", e); } } } }