blob: 27fefb41c65b89247f560be48abf95444463dda9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.cocoon.blockdeployment;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Helper class for deploying resources from the block artifacts.
*
* @version $Id$
* @since 1.0
*/
public abstract class DeploymentUtil {
protected static final Log logger = LogFactory.getLog(DeploymentUtil.class);
protected static final String BLOCK_RESOURCES_PATH = "COB-INF";
/**
* Deploy all files with a given prefix from a jar file to a directory in
* the file system.
*
* @param jarFile The jar file containing the resources.
* @param prefix The common prefix for the files.
* @param destination The destination directory.
* @throws IOException
*/
public static void deploy(JarFile jarFile, String prefix, String destination) throws IOException {
if (logger.isDebugEnabled()) {
logger.debug("Deploying jar " + jarFile + " to " + destination);
}
// FIXME - We should check if a deployment is required
final Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
final ZipEntry entry = entries.nextElement();
if (!entry.isDirectory() && entry.getName().startsWith(prefix)) {
final String fileName = destination + entry.getName().substring(prefix.length());
final File out = new File(fileName);
// create directory
out.getParentFile().mkdirs();
InputStream inStream = null;
OutputStream outStream = null;
try {
inStream = jarFile.getInputStream(entry);
outStream = new FileOutputStream(out);
IOUtils.copy(inStream, outStream);
} finally {
if (outStream != null) {
outStream.close();
}
if (inStream != null) {
inStream.close();
}
}
}
}
}
protected static void deployBlockResources(String relativeDirectory, String destinationDirectory,
Map<String, String> blockContexts) throws IOException {
final Enumeration<URL> jarUrls = DeploymentUtil.class.getClassLoader().getResources(BLOCK_RESOURCES_PATH);
while (jarUrls.hasMoreElements()) {
final URL resourceUrl = jarUrls.nextElement();
String url = resourceUrl.toExternalForm();
if ("file".equals(resourceUrl.getProtocol())) {
// FIXME: This only covers the siuation when the project is
// Maven generated if this is a file url generated by the Maven,
// it has this form
// "file:{url}/{blockname}/target/classes/COB-INF
int pos = url.indexOf("/target/classes/COB-INF");
// extract block name (if any)
if (pos >= 0) {
String blockName = url.substring(0, pos);
blockName = blockName.substring(blockName.lastIndexOf('/') + 1);
// register the root URL for the block resources
blockContexts.put(blockName, url);
}
} else if ("jar".equals(resourceUrl.getProtocol()) || "zip".equals(resourceUrl.getProtocol())) {
// if this is a jar url, it has this form:
// "jar:{url-to-jar}!/{resource-path}"
// to open the jar, we can simply remove everything after "!/"
int pos = url.indexOf('!');
url = url.substring(0, pos + 2); // +2 as we include "!/"
// Included because of Weblogic 9.2 classloader behaviour
if ("zip".equals(resourceUrl.getProtocol())) {
url = url.replaceAll("zip:", "jar:file:");
}
final URL jarUrl = new URL(url);
final JarURLConnection connection = (JarURLConnection) jarUrl.openConnection();
final JarFile jarFile = connection.getJarFile();
String blockName = jarFile.getManifest().getMainAttributes().getValue("Cocoon-Block-Name");
if (blockName == null) {
String jarPath = jarFile.getName();
// extract jar name
String jarName = jarPath.substring(jarPath.lastIndexOf(File.separatorChar) + 1);
// drop file extension
blockName = jarName.substring(0, jarName.lastIndexOf('.'));
// TODO how do we strip version from blockName?
}
final StringBuffer buffer = new StringBuffer(destinationDirectory);
buffer.append(File.separatorChar);
buffer.append(relativeDirectory);
buffer.append(File.separatorChar);
buffer.append(blockName);
String destination = buffer.toString();
deploy(jarFile, BLOCK_RESOURCES_PATH, destination);
// register the root URL for the block resources
blockContexts.put(blockName, new File(destination).toURI().toURL().toExternalForm());
}
// we only handle jar files and ordinary files
// TODO - Should we throw an exception if it's some other protocol
// type? (or log?)
}
}
public static Map<String, String> deployBlockArtifacts(String destinationDirectory) throws IOException {
if (destinationDirectory == null) {
throw new IllegalArgumentException("Destination directory must not be null.");
}
final Map<String, String> blockContexts = new HashMap<String, String>();
// deploy all artifacts containing block resources
deployBlockResources("blocks", destinationDirectory, blockContexts);
return blockContexts;
}
public static void deployJarResources(String pattern, String destinationDirectory) throws IOException {
final Enumeration<URL> jarUrls = DeploymentUtil.class.getClassLoader().getResources(pattern);
while (jarUrls.hasMoreElements()) {
final URL resourceUrl = jarUrls.nextElement();
String url = resourceUrl.toExternalForm();
// we only handle jars!
if ("jar".equals(resourceUrl.getProtocol())) {
// if this is a jar url, it has this form:
// "jar:{url-to-jar}!/{resource-path}"
// to open the jar, we can simply remove everything after "!/"
int pos = url.indexOf('!');
url = url.substring(0, pos + 2); // +2 as we include "!/"
final URL jarUrl = new URL(url);
final JarURLConnection connection = (JarURLConnection) jarUrl.openConnection();
final JarFile jarFile = connection.getJarFile();
deploy(jarFile, pattern, destinationDirectory);
}
}
}
}