/* * Copyright 2008 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.impl.opstring; import org.rioproject.opstring.OperationalString; import org.rioproject.resolver.RemoteRepository; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.net.JarURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.*; import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.Manifest; /** * An OperationalString Archive ({@code OAR}) contains information about a deployment (an {@link OperationalString}). * * @author Dennis Reedy */ public class OAR implements Serializable { private static final long serialVersionUID = 1L; private String name; private String version; private String opStringName; private URL url; private String deployDir; private String activationType; private final Set<RemoteRepository> repositories = new HashSet<RemoteRepository>(); /** * Manifest header identifying the name of the deployment */ public static final String OAR_NAME = "OAR-Name"; /** * Manifest header indicating the version of the {@code OAR} */ public static final String OAR_VERSION = "OAR-Version"; /** * Manifest header identifying the embedded {@link OperationalString} */ public static final String OAR_OPSTRING = "OAR-OperationalString"; /** * Manifest header identifying the type of activation */ public static final String OAR_ACTIVATION = "OAR-Activation"; /** * Manifest header indicating that the {@code OAR} be deployed automatically when scanned by the {@code ProvisionMonitor} */ public static final String AUTOMATIC="Automatic"; /** * Manifest header indicating that the {@code OAR} be deployed manually */ public static final String MANUAL="Manual"; /** * Create an OAR * * @param file The OperationalString Archive File * * @throws OARException If the manifest cannot be read * @throws IllegalArgumentException If the manifest is null */ public OAR(File file) throws OARException { if(file==null) throw new IllegalArgumentException("file cannot be null"); JarFile jar = null; try { jar = new JarFile(file); Manifest man = jar.getManifest(); getManifestAttributes(man); loadRepositories(jar); url = file.toURI().toURL(); } catch (IOException e) { throw new OARException("Problem processing "+file.getName(), e); } finally { try { if(jar!=null) jar.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * Create an OAR * * @param url The URL for the OperationalString Archive * * @throws OARException If the manifest cannot be read * @throws IllegalArgumentException If the url is null */ public OAR(URL url) throws OARException { if(url==null) throw new IllegalArgumentException("url cannot be null"); JarFile jar = null; try { URL oarURL; if(url.getProtocol().equals("jar")) { oarURL = url; } else { StringBuilder sb = new StringBuilder(); sb.append("jar:").append(url.toExternalForm()).append("!/"); oarURL = new URL(sb.toString()); } JarURLConnection conn = (JarURLConnection)oarURL.openConnection(); jar = conn.getJarFile(); Manifest man = jar.getManifest(); getManifestAttributes(man); loadRepositories(jar); jar.close(); this.url = url; } catch (Exception e) { throw new OARException("Problem processing "+url.toExternalForm(), e); } finally { try { if(jar!=null) jar.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * Create an OAR * * @param manifest A Manifest to the oar * * @throws OARException If the manifest cannot be read * @throws IllegalArgumentException If the manifest is null */ public OAR(Manifest manifest) throws OARException { getManifestAttributes(manifest); } /** * Get OAR attributes from the Manifest * * @param manifest A Manifest to the oar * * @throws OARException If the manifest cannot be read * @throws IllegalArgumentException If the manifest is null */ private void getManifestAttributes(Manifest manifest) throws OARException { if(manifest==null) throw new IllegalArgumentException("manifest cannot be null"); Attributes attrs = manifest.getMainAttributes(); if(attrs==null) throw new OARException("Unable to process the OAR, " + "it has no manifest attributes"); name = attrs.getValue(OAR_NAME); if(name==null) fillInAndThrow(OAR_NAME); version = attrs.getValue(OAR_VERSION); opStringName = attrs.getValue(OAR_OPSTRING); if(opStringName==null) fillInAndThrow(OAR_OPSTRING); activationType = attrs.getValue(OAR_ACTIVATION); if(activationType==null) fillInAndThrow(OAR_ACTIVATION); } /** * Get the URL for the File that this OAR was created from. * * @return A URL for the File that this OAR was created from. if the OAR * was not created from a File, return null * * @throws MalformedURLException if the URL cannot be created */ public URL getURL() throws MalformedURLException { return(url); } /** * Get the OAR-Name attribute * * @return The OAR-Name attribute */ public String getName() { return name; } public String getVersion() { return version; } /** * Get the OAR-OperationalString attribute * * @return The OAR-OperationalString attribute */ public String getOpStringName() { return opStringName; } private void setRepositories(Collection<RemoteRepository> repositories) { if(repositories==null) throw new IllegalArgumentException("repositories must not be null"); this.repositories.addAll(repositories); } public Collection<RemoteRepository> getRepositories() { Set<RemoteRepository> remoteRepositories = new HashSet<RemoteRepository>(); remoteRepositories.addAll(repositories); return remoteRepositories; } /** * Get the name of the directory to store the OAR in * * @return The directory name to extract the OAR into. The OAR-Name * manifest attribute will be used to create a directory name the OAR * will be copied to and extracted. If the OAR-Name has spaces ' ' in it, * the spaces will be translated to '-' characters, ensuring there are no * issues with directory name creation and accessibility. If the * OAR-Version manifest entry has been provided, the version will be * appended to the translated name */ public String getCompoundName() { String s = name.replace(' ', '-'); if(version!=null) s = s+"-"+version; return(s); } /** * Set the deployment directory path * * @param deployDir The deployment directory path the OAR has been * extracted to */ public void setDeployDir(String deployDir) { this.deployDir = deployDir; } /** * Get the deployment directory path * * @return The deployment directory path the OAR has been extracted to */ public String getDeployDir() { return(deployDir); } /** * Get the activation type * * @return The activation type, either <tt>Automatic</tt> or <tt>Manual</tt> */ public String getActivationType() { return(activationType); } public OperationalString[] loadOperationalStrings() throws OARException { return loadOperationalStrings(Thread.currentThread().getContextClassLoader()); } public OperationalString[] loadOperationalStrings(ClassLoader loader) throws OARException { if(url==null) throw new OARException("Cannot load OperationalString(s), unknown URL in OAR"); StringBuilder sb = new StringBuilder(); String urlExternalForm = url.toExternalForm(); if(!urlExternalForm.startsWith("jar:")) sb.append("jar:"); sb.append(url.toExternalForm()); if(!urlExternalForm.endsWith("!/")) sb.append("!/"); sb.append(getOpStringName()); try { URL opStringURL = new URL(sb.toString()); OpStringLoader osl = new OpStringLoader(loader); return osl.parseOperationalString(opStringURL); } catch (Exception e) { throw new OARException("Unable to load OperationalStrings", e); } } public String toString() { return String.format("OAR [name=%s, version=%s, opStringName=%s, url=%s, deployDir=%s, activationType=%s]", name, version, opStringName, (url==null?"unknown": url.toExternalForm()), deployDir, activationType); } private void loadRepositories(JarFile jarFile) throws IOException { JarEntry repositoriesXML = jarFile.getJarEntry("repositories.xml"); if(repositoriesXML!=null) { InputStream input = jarFile.getInputStream(repositoriesXML); RepositoryDecoder repositoryDecoder = new RepositoryDecoder(); Collection<RemoteRepository> repositories = new ArrayList<RemoteRepository>(); Collections.addAll(repositories, (RemoteRepository[]) repositoryDecoder.decode(input)); setRepositories(repositories); } } private void fillInAndThrow(String name) throws OARException { String oarName = url==null?"": " ["+url.toExternalForm()+"]"; throw new OARException("The "+name+" attribute was not found, invalid OAR"+oarName); } }