001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.geronimo.kernel.repository;
018    
019    import java.io.InputStream;
020    import java.io.File;
021    import java.io.IOException;
022    import java.io.FileOutputStream;
023    import java.io.OutputStream;
024    import java.util.zip.ZipInputStream;
025    import java.util.zip.ZipEntry;
026    
027    import org.apache.geronimo.kernel.repository.ArtifactTypeHandler;
028    import org.apache.geronimo.kernel.repository.Artifact;
029    import org.apache.geronimo.kernel.repository.FileWriteMonitor;
030    import org.apache.geronimo.kernel.config.IOUtil;
031    
032    /**
033     * @version $Rev: 476049 $ $Date: 2006-11-17 15:35:17 +1100 (Fri, 17 Nov 2006) $
034     */
035    public class UnpackArtifactTypeHandler implements ArtifactTypeHandler {
036        private final static int TRANSFER_NOTIFICATION_SIZE = 10240;  // announce every this many bytes
037        private final static int TRANSFER_BUF_SIZE = 10240;  // try this many bytes at a time
038    
039        public void install(InputStream source, int size, Artifact artifact, FileWriteMonitor monitor, File target) throws IOException {
040            // assure that the target directory exists
041            File parent = target.getParentFile();
042            if (!parent.exists() && !parent.mkdirs()) {
043                throw new RuntimeException("Unable to create directory " + parent.getAbsolutePath());
044            }
045    
046            // copy it
047            if (monitor != null) {
048                monitor.writeStarted(artifact.toString(), size);
049            }
050    
051            int total = 0;
052            ZipInputStream in = new ZipInputStream(source);
053            try {
054    
055                int threshold = UnpackArtifactTypeHandler.TRANSFER_NOTIFICATION_SIZE;
056                byte[] buffer = new byte[TRANSFER_BUF_SIZE];
057    
058                for (ZipEntry entry = in.getNextEntry(); entry != null; entry = in.getNextEntry()) {
059                    File file = new File(target, entry.getName());
060                    if (entry.isDirectory()) {
061                        file.mkdirs();
062                    } else {
063                        if (!entry.getName().equals("META-INF/startup-jar")) {
064                            file.getParentFile().mkdirs();
065                            OutputStream out = new FileOutputStream(file);
066                            try {
067                                int count;
068                                while ((count = in.read(buffer)) > 0) {
069                                    out.write(buffer, 0, count);
070                                    if (monitor != null) {
071                                        total += count;
072                                        if (total > threshold) {
073                                            threshold += UnpackArtifactTypeHandler.TRANSFER_NOTIFICATION_SIZE;
074                                            monitor.writeProgress(total);
075                                        }
076                                    }
077                                }
078                            } finally {
079                                IOUtil.flush(out);
080                                out.close();
081                            }
082                            in.closeEntry();
083                        }
084                    }
085                }
086            } catch (IOException e) {
087                IOUtil.recursiveDelete(target);
088                throw e;
089            } finally {
090                in.close();
091                if (monitor != null) {
092                    monitor.writeComplete(total);
093                }
094            }
095        }
096    }