Hi,

Thank you Daniel for your support and deep explanation.

I have chosen the second solution because i don´t like a weblogic specific
code. I attach the resulting code DeploymentUtil class.

Because of Weblogic is a very popular application server, I think this error
would be consider a bug and IMHO a patch should go in future cocoon
releases.

BR,

Juanjo

On 9/30/07, Daniel Fagerstrom <[EMAIL PROTECTED]> wrote:
>
> Juanjo Vázquez skrev:
> > Hi all,
> >
> > I´m working in an Cocoon 2.2-RC1 web application with one block.
> > Everything is ok when i deploy to Tomcat but i´m getting errors when i
> > deploy to Weblogic 9.2. I have been looking for a workaround  or a
> > solution and it seems the problem is the blocks are not deployed to the
> > public web directory in the weblogic domain.
> >
> > Everything points to the method "deployBlockResources" in
> > "DeploymentUtil" class (cocoon-spring-configuratior-1.0.0.jar) is not
> > working properly in this environment. I have been debugging the
> > application deployed to weblogic with these discoveries:
> >
> > 1. Spring loads the jar configurations with zip protocol instead jar
> > protocol, i.e.
> >
> zip:C:/bea/user_projects/domains/cm_domain/servers/AdminServer/tmp/_WL_user/proxy-ear/53xotj/war/WEB-INF/lib/cocoon-
> servlet-service-impl-1.0.0-M2.jar!/META-INF/cocoon/spring/cocoon-callstack-environment.xml
> >
> >
> > 2. In Runtime, the "URLConnection" class is a
> > "weblogic.utils.ZipUrlConnection" not a "JarURLConnection"
> >
> > Can anybody help me with this problem?
>
> Some background:
>
> Blocks can contain resources that are intended to be available in e.g.
> sitemaps. These resources are put in a directory called COB-INF at the
> root of the directory structure of a block. The blocks are ordinary jars
> that are put in WEB-INF/lib (during development the blocks can expanded
> also).
>
> The task of DeploymentUtil.deployBlockResources is to search the class
> path for all urls to COB-INF resources. If the url is of the type file:
> the url and the block name is registred. Then the resources in the
> COB-INF directory of the block is available through the blockcontext:
> source. If the url is a jar, the resources in the COB-INF directory are
> extracted to a temp directory in the file system and the url of the
> extracted resources is registred together with the clock name.
>
> For Weblogic it seem like the classloader contains zip: urls for
> resources. A solution would be to extend the
> DeploymentUtil.deployBlockResources method with a case for the zip:
> protocol, it would be similar to the jar: case but a little bit more
> compliacted as the zip protocol doesn't know about mainfest attributes.
> A problem with this is that the ZipUrlConnection is Weblogic specific,
> so the protocol handling code in deployBlockResources would need to be
> extracted to some components.
>
> Another, and much simpler solution if it works, would be to just replace
> "zip:" with "jar:" in the url string, create a new url object from the
> patched url string, and use the existing jar handling code.
>
> /Daniel
>
>
/*
 * 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.spring.configurator.impl;

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.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: DeploymentUtil.java 555608 2007-07-12 12:12:54Z felixk $
 * @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 deploy is required
        final Enumeration entries = jarFile.entries();
        while (entries.hasMoreElements()) {
            final ZipEntry entry = (ZipEntry)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    blockContexts)
    throws IOException {
        final Enumeration jarUrls = DeploymentUtil.class.getClassLoader().getResources(BLOCK_RESOURCES_PATH);
        while ( jarUrls.hasMoreElements() ) {
            final URL resourceUrl = (URL)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}/{block name}/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.replace("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).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 deployBlockArtifacts(String destinationDirectory)
    throws IOException {
        if ( destinationDirectory == null ) {
            throw new IllegalArgumentException("Destination must not be null.");
        }
        final Map blockContexts = new HashMap();
        // deploy all artifacts containing block resources
        deployBlockResources("blocks", destinationDirectory, blockContexts);
        return blockContexts;
    }

    public static void deployJarResources(String pattern, String destinationDirectory)
    throws IOException {
        final Enumeration jarUrls = DeploymentUtil.class.getClassLoader().getResources(pattern);
        while ( jarUrls.hasMoreElements() ) {
            final URL resourceUrl = (URL)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);
            }
        }
    }
}

Reply via email to